From 0222e417df45b2806c2b1ea405c45aa4a6683ac9 Mon Sep 17 00:00:00 2001 From: Marian Koreniuk Date: Tue, 30 Jul 2024 16:33:51 +0300 Subject: [PATCH] Sync 0.10.1 to proxmox integration (#242) Signed-off-by: Andrei Kvapil Co-authored-by: Mr Khachaturov <105451445+mrkhachaturov@users.noreply.github.com> Co-authored-by: Andrei Kvapil --- manifests/cozystack-installer.yaml | 4 +- packages/apps/ferretdb/values2.yaml | 56 ++ .../apps/http-cache/images/nginx-cache.json | 16 +- packages/apps/kafka/Chart.yaml | 2 +- packages/apps/kafka/templates/kafka.yaml | 14 + packages/apps/kafka/templates/topics.yaml | 4 +- packages/apps/kubernetes/Chart.yaml | 2 +- .../images/ubuntu-container-disk.json | 16 +- .../cluster-autoscaler/deployment.yaml | 1 + .../apps/kubernetes/templates/cluster.yaml | 39 +- .../apps/kubernetes/templates/csi/deploy.yaml | 1 + .../apps/kubernetes/templates/ingress.yaml | 15 + .../kubernetes/templates/kccm/manager.yaml | 1 + packages/apps/kubernetes/values.yaml | 1 + packages/apps/nats/.helmignore | 3 + packages/apps/nats/Chart.yaml | 25 + packages/apps/nats/Makefile | 2 + packages/apps/nats/README.md | 11 + packages/apps/nats/logos/nats.svg | 76 ++ packages/apps/nats/templates/nats.yaml | 43 ++ packages/apps/nats/values.schema.json | 16 + packages/apps/nats/values.yaml | 8 + packages/apps/postgres/Chart.yaml | 2 +- .../apps/postgres/templates/init-script.yaml | 99 ++- packages/apps/tenant/Chart.yaml | 2 +- packages/apps/tenant/README.md | 1 + .../apps/tenant/templates/networkpolicy.yaml | 136 ++++ packages/apps/tenant/values.schema.json | 5 + packages/apps/tenant/values.yaml | 2 + packages/apps/versions_map | 14 +- packages/core/installer/images/cozystack.json | 8 +- packages/core/installer/images/cozystack.tag | 2 +- packages/core/installer/images/matchbox.json | 10 +- .../core/platform/bundles/distro-full.yaml | 10 +- packages/core/platform/bundles/paas-full.yaml | 6 + .../core/platform/templates/namespaces.yaml | 6 +- packages/extra/etcd/Chart.yaml | 2 +- .../extra/etcd/templates/etcd-cluster.yaml | 4 + packages/extra/ingress/Chart.yaml | 2 +- packages/extra/ingress/Makefile | 5 + packages/extra/ingress/README.md | 12 +- .../ingress/templates/_cloudflare-ips.tpl | 3 + .../extra/ingress/templates/dashboard.yaml | 29 + .../ingress/templates/nginx-ingress.yaml | 14 + packages/extra/ingress/values.schema.json | 16 + packages/extra/ingress/values.yaml | 13 + packages/extra/versions_map | 6 +- .../templates/cluster-issuers.yaml | 7 + packages/system/cilium/images/cilium.json | 18 +- .../system/dashboard/images/dashboard.json | 16 +- .../system/dashboard/images/dashboard.tag | 2 +- .../dashboard/images/kubeapps-apis.json | 20 +- .../system/dashboard/images/kubeapps-apis.tag | 2 +- .../charts/etcd-operator/Chart.yaml | 4 +- .../rbac/clusterrole-manager-role.yml | 16 + .../charts/ingress-nginx/Chart.yaml | 12 +- .../ingress-nginx/charts/ingress-nginx/OWNERS | 2 +- .../charts/ingress-nginx/README.md | 120 ++-- .../ci/daemonset-extra-modules.yaml | 5 +- ...modules-default-container-sec-context.yaml | 5 +- ...odules-specific-container-sec-context.yaml | 5 +- .../ci/deployment-extra-modules.yaml | 5 +- ...t-opentelemetry-customregistry-values.yaml | 9 + .../ingress-nginx/templates/_helpers.tpl | 25 +- .../ingress-nginx/templates/_params.tpl | 11 +- .../job-patch/clusterrole.yaml | 2 +- .../job-patch/clusterrolebinding.yaml | 4 +- .../job-patch/job-createSecret.yaml | 4 +- .../job-patch/job-patchWebhook.yaml | 4 +- .../admission-webhooks/job-patch/role.yaml | 2 +- .../job-patch/rolebinding.yaml | 4 +- .../job-patch/serviceaccount.yaml | 5 +- .../templates/controller-configmap.yaml | 2 +- .../templates/controller-daemonset.yaml | 8 +- .../templates/controller-deployment.yaml | 10 +- .../controller-ingressclass-aliases.yaml | 23 + .../templates/controller-ingressclass.yaml | 15 +- .../templates/controller-keda.yaml | 2 +- .../controller-poddisruptionbudget.yaml | 12 +- .../templates/controller-prometheusrules.yaml | 2 +- .../templates/controller-role.yaml | 3 + .../controller-service-internal.yaml | 55 +- .../templates/controller-service-webhook.yaml | 2 +- .../templates/controller-service.yaml | 12 +- .../templates/controller-servicemonitor.yaml | 3 + .../templates/default-backend-deployment.yaml | 9 +- .../default-backend-extra-configmaps.yaml | 10 +- .../templates/default-backend-hpa.yaml | 16 +- .../templates/default-backend-service.yaml | 2 +- .../job-patch/clusterrole_test.yaml | 11 + .../job-patch/clusterrolebinding_test.yaml | 11 + .../job-patch/role_test.yaml | 11 + .../job-patch/rolebinding_test.yaml | 11 + .../job-patch/serviceaccount_test.yaml | 47 ++ .../controller-configmap-addheaders_test.yaml | 27 + ...ontroller-configmap-proxyheaders_test.yaml | 27 + .../tests/controller-configmap_test.yaml | 31 + .../tests/controller-daemonset_test.yaml | 140 ++++ .../tests/controller-deployment_test.yaml | 162 +++++ .../tests/controller-hpa_test.yaml | 31 + .../controller-ingressclass-aliases_test.yaml | 110 +++ .../tests/controller-ingressclass_test.yaml | 93 +++ .../tests/controller-keda_test.yaml | 31 + .../tests/controller-networkpolicy_test.yaml | 23 + .../controller-poddisruptionbudget_test.yaml | 73 ++ .../controller-service-internal_test.yaml | 25 + .../controller-service-metrics_test.yaml | 23 + .../tests/controller-service_test.yaml | 32 + .../default-backend-deployment_test.yaml | 137 ++++ ...default-backend-extra-configmaps_test.yaml | 17 +- .../tests/default-backend-service_test.yaml | 32 + .../charts/ingress-nginx/values.yaml | 397 ++++++++--- packages/system/ingress-nginx/values.yaml | 6 +- packages/system/kubeovn/images/kubeovn.json | 20 +- packages/system/nats/Chart.yaml | 3 + packages/system/nats/Makefile | 5 + packages/system/nats/charts/nats/.helmignore | 26 + packages/system/nats/charts/nats/Chart.yaml | 16 + packages/system/nats/charts/nats/README.md | 329 +++++++++ packages/system/nats/charts/nats/UPGRADING.md | 155 ++++ .../nats/charts/nats/files/config-map.yaml | 10 + .../charts/nats/files/config/cluster.yaml | 32 + .../nats/charts/nats/files/config/config.yaml | 114 +++ .../charts/nats/files/config/gateway.yaml | 11 + .../charts/nats/files/config/jetstream.yaml | 23 + .../charts/nats/files/config/leafnodes.yaml | 11 + .../nats/charts/nats/files/config/mqtt.yaml | 10 + .../charts/nats/files/config/protocol.yaml | 10 + .../charts/nats/files/config/resolver.yaml | 3 + .../nats/charts/nats/files/config/tls.yaml | 16 + .../charts/nats/files/config/websocket.yaml | 12 + .../charts/nats/files/headless-service.yaml | 24 + .../nats/charts/nats/files/ingress.yaml | 34 + .../nats/files/nats-box/contents-secret.yaml | 17 + .../nats-box/contexts-secret/context.yaml | 51 ++ .../contexts-secret/contexts-secret.yaml | 13 + .../files/nats-box/deployment/container.yaml | 46 ++ .../files/nats-box/deployment/deployment.yaml | 16 + .../nats-box/deployment/pod-template.yaml | 44 ++ .../nats/files/nats-box/service-account.yaml | 7 + .../nats/files/pod-disruption-budget.yaml | 12 + .../nats/charts/nats/files/pod-monitor.yaml | 13 + .../charts/nats/files/service-account.yaml | 7 + .../nats/charts/nats/files/service.yaml | 23 + .../files/stateful-set/jetstream-pvc.yaml | 13 + .../files/stateful-set/nats-container.yaml | 106 +++ .../nats/files/stateful-set/pod-template.yaml | 71 ++ .../stateful-set/prom-exporter-container.yaml | 30 + .../stateful-set/reloader-container.yaml | 27 + .../nats/files/stateful-set/resolver-pvc.yaml | 13 + .../nats/files/stateful-set/stateful-set.yaml | 37 + .../nats/charts/nats/templates/_helpers.tpl | 281 ++++++++ .../nats/charts/nats/templates/_jsonpatch.tpl | 219 ++++++ .../nats/templates/_toPrettyRawJson.tpl | 28 + .../nats/charts/nats/templates/_tplYaml.tpl | 114 +++ .../charts/nats/templates/config-map.yaml | 4 + .../nats/templates/extra-resources.yaml | 5 + .../nats/templates/headless-service.yaml | 4 + .../nats/charts/nats/templates/ingress.yaml | 6 + .../templates/nats-box/contents-secret.yaml | 10 + .../templates/nats-box/contexts-secret.yaml | 8 + .../nats/templates/nats-box/deployment.yaml | 8 + .../templates/nats-box/service-account.yaml | 8 + .../nats/templates/pod-disruption-budget.yaml | 6 + .../charts/nats/templates/pod-monitor.yaml | 8 + .../nats/templates/service-account.yaml | 6 + .../nats/charts/nats/templates/service.yaml | 6 + .../charts/nats/templates/stateful-set.yaml | 4 + .../nats/templates/tests/request-reply.yaml | 37 + packages/system/nats/charts/nats/values.yaml | 669 ++++++++++++++++++ packages/system/nats/values.yaml | 7 + .../system/snapshot-controller/.helmignore | 3 + .../system/snapshot-controller/Chart.yaml | 3 + packages/system/snapshot-controller/Makefile | 10 + .../charts/snapshot-controller/.helmignore | 25 + .../charts/snapshot-controller/Chart.yaml | 22 + .../charts/snapshot-controller/LICENSE | 201 ++++++ .../charts/snapshot-controller/README.md | 200 ++++++ ...age.k8s.io_volumegroupsnapshotclasses.yaml | 94 +++ ...ge.k8s.io_volumegroupsnapshotcontents.yaml | 335 +++++++++ ...t.storage.k8s.io_volumegroupsnapshots.yaml | 273 +++++++ ....storage.k8s.io_volumesnapshotclasses.yaml | 143 ++++ ...storage.k8s.io_volumesnapshotcontents.yaml | 457 ++++++++++++ ...apshot.storage.k8s.io_volumesnapshots.yaml | 351 +++++++++ .../snapshot-controller/templates/NOTES.txt | 30 + .../templates/_helpers.tpl | 134 ++++ .../templates/deployment_controller.yaml | 89 +++ .../deployment_validation_webhook.yaml | 91 +++ .../templates/networkpolicy.yaml | 20 + .../poddisruptionbudget_controller.yaml | 13 + ...oddisruptionbudget_validation_webhook.yaml | 13 + .../templates/service_controller.yaml | 16 + .../templates/service_validation_webhook.yaml | 17 + .../templates/serviceaccount_controller.yaml | 96 +++ .../serviceaccount_validation_webhook.yaml | 38 + .../templates/servicemonitor.yaml | 15 + .../templates/volumesnapshotclass.yaml | 22 + .../templates/webhook.yaml | 112 +++ .../charts/snapshot-controller/values.yaml | 180 +++++ .../system/snapshot-controller/values.yaml | 13 + 200 files changed, 8261 insertions(+), 371 deletions(-) create mode 100644 packages/apps/ferretdb/values2.yaml create mode 100644 packages/apps/nats/.helmignore create mode 100644 packages/apps/nats/Chart.yaml create mode 100644 packages/apps/nats/Makefile create mode 100644 packages/apps/nats/README.md create mode 100644 packages/apps/nats/logos/nats.svg create mode 100644 packages/apps/nats/templates/nats.yaml create mode 100644 packages/apps/nats/values.schema.json create mode 100644 packages/apps/nats/values.yaml create mode 100644 packages/apps/tenant/templates/networkpolicy.yaml create mode 100644 packages/extra/ingress/templates/_cloudflare-ips.tpl create mode 100644 packages/extra/ingress/templates/dashboard.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-opentelemetry-customregistry-values.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-ingressclass-aliases.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/clusterrole_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/clusterrolebinding_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/role_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/rolebinding_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/serviceaccount_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-configmap-addheaders_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-configmap-proxyheaders_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-configmap_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-daemonset_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-deployment_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-hpa_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-ingressclass-aliases_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-ingressclass_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-keda_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-networkpolicy_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-poddisruptionbudget_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-service-internal_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-service-metrics_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-service_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-deployment_test.yaml create mode 100644 packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-service_test.yaml create mode 100644 packages/system/nats/Chart.yaml create mode 100644 packages/system/nats/Makefile create mode 100644 packages/system/nats/charts/nats/.helmignore create mode 100644 packages/system/nats/charts/nats/Chart.yaml create mode 100644 packages/system/nats/charts/nats/README.md create mode 100644 packages/system/nats/charts/nats/UPGRADING.md create mode 100644 packages/system/nats/charts/nats/files/config-map.yaml create mode 100644 packages/system/nats/charts/nats/files/config/cluster.yaml create mode 100644 packages/system/nats/charts/nats/files/config/config.yaml create mode 100644 packages/system/nats/charts/nats/files/config/gateway.yaml create mode 100644 packages/system/nats/charts/nats/files/config/jetstream.yaml create mode 100644 packages/system/nats/charts/nats/files/config/leafnodes.yaml create mode 100644 packages/system/nats/charts/nats/files/config/mqtt.yaml create mode 100644 packages/system/nats/charts/nats/files/config/protocol.yaml create mode 100644 packages/system/nats/charts/nats/files/config/resolver.yaml create mode 100644 packages/system/nats/charts/nats/files/config/tls.yaml create mode 100644 packages/system/nats/charts/nats/files/config/websocket.yaml create mode 100644 packages/system/nats/charts/nats/files/headless-service.yaml create mode 100644 packages/system/nats/charts/nats/files/ingress.yaml create mode 100644 packages/system/nats/charts/nats/files/nats-box/contents-secret.yaml create mode 100644 packages/system/nats/charts/nats/files/nats-box/contexts-secret/context.yaml create mode 100644 packages/system/nats/charts/nats/files/nats-box/contexts-secret/contexts-secret.yaml create mode 100644 packages/system/nats/charts/nats/files/nats-box/deployment/container.yaml create mode 100644 packages/system/nats/charts/nats/files/nats-box/deployment/deployment.yaml create mode 100644 packages/system/nats/charts/nats/files/nats-box/deployment/pod-template.yaml create mode 100644 packages/system/nats/charts/nats/files/nats-box/service-account.yaml create mode 100644 packages/system/nats/charts/nats/files/pod-disruption-budget.yaml create mode 100644 packages/system/nats/charts/nats/files/pod-monitor.yaml create mode 100644 packages/system/nats/charts/nats/files/service-account.yaml create mode 100644 packages/system/nats/charts/nats/files/service.yaml create mode 100644 packages/system/nats/charts/nats/files/stateful-set/jetstream-pvc.yaml create mode 100644 packages/system/nats/charts/nats/files/stateful-set/nats-container.yaml create mode 100644 packages/system/nats/charts/nats/files/stateful-set/pod-template.yaml create mode 100644 packages/system/nats/charts/nats/files/stateful-set/prom-exporter-container.yaml create mode 100644 packages/system/nats/charts/nats/files/stateful-set/reloader-container.yaml create mode 100644 packages/system/nats/charts/nats/files/stateful-set/resolver-pvc.yaml create mode 100644 packages/system/nats/charts/nats/files/stateful-set/stateful-set.yaml create mode 100644 packages/system/nats/charts/nats/templates/_helpers.tpl create mode 100644 packages/system/nats/charts/nats/templates/_jsonpatch.tpl create mode 100644 packages/system/nats/charts/nats/templates/_toPrettyRawJson.tpl create mode 100644 packages/system/nats/charts/nats/templates/_tplYaml.tpl create mode 100644 packages/system/nats/charts/nats/templates/config-map.yaml create mode 100644 packages/system/nats/charts/nats/templates/extra-resources.yaml create mode 100644 packages/system/nats/charts/nats/templates/headless-service.yaml create mode 100644 packages/system/nats/charts/nats/templates/ingress.yaml create mode 100644 packages/system/nats/charts/nats/templates/nats-box/contents-secret.yaml create mode 100644 packages/system/nats/charts/nats/templates/nats-box/contexts-secret.yaml create mode 100644 packages/system/nats/charts/nats/templates/nats-box/deployment.yaml create mode 100644 packages/system/nats/charts/nats/templates/nats-box/service-account.yaml create mode 100644 packages/system/nats/charts/nats/templates/pod-disruption-budget.yaml create mode 100644 packages/system/nats/charts/nats/templates/pod-monitor.yaml create mode 100644 packages/system/nats/charts/nats/templates/service-account.yaml create mode 100644 packages/system/nats/charts/nats/templates/service.yaml create mode 100644 packages/system/nats/charts/nats/templates/stateful-set.yaml create mode 100644 packages/system/nats/charts/nats/templates/tests/request-reply.yaml create mode 100644 packages/system/nats/charts/nats/values.yaml create mode 100644 packages/system/nats/values.yaml create mode 100644 packages/system/snapshot-controller/.helmignore create mode 100644 packages/system/snapshot-controller/Chart.yaml create mode 100644 packages/system/snapshot-controller/Makefile create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/.helmignore create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/Chart.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/LICENSE create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/README.md create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/crds/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/crds/groupsnapshot.storage.k8s.io_volumegroupsnapshotcontents.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/crds/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/crds/snapshot.storage.k8s.io_volumesnapshotclasses.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/crds/snapshot.storage.k8s.io_volumesnapshotcontents.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/crds/snapshot.storage.k8s.io_volumesnapshots.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/NOTES.txt create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/_helpers.tpl create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/deployment_controller.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/deployment_validation_webhook.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/networkpolicy.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/poddisruptionbudget_controller.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/poddisruptionbudget_validation_webhook.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/service_controller.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/service_validation_webhook.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/serviceaccount_controller.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/serviceaccount_validation_webhook.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/servicemonitor.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/volumesnapshotclass.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/templates/webhook.yaml create mode 100644 packages/system/snapshot-controller/charts/snapshot-controller/values.yaml create mode 100644 packages/system/snapshot-controller/values.yaml diff --git a/manifests/cozystack-installer.yaml b/manifests/cozystack-installer.yaml index e88aa4c5..685401a4 100644 --- a/manifests/cozystack-installer.yaml +++ b/manifests/cozystack-installer.yaml @@ -68,7 +68,7 @@ spec: serviceAccountName: cozystack containers: - name: cozystack - image: "ghcr.io/aenix-io/cozystack/cozystack:v0.9.0" + image: "ghcr.io/aenix-io/cozystack/cozystack:v0.10.1" env: - name: KUBERNETES_SERVICE_HOST value: localhost @@ -87,7 +87,7 @@ spec: fieldRef: fieldPath: metadata.name - name: darkhttpd - image: "ghcr.io/aenix-io/cozystack/cozystack:v0.9.0" + image: "ghcr.io/aenix-io/cozystack/cozystack:v0.10.1" command: - /usr/bin/darkhttpd - /cozystack/assets diff --git a/packages/apps/ferretdb/values2.yaml b/packages/apps/ferretdb/values2.yaml new file mode 100644 index 00000000..9964dfe8 --- /dev/null +++ b/packages/apps/ferretdb/values2.yaml @@ -0,0 +1,56 @@ +## @section Common parameters + +## @param external Enable external access from outside the cluster +## @param size Persistent Volume size +## @param replicas Number of Postgres replicas +## +external: false +size: 10Gi +replicas: 1 + +## Configuration for the quorum-based synchronous replication +## @param quorum.minSyncReplicas Minimum number of synchronous replicas that must acknowledge a transaction before it is considered committed. +## @param quorum.maxSyncReplicas Maximum number of synchronous replicas that can acknowledge a transaction (must be lower than the number of instances). +quorum: + minSyncReplicas: 0 + maxSyncReplicas: 0 + +## @section Configuration parameters + +## @param users [object] Users configuration +## Example: +## users: +## user1: +## password: strongpassword +## user2: +## password: hackme +## +users: + foo: + password: asd + bar: + password: asd + baz: + password: asd + boo: + password: asd + +## @section Backup parameters + +## @param backup.enabled Enable pereiodic backups +## @param backup.s3Region The AWS S3 region where backups are stored +## @param backup.s3Bucket The S3 bucket used for storing backups +## @param backup.schedule Cron schedule for automated backups +## @param backup.cleanupStrategy The strategy for cleaning up old backups +## @param backup.s3AccessKey The access key for S3, used for authentication +## @param backup.s3SecretKey The secret key for S3, used for authentication +## @param backup.resticPassword The password for Restic backup encryption +backup: + enabled: false + s3Region: us-east-1 + s3Bucket: s3.example.org/postgres-backups + schedule: "0 2 * * *" + cleanupStrategy: "--keep-last=3 --keep-daily=3 --keep-within-weekly=1m" + s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu + s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog + resticPassword: ChaXoveekoh6eigh4siesheeda2quai0 diff --git a/packages/apps/http-cache/images/nginx-cache.json b/packages/apps/http-cache/images/nginx-cache.json index bd54b58a..11b058c6 100644 --- a/packages/apps/http-cache/images/nginx-cache.json +++ b/packages/apps/http-cache/images/nginx-cache.json @@ -32,7 +32,17 @@ } } }, - "buildx.build.ref": "amd64/amd64/gaibgudlqaxqxufa236q5ffdk", - "containerimage.config.digest": "sha256:677b0b84d7a11a31971857863a6a83b5bb863583eca86a2c2b1b89c61659e549", - "containerimage.digest": "sha256:7f864e2c9c86b77e08953258521117503309f84783ea11c617db8c2534f8b545" + "buildx.build.ref": "cozystack/cozystack0/7j4plhjjn8onm0o8q0omik63x", + "containerimage.config.digest": "sha256:f30f57d817c596f7a7d0ecfe734b7b41994eca9d36d43307206314ee37bdb286", + "containerimage.descriptor": { + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "digest": "sha256:f7d86b1a72a12b60434a12a604e9ddd3779d9fa605205c7968fe9495e764c94c", + "size": 1094, + "platform": { + "architecture": "amd64", + "os": "linux" + } + }, + "containerimage.digest": "sha256:f7d86b1a72a12b60434a12a604e9ddd3779d9fa605205c7968fe9495e764c94c", + "image.name": "ghcr.io/aenix-io/cozystack/nginx-cache:v0.1.0,ghcr.io/aenix-io/cozystack/nginx-cache:v0.1.0-v0.10.1" } \ No newline at end of file diff --git a/packages/apps/kafka/Chart.yaml b/packages/apps/kafka/Chart.yaml index 193e8d7e..716f871c 100644 --- a/packages/apps/kafka/Chart.yaml +++ b/packages/apps/kafka/Chart.yaml @@ -16,7 +16,7 @@ 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.2.1 +version: 0.2.2 # 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 diff --git a/packages/apps/kafka/templates/kafka.yaml b/packages/apps/kafka/templates/kafka.yaml index bb53c1b5..8cc9f019 100644 --- a/packages/apps/kafka/templates/kafka.yaml +++ b/packages/apps/kafka/templates/kafka.yaml @@ -26,11 +26,25 @@ spec: {{- end }} tls: false config: + {{- if eq (int .Values.kafka.replicas) 1 }} + offsets.topic.replication.factor: 1 + transaction.state.log.replication.factor: 1 + transaction.state.log.min.isr: 1 + default.replication.factor: 1 + min.insync.replicas: 1 + {{- else if eq (int .Values.kafka.replicas) 2 }} + offsets.topic.replication.factor: 2 + transaction.state.log.replication.factor: 2 + transaction.state.log.min.isr: 2 + default.replication.factor: 2 + min.insync.replicas: 2 + {{- else }} offsets.topic.replication.factor: 3 transaction.state.log.replication.factor: 3 transaction.state.log.min.isr: 2 default.replication.factor: 3 min.insync.replicas: 2 + {{- end }} storage: type: jbod volumes: diff --git a/packages/apps/kafka/templates/topics.yaml b/packages/apps/kafka/templates/topics.yaml index 63d4e6fb..712b5d67 100644 --- a/packages/apps/kafka/templates/topics.yaml +++ b/packages/apps/kafka/templates/topics.yaml @@ -9,10 +9,10 @@ metadata: spec: topicName: "{{ $topic.name }}" {{- with $topic.partitions }} - partitions: "{{ . }}" + partitions: {{ . }} {{- end }} {{- with $topic.replicas }} - replicas: "{{ . }}" + replicas: {{ . }} {{- end }} {{- with $topic.config }} config: diff --git a/packages/apps/kubernetes/Chart.yaml b/packages/apps/kubernetes/Chart.yaml index 30811454..af3ce9d1 100644 --- a/packages/apps/kubernetes/Chart.yaml +++ b/packages/apps/kubernetes/Chart.yaml @@ -16,7 +16,7 @@ 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.6.0 +version: 0.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. Versions are not expected to diff --git a/packages/apps/kubernetes/images/ubuntu-container-disk.json b/packages/apps/kubernetes/images/ubuntu-container-disk.json index e249d0e4..65729082 100644 --- a/packages/apps/kubernetes/images/ubuntu-container-disk.json +++ b/packages/apps/kubernetes/images/ubuntu-container-disk.json @@ -32,7 +32,17 @@ } } }, - "buildx.build.ref": "amd64/amd64/kk2drcq44gorgb3xwa8908pfc", - "containerimage.config.digest": "sha256:363589eb47379eb7548f047aae24045278f14db0b2026022b6bec33a04370f15", - "containerimage.digest": "sha256:f242fd77903f5f5a94ed157e98b0c4532e5ba91734d9653eaf26cfe4b23b017b" + "buildx.build.ref": "cozystack/cozystack0/xkanpm0dojuj7v0lo951qocfb", + "containerimage.config.digest": "sha256:c144c5f12a47af7880ee5f056b14177c07b585b8ab1e68b7e7900e1c923083cf", + "containerimage.descriptor": { + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "digest": "sha256:81caf89efe252ae2ca1990d08a3a314552d70ff36bcd4022b173c7150fbec805", + "size": 506, + "platform": { + "architecture": "amd64", + "os": "linux" + } + }, + "containerimage.digest": "sha256:81caf89efe252ae2ca1990d08a3a314552d70ff36bcd4022b173c7150fbec805", + "image.name": "ghcr.io/aenix-io/cozystack/ubuntu-container-disk:v1.30.1,ghcr.io/aenix-io/cozystack/ubuntu-container-disk:v1.30.1-v0.10.1" } \ No newline at end of file diff --git a/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml b/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml index 7c2a7e50..9ecf1bf4 100644 --- a/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml +++ b/packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml @@ -14,6 +14,7 @@ spec: metadata: labels: app: {{ .Release.Name }}-cluster-autoscaler + policy.cozystack.io/allow-to-apiserver: "true" spec: tolerations: - key: CriticalAddonsOnly diff --git a/packages/apps/kubernetes/templates/cluster.yaml b/packages/apps/kubernetes/templates/cluster.yaml index 0ce5d542..ed610fa9 100644 --- a/packages/apps/kubernetes/templates/cluster.yaml +++ b/packages/apps/kubernetes/templates/cluster.yaml @@ -17,6 +17,11 @@ spec: spec: runStrategy: Always template: + metadata: + labels: + {{- range .group.roles }} + node-role.kubernetes.io/{{ . }}: "" + {{- end }} spec: domain: cpu: @@ -29,14 +34,10 @@ spec: disk: bus: virtio pciAddress: 0000:07:00.0 - - name: containerd + - name: ephemeral disk: bus: virtio pciAddress: 0000:08:00.0 - - name: kubelet - disk: - bus: virtio - pciAddress: 0000:09:00.0 networkInterfaceMultiqueue: true memory: guest: {{ .group.resources.memory }} @@ -45,15 +46,10 @@ spec: - name: system containerDisk: image: "{{ $.Files.Get "images/ubuntu-container-disk.tag" | trim }}@{{ index ($.Files.Get "images/ubuntu-container-disk.json" | fromJson) "containerimage.digest" }}" - - name: containerd + - name: ephemeral emptyDisk: - capacity: 20Gi - - name: kubelet - emptyDisk: - capacity: 20Gi + capacity: {{ .group.ephemeralStorage | default "20Gi" }} {{- end }} - - --- apiVersion: cluster.x-k8s.io/v1beta1 kind: Cluster @@ -108,6 +104,9 @@ spec: hostname: {{ .Values.host | default (printf "%s.%s" .Release.Name $host) }}:443 className: "{{ $ingress }}" deployment: + podAdditionalMetadata: + labels: + policy.cozystack.io/allow-to-etcd: "true" replicas: 2 version: 1.30.1 --- @@ -132,17 +131,19 @@ spec: filesystems: - device: /dev/vdb filesystem: xfs - label: containerd - partition: "none" - - device: /dev/vdc - filesystem: xfs - label: kubelet + label: ephemeral partition: "none" mounts: - - ["LABEL=containerd", "/var/lib/containerd"] - - ["LABEL=kubelet", "/var/lib/kubelet"] + - ["LABEL=ephemeral", "/ephemeral"] + - ["/ephemeral/kubelet", "/var/lib/kubelet", "none", "bind,nofail"] + - ["/ephemeral/containerd", "/var/lib/containerd", "none", "bind,nofail"] preKubeadmCommands: - sed -i 's|root:x:|root::|' /etc/passwd + - systemctl stop containerd.service + - mkdir -p /ephemeral/kubelet /ephemeral/containerd + - mount -o bind /ephemeral/kubelet /var/lib/kubelet + - mount -o bind /ephemeral/containerd /var/lib/containerd + - systemctl start containerd.service joinConfiguration: nodeRegistration: kubeletExtraArgs: {} diff --git a/packages/apps/kubernetes/templates/csi/deploy.yaml b/packages/apps/kubernetes/templates/csi/deploy.yaml index f4fbb64d..cb21208b 100644 --- a/packages/apps/kubernetes/templates/csi/deploy.yaml +++ b/packages/apps/kubernetes/templates/csi/deploy.yaml @@ -13,6 +13,7 @@ spec: metadata: labels: app: {{ .Release.Name }}-kcsi-driver + policy.cozystack.io/allow-to-apiserver: "true" spec: serviceAccountName: {{ .Release.Name }}-kcsi priorityClassName: system-cluster-critical diff --git a/packages/apps/kubernetes/templates/ingress.yaml b/packages/apps/kubernetes/templates/ingress.yaml index e677afab..622b46ed 100644 --- a/packages/apps/kubernetes/templates/ingress.yaml +++ b/packages/apps/kubernetes/templates/ingress.yaml @@ -9,6 +9,14 @@ metadata: annotations: nginx.ingress.kubernetes.io/ssl-redirect: "false" nginx.ingress.kubernetes.io/ssl-passthrough: "true" + nginx.ingress.kubernetes.io/backend-protocol: "AUTO_HTTP" + nginx.ingress.kubernetes.io/configuration-snippet: | + set $proxy_upstream_name "{{ .Release.Namespace }}-{{ .Release.Name }}-ingress-nginx-80"; + if ($scheme = https) { + set $proxy_upstream_name "{{ .Release.Namespace }}-{{ .Release.Name }}-ingress-nginx-443"; + set $service_port 443; + } + set $proxy_host $proxy_upstream_name; spec: ingressClassName: "{{ $ingress }}" rules: @@ -16,6 +24,13 @@ spec: - host: {{ . | quote }} http: paths: + - path: / + pathType: ImplementationSpecific + backend: + service: + name: {{ $.Release.Name }}-ingress-nginx + port: + number: 80 - path: / pathType: ImplementationSpecific backend: diff --git a/packages/apps/kubernetes/templates/kccm/manager.yaml b/packages/apps/kubernetes/templates/kccm/manager.yaml index 586fdbf4..69dd58aa 100644 --- a/packages/apps/kubernetes/templates/kccm/manager.yaml +++ b/packages/apps/kubernetes/templates/kccm/manager.yaml @@ -13,6 +13,7 @@ spec: metadata: labels: k8s-app: {{ .Release.Name }}-kccm + policy.cozystack.io/allow-to-apiserver: "true" spec: tolerations: - key: CriticalAddonsOnly diff --git a/packages/apps/kubernetes/values.yaml b/packages/apps/kubernetes/values.yaml index 548e344d..38859eb2 100644 --- a/packages/apps/kubernetes/values.yaml +++ b/packages/apps/kubernetes/values.yaml @@ -16,6 +16,7 @@ nodeGroups: resources: cpu: 2 memory: 1024Mi + ephemeralStorage: 20Gi roles: - ingress-nginx diff --git a/packages/apps/nats/.helmignore b/packages/apps/nats/.helmignore new file mode 100644 index 00000000..1ea0ae84 --- /dev/null +++ b/packages/apps/nats/.helmignore @@ -0,0 +1,3 @@ +.helmignore +/logos +/Makefile diff --git a/packages/apps/nats/Chart.yaml b/packages/apps/nats/Chart.yaml new file mode 100644 index 00000000..c5477111 --- /dev/null +++ b/packages/apps/nats/Chart.yaml @@ -0,0 +1,25 @@ +apiVersion: v2 +name: nats +description: Managed NATS service +icon: /logos/nats.svg + +# 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.4.1" diff --git a/packages/apps/nats/Makefile b/packages/apps/nats/Makefile new file mode 100644 index 00000000..207e2133 --- /dev/null +++ b/packages/apps/nats/Makefile @@ -0,0 +1,2 @@ +generate: + readme-generator -v values.yaml -s values.schema.json -r README.md diff --git a/packages/apps/nats/README.md b/packages/apps/nats/README.md new file mode 100644 index 00000000..a8b4ba2d --- /dev/null +++ b/packages/apps/nats/README.md @@ -0,0 +1,11 @@ +# Managed NATS Service + +## Parameters + +### Common parameters + +| Name | Description | Value | +| ---------- | ----------------------------------------------- | ------- | +| `external` | Enable external access from outside the cluster | `false` | +| `replicas` | Persistent Volume size for NATS | `3` | + diff --git a/packages/apps/nats/logos/nats.svg b/packages/apps/nats/logos/nats.svg new file mode 100644 index 00000000..c0c0965f --- /dev/null +++ b/packages/apps/nats/logos/nats.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + diff --git a/packages/apps/nats/templates/nats.yaml b/packages/apps/nats/templates/nats.yaml new file mode 100644 index 00000000..cc78209f --- /dev/null +++ b/packages/apps/nats/templates/nats.yaml @@ -0,0 +1,43 @@ +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: {{ .Release.Name }}-system +spec: + chart: + spec: + chart: cozy-nats + reconcileStrategy: Revision + sourceRef: + kind: HelmRepository + name: cozystack-system + namespace: cozy-system + version: '*' + interval: 1m0s + timeout: 5m0s + values: + nats: + fullnameOverride: {{ .Release.Name }} + config: + cluster: + enabled: true + replicas: {{ .Values.replicas }} + monitor: + enabled: true + jetstream: + enabled: true + fileStore: + enabled: true + pvc: + enabled: true + size: 10Gi + storageClassName: local + promExporter: + enabled: true + podMonitor: + enabled: true + {{- if .Values.external }} + service: + merge: + spec: + type: LoadBalancer + {{- end }} diff --git a/packages/apps/nats/values.schema.json b/packages/apps/nats/values.schema.json new file mode 100644 index 00000000..676ac1f0 --- /dev/null +++ b/packages/apps/nats/values.schema.json @@ -0,0 +1,16 @@ +{ + "title": "Chart Values", + "type": "object", + "properties": { + "external": { + "type": "boolean", + "description": "Enable external access from outside the cluster", + "default": false + }, + "replicas": { + "type": "number", + "description": "Persistent Volume size for NATS", + "default": 3 + } + } +} \ No newline at end of file diff --git a/packages/apps/nats/values.yaml b/packages/apps/nats/values.yaml new file mode 100644 index 00000000..91adc14b --- /dev/null +++ b/packages/apps/nats/values.yaml @@ -0,0 +1,8 @@ + +## @section Common parameters + +## @param external Enable external access from outside the cluster +## @param replicas Persistent Volume size for NATS +## +external: false +replicas: 2 diff --git a/packages/apps/postgres/Chart.yaml b/packages/apps/postgres/Chart.yaml index 0bc35560..f7bd834b 100644 --- a/packages/apps/postgres/Chart.yaml +++ b/packages/apps/postgres/Chart.yaml @@ -16,7 +16,7 @@ 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.3.0 +version: 0.4.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 diff --git a/packages/apps/postgres/templates/init-script.yaml b/packages/apps/postgres/templates/init-script.yaml index f5f6431c..68ee856f 100644 --- a/packages/apps/postgres/templates/init-script.yaml +++ b/packages/apps/postgres/templates/init-script.yaml @@ -53,47 +53,80 @@ stringData: echo "== grant privileges on databases to roles" {{- range $database, $d := .Values.databases }} - - # admin psql -v ON_ERROR_STOP=1 --echo-all -d "{{ $database }}" <<\EOT - DO $$DECLARE r record; + ALTER DATABASE {{ $database }} OWNER TO {{ $database }}_admin; + GRANT CONNECT ON DATABASE {{ $database }} TO {{ $database }}_readonly; + + DO $$ DECLARE - v_schema varchar := 'public'; - v_new_owner varchar := '{{ $database }}_admin'; + schema_record record; BEGIN - FOR r IN - select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.tables where table_schema = v_schema - union all - select 'ALTER TABLE "' || sequence_schema || '"."' || sequence_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.sequences where sequence_schema = v_schema - union all - select 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' as a from information_schema.views where table_schema = v_schema - union all - select 'ALTER FUNCTION "'||nsp.nspname||'"."'||p.proname||'"('||pg_get_function_identity_arguments(p.oid)||') OWNER TO ' || v_new_owner || ';' as a from pg_proc p join pg_namespace nsp ON p.pronamespace = nsp.oid where nsp.nspname = v_schema - LOOP - EXECUTE r.a; + -- Loop over all schemas + FOR schema_record IN SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('pg_catalog', 'information_schema') LOOP + -- Changing Schema Ownership + EXECUTE format('ALTER SCHEMA %I OWNER TO %I', schema_record.schema_name, '{{ $database }}_admin'); + + -- Add rights for the admin role + EXECUTE format('GRANT ALL ON SCHEMA %I TO %I', schema_record.schema_name, '{{ $database }}_admin'); + EXECUTE format('GRANT ALL ON ALL TABLES IN SCHEMA %I TO %I', schema_record.schema_name, '{{ $database }}_admin'); + EXECUTE format('GRANT ALL ON ALL SEQUENCES IN SCHEMA %I TO %I', schema_record.schema_name, '{{ $database }}_admin'); + EXECUTE format('GRANT ALL ON ALL FUNCTIONS IN SCHEMA %I TO %I', schema_record.schema_name, '{{ $database }}_admin'); + EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON TABLES TO %I', schema_record.schema_name, '{{ $database }}_admin'); + EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON SEQUENCES TO %I', schema_record.schema_name, '{{ $database }}_admin'); + EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON FUNCTIONS TO %I', schema_record.schema_name, '{{ $database }}_admin'); + + -- Add rights for the readonly role + EXECUTE format('GRANT USAGE ON SCHEMA %I TO %I', schema_record.schema_name, '{{ $database }}_readonly'); + EXECUTE format('GRANT SELECT ON ALL TABLES IN SCHEMA %I TO %I', schema_record.schema_name, '{{ $database }}_readonly'); + EXECUTE format('GRANT USAGE ON ALL SEQUENCES IN SCHEMA %I TO %I', schema_record.schema_name, '{{ $database }}_readonly'); + EXECUTE format('GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA %I TO %I', schema_record.schema_name, '{{ $database }}_readonly'); + EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT SELECT ON TABLES TO %I', schema_record.schema_name, '{{ $database }}_readonly'); + EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT USAGE ON SEQUENCES TO %I', schema_record.schema_name, '{{ $database }}_readonly'); + EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT EXECUTE ON FUNCTIONS TO %I', schema_record.schema_name, '{{ $database }}_readonly'); END LOOP; END$$; - ALTER DATABASE {{ $database }} OWNER TO {{ $database }}_admin; - ALTER SCHEMA public OWNER TO {{ $database }}_admin; - GRANT ALL ON SCHEMA public TO {{ $database }}_admin; - GRANT ALL ON ALL TABLES IN SCHEMA public TO {{ $database }}_admin; - GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO {{ $database }}_admin; - GRANT ALL ON ALL FUNCTIONS IN SCHEMA public TO {{ $database }}_admin; - ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO {{ $database }}_admin; - ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO {{ $database }}_admin; - ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON FUNCTIONS TO {{ $database }}_admin; EOT - # readonly + echo "== setup event trigger for schema creation" psql -v ON_ERROR_STOP=1 --echo-all -d "{{ $database }}" <<\EOT - GRANT CONNECT ON DATABASE {{ $database }} TO {{ $database }}_readonly; - GRANT USAGE ON SCHEMA public TO {{ $database }}_readonly; - GRANT SELECT ON ALL TABLES IN SCHEMA public TO {{ $database }}_readonly; - GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO {{ $database }}_readonly; - GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO {{ $database }}_readonly; - ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO {{ $database }}_readonly; - ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE ON SEQUENCES TO {{ $database }}_readonly; - ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT EXECUTE ON FUNCTIONS TO {{ $database }}_readonly; + CREATE OR REPLACE FUNCTION auto_grant_schema_privileges() + RETURNS event_trigger LANGUAGE plpgsql AS $$ + DECLARE + obj record; + BEGIN + FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() WHERE command_tag = 'CREATE SCHEMA' LOOP + EXECUTE format('ALTER SCHEMA %I OWNER TO %I', obj.object_identity, '{{ $database }}_admin'); + EXECUTE format('GRANT ALL ON SCHEMA %I TO %I', obj.object_identity, '{{ $database }}_admin'); + EXECUTE format('GRANT USAGE ON SCHEMA %I TO %I', obj.object_identity, '{{ $database }}_readonly'); + EXECUTE format('GRANT SELECT ON ALL TABLES IN SCHEMA %I TO %I', obj.object_identity, '{{ $database }}_readonly'); + EXECUTE format('GRANT USAGE ON ALL SEQUENCES IN SCHEMA %I TO %I', obj.object_identity, '{{ $database }}_readonly'); + EXECUTE format('GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA %I TO %I', obj.object_identity, '{{ $database }}_readonly'); + + -- Set owner for schema + EXECUTE format('ALTER SCHEMA %I OWNER TO %I', obj.object_identity, '{{ $database }}_admin'); + + -- Set privileges for admin role + EXECUTE format('GRANT ALL ON SCHEMA %I TO %I', obj.object_identity, '{{ $database }}_admin'); + EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON TABLES TO %I', obj.object_identity, '{{ $database }}_admin'); + EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON SEQUENCES TO %I', obj.object_identity, '{{ $database }}_admin'); + EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON FUNCTIONS TO %I', obj.object_identity, '{{ $database }}_admin'); + + -- Set privileges for readonly role + EXECUTE format('GRANT USAGE ON SCHEMA %I TO %I', obj.object_identity, '{{ $database }}_readonly'); + EXECUTE format('GRANT SELECT ON ALL TABLES IN SCHEMA %I TO %I', obj.object_identity, '{{ $database }}_readonly'); + EXECUTE format('GRANT USAGE ON ALL SEQUENCES IN SCHEMA %I TO %I', obj.object_identity, '{{ $database }}_readonly'); + EXECUTE format('GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA %I TO %I', obj.object_identity, '{{ $database }}_readonly'); + EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT SELECT ON TABLES TO %I', obj.object_identity, '{{ $database }}_readonly'); + EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT USAGE ON SEQUENCES TO %I', obj.object_identity, '{{ $database }}_readonly'); + EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT EXECUTE ON FUNCTIONS TO %I', obj.object_identity, '{{ $database }}_readonly'); + END LOOP; + END; + $$; + + DROP EVENT TRIGGER IF EXISTS trigger_auto_grant; + CREATE EVENT TRIGGER trigger_auto_grant ON ddl_command_end + WHEN TAG IN ('CREATE SCHEMA') + EXECUTE PROCEDURE auto_grant_schema_privileges(); EOT {{- end }} diff --git a/packages/apps/tenant/Chart.yaml b/packages/apps/tenant/Chart.yaml index 5f531c11..700952cf 100644 --- a/packages/apps/tenant/Chart.yaml +++ b/packages/apps/tenant/Chart.yaml @@ -4,4 +4,4 @@ description: Separated tenant namespace icon: /logos/tenant.svg type: application -version: 1.2.0 +version: 1.3.0 diff --git a/packages/apps/tenant/README.md b/packages/apps/tenant/README.md index 9b17e8fc..6d0373e2 100644 --- a/packages/apps/tenant/README.md +++ b/packages/apps/tenant/README.md @@ -56,3 +56,4 @@ tenant-u1 | `etcd` | Deploy own Etcd cluster | `false` | | `monitoring` | Deploy own Monitoring Stack | `false` | | `ingress` | Deploy own Ingress Controller | `false` | +| `isolated` | Enforce tenant namespace with network policies | `false` | diff --git a/packages/apps/tenant/templates/networkpolicy.yaml b/packages/apps/tenant/templates/networkpolicy.yaml new file mode 100644 index 00000000..8b26e75a --- /dev/null +++ b/packages/apps/tenant/templates/networkpolicy.yaml @@ -0,0 +1,136 @@ +{{- if .Values.isolated }} +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: allow-internal-communication + namespace: {{ include "tenant.name" . }} +spec: + endpointSelector: {} + ingress: + - fromEndpoints: + - {} + egress: + - toEndpoints: + - {} +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: allow-external-communication + namespace: {{ include "tenant.name" . }} +spec: + endpointSelector: {} + ingress: + - fromEntities: + - world + egress: + - toEntities: + - world +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: allow-from-system + namespace: {{ include "tenant.name" . }} +spec: + endpointSelector: {} + ingress: + - fromEntities: + - cluster +--- +{{- if ne (include "tenant.name" .) "tenant-root" }} +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: allow-from-upper-tenants + namespace: {{ include "tenant.name" . }} +spec: + endpointSelector: {} + ingress: + - fromEndpoints: + - matchLabels: + "kubernetes.io/metadata.name": "tenant-root" + {{- if hasPrefix "tenant-" .Release.Namespace }} + {{- $parts := splitList "-" .Release.Namespace }} + {{- range $i, $v := $parts }} + {{- if ne $i 0 }} + - matchLabels: + "kubernetes.io/metadata.name": {{ join "-" (slice $parts 0 (add $i 1)) }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +--- +{{- if not .Values.etcd }} +{{- $existingNS := lookup "v1" "Namespace" "" .Release.Namespace }} +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: allow-to-etcd + namespace: {{ include "tenant.name" . }} +spec: + endpointSelector: + matchLabels: + policy.cozystack.io/allow-to-etcd: "true" + egress: + - toEndpoints: + - matchLabels: + io.kubernetes.pod.namespace: "{{ index $existingNS.metadata.annotations "namespace.cozystack.io/etcd" }}" + cozystack.io/service: etcd +{{- end }} +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: allow-to-apiserver + namespace: {{ include "tenant.name" . }} +spec: + endpointSelector: + matchLabels: + policy.cozystack.io/allow-to-apiserver: "true" + egress: + - toEntities: + - kube-apiserver + - toPorts: + - ports: + - port: "6443" + protocol: TCP +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: allow-to-dns + namespace: {{ include "tenant.name" . }} +spec: + endpointSelector: {} + egress: + - toEndpoints: + - matchLabels: + io.kubernetes.pod.namespace: kube-system + k8s-app: kube-dns +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: allow-to-dashboard + namespace: {{ include "tenant.name" . }} +spec: + endpointSelector: {} + egress: + - toEndpoints: + - matchLabels: + io.kubernetes.pod.namespace: cozy-dashboard +--- +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: allow-to-ingress + namespace: {{ include "tenant.name" . }} +spec: + endpointSelector: {} + egress: + - toEndpoints: + - matchLabels: + cozystack.io/service: ingress +{{- end }} diff --git a/packages/apps/tenant/values.schema.json b/packages/apps/tenant/values.schema.json index a02ffa71..7f87cda1 100644 --- a/packages/apps/tenant/values.schema.json +++ b/packages/apps/tenant/values.schema.json @@ -21,6 +21,11 @@ "type": "boolean", "description": "Deploy own Ingress Controller", "default": false + }, + "isolated": { + "type": "boolean", + "description": "Enforce tenant namespace with network policies", + "default": false } } } \ No newline at end of file diff --git a/packages/apps/tenant/values.yaml b/packages/apps/tenant/values.yaml index 3c980c00..d52e99ca 100644 --- a/packages/apps/tenant/values.yaml +++ b/packages/apps/tenant/values.yaml @@ -4,7 +4,9 @@ ## @param etcd Deploy own Etcd cluster ## @param monitoring Deploy own Monitoring Stack ## @param ingress Deploy own Ingress Controller +## @param isolated Enforce tenant namespace with network policies host: "" etcd: false monitoring: false ingress: false +isolated: false diff --git a/packages/apps/versions_map b/packages/apps/versions_map index d2968be0..a76e6701 100644 --- a/packages/apps/versions_map +++ b/packages/apps/versions_map @@ -6,20 +6,25 @@ http-cache 0.1.0 a956713 http-cache 0.2.0 HEAD kafka 0.1.0 760f86d2 kafka 0.2.0 a2cc83d -kafka 0.2.1 HEAD +kafka 0.2.1 3ac17018 +kafka 0.2.2 HEAD kubernetes 0.1.0 f642698 kubernetes 0.2.0 7cd7de73 kubernetes 0.3.0 7caccec1 kubernetes 0.4.0 6cae6ce8 kubernetes 0.5.0 6bd2d455 -kubernetes 0.6.0 HEAD +kubernetes 0.6.0 4cbc8a2c +kubernetes 0.7.0 ceefae03 +kubernetes 0.8.0 HEAD mysql 0.1.0 f642698 mysql 0.2.0 8b975ff0 mysql 0.3.0 HEAD +nats 0.1.0 HEAD postgres 0.1.0 f642698 postgres 0.2.0 7cd7de73 postgres 0.2.1 4a97e297 -postgres 0.3.0 HEAD +postgres 0.3.0 995dea6f +postgres 0.4.0 HEAD rabbitmq 0.1.0 f642698 rabbitmq 0.2.0 HEAD redis 0.1.1 f642698 @@ -31,7 +36,8 @@ tenant 0.1.4 d200480 tenant 0.1.5 e3ab858 tenant 1.0.0 7cd7de7 tenant 1.1.0 4da8ac3b -tenant 1.2.0 HEAD +tenant 1.2.0 15478a88 +tenant 1.3.0 HEAD virtual-machine 0.1.4 f2015d6 virtual-machine 0.1.5 7cd7de7 virtual-machine 0.2.0 HEAD diff --git a/packages/core/installer/images/cozystack.json b/packages/core/installer/images/cozystack.json index 571f9aa7..5bd2cc81 100644 --- a/packages/core/installer/images/cozystack.json +++ b/packages/core/installer/images/cozystack.json @@ -1,10 +1,10 @@ { - "buildx.build.ref": "priceless_leavitt/priceless_leavitt0/ta5cc9q3mqtwjyuvg8fviqhe6", + "buildx.build.ref": "cozystack/cozystack0/zk58yqp4vkrfgx3gdjumn9k70", "containerimage.descriptor": { "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", - "digest": "sha256:bcaef325861d91b955f536bdd57ae3a6099d8657f081054a6dee3c027cfce97f", + "digest": "sha256:b92988122fa68adc85751384170a46895b5761cc5bf27e80b0b53b12b89b6d6c", "size": 685 }, - "containerimage.digest": "sha256:bcaef325861d91b955f536bdd57ae3a6099d8657f081054a6dee3c027cfce97f", - "image.name": "ghcr.io/aenix-io/cozystack/cozystack:v0.9.0" + "containerimage.digest": "sha256:b92988122fa68adc85751384170a46895b5761cc5bf27e80b0b53b12b89b6d6c", + "image.name": "ghcr.io/aenix-io/cozystack/cozystack:latest" } \ No newline at end of file diff --git a/packages/core/installer/images/cozystack.tag b/packages/core/installer/images/cozystack.tag index aff03e70..602d7b26 100644 --- a/packages/core/installer/images/cozystack.tag +++ b/packages/core/installer/images/cozystack.tag @@ -1 +1 @@ -ghcr.io/aenix-io/cozystack/cozystack:v0.9.0 +ghcr.io/aenix-io/cozystack/cozystack:latest diff --git a/packages/core/installer/images/matchbox.json b/packages/core/installer/images/matchbox.json index 930a0ce7..c93aacbb 100644 --- a/packages/core/installer/images/matchbox.json +++ b/packages/core/installer/images/matchbox.json @@ -29,17 +29,17 @@ } } }, - "buildx.build.ref": "priceless_leavitt/priceless_leavitt0/k5n5is33n6zu6an3nmlnylejx", - "containerimage.config.digest": "sha256:4676a205eae74f1b16a9065921c612ee85e123ab6566a238edb4bbaf79b2e148", + "buildx.build.ref": "cozystack/cozystack0/qu2ygr61roizh7ga2l4kkmdx6", + "containerimage.config.digest": "sha256:94aa5abc006ac672ccdd91b8d9361fd14de6e0b286299f4e44dd09002becc3b7", "containerimage.descriptor": { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", - "digest": "sha256:7aa044756c40c2a222668f735ad9490b52341b57dca27e57b98f5de235d87ad7", + "digest": "sha256:b1e6084402619dde9dcdc8251cd581cbfc3940c885e938547b7b7306376a411e", "size": 1488, "platform": { "architecture": "amd64", "os": "linux" } }, - "containerimage.digest": "sha256:7aa044756c40c2a222668f735ad9490b52341b57dca27e57b98f5de235d87ad7", - "image.name": "ghcr.io/aenix-io/cozystack/matchbox:v0.9.0,ghcr.io/aenix-io/cozystack/matchbox:v1.7.1-v0.9.0" + "containerimage.digest": "sha256:b1e6084402619dde9dcdc8251cd581cbfc3940c885e938547b7b7306376a411e", + "image.name": "ghcr.io/aenix-io/cozystack/matchbox:v0.10.1,ghcr.io/aenix-io/cozystack/matchbox:v1.7.1-v0.10.1" } \ No newline at end of file diff --git a/packages/core/platform/bundles/distro-full.yaml b/packages/core/platform/bundles/distro-full.yaml index c3e65e3f..59a32fa9 100644 --- a/packages/core/platform/bundles/distro-full.yaml +++ b/packages/core/platform/bundles/distro-full.yaml @@ -93,13 +93,13 @@ releases: releaseName: kafka-operator chart: cozy-kafka-operator namespace: cozy-kafka-operator - dependsOn: [cilium,kubeovn] + dependsOn: [cilium] - name: clickhouse-operator releaseName: clickhouse-operator chart: cozy-clickhouse-operator namespace: cozy-clickhouse-operator - dependsOn: [cilium,kubeovn] + dependsOn: [cilium] - name: rabbitmq-operator releaseName: rabbitmq-operator @@ -119,6 +119,12 @@ releases: namespace: cozy-linstor dependsOn: [cilium,cert-manager] +- name: snapshot-controller + releaseName: snapshot-controller + chart: cozy-snapshot-controller + namespace: cozy-snapshot-controller + dependsOn: [cilium,cert-manager-issuers] + - name: linstor releaseName: linstor chart: cozy-linstor diff --git a/packages/core/platform/bundles/paas-full.yaml b/packages/core/platform/bundles/paas-full.yaml index 4ed95257..65c259a6 100644 --- a/packages/core/platform/bundles/paas-full.yaml +++ b/packages/core/platform/bundles/paas-full.yaml @@ -155,6 +155,12 @@ releases: privileged: true dependsOn: [piraeus-operator,cilium,kubeovn,cert-manager] +- name: snapshot-controller + releaseName: snapshot-controller + chart: cozy-snapshot-controller + namespace: cozy-snapshot-controller + dependsOn: [cilium,kubeovn,cert-manager-issuers] + - name: telepresence releaseName: traffic-manager chart: cozy-telepresence diff --git a/packages/core/platform/templates/namespaces.yaml b/packages/core/platform/templates/namespaces.yaml index 0d35d7ec..669d852c 100644 --- a/packages/core/platform/templates/namespaces.yaml +++ b/packages/core/platform/templates/namespaces.yaml @@ -15,6 +15,7 @@ {{- end }} {{/* Add extra namespaces */}} +{{- $_ := set $namespaces "cozy-system" true }} {{- $_ := set $namespaces "cozy-public" false }} {{- range $namespace, $privileged := $namespaces }} @@ -24,9 +25,10 @@ kind: Namespace metadata: annotations: "helm.sh/resource-policy": keep - {{- if $privileged }} labels: + cozystack.io/system: "true" + {{- if $privileged }} pod-security.kubernetes.io/enforce: privileged - {{- end }} + {{- end }} name: {{ $namespace }} {{- end }} diff --git a/packages/extra/etcd/Chart.yaml b/packages/extra/etcd/Chart.yaml index dc79f3f5..c56e2ade 100644 --- a/packages/extra/etcd/Chart.yaml +++ b/packages/extra/etcd/Chart.yaml @@ -3,4 +3,4 @@ name: etcd description: Storage for Kubernetes clusters icon: /logos/etcd.svg type: application -version: 2.1.0 +version: 2.2.0 diff --git a/packages/extra/etcd/templates/etcd-cluster.yaml b/packages/extra/etcd/templates/etcd-cluster.yaml index 6edf5616..b717031e 100644 --- a/packages/extra/etcd/templates/etcd-cluster.yaml +++ b/packages/extra/etcd/templates/etcd-cluster.yaml @@ -33,6 +33,9 @@ spec: clientTrustedCASecret: etcd-ca-tls clientSecret: etcd-client-tls podTemplate: + metadata: + labels: + cozystack.io/service: etcd spec: topologySpreadConstraints: - maxSkew: 1 @@ -41,6 +44,7 @@ spec: labelSelector: matchLabels: app.kubernetes.io/instance: etcd + podDisruptionBudgetTemplate: {} --- apiVersion: cert-manager.io/v1 kind: Issuer diff --git a/packages/extra/ingress/Chart.yaml b/packages/extra/ingress/Chart.yaml index f0ff843f..664a41c5 100644 --- a/packages/extra/ingress/Chart.yaml +++ b/packages/extra/ingress/Chart.yaml @@ -3,4 +3,4 @@ name: ingress description: NGINX Ingress Controller icon: /logos/ingress-nginx.svg type: application -version: 1.3.0 +version: 1.2.0 diff --git a/packages/extra/ingress/Makefile b/packages/extra/ingress/Makefile index 207e2133..ae3389f5 100644 --- a/packages/extra/ingress/Makefile +++ b/packages/extra/ingress/Makefile @@ -1,2 +1,7 @@ +update: get-cloudflare-ips + +get-cloudflare-ips: + printf '{{- define "ingress.cloudflare-ips" -}}\n%s,%s\n{{- end }}\n' "$$(curl -s https://www.cloudflare.com/ips-v4/ | tr '\n' ,)" "$$(curl -s https://www.cloudflare.com/ips-v6/ | tr '\n' ,)" > templates/_cloudflare-ips.tpl + generate: readme-generator -v values.yaml -s values.schema.json -r README.md diff --git a/packages/extra/ingress/README.md b/packages/extra/ingress/README.md index 6167256a..0d00844c 100644 --- a/packages/extra/ingress/README.md +++ b/packages/extra/ingress/README.md @@ -4,7 +4,11 @@ ### Common parameters -| Name | Description | Value | -| ------------- | -------------------------------- | ----- | -| `replicas` | Number of ingress-nginx replicas | `2` | -| `externalIPs` | List of externalIPs for service. | `[]` | +| Name | Description | Value | +| ---------------- | ----------------------------------------------------------------- | ------- | +| `replicas` | Number of ingress-nginx replicas | `2` | +| `externalIPs` | List of externalIPs for service. | `[]` | +| `whitelist` | List of client networks | `[]` | +| `clouflareProxy` | Restoring original visitor IPs when Cloudflare proxied is enabled | `false` | +| `dashboard` | Should ingress serve Cozystack service dashboard | `false` | + diff --git a/packages/extra/ingress/templates/_cloudflare-ips.tpl b/packages/extra/ingress/templates/_cloudflare-ips.tpl new file mode 100644 index 00000000..91439284 --- /dev/null +++ b/packages/extra/ingress/templates/_cloudflare-ips.tpl @@ -0,0 +1,3 @@ +{{- define "ingress.cloudflare-ips" -}} +173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22,2400:cb00::/32,2606:4700::/32,2803:f800::/32,2405:b500::/32,2405:8100::/32,2a06:98c0::/29,2c0f:f248::/32 +{{- end }} diff --git a/packages/extra/ingress/templates/dashboard.yaml b/packages/extra/ingress/templates/dashboard.yaml new file mode 100644 index 00000000..940fdefe --- /dev/null +++ b/packages/extra/ingress/templates/dashboard.yaml @@ -0,0 +1,29 @@ +{{- $myNS := lookup "v1" "Namespace" "" .Release.Namespace }} +{{- $host := index $myNS.metadata.annotations "namespace.cozystack.io/host" }} +{{- if .Values.dashboard }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + acme.cert-manager.io/http01-ingress-class: tenant-root + name: dashboard-{{ .Release.Namespace }} + namespace: cozy-dashboard +spec: + ingressClassName: {{ .Release.Namespace }} + rules: + - host: dashboard.{{ $host }} + http: + paths: + - backend: + service: + name: dashboard + port: + number: 80 + path: / + pathType: Prefix + tls: + - hosts: + - dashboard.{{ $host }} + secretName: dashboard-{{ .Release.Namespace }}-tls +{{- end }} diff --git a/packages/extra/ingress/templates/nginx-ingress.yaml b/packages/extra/ingress/templates/nginx-ingress.yaml index 646a156e..d0b67be4 100644 --- a/packages/extra/ingress/templates/nginx-ingress.yaml +++ b/packages/extra/ingress/templates/nginx-ingress.yaml @@ -23,6 +23,9 @@ spec: ingressClassResource: name: {{ .Release.Namespace }} controllerValue: k8s.io/ingress-nginx-{{ .Release.Namespace }} + podLabels: + cozystack.io/service: ingress + policy.cozystack.io/allow-to-apiserver: "true" {{- if not (eq .Release.Namespace "tenant-root") }} admissionWebhooks: enabled: false @@ -37,3 +40,14 @@ spec: type: LoadBalancer externalTrafficPolicy: Local {{- end }} + {{- if or .Values.whitelist .Values.clouflareProxy }} + config: + {{- with .Values.whitelist }} + whitelist-source-range: "{{ join "," . }}" + {{- end }} + {{- if .Values.clouflareProxy }} + set_real_ip_from: "{{ include "ingress.cloudflare-ips" . }}" + use-forwarded-headers: "true" + server-snippet: "real_ip_header CF-Connecting-IP;" + {{- end }} + {{- end }} diff --git a/packages/extra/ingress/values.schema.json b/packages/extra/ingress/values.schema.json index 48b05272..e669d70e 100644 --- a/packages/extra/ingress/values.schema.json +++ b/packages/extra/ingress/values.schema.json @@ -14,6 +14,22 @@ "items": { "type": "string" } + }, + "whitelist": { + "type": "array", + "description": "List of client networks", + "default": [], + "items": {} + }, + "clouflareProxy": { + "type": "boolean", + "description": "Restoring original visitor IPs when Cloudflare proxied is enabled", + "default": false + }, + "dashboard": { + "type": "boolean", + "description": "Should ingress serve Cozystack service dashboard", + "default": false } } } \ No newline at end of file diff --git a/packages/extra/ingress/values.yaml b/packages/extra/ingress/values.yaml index 85b78e6f..b05d6bb5 100644 --- a/packages/extra/ingress/values.yaml +++ b/packages/extra/ingress/values.yaml @@ -14,3 +14,16 @@ replicas: 2 ## - "11.22.33.46" ## externalIPs: [] + +## @param whitelist List of client networks +## Example: +## whitelist: +## - "1.2.3.4" +## - "10.100.0.0/16" +whitelist: [] + +## @param clouflareProxy Restoring original visitor IPs when Cloudflare proxied is enabled +clouflareProxy: false + +## @param dashboard Should ingress serve Cozystack service dashboard +dashboard: false diff --git a/packages/extra/versions_map b/packages/extra/versions_map index e56c2dec..8453643d 100644 --- a/packages/extra/versions_map +++ b/packages/extra/versions_map @@ -1,11 +1,11 @@ etcd 1.0.0 f7eaab0 etcd 2.0.0 a6d0f7cf etcd 2.0.1 6fc1cc7d -etcd 2.1.0 HEAD +etcd 2.1.0 2b00fcf8 +etcd 2.2.0 HEAD ingress 1.0.0 f642698 ingress 1.1.0 838bee5d -ingress 1.2.0 07d666c0 -ingress 1.3.0 HEAD +ingress 1.2.0 HEAD monitoring 1.0.0 f642698 monitoring 1.1.0 15478a88 monitoring 1.2.0 HEAD diff --git a/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml b/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml index 83f9be1b..ec52575f 100644 --- a/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml +++ b/packages/system/cert-manager-issuers/templates/cluster-issuers.yaml @@ -26,3 +26,10 @@ spec: - http01: ingress: class: nginx +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: selfsigned-cluster-issuer +spec: + selfSigned: {} diff --git a/packages/system/cilium/images/cilium.json b/packages/system/cilium/images/cilium.json index d42c822d..fb74829e 100644 --- a/packages/system/cilium/images/cilium.json +++ b/packages/system/cilium/images/cilium.json @@ -11,7 +11,7 @@ { "uri": "pkg:docker/golang@1.22-bookworm?platform=linux%2Famd64", "digest": { - "sha256": "6c2780255bb7b881e904e303be0d7a079054160b2ce1efde446693c0850a39ad" + "sha256": "af9b40f2b1851be993763b85288f8434af87b5678af04355b1e33ff530b5765f" } }, { @@ -45,7 +45,17 @@ } } }, - "buildx.build.ref": "amd64/amd64/ydz7c2pwlqaadvlo84t1spegq", - "containerimage.config.digest": "sha256:1f918c5f4bd8a1c90596b7d4256c8a208482141ae3363ab0b4627203b3fa3b32", - "containerimage.digest": "sha256:90e2235e75febcac777c0338fa93d5e7522d82d029facb0c318305ed178a42ac" + "buildx.build.ref": "cozystack/cozystack0/3a5uyqqyj3lnwkgdniwjp341a", + "containerimage.config.digest": "sha256:db99b8b1e565f406af5b240b1ef76b5cc3ba1b510c6e035e1497c5089d65ee12", + "containerimage.descriptor": { + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "digest": "sha256:0e9fa8f6f5194b84227ea7e7b93ef77244b5550ec62671e04d398818dccfb282", + "size": 2083, + "platform": { + "architecture": "amd64", + "os": "linux" + } + }, + "containerimage.digest": "sha256:0e9fa8f6f5194b84227ea7e7b93ef77244b5550ec62671e04d398818dccfb282", + "image.name": "ghcr.io/aenix-io/cozystack/cilium:1.15.5,ghcr.io/aenix-io/cozystack/cilium:1.15.5-v0.10.1" } \ No newline at end of file diff --git a/packages/system/dashboard/images/dashboard.json b/packages/system/dashboard/images/dashboard.json index b5de5c91..a97ddb95 100644 --- a/packages/system/dashboard/images/dashboard.json +++ b/packages/system/dashboard/images/dashboard.json @@ -35,7 +35,17 @@ } } }, - "buildx.build.ref": "amd64/amd64/vvxs4dbzlno0vtdl1zudk54fj", - "containerimage.config.digest": "sha256:52a7ac58f30de8bec104f3fa9b3dcc674f37edfee184c5d4229e24f69f4ddcb2", - "containerimage.digest": "sha256:8906436ebd6452549f0634c6db693c7c3248c123f0c882bb8b1bde34ec05aeb6" + "buildx.build.ref": "cozystack/cozystack0/puq8k1x2nsc986l15a2vanb8s", + "containerimage.config.digest": "sha256:2c68c6ce6620a8c8afd84fed1c2265738d661a47ded0be21b2517b0309ed7307", + "containerimage.descriptor": { + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "digest": "sha256:fdabfe2caa3fe2d92ca4a07b60a55c91163d7db25aa12cc4c6034c32ac1dcb17", + "size": 703, + "platform": { + "architecture": "amd64", + "os": "linux" + } + }, + "containerimage.digest": "sha256:fdabfe2caa3fe2d92ca4a07b60a55c91163d7db25aa12cc4c6034c32ac1dcb17", + "image.name": "ghcr.io/aenix-io/cozystack/dashboard:v0.10.1" } \ No newline at end of file diff --git a/packages/system/dashboard/images/dashboard.tag b/packages/system/dashboard/images/dashboard.tag index bff2f641..2158032b 100644 --- a/packages/system/dashboard/images/dashboard.tag +++ b/packages/system/dashboard/images/dashboard.tag @@ -1 +1 @@ -ghcr.io/aenix-io/cozystack/dashboard:v0.9.0 +ghcr.io/aenix-io/cozystack/dashboard:v0.10.1 diff --git a/packages/system/dashboard/images/kubeapps-apis.json b/packages/system/dashboard/images/kubeapps-apis.json index c3dd111a..15913615 100644 --- a/packages/system/dashboard/images/kubeapps-apis.json +++ b/packages/system/dashboard/images/kubeapps-apis.json @@ -11,13 +11,13 @@ { "uri": "pkg:docker/bitnami/minideb@bookworm?platform=linux%2Famd64", "digest": { - "sha256": "29b77c65b015126298b9b5d6c20a389f538145c619c8e049ccf2e7cd436e023a" + "sha256": "b13cb4b41be91e22858e9b050a51137b636a34694a92ff17c27cb010e5f93f04" } }, { "uri": "pkg:docker/alpine@latest?platform=linux%2Famd64", "digest": { - "sha256": "b89d9c93e9ed3597455c90a0b88a8bbb5cb7188438f70953fede212a0c4394e0" + "sha256": "0a4eaa0eecf5f8c050e5bba433f58c052be7587ee8af3e8b3910ef9ab5fbe9f5" } } ], @@ -41,7 +41,17 @@ } } }, - "buildx.build.ref": "amd64/amd64/p2w3cwt8rnd7ivkbmg86ugjj0", - "containerimage.config.digest": "sha256:28621d87b70bc82caf060b33313051703456a2915e95371bcbe5c0e1e5b9daa3", - "containerimage.digest": "sha256:1b6826f030c6d288f9d91476b636300e544bbf55687e59f6de1765d1320faf7b" + "buildx.build.ref": "cozystack/cozystack0/nk99hhpt81cl5xu6eecdk86qs", + "containerimage.config.digest": "sha256:662ea8b8642d1c6662e5eef79ea8329863f5178a80457e1faf983506efe7a611", + "containerimage.descriptor": { + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "digest": "sha256:eaedcb64abd1c245bd2959c66df430d0fcbbb5968334501f484231707de7ed7d", + "size": 1890, + "platform": { + "architecture": "amd64", + "os": "linux" + } + }, + "containerimage.digest": "sha256:eaedcb64abd1c245bd2959c66df430d0fcbbb5968334501f484231707de7ed7d", + "image.name": "ghcr.io/aenix-io/cozystack/kubeapps-apis:v0.10.1" } \ No newline at end of file diff --git a/packages/system/dashboard/images/kubeapps-apis.tag b/packages/system/dashboard/images/kubeapps-apis.tag index 231ec10a..0f05e344 100644 --- a/packages/system/dashboard/images/kubeapps-apis.tag +++ b/packages/system/dashboard/images/kubeapps-apis.tag @@ -1 +1 @@ -ghcr.io/aenix-io/cozystack/kubeapps-apis:v0.9.0 +ghcr.io/aenix-io/cozystack/kubeapps-apis:v0.10.1 diff --git a/packages/system/etcd-operator/charts/etcd-operator/Chart.yaml b/packages/system/etcd-operator/charts/etcd-operator/Chart.yaml index ca799e82..a68aca7b 100644 --- a/packages/system/etcd-operator/charts/etcd-operator/Chart.yaml +++ b/packages/system/etcd-operator/charts/etcd-operator/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -appVersion: v0.3.1 +appVersion: v0.4.0 name: etcd-operator type: application -version: 0.3.1 +version: 0.4.0 diff --git a/packages/system/etcd-operator/charts/etcd-operator/templates/rbac/clusterrole-manager-role.yml b/packages/system/etcd-operator/charts/etcd-operator/templates/rbac/clusterrole-manager-role.yml index 6cc79370..534e00ad 100644 --- a/packages/system/etcd-operator/charts/etcd-operator/templates/rbac/clusterrole-manager-role.yml +++ b/packages/system/etcd-operator/charts/etcd-operator/templates/rbac/clusterrole-manager-role.yml @@ -57,6 +57,22 @@ rules: - patch - update - watch + - apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - list + - patch + - watch + - apiGroups: + - "storage.k8s.io" + resources: + - storageclasses + verbs: + - get + - list - apiGroups: - etcd.aenix.io resources: diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/Chart.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/Chart.yaml index 7e633f4f..62c880fc 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/Chart.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/Chart.yaml @@ -1,8 +1,9 @@ annotations: - artifacthub.io/changes: '- "Update Ingress-Nginx version controller-v1.9.4"' + artifacthub.io/changes: | + - Update Ingress-Nginx version controller-v1.11.1 artifacthub.io/prerelease: "false" apiVersion: v2 -appVersion: 1.9.4 +appVersion: 1.11.1 description: Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer home: https://github.com/kubernetes/ingress-nginx @@ -10,12 +11,15 @@ icon: https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Nginx_logo.svg/5 keywords: - ingress - nginx -kubeVersion: '>=1.20.0-0' +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.8.4 +version: 4.11.1 diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/OWNERS b/packages/system/ingress-nginx/charts/ingress-nginx/OWNERS index 6b7e049c..d588ede6 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/OWNERS +++ b/packages/system/ingress-nginx/charts/ingress-nginx/OWNERS @@ -1,4 +1,4 @@ -# See the OWNERS docs: https://github.com/kubernetes/community/blob/master/contributors/guide/owners.md +# See the OWNERS docs: https://www.kubernetes.dev/docs/guide/owners approvers: - ingress-nginx-helm-maintainers diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/README.md b/packages/system/ingress-nginx/charts/ingress-nginx/README.md index c03f290d..0acf3da9 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/README.md +++ b/packages/system/ingress-nginx/charts/ingress-nginx/README.md @@ -2,7 +2,7 @@ [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Ingress controller for Kubernetes using NGINX as a reverse proxy and load balancer -![Version: 4.8.4](https://img.shields.io/badge/Version-4.8.4-informational?style=flat-square) ![AppVersion: 1.9.4](https://img.shields.io/badge/AppVersion-1.9.4-informational?style=flat-square) +![Version: 4.11.1](https://img.shields.io/badge/Version-4.11.1-informational?style=flat-square) ![AppVersion: 1.11.1](https://img.shields.io/badge/AppVersion-1.11.1-informational?style=flat-square) To use, add `ingressClassName: nginx` spec field or the `kubernetes.io/ingress.class: nginx` annotation to your Ingress resources. @@ -10,7 +10,7 @@ This chart bootstraps an ingress-nginx deployment on a [Kubernetes](http://kuber ## Requirements -Kubernetes: `>=1.20.0-0` +Kubernetes: `>=1.21.0-0` ## Get Repo Info @@ -253,17 +253,23 @@ As of version `1.26.0` of this chart, by simply not providing any clusterIP valu | controller.admissionWebhooks.namespaceSelector | object | `{}` | | | controller.admissionWebhooks.objectSelector | object | `{}` | | | controller.admissionWebhooks.patch.enabled | bool | `true` | | -| controller.admissionWebhooks.patch.image.digest | string | `"sha256:a7943503b45d552785aa3b5e457f169a5661fb94d82b8a3373bcd9ebaf9aac80"` | | +| controller.admissionWebhooks.patch.image.digest | string | `"sha256:36d05b4077fb8e3d13663702fa337f124675ba8667cbd949c03a8e8ea6fa4366"` | | | 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 | `"v20231011-8b53cabe0"` | | +| controller.admissionWebhooks.patch.image.tag | string | `"v1.4.1"` | | | 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 | `{}` | | @@ -285,7 +291,7 @@ As of version `1.26.0` of this chart, by simply not providing any clusterIP valu | controller.autoscaling.targetCPUUtilizationPercentage | int | `50` | | | controller.autoscaling.targetMemoryUtilizationPercentage | int | `50` | | | controller.autoscalingTemplate | list | `[]` | | -| controller.config | object | `{}` | Will add custom configuration options to Nginx https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/ | +| 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 | @@ -293,9 +299,11 @@ As of version `1.26.0` of this chart, by simply not providing any clusterIP valu | 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 | @@ -317,8 +325,8 @@ As of version `1.26.0` of this chart, by simply not providing any clusterIP valu | controller.hostname | object | `{}` | Optionally customize the pod hostname. | | controller.image.allowPrivilegeEscalation | bool | `false` | | | controller.image.chroot | bool | `false` | | -| controller.image.digest | string | `"sha256:5b161f051d017e55d358435f295f5e9a297e66158f136321d9b04520ec6c48a3"` | | -| controller.image.digestChroot | string | `"sha256:5976b1067cfbca8a21d0ba53d71f83543a73316a61ea7f7e436d6cf84ddf9b26"` | | +| controller.image.digest | string | `"sha256:e6439a12b52076965928e83b7b56aae6731231677b01e81818bce7fa5c60161a"` | | +| controller.image.digestChroot | string | `"sha256:7cabe4bd7558bfdf5b707976d7be56fd15ffece735d7c90fc238b6eda290fd8d"` | | | controller.image.image | string | `"ingress-nginx/controller"` | | | controller.image.pullPolicy | string | `"IfNotPresent"` | | | controller.image.readOnlyRootFilesystem | bool | `false` | | @@ -326,14 +334,17 @@ As of version `1.26.0` of this chart, by simply not providing any clusterIP valu | controller.image.runAsNonRoot | bool | `true` | | | controller.image.runAsUser | int | `101` | | | controller.image.seccompProfile.type | string | `"RuntimeDefault"` | | -| controller.image.tag | string | `"v1.9.4"` | | +| controller.image.tag | string | `"v1.11.1"` | | | 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.controllerValue | string | `"k8s.io/ingress-nginx"` | Controller-value of the controller that is processing this ingressClass | -| controller.ingressClassResource.default | bool | `false` | Is this the default ingressClass for the cluster | -| controller.ingressClassResource.enabled | bool | `true` | Is this ingressClass enabled or not | -| controller.ingressClassResource.name | string | `"nginx"` | Name of the ingressClass | -| controller.ingressClassResource.parameters | object | `{}` | Parameters is a link to a custom resource containing additional configuration for the controller. This is optional if the controller does not require extra parameters. | +| 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` | | @@ -369,6 +380,7 @@ As of version `1.26.0` of this chart, by simply not providing any clusterIP valu | controller.metrics.service.servicePort | int | `10254` | | | controller.metrics.service.type | string | `"ClusterIP"` | | | controller.metrics.serviceMonitor.additionalLabels | object | `{}` | | +| controller.metrics.serviceMonitor.annotations | object | `{}` | | | controller.metrics.serviceMonitor.enabled | bool | `false` | | | controller.metrics.serviceMonitor.metricRelabelings | list | `[]` | | | controller.metrics.serviceMonitor.namespace | string | `""` | | @@ -387,9 +399,12 @@ As of version `1.26.0` of this chart, by simply not providing any clusterIP valu | 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.distroless | bool | `true` | | | controller.opentelemetry.enabled | bool | `false` | | -| controller.opentelemetry.image | string | `"registry.k8s.io/ingress-nginx/opentelemetry:v20230721-3e2062ee5@sha256:13bee3f5223883d3ca62fee7309ad02d22ec00ff0d7033e3e9aca7a9f60fd472"` | | +| controller.opentelemetry.image.digest | string | `"sha256:13bee3f5223883d3ca62fee7309ad02d22ec00ff0d7033e3e9aca7a9f60fd472"` | | +| controller.opentelemetry.image.distroless | bool | `true` | | +| controller.opentelemetry.image.image | string | `"ingress-nginx/opentelemetry"` | | +| controller.opentelemetry.image.registry | string | `"registry.k8s.io"` | | +| controller.opentelemetry.image.tag | string | `"v20230721-3e2062ee5"` | | | controller.opentelemetry.name | string | `"opentelemetry"` | | | controller.opentelemetry.resources | object | `{}` | | | controller.podAnnotations | object | `{}` | Annotations to be added to controller pods # | @@ -415,34 +430,50 @@ As of version `1.26.0` of this chart, by simply not providing any clusterIP valu | 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 are mandatory for the load balancer to come up. Varies with the cloud service. Values passed through helm tpl engine. | -| controller.service.appProtocol | bool | `true` | If enabled is adding an appProtocol option for Kubernetes service. An appProtocol field replacing annotations that were using for setting a backend protocol. Here is an example for AWS: service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http It allows choosing the protocol for each backend specified in the Kubernetes service. See the following GitHub issue for more details about the purpose: https://github.com/kubernetes/kubernetes/issues/40244 Will be ignored for Kubernetes versions older than 1.20 # | -| controller.service.enableHttp | bool | `true` | | -| controller.service.enableHttps | bool | `true` | | -| controller.service.enabled | bool | `true` | | -| controller.service.external.enabled | bool | `true` | | -| controller.service.externalIPs | list | `[]` | List of IP addresses at which the controller services are available # Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips # | -| controller.service.internal.annotations | object | `{}` | Annotations are mandatory for the load balancer to come up. Varies with the cloud service. Values passed through helm tpl engine. | -| controller.service.internal.enabled | bool | `false` | Enables an additional internal load balancer (besides the external one). | -| controller.service.internal.loadBalancerIP | string | `""` | Used by cloud providers to connect the resulting internal LoadBalancer to a pre-existing static IP. Make sure to add to the service the needed annotation to specify the subnet which the static IP belongs to. For instance, `networking.gke.io/internal-load-balancer-subnet` for GCP and `service.beta.kubernetes.io/aws-load-balancer-subnets` for AWS. | -| controller.service.internal.loadBalancerSourceRanges | list | `[]` | Restrict access For LoadBalancer service. Defaults to 0.0.0.0/0. | -| controller.service.internal.ports | object | `{}` | Custom port mapping for internal service | -| controller.service.internal.targetPorts | object | `{}` | Custom target port mapping for internal service | -| controller.service.ipFamilies | list | `["IPv4"]` | List of IP families (e.g. IPv4, IPv6) assigned to the 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/ | -| controller.service.ipFamilyPolicy | string | `"SingleStack"` | Represents the dual-stack-ness requested or required by this Service. Possible values are SingleStack, PreferDualStack or RequireDualStack. The ipFamilies and clusterIPs fields depend on the value of this field. # Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ | -| controller.service.labels | object | `{}` | | -| controller.service.loadBalancerClass | string | `""` | Used by cloud providers to select a load balancer implementation other than the cloud provider default. https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class | -| controller.service.loadBalancerIP | string | `""` | Used by cloud providers to connect the resulting `LoadBalancer` to a pre-existing static IP according to https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer | -| controller.service.loadBalancerSourceRanges | list | `[]` | | -| controller.service.nodePorts.http | string | `""` | | -| controller.service.nodePorts.https | string | `""` | | -| controller.service.nodePorts.tcp | object | `{}` | | -| controller.service.nodePorts.udp | object | `{}` | | -| controller.service.ports.http | int | `80` | | -| controller.service.ports.https | int | `443` | | -| controller.service.targetPorts.http | string | `"http"` | | -| controller.service.targetPorts.https | string | `"https"` | | -| controller.service.type | string | `"LoadBalancer"` | | +| 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 | @@ -454,7 +485,7 @@ As of version `1.26.0` of this chart, by simply not providing any clusterIP valu | 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 | `{}` | | +| 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` | | @@ -510,6 +541,7 @@ As of version `1.26.0` of this chart, by simply not providing any clusterIP valu | 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/ | diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-extra-modules.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-extra-modules.yaml index f299dbf1..52a32fcb 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-extra-modules.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/daemonset-extra-modules.yaml @@ -7,4 +7,7 @@ controller: type: ClusterIP extraModules: - name: opentelemetry - image: busybox + image: + registry: registry.k8s.io + image: busybox + tag: latest diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-default-container-sec-context.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-default-container-sec-context.yaml index 2310c344..91b1b98a 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-default-container-sec-context.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-default-container-sec-context.yaml @@ -9,4 +9,7 @@ controller: allowPrivilegeEscalation: false extraModules: - name: opentelemetry - image: busybox + image: + registry: registry.k8s.io + image: busybox + tag: latest diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-specific-container-sec-context.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-specific-container-sec-context.yaml index bd2f011c..b6013c7d 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-specific-container-sec-context.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules-specific-container-sec-context.yaml @@ -7,6 +7,9 @@ controller: type: ClusterIP extraModules: - name: opentelemetry - image: busybox + image: + registry: registry.k8s.io + image: busybox + tag: latest containerSecurityContext: allowPrivilegeEscalation: false diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules.yaml index ec592354..2fbe1cc0 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-extra-modules.yaml @@ -7,4 +7,7 @@ controller: type: ClusterIP extraModules: - name: opentelemetry - image: busybox + image: + registry: registry.k8s.io + image: busybox + tag: latest diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-opentelemetry-customregistry-values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-opentelemetry-customregistry-values.yaml new file mode 100644 index 00000000..fb3ef444 --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/ci/deployment-opentelemetry-customregistry-values.yaml @@ -0,0 +1,9 @@ +controller: + image: + repository: ingress-controller/controller + tag: 1.0.0-dev + digest: null + service: + type: ClusterIP + opentelemetry: + enabled: true diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/_helpers.tpl b/packages/system/ingress-nginx/charts/ingress-nginx/templates/_helpers.tpl index c936dab7..0c6a3e20 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/_helpers.tpl +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/_helpers.tpl @@ -167,6 +167,17 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this {{- 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). @@ -242,22 +253,13 @@ Check the ingress controller version tag is at most three versions behind the la {{- end -}} {{- end -}} -{{/* -IngressClass parameters. -*/}} -{{- define "ingressClass.parameters" -}} - {{- if .Values.controller.ingressClassResource.parameters -}} - parameters: -{{ toYaml .Values.controller.ingressClassResource.parameters | indent 4}} - {{ end }} -{{- end -}} - {{/* Extra modules. */}} {{- define "extraModules" -}} - name: {{ .name }} - image: {{ .image }} + {{- with .image }} + image: {{ if .repository }}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{ end }}:{{ .tag }}{{ if .digest }}@{{ .digest }}{{ end }} command: {{- if .distroless }} - /init_module @@ -266,6 +268,7 @@ Extra modules. - -c - /usr/local/bin/init_module.sh {{- end }} + {{- end }} {{- if .containerSecurityContext }} securityContext: {{ toYaml .containerSecurityContext | nindent 4 }} {{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/_params.tpl b/packages/system/ingress-nginx/charts/ingress-nginx/templates/_params.tpl index 47d024e8..48569a8b 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/_params.tpl +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/_params.tpl @@ -29,7 +29,7 @@ - --watch-namespace={{ default "$(POD_NAMESPACE)" .Values.controller.scope.namespace }} {{- end }} {{- if and (not .Values.controller.scope.enabled) .Values.controller.scope.namespaceSelector }} -- --watch-namespace-selector={{ default "" .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 }} @@ -54,9 +54,18 @@ {{- 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 }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml index 8271dc40..a2184820 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrole.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +{{- 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: diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml index 3fe842d1..b8938843 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/clusterrolebinding.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +{{- 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: @@ -18,6 +18,6 @@ roleRef: name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} subjects: - kind: ServiceAccount - name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + name: {{ include "ingress-nginx.admissionWebhooks.patch.serviceAccountName" . }} namespace: {{ include "ingress-nginx.namespace" . }} {{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml index c29083f2..17661646 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-createSecret.yaml @@ -43,7 +43,7 @@ spec: containers: - name: create {{- with .Values.controller.admissionWebhooks.patch.image }} - image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{- end -}}:{{ .tag }}{{- if (.digest) -}} @{{.digest}} {{- end -}}" + image: {{ if .repository }}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{ end }}:{{ .tag }}{{ if .digest }}@{{ .digest }}{{ end }} {{- end }} imagePullPolicy: {{ .Values.controller.admissionWebhooks.patch.image.pullPolicy }} args: @@ -66,7 +66,7 @@ spec: resources: {{ toYaml .Values.controller.admissionWebhooks.createSecretJob.resources | nindent 12 }} {{- end }} restartPolicy: OnFailure - serviceAccountName: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + serviceAccountName: {{ include "ingress-nginx.admissionWebhooks.patch.serviceAccountName" . }} {{- if .Values.controller.admissionWebhooks.patch.nodeSelector }} nodeSelector: {{ toYaml .Values.controller.admissionWebhooks.patch.nodeSelector | nindent 8 }} {{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml index cbc4a761..f7d44a24 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/job-patchWebhook.yaml @@ -43,7 +43,7 @@ spec: containers: - name: patch {{- with .Values.controller.admissionWebhooks.patch.image }} - image: "{{- if .repository -}}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{- end -}}:{{ .tag }}{{- if (.digest) -}} @{{.digest}} {{- end -}}" + image: {{ if .repository }}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{ end }}:{{ .tag }}{{ if .digest }}@{{ .digest }}{{ end }} {{- end }} imagePullPolicy: {{ .Values.controller.admissionWebhooks.patch.image.pullPolicy }} args: @@ -68,7 +68,7 @@ spec: resources: {{ toYaml .Values.controller.admissionWebhooks.patchWebhookJob.resources | nindent 12 }} {{- end }} restartPolicy: OnFailure - serviceAccountName: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + serviceAccountName: {{ include "ingress-nginx.admissionWebhooks.patch.serviceAccountName" . }} {{- if .Values.controller.admissionWebhooks.patch.nodeSelector }} nodeSelector: {{ toYaml .Values.controller.admissionWebhooks.patch.nodeSelector | nindent 8 }} {{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/role.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/role.yaml index 5b05d9b0..c4b23aa0 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/role.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/role.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +{{- 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: diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml index 48a17556..425e8d82 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/rolebinding.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +{{- 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: @@ -19,6 +19,6 @@ roleRef: name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} subjects: - kind: ServiceAccount - name: {{ include "ingress-nginx.admissionWebhooks.fullname" . }} + name: {{ include "ingress-nginx.admissionWebhooks.patch.serviceAccountName" . }} namespace: {{ include "ingress-nginx.namespace" . }} {{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml index 91bbf22b..52f94dcc 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/admission-webhooks/job-patch/serviceaccount.yaml @@ -1,8 +1,8 @@ -{{- if and .Values.controller.admissionWebhooks.enabled .Values.controller.admissionWebhooks.patch.enabled (not .Values.controller.admissionWebhooks.certManager.enabled) -}} +{{- 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.fullname" . }} + name: {{ include "ingress-nginx.admissionWebhooks.patch.serviceAccountName" . }} namespace: {{ include "ingress-nginx.namespace" . }} annotations: "helm.sh/hook": pre-install,pre-upgrade,post-install,post-upgrade @@ -13,4 +13,5 @@ metadata: {{- with .Values.controller.admissionWebhooks.patch.labels }} {{- toYaml . | nindent 4 }} {{- end }} +automountServiceAccountToken: {{ .Values.controller.admissionWebhooks.patch.serviceAccount.automountServiceAccountToken }} {{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap.yaml index 662a1620..22080d11 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-configmap.yaml @@ -24,5 +24,5 @@ data: ssl-dh-param: {{ include "ingress-nginx.namespace" . }}/{{ include "ingress-nginx.controller.fullname" . }} {{- end }} {{- range $key, $value := .Values.controller.config }} - {{- $key | nindent 2 }}: {{ $value | quote }} + {{- $key | nindent 2 }}: {{ tpl (toString $value) $ | quote }} {{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml index 887d7a20..80ad656b 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-daemonset.yaml @@ -77,7 +77,7 @@ spec: 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" . }}" + 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 }} @@ -186,13 +186,13 @@ spec: {{- if .Values.controller.extraModules }} {{- range .Values.controller.extraModules }} {{- $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} - {{- include "extraModules" (dict "name" .name "image" .image "distroless" .distroless "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- 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 "distroless" .distroless "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- include "extraModules" (dict "name" .name "image" .image "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} {{- end }} {{- end }} {{- end }} @@ -206,7 +206,7 @@ spec: tolerations: {{ toYaml .Values.controller.tolerations | nindent 8 }} {{- end }} {{- if .Values.controller.affinity }} - affinity: {{ toYaml .Values.controller.affinity | nindent 8 }} + affinity: {{ tpl (toYaml .Values.controller.affinity) $ | nindent 8 }} {{- end }} {{- if .Values.controller.topologySpreadConstraints }} topologySpreadConstraints: {{ tpl (toYaml .Values.controller.topologySpreadConstraints) $ | nindent 8 }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-deployment.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-deployment.yaml index b504faec..e2915a76 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-deployment.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-deployment.yaml @@ -19,7 +19,7 @@ spec: matchLabels: {{- include "ingress-nginx.selectorLabels" . | nindent 6 }} app.kubernetes.io/component: controller - {{- if not (or .Values.controller.autoscaling.enabled .Values.controller.keda.enabled) }} + {{- if eq .Values.controller.autoscaling.enabled .Values.controller.keda.enabled }} replicas: {{ .Values.controller.replicaCount }} {{- end }} revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} @@ -80,7 +80,7 @@ spec: 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" . }}" + 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 }} @@ -189,13 +189,13 @@ spec: {{- if .Values.controller.extraModules }} {{- range .Values.controller.extraModules }} {{- $containerSecurityContext := .containerSecurityContext | default $.Values.controller.containerSecurityContext }} - {{- include "extraModules" (dict "name" .name "image" .image "distroless" .distroless "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- 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 "distroless" .distroless "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} + {{- include "extraModules" (dict "name" .name "image" .image "containerSecurityContext" $containerSecurityContext "resources" .resources) | nindent 8 }} {{- end }} {{- end }} {{- end }} @@ -209,7 +209,7 @@ spec: tolerations: {{ toYaml .Values.controller.tolerations | nindent 8 }} {{- end }} {{- if .Values.controller.affinity }} - affinity: {{ toYaml .Values.controller.affinity | nindent 8 }} + affinity: {{ tpl (toYaml .Values.controller.affinity) $ | nindent 8 }} {{- end }} {{- if .Values.controller.topologySpreadConstraints }} topologySpreadConstraints: {{ tpl (toYaml .Values.controller.topologySpreadConstraints) $ | nindent 8 }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-ingressclass-aliases.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-ingressclass-aliases.yaml new file mode 100644 index 00000000..ffe22310 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-ingressclass.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-ingressclass.yaml index 9492784a..98479a52 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-ingressclass.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-ingressclass.yaml @@ -1,6 +1,4 @@ {{- if .Values.controller.ingressClassResource.enabled -}} -# We don't support namespaced ingressClass yet -# So a ClusterRole and a ClusterRoleBinding is required apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: @@ -11,11 +9,18 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} name: {{ .Values.controller.ingressClassResource.name }} -{{- if .Values.controller.ingressClassResource.default }} + {{- if or .Values.controller.ingressClassResource.default .Values.controller.ingressClassResource.annotations }} annotations: + {{- if .Values.controller.ingressClassResource.default }} ingressclass.kubernetes.io/is-default-class: "true" -{{- end }} + {{- end }} + {{- if .Values.controller.ingressClassResource.annotations }} + {{- toYaml .Values.controller.ingressClassResource.annotations | nindent 4 }} + {{- end }} + {{- end }} spec: controller: {{ .Values.controller.ingressClassResource.controllerValue }} - {{ template "ingressClass.parameters" . }} + {{- with .Values.controller.ingressClassResource.parameters }} + parameters: {{ toYaml . | nindent 4 }} + {{- end }} {{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-keda.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-keda.yaml index 6ff9c0b2..24d30fa0 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-keda.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-keda.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.controller.keda.enabled (eq .Values.controller.kind "Deployment") -}} +{{- if and (eq .Values.controller.kind "Deployment") .Values.controller.keda.enabled (not .Values.controller.autoscaling.enabled) -}} apiVersion: {{ .Values.controller.keda.apiVersion }} kind: ScaledObject metadata: diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-poddisruptionbudget.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-poddisruptionbudget.yaml index 8cb7d4b9..8e0181f9 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-poddisruptionbudget.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-poddisruptionbudget.yaml @@ -1,4 +1,13 @@ -{{- if or (and .Values.controller.autoscaling.enabled (gt (.Values.controller.autoscaling.minReplicas | int) 1)) (and (not .Values.controller.autoscaling.enabled) (gt (.Values.controller.replicaCount | int) 1)) }} +# 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: @@ -24,3 +33,4 @@ spec: maxUnavailable: {{ .Values.controller.maxUnavailable }} {{- end }} {{- end }} +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-prometheusrules.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-prometheusrules.yaml index f0b93cc8..41684c37 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-prometheusrules.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-prometheusrules.yaml @@ -1,4 +1,4 @@ -{{- if and ( .Values.controller.metrics.enabled ) ( .Values.controller.metrics.prometheusRule.enabled ) ( .Capabilities.APIVersions.Has "monitoring.coreos.com/v1" ) -}} +{{- if and .Values.controller.metrics.enabled .Values.controller.metrics.prometheusRule.enabled -}} apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-role.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-role.yaml index f6217a29..a94b3997 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-role.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-role.yaml @@ -44,12 +44,15 @@ rules: - 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: diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-internal.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-internal.yaml index b69a09f6..6d0b47ca 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-internal.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-internal.yaml @@ -1,4 +1,4 @@ -{{- if and .Values.controller.service.enabled .Values.controller.service.internal.enabled .Values.controller.service.internal.annotations}} +{{- if and .Values.controller.service.enabled .Values.controller.service.internal.enabled .Values.controller.service.internal.annotations -}} apiVersion: v1 kind: Service metadata: @@ -15,9 +15,12 @@ metadata: name: {{ include "ingress-nginx.controller.fullname" . }}-internal namespace: {{ include "ingress-nginx.namespace" . }} spec: - type: "{{ .Values.controller.service.type }}" -{{- if hasKey .Values.controller.service.internal "allocateLoadBalancerNodePorts" }} - allocateLoadBalancerNodePorts: {{ .Values.controller.service.internal.allocateLoadBalancerNodePorts }} + 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 }} @@ -25,8 +28,28 @@ spec: {{- 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")) }} @@ -35,11 +58,11 @@ spec: 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 semverCompare ">=1.20" .Capabilities.KubeVersion.Version }} + {{- 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.nodePorts.http))) }} - nodePort: {{ .Values.controller.service.nodePorts.http }} + {{- 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 }} @@ -47,11 +70,11 @@ spec: 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 semverCompare ">=1.20" .Capabilities.KubeVersion.Version }} + {{- 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.nodePorts.https))) }} - nodePort: {{ .Values.controller.service.nodePorts.https }} + {{- 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 }} @@ -59,9 +82,9 @@ spec: 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 }} + {{- 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 }} @@ -70,9 +93,9 @@ spec: 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 }} + {{- 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 }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-webhook.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-webhook.yaml index 2d02e23a..6dcf1a10 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-webhook.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service-webhook.yaml @@ -31,7 +31,7 @@ spec: - name: https-webhook port: 443 targetPort: webhook - {{- if semverCompare ">=1.20" .Capabilities.KubeVersion.Version }} + {{- if semverCompare ">=1.20.0-0" .Capabilities.KubeVersion.Version }} appProtocol: https {{- end }} selector: diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service.yaml index d8163501..cb78a703 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-service.yaml @@ -16,9 +16,6 @@ metadata: namespace: {{ include "ingress-nginx.namespace" . }} spec: type: {{ .Values.controller.service.type }} -{{- if hasKey .Values.controller.service "allocateLoadBalancerNodePorts" }} - allocateLoadBalancerNodePorts: {{ .Values.controller.service.allocateLoadBalancerNodePorts }} -{{- end }} {{- if .Values.controller.service.clusterIP }} clusterIP: {{ .Values.controller.service.clusterIP }} {{- end }} @@ -34,6 +31,9 @@ spec: {{- 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 }} @@ -47,8 +47,6 @@ spec: {{- if .Values.controller.service.ipFamilyPolicy }} ipFamilyPolicy: {{ .Values.controller.service.ipFamilyPolicy }} {{- end }} -{{- end }} -{{- if semverCompare ">=1.21.0-0" .Capabilities.KubeVersion.Version -}} {{- if .Values.controller.service.ipFamilies }} ipFamilies: {{ toYaml .Values.controller.service.ipFamilies | nindent 4 }} {{- end }} @@ -60,7 +58,7 @@ spec: port: {{ .Values.controller.service.ports.http }} protocol: TCP targetPort: {{ .Values.controller.service.targetPorts.http }} - {{- if and (semverCompare ">=1.20" .Capabilities.KubeVersion.Version) (.Values.controller.service.appProtocol) }} + {{- 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))) }} @@ -72,7 +70,7 @@ spec: port: {{ .Values.controller.service.ports.https }} protocol: TCP targetPort: {{ .Values.controller.service.targetPorts.https }} - {{- if and (semverCompare ">=1.20" .Capabilities.KubeVersion.Version) (.Values.controller.service.appProtocol) }} + {{- 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))) }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-servicemonitor.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-servicemonitor.yaml index 585fd0cb..62301da4 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-servicemonitor.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/controller-servicemonitor.yaml @@ -14,6 +14,9 @@ metadata: {{- 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 }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-deployment.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-deployment.yaml index ed88e6bc..c6ccdd5c 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-deployment.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-deployment.yaml @@ -30,7 +30,7 @@ spec: annotations: {{ toYaml .Values.defaultBackend.podAnnotations | nindent 8 }} {{- end }} labels: - {{- include "ingress-nginx.selectorLabels" . | nindent 8 }} + {{- include "ingress-nginx.labels" . | nindent 8 }} app.kubernetes.io/component: default-backend {{- with .Values.defaultBackend.labels }} {{- toYaml . | nindent 8 }} @@ -51,7 +51,7 @@ spec: 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 -}}" + image: {{ if .repository }}{{ .repository }}{{ else }}{{ .registry }}/{{ .image }}{{ end }}:{{ .tag }}{{ if .digest }}@{{ .digest }}{{ end }} {{- end }} imagePullPolicy: {{ .Values.defaultBackend.image.pullPolicy }} {{- if .Values.defaultBackend.extraArgs }} @@ -107,7 +107,10 @@ spec: tolerations: {{ toYaml .Values.defaultBackend.tolerations | nindent 8 }} {{- end }} {{- if .Values.defaultBackend.affinity }} - affinity: {{ toYaml .Values.defaultBackend.affinity | nindent 8 }} + 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 }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-extra-configmaps.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-extra-configmaps.yaml index 88b59280..9af56cf3 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-extra-configmaps.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-extra-configmaps.yaml @@ -1,23 +1,23 @@ {{- if .Values.defaultBackend.enabled }} - {{- range .Values.defaultBackend.extraConfigMaps }} +{{- range .Values.defaultBackend.extraConfigMaps }} --- apiVersion: v1 kind: ConfigMap metadata: - name: {{ .name }} - namespace: {{ include "ingress-nginx.namespace" $ | quote }} 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 }} - +{{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-hpa.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-hpa.yaml index 69932389..49bcdcfd 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-hpa.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-hpa.yaml @@ -21,14 +21,6 @@ spec: minReplicas: {{ .Values.defaultBackend.autoscaling.minReplicas }} maxReplicas: {{ .Values.defaultBackend.autoscaling.maxReplicas }} metrics: - {{- with .Values.defaultBackend.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ . }} - {{- end }} {{- with .Values.defaultBackend.autoscaling.targetMemoryUtilizationPercentage }} - type: Resource resource: @@ -37,4 +29,12 @@ spec: type: Utilization averageUtilization: {{ . }} {{- end }} + {{- with .Values.defaultBackend.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ . }} + {{- end }} {{- end }} diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-service.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-service.yaml index 2cccd6e9..65b6b836 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-service.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/templates/default-backend-service.yaml @@ -32,7 +32,7 @@ spec: port: {{ .Values.defaultBackend.service.servicePort }} protocol: TCP targetPort: http - {{- if semverCompare ">=1.20" .Capabilities.KubeVersion.Version }} + {{- if semverCompare ">=1.20.0-0" .Capabilities.KubeVersion.Version }} appProtocol: http {{- end }} selector: diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/clusterrole_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/clusterrole_test.yaml new file mode 100644 index 00000000..d7a8b885 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/clusterrolebinding_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/clusterrolebinding_test.yaml new file mode 100644 index 00000000..d7c3266d --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/role_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/role_test.yaml new file mode 100644 index 00000000..a236f3d7 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/rolebinding_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/rolebinding_test.yaml new file mode 100644 index 00000000..74abaa16 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/serviceaccount_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/admission-webhooks/job-patch/serviceaccount_test.yaml new file mode 100644 index 00000000..7c30d1e6 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-configmap-addheaders_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-configmap-addheaders_test.yaml new file mode 100644 index 00000000..e831d50c --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-configmap-proxyheaders_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-configmap-proxyheaders_test.yaml new file mode 100644 index 00000000..0634a373 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-configmap_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-configmap_test.yaml new file mode 100644 index 00000000..9cfea980 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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: + global-rate-limit-memcached-host: "memcached.{{ .Release.Namespace }}.svc.kubernetes.local" + global-rate-limit-memcached-port: 11211 + use-gzip: true + asserts: + - equal: + path: data.global-rate-limit-memcached-host + value: memcached.NAMESPACE.svc.kubernetes.local + - equal: + path: data.global-rate-limit-memcached-port + value: "11211" + - equal: + path: data.use-gzip + value: "true" diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-daemonset_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-daemonset_test.yaml new file mode 100644 index 00000000..6ee794af --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-daemonset_test.yaml @@ -0,0 +1,140 @@ +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 diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-deployment_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-deployment_test.yaml new file mode 100644 index 00000000..82b97a0f --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-deployment_test.yaml @@ -0,0 +1,162 @@ +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 diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-hpa_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-hpa_test.yaml new file mode 100644 index 00000000..869d3a69 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-ingressclass-aliases_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-ingressclass-aliases_test.yaml new file mode 100644 index 00000000..9a4a576b --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-ingressclass_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-ingressclass_test.yaml new file mode 100644 index 00000000..b3384af3 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-keda_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-keda_test.yaml new file mode 100644 index 00000000..80028348 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-networkpolicy_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-networkpolicy_test.yaml new file mode 100644 index 00000000..5de12e9c --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-poddisruptionbudget_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-poddisruptionbudget_test.yaml new file mode 100644 index 00000000..48b4fafc --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-poddisruptionbudget_test.yaml @@ -0,0 +1,73 @@ +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 diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-service-internal_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-service-internal_test.yaml new file mode 100644 index 00000000..5465e1a2 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-service-metrics_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-service-metrics_test.yaml new file mode 100644 index 00000000..afdb9404 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-service_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/controller-service_test.yaml new file mode 100644 index 00000000..10574f22 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-deployment_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-deployment_test.yaml new file mode 100644 index 00000000..e237fe7e --- /dev/null +++ b/packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-deployment_test.yaml @@ -0,0 +1,137 @@ +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 diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-extra-configmaps_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-extra-configmaps_test.yaml index b18ceedf..aa600e74 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-extra-configmaps_test.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-extra-configmaps_test.yaml @@ -1,19 +1,18 @@ -suite: test default backend extra ConfigMaps +suite: Default Backend > Extra ConfigMaps templates: - default-backend-extra-configmaps.yaml tests: - - it: should not create any ConfigMap by default + - it: should not create a ConfigMap if `defaultBackend.extraConfigMaps` is empty set: - Release.Namespace: default defaultBackend.enabled: true + defaultBackend.extraConfigMaps: [] asserts: - hasDocuments: count: 0 - - it: should create one ConfigMap + - it: should create one ConfigMap if `defaultBackend.extraConfigMaps` has one element set: - Release.Namespace: default defaultBackend.enabled: true defaultBackend.extraConfigMaps: - name: my-configmap-1 @@ -27,10 +26,12 @@ tests: - equal: path: metadata.name value: my-configmap-1 + - equal: + path: data.key1 + value: value1 - - it: should correctly render multiple ConfigMaps + - it: should create two ConfigMaps if `defaultBackend.extraConfigMaps` has two elements set: - Release.Namespace: nginx defaultBackend.enabled: true defaultBackend.extraConfigMaps: - name: my-configmap-1 @@ -46,4 +47,4 @@ tests: of: ConfigMap - matchRegex: path: metadata.name - pattern: "my-configmap-\\d+" + pattern: my-configmap-(1|2) diff --git a/packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-service_test.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/tests/default-backend-service_test.yaml new file mode 100644 index 00000000..f16904f9 --- /dev/null +++ b/packages/system/ingress-nginx/charts/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/packages/system/ingress-nginx/charts/ingress-nginx/values.yaml b/packages/system/ingress-nginx/charts/ingress-nginx/values.yaml index c1e89d77..92735d2a 100644 --- a/packages/system/ingress-nginx/charts/ingress-nginx/values.yaml +++ b/packages/system/ingress-nginx/charts/ingress-nginx/values.yaml @@ -9,7 +9,6 @@ # -- Override the deployment namespace; defaults to .Release.Namespace namespaceOverride: "" - ## Labels to apply to all resources ## commonLabels: {} @@ -27,9 +26,9 @@ 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.9.4" - digest: sha256:5b161f051d017e55d358435f295f5e9a297e66158f136321d9b04520ec6c48a3 - digestChroot: sha256:5976b1067cfbca8a21d0ba53d71f83543a73316a61ea7f7e436d6cf84ddf9b26 + tag: "v1.11.1" + digest: sha256:e6439a12b52076965928e83b7b56aae6731231677b01e81818bce7fa5c60161a + digestChroot: sha256:7cabe4bd7558bfdf5b707976d7be56fd15ffece735d7c90fc238b6eda290fd8d pullPolicy: IfNotPresent runAsNonRoot: true # www-data -> uid 101 @@ -46,7 +45,8 @@ controller: containerPort: http: 80 https: 443 - # -- Will add custom configuration options to Nginx https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/ + # -- 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: {} @@ -84,6 +84,10 @@ controller: # -- 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. @@ -109,21 +113,39 @@ controller: 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 - ## IngressClass resources are supported since k8s >= 1.18 and required since k8s >= 1.19 + # -- 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 of the IngressClass name: nginx - # -- Is this ingressClass enabled or not + # -- Create the IngressClass or not enabled: true - # -- Is this the default ingressClass for the cluster + # -- 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 - # -- Controller-value of the controller that is processing this ingressClass - controllerValue: "k8s.io/ingress-nginx" - # -- Parameters is a link to a custom resource containing additional - # configuration for the controller. This is optional if the controller - # does not require extra parameters. + # -- 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 @@ -140,7 +162,6 @@ controller: # "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 @@ -239,11 +260,11 @@ controller: # - key: app.kubernetes.io/name # operator: In # values: - # - ingress-nginx + # - '{{ include "ingress-nginx.name" . }}' # - key: app.kubernetes.io/instance # operator: In # values: - # - ingress-nginx + # - '{{ .Release.Name }}' # - key: app.kubernetes.io/component # operator: In # values: @@ -258,16 +279,16 @@ controller: # - key: app.kubernetes.io/name # operator: In # values: - # - ingress-nginx + # - '{{ include "ingress-nginx.name" . }}' # - key: app.kubernetes.io/instance # operator: In # values: - # - ingress-nginx + # - '{{ .Release.Name }}' # - key: app.kubernetes.io/component # operator: In # values: # - controller - # topologyKey: "kubernetes.io/hostname" + # 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/ @@ -445,102 +466,170 @@ controller: 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 - # -- If enabled is adding an appProtocol option for Kubernetes service. An appProtocol field replacing annotations that were - # using for setting a backend protocol. Here is an example for AWS: service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http - # It allows choosing the protocol for each backend specified in the Kubernetes service. - # See the following GitHub issue for more details about the purpose: https://github.com/kubernetes/kubernetes/issues/40244 - # Will be ignored for Kubernetes versions older than 1.20 - ## - appProtocol: true - # -- Annotations are mandatory for the load balancer to come up. Varies with the cloud service. Values passed through helm tpl engine. + 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: {} - # clusterIP: "" - - # -- List of IP addresses at which the controller services are available - ## Ref: https://kubernetes.io/docs/concepts/services-networking/service/#external-ips - ## + # -- 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: [] - # -- Set to false to disable loadbalancer node port allocation - # See https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation - # allocateLoadBalancerNodePorts: true - # -- Used by cloud providers to connect the resulting `LoadBalancer` to a pre-existing static IP according to https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer + # -- 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: [] - # -- Used by cloud providers to select a load balancer implementation other than the cloud provider default. https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-class + # -- 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: "" - enableHttp: true - enableHttps: true - ## Set external traffic policy to: "Local" to preserve source IP on providers supporting it. - ## Ref: https://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-typeloadbalancer - # externalTrafficPolicy: "" + # -- 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 - ## Must be either "None" or "ClientIP" if set. Kubernetes will default to "None". - ## Ref: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies - # sessionAffinity: "" - - ## Specifies the health check node port (numeric port number) for the service. If healthCheckNodePort isn’t specified, - ## the service controller allocates a port from your cluster’s NodePort range. - ## Ref: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip + # -- 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-ness requested or required by this Service. Possible values are - # SingleStack, PreferDualStack or RequireDualStack. - # The ipFamilies and clusterIPs fields depend on the value of this field. - ## Ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/ - ipFamilyPolicy: "SingleStack" - # -- List of IP families (e.g. IPv4, IPv6) assigned to the 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/ + # -- 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 - type: LoadBalancer - ## type: NodePort - ## nodePorts: - ## http: 32080 - ## https: 32443 - ## tcp: - ## 8080: 32808 + # -- 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: {} - external: - enabled: true internal: - # -- Enables an additional internal load balancer (besides the external one). + # -- Enable the internal controller service or not. Remember to configure `controller.service.internal.annotations` when enabling this. enabled: false - # -- Annotations are mandatory for the load balancer to come up. Varies with the cloud service. Values passed through helm tpl engine. + # -- 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: {} - # -- Set to false to disable loadbalancer node port allocation - # See https://kubernetes.io/docs/concepts/services-networking/service/#load-balancer-nodeport-allocation - # allocateLoadBalancerNodePorts: true - # -- Used by cloud providers to connect the resulting internal LoadBalancer to a pre-existing static IP. Make sure to add to the service the needed annotation to specify the subnet which the static IP belongs to. For instance, `networking.gke.io/internal-load-balancer-subnet` for GCP and `service.beta.kubernetes.io/aws-load-balancer-subnets` for AWS. + # -- 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 For LoadBalancer service. Defaults to 0.0.0.0/0. + # -- Restrict access to the internal controller service. Values must be CIDRs. Allows any source address by default. loadBalancerSourceRanges: [] - ## Set external traffic policy to: "Local" to preserve source IP on - ## providers supporting it - ## Ref: https://kubernetes.io/docs/tutorials/services/source-ip/#source-ip-for-services-with-typeloadbalancer - # externalTrafficPolicy: "" + # -- 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 - # -- Custom port mapping for internal service + # -- 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: {} - # http: 80 - # https: 443 + # -- 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 - # -- Custom target port mapping for internal service targetPorts: {} - # http: http - # https: https + # -- 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 @@ -587,8 +676,15 @@ controller: # -- Modules, which are mounted into the core nginx image. See values.yaml for a sample to add opentelemetry module extraModules: [] # - name: mytestmodule - # image: registry.k8s.io/ingress-nginx/mytestmodule - # distroless: false + # 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: @@ -608,8 +704,15 @@ controller: opentelemetry: enabled: false name: opentelemetry - image: registry.k8s.io/ingress-nginx/opentelemetry:v20230721-3e2062ee5@sha256:13bee3f5223883d3ca62fee7309ad02d22ec00ff0d7033e3e9aca7a9f60fd472 - distroless: true + image: + registry: registry.k8s.io + image: ingress-nginx/opentelemetry + ## 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: "v20230721-3e2062ee5" + digest: sha256:13bee3f5223883d3ca62fee7309ad02d22ec00ff0d7033e3e9aca7a9f60fd472 + distroless: true containerSecurityContext: runAsNonRoot: true # -- The image's default user, inherited from its base image `cgr.dev/chainguard/static`. @@ -619,7 +722,7 @@ controller: type: RuntimeDefault capabilities: drop: - - ALL + - ALL readOnlyRootFilesystem: true resources: {} admissionWebhooks: @@ -670,7 +773,7 @@ controller: type: RuntimeDefault capabilities: drop: - - ALL + - ALL readOnlyRootFilesystem: true resources: {} # limits: @@ -690,7 +793,7 @@ controller: type: RuntimeDefault capabilities: drop: - - ALL + - ALL readOnlyRootFilesystem: true resources: {} patch: @@ -701,8 +804,8 @@ 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: v20231011-8b53cabe0 - digest: sha256:a7943503b45d552785aa3b5e457f169a5661fb94d82b8a3373bcd9ebaf9aac80 + tag: v1.4.1 + digest: sha256:36d05b4077fb8e3d13663702fa337f124675ba8667cbd949c03a8e8ea6fa4366 pullPolicy: IfNotPresent # -- Provide a priority class name to the webhook patching job ## @@ -719,6 +822,18 @@ controller: 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 @@ -758,6 +873,7 @@ controller: serviceMonitor: enabled: false additionalLabels: {} + annotations: {} ## The label to use to retrieve the job name from. ## jobLabel: "app.kubernetes.io/name" namespace: "" @@ -895,7 +1011,68 @@ defaultBackend: # 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 @@ -931,21 +1108,21 @@ defaultBackend: ## Additional volumes to the default backend pod. # - name: copy-portal-skins # emptyDir: {} + extraConfigMaps: [] - ## Additional configmaps to the default backend pod. - # Example ConfigMap, uncomment and configure as needed - # - 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: | - # + ## 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: {} @@ -996,13 +1173,13 @@ imagePullSecrets: [] ## Ref: https://github.com/kubernetes/ingress-nginx/blob/main/docs/user-guide/exposing-tcp-udp-services.md ## tcp: {} -# 8080: "default/example-tcp-svc:9000" +# "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" +# "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 diff --git a/packages/system/ingress-nginx/values.yaml b/packages/system/ingress-nginx/values.yaml index 16018ed0..f355dd48 100644 --- a/packages/system/ingress-nginx/values.yaml +++ b/packages/system/ingress-nginx/values.yaml @@ -5,8 +5,8 @@ ingress-nginx: image: registry: ghcr.io image: kvaps/ingress-nginx-with-protobuf-exporter/controller - tag: v1.8.1 - digest: "sha256:7933a0729c716a8bf879218451ff43ee9c1a8f4850feffb12f81eb9439aefc23" + tag: v1.11.1 + digest: sha256:76ca6d7898445140785091ff4a2b21df8c2b50fd1922fff6bd5118af75d33ab2 allowSnippetAnnotations: true replicaCount: 2 admissionWebhooks: @@ -16,7 +16,7 @@ ingress-nginx: enabled: true extraContainers: - name: protobuf-exporter - image: ghcr.io/kvaps/ingress-nginx-with-protobuf-exporter/protobuf-exporter:v1.8.1@sha256:9b6f3f2688592a0f25038bc15e107642d7374359cbd87442920df1c45f27fe4d + image: ghcr.io/kvaps/ingress-nginx-with-protobuf-exporter/protobuf-exporter:v1.11.1@sha256:82abdc9ab80b406dbeb8cd43fd8759b25c5ea77eb95f924bedc61453b9a3f693 args: - --server.telemetry-address=0.0.0.0:9090 - --server.exporter-address=0.0.0.0:9091 diff --git a/packages/system/kubeovn/images/kubeovn.json b/packages/system/kubeovn/images/kubeovn.json index 3c163b02..02e20ede 100644 --- a/packages/system/kubeovn/images/kubeovn.json +++ b/packages/system/kubeovn/images/kubeovn.json @@ -5,13 +5,13 @@ { "uri": "pkg:docker/kubeovn/kube-ovn-base@v1.13.0?platform=linux%2Famd64", "digest": { - "sha256": "b383903ab2427169bfd27ac49ec1f835e01be552dd391aae92a63d6a5d04f05d" + "sha256": "789041d6e02edaa9a28f9385e2175d47cecd564d163e7a0fb89d225de8ada2a2" } }, { "uri": "pkg:docker/golang@1.22-bookworm?platform=linux%2Famd64", "digest": { - "sha256": "6c2780255bb7b881e904e303be0d7a079054160b2ce1efde446693c0850a39ad" + "sha256": "800e361142daeb47b5e5bce2ede55be8d67159be75748cb31cbb48798ebec39d" } } ], @@ -35,7 +35,17 @@ } } }, - "buildx.build.ref": "amd64/amd64/59sogfe3191kwbdbmplhsarwj", - "containerimage.config.digest": "sha256:c60b915c03796938fee46e305997e540bd71f688f9f6b7c4b5846168501768fb", - "containerimage.digest": "sha256:731d2f079c6ef243731f2f7fd70f36b4da4c50626622b496241ecfe9f98913c0" + "buildx.build.ref": "mybuild/mybuild0/sgrxqzg8w1l4zxyi2tpcluk8p", + "containerimage.config.digest": "sha256:7bdcdea14eb90de0b87b53e79e1b1fbe35ead5be316a7b4f83859454cb5506af", + "containerimage.descriptor": { + "mediaType": "application/vnd.docker.distribution.manifest.v2+json", + "digest": "sha256:89cac6416d9a8bae534d1f5276b0d0a399e873d6b919bb6a3ad780ecf71c8b81", + "size": 4621, + "platform": { + "architecture": "amd64", + "os": "linux" + } + }, + "containerimage.digest": "sha256:89cac6416d9a8bae534d1f5276b0d0a399e873d6b919bb6a3ad780ecf71c8b81", + "image.name": "ghcr.io/aenix-io/cozystack/kubeovn:v1.13.0,ghcr.io/aenix-io/cozystack/kubeovn:v1.13.0-v0.10.0" } \ No newline at end of file diff --git a/packages/system/nats/Chart.yaml b/packages/system/nats/Chart.yaml new file mode 100644 index 00000000..25947dad --- /dev/null +++ b/packages/system/nats/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: cozy-nats +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/nats/Makefile b/packages/system/nats/Makefile new file mode 100644 index 00000000..738b387d --- /dev/null +++ b/packages/system/nats/Makefile @@ -0,0 +1,5 @@ +update: + rm -rf charts + helm repo add nats https://nats-io.github.io/k8s/helm/charts/ + helm repo update nats + helm pull nats/nats --untar --untardir charts diff --git a/packages/system/nats/charts/nats/.helmignore b/packages/system/nats/charts/nats/.helmignore new file mode 100644 index 00000000..240dfde2 --- /dev/null +++ b/packages/system/nats/charts/nats/.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 +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ + +# template tests +/test diff --git a/packages/system/nats/charts/nats/Chart.yaml b/packages/system/nats/charts/nats/Chart.yaml new file mode 100644 index 00000000..e59601a9 --- /dev/null +++ b/packages/system/nats/charts/nats/Chart.yaml @@ -0,0 +1,16 @@ +apiVersion: v2 +appVersion: 2.10.17 +description: A Helm chart for the NATS.io High Speed Cloud Native Distributed Communications + Technology. +home: http://github.com/nats-io/k8s +icon: https://nats.io/img/nats-icon-color.png +keywords: +- nats +- messaging +- cncf +maintainers: +- email: info@nats.io + name: The NATS Authors + url: https://github.com/nats-io +name: nats +version: 1.2.1 diff --git a/packages/system/nats/charts/nats/README.md b/packages/system/nats/charts/nats/README.md new file mode 100644 index 00000000..0916999d --- /dev/null +++ b/packages/system/nats/charts/nats/README.md @@ -0,0 +1,329 @@ +# NATS Server + +--- + +[NATS](https://nats.io) is a simple, secure and performant communications system for digital systems, services and devices. +NATS is part of the Cloud Native Computing Foundation ([CNCF](https://cncf.io)). +NATS has over [30 client language implementations](https://nats.io/download/), and its server can run on-premise, in the cloud, at the edge, and even on a Raspberry Pi. +NATS can secure and simplify design and operation of modern distributed systems. + +```shell +helm repo add nats https://nats-io.github.io/k8s/helm/charts/ +helm upgrade --install nats nats/nats +``` + +## Upgrade Nodes + +- **Upgrading from 0.x**: The `values.yaml` schema changed significantly from 0.x to 1.x. Read [UPGRADING.md](UPGRADING.md) for instructions on upgrading a 0.x release to 1.x. + +## Values + +There are a handful of explicitly defined options which are documented with comments in the [values.yaml](values.yaml) file. + +Everything in the NATS Config or Kubernetes Resources can be overridden by `merge` and `patch`, which is supported for the following values: + +| key | type | enabled by default | +|----------------------------------|-----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------| +| `config` | [NATS Config](https://docs.nats.io/running-a-nats-service/configuration) | yes | +| `config.cluster` | [NATS Cluster](https://docs.nats.io/running-a-nats-service/configuration/clustering/cluster_config) | no | +| `config.cluster.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no | +| `config.jetstream` | [NATS JetStream](https://docs.nats.io/running-a-nats-service/configuration#jetstream) | no | +| `config.jetstream.fileStore.pvc` | [k8s PVC](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core) | yes, when `config.jetstream` is enabled | +| `config.nats.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no | +| `config.leafnodes` | [NATS LeafNodes](https://docs.nats.io/running-a-nats-service/configuration/leafnodes/leafnode_conf) | no | +| `config.leafnodes.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no | +| `config.websocket` | [NATS WebSocket](https://docs.nats.io/running-a-nats-service/configuration/websocket/websocket_conf) | no | +| `config.websocket.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no | +| `config.websocket.ingress` | [k8s Ingress](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#ingress-v1-networking-k8s-io) | no | +| `config.mqtt` | [NATS MQTT](https://docs.nats.io/running-a-nats-service/configuration/mqtt/mqtt_config) | no | +| `config.mqtt.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no | +| `config.gateway` | [NATS Gateway](https://docs.nats.io/running-a-nats-service/configuration/gateways/gateway#gateway-configuration-block) | no | +| `config.gateway.tls` | [NATS TLS](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls) | no | +| `config.resolver` | [NATS Resolver](https://docs.nats.io/running-a-nats-service/configuration/securing_nats/auth_intro/jwt/resolver) | no | +| `config.resolver.pvc` | [k8s PVC](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core) | yes, when `config.resolver` is enabled | +| `container` | nats [k8s Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core) | yes | +| `reloader` | config reloader [k8s Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core) | yes | +| `promExporter` | prometheus exporter [k8s Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core) | no | +| `promExporter.podMonitor` | [prometheus PodMonitor](https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.PodMonitor) | no | +| `service` | [k8s Service](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core) | yes | +| `statefulSet` | [k8s StatefulSet](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#statefulset-v1-apps) | yes | +| `podTemplate` | [k8s PodTemplate](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core) | yes | +| `headlessService` | [k8s Service](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core) | yes | +| `configMap` | [k8s ConfigMap](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#configmap-v1-core) | yes | +| `natsBox.contexts.default` | [NATS Context](https://docs.nats.io/using-nats/nats-tools/nats_cli#nats-contexts) | yes | +| `natsBox.contexts.[name]` | [NATS Context](https://docs.nats.io/using-nats/nats-tools/nats_cli#nats-contexts) | no | +| `natsBox.container` | nats-box [k8s Container](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core) | yes | +| `natsBox.deployment` | [k8s Deployment](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#deployment-v1-apps) | yes | +| `natsBox.podTemplate` | [k8s PodTemplate](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core) | yes | +| `natsBox.contextsSecret` | [k8s Secret](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core) | yes | +| `natsBox.contentsSecret` | [k8s Secret](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core) | yes | + +### Merge + +Merging is performed using the Helm `merge` function. Example - add NATS accounts and container resources: + +```yaml +config: + merge: + accounts: + A: + users: + - {user: a, password: a} + B: + users: + - {user: b, password: b} +natsBox: + contexts: + a: + merge: {user: a, password: a} + b: + merge: {user: b, password: b} + defaultContextName: a +``` + +## Patch + +Patching is performed using [JSON Patch](https://jsonpatch.com/). Example - add additional route to end of route list: + +```yaml +config: + cluster: + enabled: true + patch: + - op: add + path: /routes/- + value: nats://demo.nats.io:6222 +``` + +## Common Configurations + +### JetStream Cluster on 3 separate hosts + +```yaml +config: + cluster: + enabled: true + replicas: 3 + jetstream: + enabled: true + fileStore: + pvc: + size: 10Gi + +podTemplate: + topologySpreadConstraints: + kubernetes.io/hostname: + maxSkew: 1 + whenUnsatisfiable: DoNotSchedule +``` + +### NATS Container Resources + +```yaml +container: + env: + # different from k8s units, suffix must be B, KiB, MiB, GiB, or TiB + # should be ~90% of memory limit + GOMEMLIMIT: 7GiB + merge: + # recommended limit is at least 2 CPU cores and 8Gi Memory for production JetStream clusters + resources: + requests: + cpu: "2" + memory: 8Gi + limits: + cpu: "2" + memory: 8Gi +``` + +### Specify Image Version + +```yaml +container: + image: + tag: x.y.z-alpine +``` + +### Operator Mode with NATS Resolver + +Run `nsc generate config --nats-resolver` and replace the `OPERATOR_JWT`, `SYS_ACCOUNT_ID`, and `SYS_ACCOUNT_JWT` with your values. +Make sure that you do not include the trailing `,` in the `SYS_ACCOUNT_JWT`. + +``` +config: + resolver: + enabled: true + merge: + type: full + interval: 2m + timeout: 1.9s + merge: + operator: OPERATOR_JWT + system_account: SYS_ACCOUNT_ID + resolver_preload: + SYS_ACCOUNT_ID: SYS_ACCOUNT_JWT +``` + + +## Accessing NATS + +The chart contains 2 services by default, `service` and `headlessService`. + +### `service` + +The `service` is intended to be accessed by NATS Clients. It is a `ClusterIP` service by default, however it can easily be changed to a different service type. + +The `nats`, `websocket`, `leafnodes`, and `mqtt` ports will be exposed through this service by default if they are enabled. + +Example: change this service type to a `LoadBalancer`: + +```yaml +service: + merge: + spec: + type: LoadBalancer +``` + +### `headlessService` + +The `headlessService` is used for NATS Servers in the Stateful Set to discover one another. It is primarily intended to be used for Cluster Route connections. + +### TLS Considerations + +The TLS Certificate used for Client Connections should have a SAN covering DNS Name that clients access the `service` at. + +The TLS Certificate used for Cluster Route Connections should have a SAN covering the DNS Name that routes access each other on the `headlessService` at. This is `*.` by default. + +## Advanced Features + +### Templating Values + +Anything in `values.yaml` can be templated: + +- maps matching the following syntax will be templated and parsed as YAML: + ```yaml + $tplYaml: | + yaml template + ``` +- maps matching the follow syntax will be templated, parsed as YAML, and spread into the parent map/slice + ```yaml + $tplYamlSpread: | + yaml template + ``` + +Example - change service name: + +```yaml +service: + name: + $tplYaml: >- + {{ include "nats.fullname" . }}-svc +``` + +### NATS Config Units and Variables + +NATS configuration extends JSON, and can represent Units and Variables. They must be wrapped in `<< >>` in order to template correctly. Example: + +```yaml +config: + merge: + authorization: + # variable + token: << $TOKEN >> + # units + max_payload: << 2MB >> +``` + +templates to the `nats.conf`: + +``` +{ + "authorization": { + "token": $TOKEN + }, + "max_payload": 2MB, + "port": 4222, + ... +} +``` + +### NATS Config Includes + +Any NATS Config key ending in `$include` will be replaced with an include directive. Included files should be in paths relative to `/etc/nats-config`. Multiple `$include` keys are supported by using a prefix, and will be sorted alphabetically. Example: + +```yaml +config: + merge: + 00$include: auth.conf + 01$include: params.conf +configMap: + merge: + data: + auth.conf: | + accounts: { + A: { + users: [ + {user: a, password: a} + ] + }, + B: { + users: [ + {user: b, password: b} + ] + }, + } + params.conf: | + max_payload: 2MB +``` + +templates to the `nats.conf`: + +``` +include auth.conf; +"port": 4222, +... +include params.conf; +``` + +### Extra Resources + +Enables adding additional arbitrary resources. Example - expose WebSocket via VirtualService in Istio: + +```yaml +config: + websocket: + enabled: true +extraResources: +- apiVersion: networking.istio.io/v1beta1 + kind: VirtualService + metadata: + namespace: + $tplYamlSpread: > + {{ include "nats.metadataNamespace" $ }} + name: + $tplYaml: > + {{ include "nats.fullname" $ | quote }} + labels: + $tplYaml: | + {{ include "nats.labels" $ }} + spec: + hosts: + - demo.nats.io + gateways: + - my-gateway + http: + - name: default + match: + - name: root + uri: + exact: / + route: + - destination: + host: + $tplYaml: > + {{ .Values.service.name | quote }} + port: + number: + $tplYaml: > + {{ .Values.config.websocket.port }} +``` diff --git a/packages/system/nats/charts/nats/UPGRADING.md b/packages/system/nats/charts/nats/UPGRADING.md new file mode 100644 index 00000000..9cc17799 --- /dev/null +++ b/packages/system/nats/charts/nats/UPGRADING.md @@ -0,0 +1,155 @@ +# Upgrading from 0.x to 1.x + +Instructions for upgrading an existing `nats` 0.x release to 1.x. + +## Rename Immutable Fields + +There are a number of immutable fields in the NATS Stateful Set and NATS Box deployment. All 1.x `values.yaml` files targeting an existing 0.x release will require some or all of these settings: + +```yaml +config: + # required if using JetStream file storage + jetstream: + # uncomment the next line if using JetStream file storage + # enabled: true + fileStore: + pvc: + name: + $tplYaml: >- + {{ include "nats.fullname" . }}-js-pvc + # set other PVC options here to make it match 0.x, refer to values.yaml for schema + + # required if using a full or cache resolver + resolver: + # uncomment the next line if using a full or cache resolver + # enabled: true + pvc: + name: nats-jwt-pvc + # set other PVC options here to make it match 0.x, refer to values.yaml for schema + +# required +statefulSet: + patch: + - op: remove + path: /spec/selector/matchLabels/app.kubernetes.io~1component + - $tplYamlSpread: |- + {{- if and + .Values.config.jetstream.enabled + .Values.config.jetstream.fileStore.enabled + .Values.config.jetstream.fileStore.pvc.enabled + .Values.config.resolver.enabled + .Values.config.resolver.pvc.enabled + }} + - op: move + from: /spec/volumeClaimTemplates/0 + path: /spec/volumeClaimTemplates/1 + {{- else}} + [] + {{- end }} + +# required +headlessService: + name: + $tplYaml: >- + {{ include "nats.fullname" . }} + +# required unless 0.x values explicitly set nats.serviceAccount.create=false +serviceAccount: + enabled: true + +# required to use new ClusterIP service for Clients accessing NATS +# if using TLS, this may require adding another SAN +service: + # uncomment the next line to disable the new ClusterIP service + # enabled: false + name: + $tplYaml: >- + {{ include "nats.fullname" . }}-svc + +# required if using NatsBox +natsBox: + deployment: + patch: + - op: replace + path: /spec/selector/matchLabels + value: + app: nats-box + - op: add + path: /spec/template/metadata/labels/app + value: nats-box +``` + +## Update NATS Config to new values.yaml schema + +Most values that control the NATS Config have changed and moved under the `config` key. Refer to the 1.x Chart's [values.yaml](values.yaml) for the complete schema. + +After migrating to the new values schema, ensure that changes you expect in the NATS Config files match by templating the old and new config files. + +Template your old 0.x Config Map, this example uses a file called `values-old.yaml`: + +```sh +helm template \ + --version "0.x" \ + -f values-old.yaml \ + -s templates/configmap.yaml \ + nats \ + nats/nats +``` + +Template your new 1.x Config Map, this example uses a file called `values.yaml`: + +```sh +helm template \ + --version "^1-beta" \ + -f values.yaml \ + -s templates/config-map.yaml \ + nats \ + nats/nats +``` + +## Update Kubernetes Resources to new values.yaml schema + +Most values that control Kubernetes Resources have been changed. Refer to the 1.x Chart's [values.yaml](values.yaml) for the complete schema. + +After migrating to the new values schema, ensure that changes you expect in resources match by templating the old and new resources. + +| Resource | 0.x Template File | 1.x Template File | +|-------------------------|---------------------------------|-------------------------------------------| +| Config Map | `templates/configmap.yaml` | `templates/config-map.yaml` | +| Stateful Set | `templates/statefulset.yaml` | `templates/stateful-set.yaml` | +| Headless Service | `templates/service.yaml` | `templates/headless-service.yaml` | +| ClusterIP Service | N/A | `templates/service.yaml` | +| Network Policy | `templates/networkpolicy.yaml` | N/A | +| Pod Disruption Budget | `templates/pdb.yaml` | `templates/pod-disruption-budget.yaml` | +| Service Account | `templates/rbac.yaml` | `templates/service-account.yaml` | +| Resource | `templates/` | `templates/` | +| Resource | `templates/` | `templates/` | +| Prometheus Monitor | `templates/serviceMonitor.yaml` | `templates/pod-monitor.yaml` | +| NatsBox Deployment | `templates/nats-box.yaml` | `templates/nats-box/deployment.yaml` | +| NatsBox Service Account | N/A | `templates/nats-box/service-account.yaml` | +| NatsBox Contents Secret | N/A | `templates/nats-box/contents-secret.yaml` | +| NatsBox Contexts Secret | N/A | `templates/nats-box/contexts-secret.yaml` | + +For example, to check that the Stateful Set matches: + +Template your old 0.x Stateful Set, this example uses a file called `values-old.yaml`: + +```sh +helm template \ + --version "0.x" \ + -f values-old.yaml \ + -s templates/statefulset.yaml \ + nats \ + nats/nats +``` + +Template your new 1.x Stateful Set, this example uses a file called `values.yaml`: + +```sh +helm template \ + --version "^1-beta" \ + -f values.yaml \ + -s templates/stateful-set.yaml \ + nats \ + nats/nats +``` diff --git a/packages/system/nats/charts/nats/files/config-map.yaml b/packages/system/nats/charts/nats/files/config-map.yaml new file mode 100644 index 00000000..89ee3c28 --- /dev/null +++ b/packages/system/nats/charts/nats/files/config-map.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.configMap.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +data: + nats.conf: | + {{- include "nats.formatConfig" .config | nindent 4 }} diff --git a/packages/system/nats/charts/nats/files/config/cluster.yaml b/packages/system/nats/charts/nats/files/config/cluster.yaml new file mode 100644 index 00000000..719cb8ad --- /dev/null +++ b/packages/system/nats/charts/nats/files/config/cluster.yaml @@ -0,0 +1,32 @@ +{{- with .Values.config.cluster }} +name: {{ $.Values.statefulSet.name }} +port: {{ .port }} +no_advertise: true +routes: +{{- $proto := ternary "tls" "nats" .tls.enabled }} +{{- $auth := "" }} +{{- if and .routeURLs.user .routeURLs.password }} + {{- $auth = printf "%s:%s@" (urlquery .routeURLs.user) (urlquery .routeURLs.password) -}} +{{- end }} +{{- $domain := $.Values.headlessService.name }} +{{- if .routeURLs.useFQDN }} + {{- $domain = printf "%s.%s.svc.%s" $domain (include "nats.namespace" $) .routeURLs.k8sClusterDomain }} +{{- end }} +{{- $port := (int .port) }} +{{- range $i, $_ := until (int .replicas) }} +- {{ printf "%s://%s%s-%d.%s:%d" $proto $auth $.Values.statefulSet.name $i $domain $port }} +{{- end }} + +{{- if and .routeURLs.user .routeURLs.password }} +authorization: + user: {{ .routeURLs.user | quote }} + password: {{ .routeURLs.password | quote }} +{{- end }} + +{{- with .tls }} +{{- if .enabled }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/config/config.yaml b/packages/system/nats/charts/nats/files/config/config.yaml new file mode 100644 index 00000000..92fd96f1 --- /dev/null +++ b/packages/system/nats/charts/nats/files/config/config.yaml @@ -0,0 +1,114 @@ +{{- with .Values.config }} + +server_name: << $SERVER_NAME >> +lame_duck_grace_period: 10s +lame_duck_duration: 30s +pid_file: /var/run/nats/nats.pid + +######################################## +# NATS +######################################## +{{- with .nats }} +port: {{ .port }} + +{{- with .tls }} +{{- if .enabled }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} + +######################################## +# leafnodes +######################################## +{{- with .leafnodes }} +{{- if .enabled }} +leafnodes: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/leafnodes.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +######################################## +# websocket +######################################## +{{- with .websocket }} +{{- if .enabled }} +websocket: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/websocket.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +######################################## +# MQTT +######################################## +{{- with .mqtt }} +{{- if .enabled }} +mqtt: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/mqtt.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +######################################## +# cluster +######################################## +{{- with .cluster }} +{{- if .enabled }} +cluster: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/cluster.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +######################################## +# gateway +######################################## +{{- with .gateway }} +{{- if .enabled }} +gateway: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/gateway.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +######################################## +# monitor +######################################## +{{- with .monitor }} +{{- if .enabled }} +{{- if .tls.enabled }} +https_port: {{ .port }} +{{- else }} +http_port: {{ .port }} +{{- end }} +{{- end }} +{{- end }} + +######################################## +# profiling +######################################## +{{- with .profiling }} +{{- if .enabled }} +prof_port: {{ .port }} +{{- end }} +{{- end }} + +######################################## +# jetstream +######################################## +{{- with $.Values.config.jetstream -}} +{{- if .enabled }} +jetstream: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/jetstream.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +######################################## +# resolver +######################################## +{{- with $.Values.config.resolver -}} +{{- if .enabled }} +resolver: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/resolver.yaml" "ctx" $) .) | nindent 2 }} +{{- end }} +{{- end }} + +{{- end }} diff --git a/packages/system/nats/charts/nats/files/config/gateway.yaml b/packages/system/nats/charts/nats/files/config/gateway.yaml new file mode 100644 index 00000000..32d4ed9f --- /dev/null +++ b/packages/system/nats/charts/nats/files/config/gateway.yaml @@ -0,0 +1,11 @@ +{{- with .Values.config.gateway }} +name: {{ $.Values.statefulSet.name }} +port: {{ .port }} + +{{- with .tls }} +{{- if .enabled }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/config/jetstream.yaml b/packages/system/nats/charts/nats/files/config/jetstream.yaml new file mode 100644 index 00000000..17262f64 --- /dev/null +++ b/packages/system/nats/charts/nats/files/config/jetstream.yaml @@ -0,0 +1,23 @@ +{{- with .Values.config.jetstream }} +{{- with .memoryStore }} +{{- if .enabled }} +{{- with .maxSize }} +max_memory_store: << {{ . }} >> +{{- end }} +{{- else }} +max_memory_store: 0 +{{- end }} +{{- end }} +{{- with .fileStore }} +{{- if .enabled }} +store_dir: {{ .dir }} +{{- if .maxSize }} +max_file_store: << {{ .maxSize }} >> +{{- else if .pvc.enabled }} +max_file_store: << {{ .pvc.size }} >> +{{- end }} +{{- else }} +max_file_store: 0 +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/config/leafnodes.yaml b/packages/system/nats/charts/nats/files/config/leafnodes.yaml new file mode 100644 index 00000000..3a1d9a14 --- /dev/null +++ b/packages/system/nats/charts/nats/files/config/leafnodes.yaml @@ -0,0 +1,11 @@ +{{- with .Values.config.leafnodes }} +port: {{ .port }} +no_advertise: true + +{{- with .tls }} +{{- if .enabled }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/config/mqtt.yaml b/packages/system/nats/charts/nats/files/config/mqtt.yaml new file mode 100644 index 00000000..e25d8a3e --- /dev/null +++ b/packages/system/nats/charts/nats/files/config/mqtt.yaml @@ -0,0 +1,10 @@ +{{- with .Values.config.mqtt }} +port: {{ .port }} + +{{- with .tls }} +{{- if .enabled }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/config/protocol.yaml b/packages/system/nats/charts/nats/files/config/protocol.yaml new file mode 100644 index 00000000..288c80d7 --- /dev/null +++ b/packages/system/nats/charts/nats/files/config/protocol.yaml @@ -0,0 +1,10 @@ +{{- with .protocol }} +port: {{ .port }} + +{{- with .tls }} +{{- if .enabled }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/config/resolver.yaml b/packages/system/nats/charts/nats/files/config/resolver.yaml new file mode 100644 index 00000000..a6761c40 --- /dev/null +++ b/packages/system/nats/charts/nats/files/config/resolver.yaml @@ -0,0 +1,3 @@ +{{- with .Values.config.resolver }} +dir: {{ .dir }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/config/tls.yaml b/packages/system/nats/charts/nats/files/config/tls.yaml new file mode 100644 index 00000000..26aee015 --- /dev/null +++ b/packages/system/nats/charts/nats/files/config/tls.yaml @@ -0,0 +1,16 @@ +# tls +{{- with .tls }} +{{- if .secretName }} +{{- $dir := trimSuffix "/" .dir }} +cert_file: {{ printf "%s/%s" $dir (.cert | default "tls.crt") | quote }} +key_file: {{ printf "%s/%s" $dir (.key | default "tls.key") | quote }} +{{- end }} +{{- end }} + +# tlsCA +{{- with $.Values.tlsCA }} +{{- if and .enabled (or .configMapName .secretName) }} +{{- $dir := trimSuffix "/" .dir }} +ca_file: {{ printf "%s/%s" $dir (.key | default "ca.crt") | quote }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/config/websocket.yaml b/packages/system/nats/charts/nats/files/config/websocket.yaml new file mode 100644 index 00000000..afcd178a --- /dev/null +++ b/packages/system/nats/charts/nats/files/config/websocket.yaml @@ -0,0 +1,12 @@ +{{- with .Values.config.websocket }} +port: {{ .port }} + +{{- if .tls.enabled }} +{{- with .tls }} +tls: + {{- include "nats.loadMergePatch" (merge (dict "file" "config/tls.yaml" "ctx" (merge (dict "tls" .) $)) .) | nindent 2 }} +{{- end }} +{{- else }} +no_tls: true +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/headless-service.yaml b/packages/system/nats/charts/nats/files/headless-service.yaml new file mode 100644 index 00000000..da6552b3 --- /dev/null +++ b/packages/system/nats/charts/nats/files/headless-service.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: Service +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.headlessService.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +spec: + selector: + {{- include "nats.selectorLabels" $ | nindent 4 }} + clusterIP: None + publishNotReadyAddresses: true + ports: + {{- range $protocol := list "nats" "leafnodes" "websocket" "mqtt" "cluster" "gateway" "monitor" "profiling" }} + {{- $configProtocol := get $.Values.config $protocol }} + {{- if or (eq $protocol "nats") $configProtocol.enabled }} + {{- $tlsEnabled := false }} + {{- if hasKey $configProtocol "tls" }} + {{- $tlsEnabled = $configProtocol.tls.enabled }} + {{- end }} + {{- $appProtocol := or (eq $protocol "websocket") (eq $protocol "monitor") | ternary ($tlsEnabled | ternary "https" "http") ($tlsEnabled | ternary "tls" "tcp") }} + - {{ dict "name" $protocol "port" $configProtocol.port "targetPort" $protocol "appProtocol" $appProtocol | toYaml | nindent 4 }} + {{- end }} + {{- end }} diff --git a/packages/system/nats/charts/nats/files/ingress.yaml b/packages/system/nats/charts/nats/files/ingress.yaml new file mode 100644 index 00000000..b59f0fa5 --- /dev/null +++ b/packages/system/nats/charts/nats/files/ingress.yaml @@ -0,0 +1,34 @@ +{{- with .Values.config.websocket.ingress }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +spec: + {{- with .className }} + ingressClassName: {{ . | quote }} + {{- end }} + rules: + {{- $path := .path }} + {{- $pathType := .pathType }} + {{- range .hosts }} + - host: {{ . | quote }} + http: + paths: + - path: {{ $path | quote }} + pathType: {{ $pathType | quote }} + backend: + service: + name: {{ $.Values.service.name }} + port: + name: websocket + {{- end }} + {{- if .tlsSecretName }} + tls: + - secretName: {{ .tlsSecretName | quote }} + hosts: + {{- toYaml .hosts | nindent 4 }} + {{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/nats-box/contents-secret.yaml b/packages/system/nats/charts/nats/files/nats-box/contents-secret.yaml new file mode 100644 index 00000000..6e8fdb26 --- /dev/null +++ b/packages/system/nats/charts/nats/files/nats-box/contents-secret.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Secret +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.natsBox.contentsSecret.name }} + labels: + {{- include "natsBox.labels" $ | nindent 4 }} +type: Opaque +stringData: + {{- range $ctxKey, $ctxVal := .Values.natsBox.contexts }} + {{- range $secretKey, $secretVal := dict "creds" "creds" "nkey" "nk" }} + {{- $secret := get $ctxVal $secretKey }} + {{- if and $secret $secret.contents }} + "{{ $ctxKey }}.{{ $secretVal }}": {{ $secret.contents | quote }} + {{- end }} + {{- end }} + {{- end }} diff --git a/packages/system/nats/charts/nats/files/nats-box/contexts-secret/context.yaml b/packages/system/nats/charts/nats/files/nats-box/contexts-secret/context.yaml new file mode 100644 index 00000000..54480eac --- /dev/null +++ b/packages/system/nats/charts/nats/files/nats-box/contexts-secret/context.yaml @@ -0,0 +1,51 @@ +{{- $contextName := .contextName }} + +# url +{{- if .Values.service.enabled }} +url: nats://{{ .Values.service.name }} +{{- else }} +url: nats://{{ .Values.headlessService.name }} +{{- end }} + +{{- with .context }} + +# creds +{{- with .creds}} +{{- if .contents }} +creds: /etc/nats-contents/{{ $contextName }}.creds +{{- else if .secretName }} +{{- $dir := trimSuffix "/" .dir }} +creds: {{ printf "%s/%s" $dir (.key | default "nats.creds") | quote }} +{{- end }} +{{- end }} + +# nkey +{{- with .nkey}} +{{- if .contents }} +nkey: /etc/nats-contents/{{ $contextName }}.nk +{{- else if .secretName }} +{{- $dir := trimSuffix "/" .dir }} +nkey: {{ printf "%s/%s" $dir (.key | default "nats.nk") | quote }} +{{- end }} +{{- end }} + +# tls +{{- with .tls }} +{{- if .secretName }} +{{- $dir := trimSuffix "/" .dir }} +cert: {{ printf "%s/%s" $dir (.cert | default "tls.crt") | quote }} +key: {{ printf "%s/%s" $dir (.key | default "tls.key") | quote }} +{{- end }} +{{- end }} + +# tlsCA +{{- if $.Values.config.nats.tls.enabled }} +{{- with $.Values.tlsCA }} +{{- if and .enabled (or .configMapName .secretName) }} +{{- $dir := trimSuffix "/" .dir }} +ca: {{ printf "%s/%s" $dir (.key | default "ca.crt") | quote }} +{{- end }} +{{- end }} +{{- end }} + +{{- end }} diff --git a/packages/system/nats/charts/nats/files/nats-box/contexts-secret/contexts-secret.yaml b/packages/system/nats/charts/nats/files/nats-box/contexts-secret/contexts-secret.yaml new file mode 100644 index 00000000..0ce8d1d8 --- /dev/null +++ b/packages/system/nats/charts/nats/files/nats-box/contexts-secret/contexts-secret.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Secret +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.natsBox.contextsSecret.name }} + labels: + {{- include "natsBox.labels" $ | nindent 4 }} +type: Opaque +stringData: +{{- range $ctxKey, $ctxVal := .Values.natsBox.contexts }} + "{{ $ctxKey }}.json": | + {{- include "toPrettyRawJson" (include "nats.loadMergePatch" (dict "file" "nats-box/contexts-secret/context.yaml" "merge" (.merge | default dict) "patch" (.patch | default list) "ctx" (merge (dict "contextName" $ctxKey "context" $ctxVal) $)) | fromYaml) | nindent 4 }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/nats-box/deployment/container.yaml b/packages/system/nats/charts/nats/files/nats-box/deployment/container.yaml new file mode 100644 index 00000000..aa1753b4 --- /dev/null +++ b/packages/system/nats/charts/nats/files/nats-box/deployment/container.yaml @@ -0,0 +1,46 @@ +name: nats-box +{{ include "nats.image" (merge (pick $.Values "global") .Values.natsBox.container.image) }} + +{{- with .Values.natsBox.container.env }} +env: +{{- include "nats.env" . }} +{{- end }} + +command: +- sh +- -ec +- | + work_dir="$(pwd)" + mkdir -p "$XDG_CONFIG_HOME/nats" + cd "$XDG_CONFIG_HOME/nats" + if ! [ -s context ]; then + ln -s /etc/nats-contexts context + fi + {{- if .Values.natsBox.defaultContextName }} + if ! [ -f context.txt ]; then + echo -n {{ .Values.natsBox.defaultContextName | quote }} > context.txt + fi + {{- end }} + cd "$work_dir" + exec /entrypoint.sh "$@" +- -- +args: +- sh +- -ec +- trap true INT TERM; sleep infinity & wait +volumeMounts: +# contexts secret +- name: contexts + mountPath: /etc/nats-contexts +# contents secret +{{- if .hasContentsSecret }} +- name: contents + mountPath: /etc/nats-contents +{{- end }} +# tlsCA +{{- include "nats.tlsCAVolumeMount" $ }} +# secrets +{{- range (include "natsBox.secretNames" $ | fromJson).secretNames }} +- name: {{ .name | quote }} + mountPath: {{ .dir | quote }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/nats-box/deployment/deployment.yaml b/packages/system/nats/charts/nats/files/nats-box/deployment/deployment.yaml new file mode 100644 index 00000000..bf39dd8d --- /dev/null +++ b/packages/system/nats/charts/nats/files/nats-box/deployment/deployment.yaml @@ -0,0 +1,16 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.natsBox.deployment.name }} + labels: + {{- include "natsBox.labels" $ | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "natsBox.selectorLabels" $ | nindent 6 }} + replicas: 1 + template: + {{- with .Values.natsBox.podTemplate }} + {{ include "nats.loadMergePatch" (merge (dict "file" "nats-box/deployment/pod-template.yaml" "ctx" $) .) | nindent 4 }} + {{- end }} diff --git a/packages/system/nats/charts/nats/files/nats-box/deployment/pod-template.yaml b/packages/system/nats/charts/nats/files/nats-box/deployment/pod-template.yaml new file mode 100644 index 00000000..71056bfb --- /dev/null +++ b/packages/system/nats/charts/nats/files/nats-box/deployment/pod-template.yaml @@ -0,0 +1,44 @@ +metadata: + labels: + {{- include "natsBox.labels" $ | nindent 4 }} +spec: + containers: + {{- with .Values.natsBox.container }} + - {{ include "nats.loadMergePatch" (merge (dict "file" "nats-box/deployment/container.yaml" "ctx" $) .) | nindent 4 }} + {{- end }} + + # service discovery uses DNS; don't need service env vars + enableServiceLinks: false + + {{- with .Values.global.image.pullSecretNames }} + imagePullSecrets: + {{- range . }} + - name: {{ . | quote }} + {{- end }} + {{- end }} + + {{- with .Values.natsBox.serviceAccount }} + {{- if .enabled }} + serviceAccountName: {{ .name | quote }} + {{- end }} + {{- end }} + + volumes: + # contexts secret + - name: contexts + secret: + secretName: {{ .Values.natsBox.contextsSecret.name }} + # contents secret + {{- if .hasContentsSecret }} + - name: contents + secret: + secretName: {{ .Values.natsBox.contentsSecret.name }} + {{- end }} + # tlsCA + {{- include "nats.tlsCAVolume" $ | nindent 2 }} + # secrets + {{- range (include "natsBox.secretNames" $ | fromJson).secretNames }} + - name: {{ .name | quote }} + secret: + secretName: {{ .secretName | quote }} + {{- end }} diff --git a/packages/system/nats/charts/nats/files/nats-box/service-account.yaml b/packages/system/nats/charts/nats/files/nats-box/service-account.yaml new file mode 100644 index 00000000..c31e52f1 --- /dev/null +++ b/packages/system/nats/charts/nats/files/nats-box/service-account.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.natsBox.serviceAccount.name }} + labels: + {{- include "natsBox.labels" $ | nindent 4 }} diff --git a/packages/system/nats/charts/nats/files/pod-disruption-budget.yaml b/packages/system/nats/charts/nats/files/pod-disruption-budget.yaml new file mode 100644 index 00000000..fd1fdead --- /dev/null +++ b/packages/system/nats/charts/nats/files/pod-disruption-budget.yaml @@ -0,0 +1,12 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.podDisruptionBudget.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +spec: + maxUnavailable: 1 + selector: + matchLabels: + {{- include "nats.selectorLabels" $ | nindent 6 }} diff --git a/packages/system/nats/charts/nats/files/pod-monitor.yaml b/packages/system/nats/charts/nats/files/pod-monitor.yaml new file mode 100644 index 00000000..c6c8eae0 --- /dev/null +++ b/packages/system/nats/charts/nats/files/pod-monitor.yaml @@ -0,0 +1,13 @@ +apiVersion: monitoring.coreos.com/v1 +kind: PodMonitor +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.promExporter.podMonitor.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "nats.selectorLabels" $ | nindent 6 }} + podMetricsEndpoints: + - port: prom-metrics diff --git a/packages/system/nats/charts/nats/files/service-account.yaml b/packages/system/nats/charts/nats/files/service-account.yaml new file mode 100644 index 00000000..22c18cc7 --- /dev/null +++ b/packages/system/nats/charts/nats/files/service-account.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.serviceAccount.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} diff --git a/packages/system/nats/charts/nats/files/service.yaml b/packages/system/nats/charts/nats/files/service.yaml new file mode 100644 index 00000000..db08fe5b --- /dev/null +++ b/packages/system/nats/charts/nats/files/service.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Service +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.service.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +spec: + selector: + {{- include "nats.selectorLabels" $ | nindent 4 }} + ports: + {{- range $protocol := list "nats" "leafnodes" "websocket" "mqtt" "cluster" "gateway" "monitor" "profiling" }} + {{- $configProtocol := get $.Values.config $protocol }} + {{- $servicePort := get $.Values.service.ports $protocol }} + {{- if and (or (eq $protocol "nats") $configProtocol.enabled) $servicePort.enabled }} + {{- $tlsEnabled := false }} + {{- if hasKey $configProtocol "tls" }} + {{- $tlsEnabled = $configProtocol.tls.enabled }} + {{- end }} + {{- $appProtocol := or (eq $protocol "websocket") (eq $protocol "monitor") | ternary ($tlsEnabled | ternary "https" "http") ($tlsEnabled | ternary "tls" "tcp") }} + - {{ merge (dict "name" $protocol "targetPort" $protocol "appProtocol" $appProtocol) (omit $servicePort "enabled") (dict "port" $configProtocol.port) | toYaml | nindent 4 }} + {{- end }} + {{- end }} diff --git a/packages/system/nats/charts/nats/files/stateful-set/jetstream-pvc.yaml b/packages/system/nats/charts/nats/files/stateful-set/jetstream-pvc.yaml new file mode 100644 index 00000000..a43f2005 --- /dev/null +++ b/packages/system/nats/charts/nats/files/stateful-set/jetstream-pvc.yaml @@ -0,0 +1,13 @@ +{{- with .Values.config.jetstream.fileStore.pvc }} +metadata: + name: {{ .name }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .size | quote }} + {{- with .storageClassName }} + storageClassName: {{ . | quote }} + {{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/stateful-set/nats-container.yaml b/packages/system/nats/charts/nats/files/stateful-set/nats-container.yaml new file mode 100644 index 00000000..c5402efe --- /dev/null +++ b/packages/system/nats/charts/nats/files/stateful-set/nats-container.yaml @@ -0,0 +1,106 @@ +name: nats +{{ include "nats.image" (merge (pick $.Values "global") .Values.container.image) }} + +ports: +{{- range $protocol := list "nats" "leafnodes" "websocket" "mqtt" "cluster" "gateway" "monitor" "profiling" }} +{{- $configProtocol := get $.Values.config $protocol }} +{{- $containerPort := get $.Values.container.ports $protocol }} +{{- if or (eq $protocol "nats") $configProtocol.enabled }} +- {{ merge (dict "name" $protocol "containerPort" $configProtocol.port) $containerPort | toYaml | nindent 2 }} +{{- end }} +{{- end }} + +args: +- --config +- /etc/nats-config/nats.conf + +env: +- name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name +- name: SERVER_NAME + value: {{ printf "%s$(POD_NAME)" .Values.config.serverNamePrefix | quote }} +{{- with .Values.container.env }} +{{- include "nats.env" . }} +{{- end }} + +lifecycle: + preStop: + exec: + # send the lame duck shutdown signal to trigger a graceful shutdown + command: + - nats-server + - -sl=ldm=/var/run/nats/nats.pid + +{{- with .Values.config.monitor }} +{{- if .enabled }} +startupProbe: + httpGet: + path: /healthz + port: monitor + {{- if .tls.enabled }} + scheme: HTTPS + {{- end}} + initialDelaySeconds: 10 + timeoutSeconds: 5 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 90 +readinessProbe: + httpGet: + path: /healthz?js-server-only=true + port: monitor + {{- if .tls.enabled }} + scheme: HTTPS + {{- end}} + initialDelaySeconds: 10 + timeoutSeconds: 5 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 +livenessProbe: + httpGet: + path: /healthz?js-enabled-only=true + port: monitor + {{- if .tls.enabled }} + scheme: HTTPS + {{- end}} + initialDelaySeconds: 10 + timeoutSeconds: 5 + periodSeconds: 30 + successThreshold: 1 + failureThreshold: 3 +{{- end }} +{{- end }} + +volumeMounts: +# nats config +- name: config + mountPath: /etc/nats-config +# PID volume +- name: pid + mountPath: /var/run/nats +# JetStream PVC +{{- with .Values.config.jetstream }} +{{- if and .enabled .fileStore.enabled .fileStore.pvc.enabled }} +{{- with .fileStore }} +- name: {{ .pvc.name }} + mountPath: {{ .dir | quote }} +{{- end }} +{{- end }} +{{- end }} +# resolver PVC +{{- with .Values.config.resolver }} +{{- if and .enabled .pvc.enabled }} +- name: {{ .pvc.name }} + mountPath: {{ .dir | quote }} +{{- end }} +{{- end }} +# tlsCA +{{- include "nats.tlsCAVolumeMount" $ }} +# secrets +{{- range (include "nats.secretNames" $ | fromJson).secretNames }} +- name: {{ .name | quote }} + mountPath: {{ .dir | quote }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/stateful-set/pod-template.yaml b/packages/system/nats/charts/nats/files/stateful-set/pod-template.yaml new file mode 100644 index 00000000..bb1d8d7b --- /dev/null +++ b/packages/system/nats/charts/nats/files/stateful-set/pod-template.yaml @@ -0,0 +1,71 @@ +metadata: + labels: + {{- include "nats.labels" $ | nindent 4 }} + annotations: + {{- if .Values.podTemplate.configChecksumAnnotation }} + {{- $configMap := include "nats.loadMergePatch" (merge (dict "file" "config-map.yaml" "ctx" $) $.Values.configMap) }} + checksum/config: {{ sha256sum $configMap }} + {{- end }} +spec: + containers: + # nats + {{- $nats := dict }} + {{- with .Values.container }} + {{- $nats = include "nats.loadMergePatch" (merge (dict "file" "stateful-set/nats-container.yaml" "ctx" $) .) | fromYaml }} + - {{ toYaml $nats | nindent 4 }} + {{- end }} + # reloader + {{- with .Values.reloader }} + {{- if .enabled }} + - {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/reloader-container.yaml" "ctx" (merge (dict "natsVolumeMounts" $nats.volumeMounts) $)) .) | nindent 4 }} + {{- end }} + {{- end }} + {{- with .Values.promExporter }} + {{- if .enabled }} + - {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/prom-exporter-container.yaml" "ctx" $) .) | nindent 4 }} + {{- end }} + {{- end }} + + # service discovery uses DNS; don't need service env vars + enableServiceLinks: false + + {{- with .Values.global.image.pullSecretNames }} + imagePullSecrets: + {{- range . }} + - name: {{ . | quote }} + {{- end }} + {{- end }} + + {{- with .Values.serviceAccount }} + {{- if .enabled }} + serviceAccountName: {{ .name | quote }} + {{- end }} + {{- end }} + + {{- if .Values.reloader.enabled }} + shareProcessNamespace: true + {{- end }} + + volumes: + # nats config + - name: config + configMap: + name: {{ .Values.configMap.name }} + # PID volume + - name: pid + emptyDir: {} + # tlsCA + {{- include "nats.tlsCAVolume" $ | nindent 2 }} + # secrets + {{- range (include "nats.secretNames" $ | fromJson).secretNames }} + - name: {{ .name | quote }} + secret: + secretName: {{ .secretName | quote }} + {{- end }} + + {{- with .Values.podTemplate.topologySpreadConstraints }} + topologySpreadConstraints: + {{- range $k, $v := . }} + - {{ merge (dict "topologyKey" $k "labelSelector" (dict "matchLabels" (include "nats.selectorLabels" $ | fromYaml))) $v | toYaml | nindent 4 }} + {{- end }} + {{- end}} diff --git a/packages/system/nats/charts/nats/files/stateful-set/prom-exporter-container.yaml b/packages/system/nats/charts/nats/files/stateful-set/prom-exporter-container.yaml new file mode 100644 index 00000000..c3e1b6fb --- /dev/null +++ b/packages/system/nats/charts/nats/files/stateful-set/prom-exporter-container.yaml @@ -0,0 +1,30 @@ +name: prom-exporter +{{ include "nats.image" (merge (pick $.Values "global") .Values.promExporter.image) }} + +ports: +- name: prom-metrics + containerPort: {{ .Values.promExporter.port }} + +{{- with .Values.promExporter.env }} +env: +{{- include "nats.env" . }} +{{- end }} + +args: +- -port={{ .Values.promExporter.port }} +- -connz +- -routez +- -subz +- -varz +- -prefix=nats +- -use_internal_server_id +{{- if .Values.config.jetstream.enabled }} +- -jsz=all +{{- end }} +{{- if .Values.config.leafnodes.enabled }} +- -leafz +{{- end }} +{{- if .Values.config.gateway.enabled }} +- -gatewayz +{{- end }} +- http://localhost:{{ .Values.config.monitor.port }}/ diff --git a/packages/system/nats/charts/nats/files/stateful-set/reloader-container.yaml b/packages/system/nats/charts/nats/files/stateful-set/reloader-container.yaml new file mode 100644 index 00000000..96722045 --- /dev/null +++ b/packages/system/nats/charts/nats/files/stateful-set/reloader-container.yaml @@ -0,0 +1,27 @@ +name: reloader +{{ include "nats.image" (merge (pick $.Values "global") .Values.reloader.image) }} + +{{- with .Values.reloader.env }} +env: +{{- include "nats.env" . }} +{{- end }} + +args: +- -pid +- /var/run/nats/nats.pid +- -config +- /etc/nats-config/nats.conf +{{ include "nats.reloaderConfig" (dict "config" .config "dir" "/etc/nats-config") }} + +volumeMounts: +- name: pid + mountPath: /var/run/nats +{{- range $mnt := .natsVolumeMounts }} +{{- $found := false }} +{{- range $.Values.reloader.natsVolumeMountPrefixes }} +{{- if and (not $found) (hasPrefix . $mnt.mountPath) }} +{{- $found = true }} +- {{ toYaml $mnt | nindent 2}} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/stateful-set/resolver-pvc.yaml b/packages/system/nats/charts/nats/files/stateful-set/resolver-pvc.yaml new file mode 100644 index 00000000..3634cd82 --- /dev/null +++ b/packages/system/nats/charts/nats/files/stateful-set/resolver-pvc.yaml @@ -0,0 +1,13 @@ +{{- with .Values.config.resolver.pvc }} +metadata: + name: {{ .name }} +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .size | quote }} + {{- with .storageClassName }} + storageClassName: {{ . | quote }} + {{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/files/stateful-set/stateful-set.yaml b/packages/system/nats/charts/nats/files/stateful-set/stateful-set.yaml new file mode 100644 index 00000000..cd8082cb --- /dev/null +++ b/packages/system/nats/charts/nats/files/stateful-set/stateful-set.yaml @@ -0,0 +1,37 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + {{- include "nats.metadataNamespace" $ | nindent 2 }} + name: {{ .Values.statefulSet.name }} + labels: + {{- include "nats.labels" $ | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "nats.selectorLabels" $ | nindent 6 }} + {{- if .Values.config.cluster.enabled }} + replicas: {{ .Values.config.cluster.replicas }} + {{- else }} + replicas: 1 + {{- end }} + serviceName: {{ .Values.headlessService.name }} + podManagementPolicy: Parallel + template: + {{- with .Values.podTemplate }} + {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/pod-template.yaml" "ctx" $) .) | nindent 4 }} + {{- end }} + volumeClaimTemplates: + {{- with .Values.config.jetstream }} + {{- if and .enabled .fileStore.enabled .fileStore.pvc.enabled }} + {{- with .fileStore.pvc }} + - {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/jetstream-pvc.yaml" "ctx" $) .) | nindent 4 }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.config.resolver }} + {{- if and .enabled .pvc.enabled }} + {{- with .pvc }} + - {{ include "nats.loadMergePatch" (merge (dict "file" "stateful-set/resolver-pvc.yaml" "ctx" $) .) | nindent 4 }} + {{- end }} + {{- end }} + {{- end }} diff --git a/packages/system/nats/charts/nats/templates/_helpers.tpl b/packages/system/nats/charts/nats/templates/_helpers.tpl new file mode 100644 index 00000000..ba831397 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/_helpers.tpl @@ -0,0 +1,281 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "nats.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 "nats.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 "nats.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Print the namespace +*/}} +{{- define "nats.namespace" -}} +{{- default .Release.Namespace .Values.namespaceOverride }} +{{- end }} + +{{/* +Print the namespace for the metadata section +*/}} +{{- define "nats.metadataNamespace" -}} +{{- with .Values.namespaceOverride }} +namespace: {{ . | quote }} +{{- end }} +{{- end }} + +{{/* +Set default values. +*/}} +{{- define "nats.defaultValues" }} +{{- if not .defaultValuesSet }} + {{- $name := include "nats.fullname" . }} + {{- with .Values }} + {{- $_ := set .config.jetstream.fileStore.pvc "name" (.config.jetstream.fileStore.pvc.name | default (printf "%s-js" $name)) }} + {{- $_ := set .config.resolver.pvc "name" (.config.resolver.pvc.name | default (printf "%s-resolver" $name)) }} + {{- $_ := set .config.websocket.ingress "name" (.config.websocket.ingress.name | default (printf "%s-ws" $name)) }} + {{- $_ := set .configMap "name" (.configMap.name | default (printf "%s-config" $name)) }} + {{- $_ := set .headlessService "name" (.headlessService.name | default (printf "%s-headless" $name)) }} + {{- $_ := set .natsBox.contentsSecret "name" (.natsBox.contentsSecret.name | default (printf "%s-box-contents" $name)) }} + {{- $_ := set .natsBox.contextsSecret "name" (.natsBox.contextsSecret.name | default (printf "%s-box-contexts" $name)) }} + {{- $_ := set .natsBox.deployment "name" (.natsBox.deployment.name | default (printf "%s-box" $name)) }} + {{- $_ := set .natsBox.serviceAccount "name" (.natsBox.serviceAccount.name | default (printf "%s-box" $name)) }} + {{- $_ := set .podDisruptionBudget "name" (.podDisruptionBudget.name | default $name) }} + {{- $_ := set .service "name" (.service.name | default $name) }} + {{- $_ := set .serviceAccount "name" (.serviceAccount.name | default $name) }} + {{- $_ := set .statefulSet "name" (.statefulSet.name | default $name) }} + {{- $_ := set .promExporter.podMonitor "name" (.promExporter.podMonitor.name | default $name) }} + {{- end }} + + {{- $values := get (include "tplYaml" (dict "doc" .Values "ctx" $) | fromJson) "doc" }} + {{- $_ := set . "Values" $values }} + + {{- $hasContentsSecret := false }} + {{- range $ctxKey, $ctxVal := .Values.natsBox.contexts }} + {{- range $secretKey, $secretVal := dict "creds" "nats-creds" "nkey" "nats-nkeys" "tls" "nats-certs" }} + {{- $secret := get $ctxVal $secretKey }} + {{- if $secret }} + {{- $_ := set $secret "dir" ($secret.dir | default (printf "/etc/%s/%s" $secretVal $ctxKey)) }} + {{- if and (ne $secretKey "tls") $secret.contents }} + {{- $hasContentsSecret = true }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- $_ := set $ "hasContentsSecret" $hasContentsSecret }} + + {{- with .Values.config }} + {{- $config := include "nats.loadMergePatch" (merge (dict "file" "config/config.yaml" "ctx" $) .) | fromYaml }} + {{- $_ := set $ "config" $config }} + {{- end }} + + {{- $_ := set . "defaultValuesSet" true }} +{{- end }} +{{- end }} + +{{/* +NATS labels +*/}} +{{- define "nats.labels" -}} +{{- with .Values.global.labels -}} +{{ toYaml . }} +{{ end -}} +helm.sh/chart: {{ include "nats.chart" . }} +{{ include "nats.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +NATS selector labels +*/}} +{{- define "nats.selectorLabels" -}} +app.kubernetes.io/name: {{ include "nats.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: nats +{{- end }} + +{{/* +NATS Box labels +*/}} +{{- define "natsBox.labels" -}} +{{- with .Values.global.labels -}} +{{ toYaml . }} +{{ end -}} +helm.sh/chart: {{ include "nats.chart" . }} +{{ include "natsBox.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +NATS Box selector labels +*/}} +{{- define "natsBox.selectorLabels" -}} +app.kubernetes.io/name: {{ include "nats.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/component: nats-box +{{- end }} + +{{/* +Print the image +*/}} +{{- define "nats.image" }} +{{- $image := printf "%s:%s" .repository .tag }} +{{- if or .registry .global.image.registry }} +{{- $image = printf "%s/%s" (.registry | default .global.image.registry) $image }} +{{- end -}} +image: {{ $image }} +{{- if or .pullPolicy .global.image.pullPolicy }} +imagePullPolicy: {{ .pullPolicy | default .global.image.pullPolicy }} +{{- end }} +{{- end }} + +{{- define "nats.secretNames" -}} +{{- $secrets := list }} +{{- range $protocol := list "nats" "leafnodes" "websocket" "mqtt" "cluster" "gateway" }} + {{- $configProtocol := get $.Values.config $protocol }} + {{- if and (or (eq $protocol "nats") $configProtocol.enabled) $configProtocol.tls.enabled $configProtocol.tls.secretName }} + {{- $secrets = append $secrets (merge (dict "name" (printf "%s-tls" $protocol)) $configProtocol.tls) }} + {{- end }} +{{- end }} +{{- toJson (dict "secretNames" $secrets) }} +{{- end }} + +{{- define "natsBox.secretNames" -}} +{{- $secrets := list }} +{{- range $ctxKey, $ctxVal := .Values.natsBox.contexts }} +{{- range $secretKey, $secretVal := dict "creds" "nats-creds" "nkey" "nats-nkeys" "tls" "nats-certs" }} + {{- $secret := get $ctxVal $secretKey }} + {{- if and $secret $secret.secretName }} + {{- $secrets = append $secrets (merge (dict "name" (printf "ctx-%s-%s" $ctxKey $secretKey)) $secret) }} + {{- end }} + {{- end }} +{{- end }} +{{- toJson (dict "secretNames" $secrets) }} +{{- end }} + +{{- define "nats.tlsCAVolume" -}} +{{- with .Values.tlsCA }} +{{- if and .enabled (or .configMapName .secretName) }} +- name: tls-ca +{{- if .configMapName }} + configMap: + name: {{ .configMapName | quote }} +{{- else if .secretName }} + secret: + secretName: {{ .secretName | quote }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} + +{{- define "nats.tlsCAVolumeMount" -}} +{{- with .Values.tlsCA }} +{{- if and .enabled (or .configMapName .secretName) }} +- name: tls-ca + mountPath: {{ .dir | quote }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +translates env var map to list +*/}} +{{- define "nats.env" -}} +{{- range $k, $v := . }} +{{- if kindIs "string" $v }} +- name: {{ $k | quote }} + value: {{ $v | quote }} +{{- else if kindIs "map" $v }} +- {{ merge (dict "name" $k) $v | toYaml | nindent 2 }} +{{- else }} +{{- fail (cat "env var" $k "must be string or map, got" (kindOf $v)) }} +{{- end }} +{{- end }} +{{- end }} + +{{- /* +nats.loadMergePatch +input: map with 4 keys: +- file: name of file to load +- ctx: context to pass to tpl +- merge: interface{} to merge +- patch: []interface{} valid JSON Patch document +output: JSON encoded map with 1 key: +- doc: interface{} patched json result +*/}} +{{- define "nats.loadMergePatch" -}} +{{- $doc := tpl (.ctx.Files.Get (printf "files/%s" .file)) .ctx | fromYaml | default dict -}} +{{- $doc = mergeOverwrite $doc (deepCopy (.merge | default dict)) -}} +{{- get (include "jsonpatch" (dict "doc" $doc "patch" (.patch | default list)) | fromJson ) "doc" | toYaml -}} +{{- end }} + + +{{- /* +nats.reloaderConfig +input: map with 2 keys: +- config: interface{} nats config +- dir: dir config file is in +output: YAML list of reloader config files +*/}} +{{- define "nats.reloaderConfig" -}} + {{- $dir := trimSuffix "/" .dir -}} + {{- with .config -}} + {{- if kindIs "map" . -}} + {{- range $k, $v := . -}} + {{- if or (eq $k "cert_file") (eq $k "key_file") (eq $k "ca_file") }} +- -config +- {{ $v }} + {{- else if hasSuffix "$include" $k }} +- -config +- {{ clean (printf "%s/%s" $dir $v) }} + {{- else }} + {{- include "nats.reloaderConfig" (dict "config" $v "dir" $dir) }} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} + + +{{- /* +nats.formatConfig +input: map[string]interface{} +output: string with following format rules +1. keys ending in $natsRaw are unquoted +2. keys ending in $natsInclude are converted to include directives +*/}} +{{- define "nats.formatConfig" -}} + {{- + (regexReplaceAll "\"<<\\s+(.*)\\s+>>\"" + (regexReplaceAll "\".*\\$include\": \"(.*)\",?" (include "toPrettyRawJson" .) "include ${1};") + "${1}") + -}} +{{- end -}} diff --git a/packages/system/nats/charts/nats/templates/_jsonpatch.tpl b/packages/system/nats/charts/nats/templates/_jsonpatch.tpl new file mode 100644 index 00000000..cd42c3bb --- /dev/null +++ b/packages/system/nats/charts/nats/templates/_jsonpatch.tpl @@ -0,0 +1,219 @@ +{{- /* +jsonpatch +input: map with 2 keys: +- doc: interface{} valid JSON document +- patch: []interface{} valid JSON Patch document +output: JSON encoded map with 1 key: +- doc: interface{} patched json result +*/}} +{{- define "jsonpatch" -}} + {{- $params := fromJson (toJson .) -}} + {{- $patches := $params.patch -}} + {{- $docContainer := pick $params "doc" -}} + + {{- range $patch := $patches -}} + {{- if not (hasKey $patch "op") -}} + {{- fail "patch is missing op key" -}} + {{- end -}} + {{- if and (ne $patch.op "add") (ne $patch.op "remove") (ne $patch.op "replace") (ne $patch.op "copy") (ne $patch.op "move") (ne $patch.op "test") -}} + {{- fail (cat "patch has invalid op" $patch.op) -}} + {{- end -}} + {{- if not (hasKey $patch "path") -}} + {{- fail "patch is missing path key" -}} + {{- end -}} + {{- if and (or (eq $patch.op "add") (eq $patch.op "replace") (eq $patch.op "test")) (not (hasKey $patch "value")) -}} + {{- fail (cat "patch with op" $patch.op "is missing value key") -}} + {{- end -}} + {{- if and (or (eq $patch.op "copy") (eq $patch.op "move")) (not (hasKey $patch "from")) -}} + {{- fail (cat "patch with op" $patch.op "is missing from key") -}} + {{- end -}} + + {{- $opPathKeys := list "path" -}} + {{- if or (eq $patch.op "copy") (eq $patch.op "move") -}} + {{- $opPathKeys = append $opPathKeys "from" -}} + {{- end -}} + {{- $reSlice := list -}} + + {{- range $opPathKey := $opPathKeys -}} + {{- $obj := $docContainer -}} + {{- if and (eq $patch.op "copy") (eq $opPathKey "from") -}} + {{- $obj = (fromJson (toJson $docContainer)) -}} + {{- end -}} + {{- $key := "doc" -}} + {{- $lastMap := dict "root" $obj -}} + {{- $lastKey := "root" -}} + {{- $paths := (splitList "/" (get $patch $opPathKey)) -}} + {{- $firstPath := index $paths 0 -}} + {{- if ne (index $paths 0) "" -}} + {{- fail (cat "invalid" $opPathKey (get $patch $opPathKey) "must be empty string or start with /") -}} + {{- end -}} + {{- $paths = slice $paths 1 -}} + + {{- range $path := $paths -}} + {{- $path = replace "~1" "/" $path -}} + {{- $path = replace "~0" "~" $path -}} + + {{- if kindIs "slice" $obj -}} + {{- $mapObj := dict -}} + {{- range $i, $v := $obj -}} + {{- $_ := set $mapObj (toString $i) $v -}} + {{- end -}} + {{- $obj = $mapObj -}} + {{- $_ := set $lastMap $lastKey $obj -}} + {{- $reSlice = prepend $reSlice (dict "lastMap" $lastMap "lastKey" $lastKey "mapObj" $obj) -}} + {{- end -}} + + {{- if kindIs "map" $obj -}} + {{- if not (hasKey $obj $key) -}} + {{- fail (cat "key" $key "does not exist") -}} + {{- end -}} + {{- $lastKey = $key -}} + {{- $lastMap = $obj -}} + {{- $obj = index $obj $key -}} + {{- $key = $path -}} + {{- else -}} + {{- fail (cat "cannot iterate into path" $key "on type" (kindOf $obj)) -}} + {{- end -}} + {{- end -}} + + {{- $_ := set $patch (printf "%sKey" $opPathKey) $key -}} + {{- $_ := set $patch (printf "%sLastKey" $opPathKey) $lastKey -}} + {{- $_ = set $patch (printf "%sLastMap" $opPathKey) $lastMap -}} + {{- end -}} + + {{- if eq $patch.op "move" }} + {{- if and (ne $patch.path $patch.from) (hasPrefix (printf "%s/" $patch.path) (printf "%s/" $patch.from)) -}} + {{- fail (cat "from" $patch.from "may not be a child of path" $patch.path) -}} + {{- end -}} + {{- end -}} + + {{- if or (eq $patch.op "move") (eq $patch.op "copy") (eq $patch.op "test") }} + {{- $key := $patch.fromKey -}} + {{- $lastMap := $patch.fromLastMap -}} + {{- $lastKey := $patch.fromLastKey -}} + {{- $setKey := "value" -}} + {{- if eq $patch.op "test" }} + {{- $key = $patch.pathKey -}} + {{- $lastMap = $patch.pathLastMap -}} + {{- $lastKey = $patch.pathLastKey -}} + {{- $setKey = "testValue" -}} + {{- end -}} + {{- $obj := index $lastMap $lastKey -}} + + {{- if kindIs "map" $obj -}} + {{- if not (hasKey $obj $key) -}} + {{- fail (cat $key "does not exist") -}} + {{- end -}} + {{- $_ := set $patch $setKey (index $obj $key) -}} + + {{- else if kindIs "slice" $obj -}} + {{- $i := atoi $key -}} + {{- if ne $key (toString $i) -}} + {{- fail (cat "cannot convert" $key "to int") -}} + {{- end -}} + {{- if lt $i 0 -}} + {{- fail "slice index <0" -}} + {{- else if lt $i (len $obj) -}} + {{- $_ := set $patch $setKey (index $obj $i) -}} + {{- else -}} + {{- fail "slice index >= slice length" -}} + {{- end -}} + + {{- else -}} + {{- fail (cat "cannot" $patch.op $key "on type" (kindOf $obj)) -}} + {{- end -}} + {{- end -}} + + {{- if or (eq $patch.op "remove") (eq $patch.op "replace") (eq $patch.op "move") }} + {{- $key := $patch.pathKey -}} + {{- $lastMap := $patch.pathLastMap -}} + {{- $lastKey := $patch.pathLastKey -}} + {{- if eq $patch.op "move" }} + {{- $key = $patch.fromKey -}} + {{- $lastMap = $patch.fromLastMap -}} + {{- $lastKey = $patch.fromLastKey -}} + {{- end -}} + {{- $obj := index $lastMap $lastKey -}} + + {{- if kindIs "map" $obj -}} + {{- if not (hasKey $obj $key) -}} + {{- fail (cat $key "does not exist") -}} + {{- end -}} + {{- $_ := unset $obj $key -}} + + {{- else if kindIs "slice" $obj -}} + {{- $i := atoi $key -}} + {{- if ne $key (toString $i) -}} + {{- fail (cat "cannot convert" $key "to int") -}} + {{- end -}} + {{- if lt $i 0 -}} + {{- fail "slice index <0" -}} + {{- else if eq $i 0 -}} + {{- $_ := set $lastMap $lastKey (slice $obj 1) -}} + {{- else if lt $i (sub (len $obj) 1) -}} + {{- $_ := set $lastMap $lastKey (concat (slice $obj 0 $i) (slice $obj (add $i 1) (len $obj))) -}} + {{- else if eq $i (sub (len $obj) 1) -}} + {{- $_ := set $lastMap $lastKey (slice $obj 0 (sub (len $obj) 1)) -}} + {{- else -}} + {{- fail "slice index >= slice length" -}} + {{- end -}} + + {{- else -}} + {{- fail (cat "cannot" $patch.op $key "on type" (kindOf $obj)) -}} + {{- end -}} + {{- end -}} + + {{- if or (eq $patch.op "add") (eq $patch.op "replace") (eq $patch.op "move") (eq $patch.op "copy") }} + {{- $key := $patch.pathKey -}} + {{- $lastMap := $patch.pathLastMap -}} + {{- $lastKey := $patch.pathLastKey -}} + {{- $value := $patch.value -}} + {{- $obj := index $lastMap $lastKey -}} + + {{- if kindIs "map" $obj -}} + {{- $_ := set $obj $key $value -}} + + {{- else if kindIs "slice" $obj -}} + {{- $i := 0 -}} + {{- if eq $key "-" -}} + {{- $i = len $obj -}} + {{- else -}} + {{- $i = atoi $key -}} + {{- if ne $key (toString $i) -}} + {{- fail (cat "cannot convert" $key "to int") -}} + {{- end -}} + {{- end -}} + {{- if lt $i 0 -}} + {{- fail "slice index <0" -}} + {{- else if eq $i 0 -}} + {{- $_ := set $lastMap $lastKey (prepend $obj $value) -}} + {{- else if lt $i (len $obj) -}} + {{- $_ := set $lastMap $lastKey (concat (append (slice $obj 0 $i) $value) (slice $obj $i)) -}} + {{- else if eq $i (len $obj) -}} + {{- $_ := set $lastMap $lastKey (append $obj $value) -}} + {{- else -}} + {{- fail "slice index > slice length" -}} + {{- end -}} + + {{- else -}} + {{- fail (cat "cannot" $patch.op $key "on type" (kindOf $obj)) -}} + {{- end -}} + {{- end -}} + + {{- if eq $patch.op "test" }} + {{- if not (deepEqual $patch.value $patch.testValue) }} + {{- fail (cat "test failed, expected" (toJson $patch.value) "but got" (toJson $patch.testValue)) -}} + {{- end -}} + {{- end -}} + + {{- range $reSliceOp := $reSlice -}} + {{- $sliceObj := list -}} + {{- range $i := until (len $reSliceOp.mapObj) -}} + {{- $sliceObj = append $sliceObj (index $reSliceOp.mapObj (toString $i)) -}} + {{- end -}} + {{- $_ := set $reSliceOp.lastMap $reSliceOp.lastKey $sliceObj -}} + {{- end -}} + + {{- end -}} + {{- toJson $docContainer -}} +{{- end -}} diff --git a/packages/system/nats/charts/nats/templates/_toPrettyRawJson.tpl b/packages/system/nats/charts/nats/templates/_toPrettyRawJson.tpl new file mode 100644 index 00000000..612a62f9 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/_toPrettyRawJson.tpl @@ -0,0 +1,28 @@ +{{- /* +toPrettyRawJson +input: interface{} valid JSON document +output: pretty raw JSON string +*/}} +{{- define "toPrettyRawJson" -}} + {{- include "toPrettyRawJsonStr" (toPrettyJson .) -}} +{{- end -}} + +{{- /* +toPrettyRawJsonStr +input: pretty JSON string +output: pretty raw JSON string +*/}} +{{- define "toPrettyRawJsonStr" -}} + {{- $s := + (regexReplaceAll "([^\\\\](?:\\\\\\\\)*)\\\\u003e" + (regexReplaceAll "([^\\\\](?:\\\\\\\\)*)\\\\u003c" + (regexReplaceAll "([^\\\\](?:\\\\\\\\)*)\\\\u0026" . "${1}&") + "${1}<") + "${1}>") + -}} + {{- if regexMatch "([^\\\\](?:\\\\\\\\)*)\\\\u00(26|3c|3e)" $s -}} + {{- include "toPrettyRawJsonStr" $s -}} + {{- else -}} + {{- $s -}} + {{- end -}} +{{- end -}} diff --git a/packages/system/nats/charts/nats/templates/_tplYaml.tpl b/packages/system/nats/charts/nats/templates/_tplYaml.tpl new file mode 100644 index 00000000..f42b9c16 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/_tplYaml.tpl @@ -0,0 +1,114 @@ +{{- /* +tplYaml +input: map with 2 keys: +- doc: interface{} +- ctx: context to pass to tpl function +output: JSON encoded map with 1 key: +- doc: interface{} with any keys called tpl or tplSpread values templated and replaced + +maps matching the following syntax will be templated and parsed as YAML +{ + $tplYaml: string +} + +maps matching the follow syntax will be templated, parsed as YAML, and spread into the parent map/slice +{ + $tplYamlSpread: string +} +*/}} +{{- define "tplYaml" -}} + {{- $patch := get (include "tplYamlItr" (dict "ctx" .ctx "parentKind" "" "parentPath" "" "path" "/" "value" .doc) | fromJson) "patch" -}} + {{- include "jsonpatch" (dict "doc" .doc "patch" $patch) -}} +{{- end -}} + +{{- /* +tplYamlItr +input: map with 4 keys: +- path: string JSONPath to current element +- parentKind: string kind of parent element +- parentPath: string JSONPath to parent element +- value: interface{} +- ctx: context to pass to tpl function +output: JSON encoded map with 1 key: +- patch: list of patches to apply in order to template +*/}} +{{- define "tplYamlItr" -}} + {{- $params := . -}} + {{- $kind := kindOf $params.value -}} + {{- $patch := list -}} + {{- $joinPath := $params.path -}} + {{- if eq $params.path "/" -}} + {{- $joinPath = "" -}} + {{- end -}} + {{- $joinParentPath := $params.parentPath -}} + {{- if eq $params.parentPath "/" -}} + {{- $joinParentPath = "" -}} + {{- end -}} + + {{- if eq $kind "slice" -}} + {{- $iAdj := 0 -}} + {{- range $i, $v := $params.value -}} + {{- $iPath := printf "%s/%d" $joinPath (add $i $iAdj) -}} + {{- $itrPatch := get (include "tplYamlItr" (dict "ctx" $params.ctx "parentKind" $kind "parentPath" $params.path "path" $iPath "value" $v) | fromJson) "patch" -}} + {{- $itrLen := len $itrPatch -}} + {{- if gt $itrLen 0 -}} + {{- $patch = concat $patch $itrPatch -}} + {{- if eq (get (index $itrPatch 0) "op") "remove" -}} + {{- $iAdj = add $iAdj (sub $itrLen 2) -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- else if eq $kind "map" -}} + {{- if and (eq (len $params.value) 1) (or (hasKey $params.value "$tplYaml") (hasKey $params.value "$tplYamlSpread")) -}} + {{- $tpl := get $params.value "$tplYaml" -}} + {{- $spread := false -}} + {{- if hasKey $params.value "$tplYamlSpread" -}} + {{- if eq $params.path "/" -}} + {{- fail "cannot $tplYamlSpread on root object" -}} + {{- end -}} + {{- $tpl = get $params.value "$tplYamlSpread" -}} + {{- $spread = true -}} + {{- end -}} + + {{- $res := tpl $tpl $params.ctx -}} + {{- $res = get (fromYaml (tpl "tpl: {{ nindent 2 .res }}" (merge (dict "res" $res) $params.ctx))) "tpl" -}} + + {{- if eq $spread false -}} + {{- $patch = append $patch (dict "op" "replace" "path" $params.path "value" $res) -}} + {{- else -}} + {{- $resKind := kindOf $res -}} + {{- if and (ne $resKind "invalid") (ne $resKind $params.parentKind) -}} + {{- fail (cat "can only $tplYamlSpread slice onto a slice or map onto a map; attempted to spread" $resKind "on" $params.parentKind "at path" $params.path) -}} + {{- end -}} + {{- $patch = append $patch (dict "op" "remove" "path" $params.path) -}} + {{- if eq $resKind "invalid" -}} + {{- /* no-op */ -}} + {{- else if eq $resKind "slice" -}} + {{- range $v := reverse $res -}} + {{- $patch = append $patch (dict "op" "add" "path" $params.path "value" $v) -}} + {{- end -}} + {{- else -}} + {{- range $k, $v := $res -}} + {{- $kPath := replace "~" "~0" $k -}} + {{- $kPath = replace "/" "~1" $kPath -}} + {{- $kPath = printf "%s/%s" $joinParentPath $kPath -}} + {{- $patch = append $patch (dict "op" "add" "path" $kPath "value" $v) -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- else -}} + {{- range $k, $v := $params.value -}} + {{- $kPath := replace "~" "~0" $k -}} + {{- $kPath = replace "/" "~1" $kPath -}} + {{- $kPath = printf "%s/%s" $joinPath $kPath -}} + {{- $itrPatch := get (include "tplYamlItr" (dict "ctx" $params.ctx "parentKind" $kind "parentPath" $params.path "path" $kPath "value" $v) | fromJson) "patch" -}} + {{- if gt (len $itrPatch) 0 -}} + {{- $patch = concat $patch $itrPatch -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{- toJson (dict "patch" $patch) -}} +{{- end -}} diff --git a/packages/system/nats/charts/nats/templates/config-map.yaml b/packages/system/nats/charts/nats/templates/config-map.yaml new file mode 100644 index 00000000..b95afda2 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/config-map.yaml @@ -0,0 +1,4 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.configMap }} +{{- include "nats.loadMergePatch" (merge (dict "file" "config-map.yaml" "ctx" $) .) }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/extra-resources.yaml b/packages/system/nats/charts/nats/templates/extra-resources.yaml new file mode 100644 index 00000000..c11f0085 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/extra-resources.yaml @@ -0,0 +1,5 @@ +{{- include "nats.defaultValues" . }} +{{- range .Values.extraResources }} +--- +{{ . | toYaml }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/headless-service.yaml b/packages/system/nats/charts/nats/templates/headless-service.yaml new file mode 100644 index 00000000..f11a83d1 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/headless-service.yaml @@ -0,0 +1,4 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.headlessService }} +{{- include "nats.loadMergePatch" (merge (dict "file" "headless-service.yaml" "ctx" $) .) }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/ingress.yaml b/packages/system/nats/charts/nats/templates/ingress.yaml new file mode 100644 index 00000000..eccd73ff --- /dev/null +++ b/packages/system/nats/charts/nats/templates/ingress.yaml @@ -0,0 +1,6 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.config.websocket.ingress }} +{{- if and .enabled .hosts $.Values.config.websocket.enabled $.Values.service.enabled $.Values.service.ports.websocket.enabled }} +{{- include "nats.loadMergePatch" (merge (dict "file" "ingress.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/nats-box/contents-secret.yaml b/packages/system/nats/charts/nats/templates/nats-box/contents-secret.yaml new file mode 100644 index 00000000..db629bf7 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/nats-box/contents-secret.yaml @@ -0,0 +1,10 @@ +{{- include "nats.defaultValues" . }} +{{- if .hasContentsSecret }} +{{- with .Values.natsBox }} +{{- if .enabled }} +{{- with .contentsSecret}} +{{- include "nats.loadMergePatch" (merge (dict "file" "nats-box/contents-secret.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/nats-box/contexts-secret.yaml b/packages/system/nats/charts/nats/templates/nats-box/contexts-secret.yaml new file mode 100644 index 00000000..5ae20f45 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/nats-box/contexts-secret.yaml @@ -0,0 +1,8 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.natsBox }} +{{- if .enabled }} +{{- with .contextsSecret}} +{{- include "nats.loadMergePatch" (merge (dict "file" "nats-box/contexts-secret/contexts-secret.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/nats-box/deployment.yaml b/packages/system/nats/charts/nats/templates/nats-box/deployment.yaml new file mode 100644 index 00000000..a063332a --- /dev/null +++ b/packages/system/nats/charts/nats/templates/nats-box/deployment.yaml @@ -0,0 +1,8 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.natsBox }} +{{- if .enabled }} +{{- with .deployment }} +{{- include "nats.loadMergePatch" (merge (dict "file" "nats-box/deployment/deployment.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/nats-box/service-account.yaml b/packages/system/nats/charts/nats/templates/nats-box/service-account.yaml new file mode 100644 index 00000000..e11bdd36 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/nats-box/service-account.yaml @@ -0,0 +1,8 @@ +{{- include "nats.defaultValues" . }} +{{- if .Values.natsBox.enabled }} +{{- with .Values.natsBox.serviceAccount }} +{{- if .enabled }} +{{- include "nats.loadMergePatch" (merge (dict "file" "nats-box/service-account.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/pod-disruption-budget.yaml b/packages/system/nats/charts/nats/templates/pod-disruption-budget.yaml new file mode 100644 index 00000000..91172262 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/pod-disruption-budget.yaml @@ -0,0 +1,6 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.podDisruptionBudget }} +{{- if .enabled }} +{{- include "nats.loadMergePatch" (merge (dict "file" "pod-disruption-budget.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/pod-monitor.yaml b/packages/system/nats/charts/nats/templates/pod-monitor.yaml new file mode 100644 index 00000000..0e42a43a --- /dev/null +++ b/packages/system/nats/charts/nats/templates/pod-monitor.yaml @@ -0,0 +1,8 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.promExporter }} +{{- if and .enabled .podMonitor.enabled }} +{{- with .podMonitor }} +{{- include "nats.loadMergePatch" (merge (dict "file" "pod-monitor.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/service-account.yaml b/packages/system/nats/charts/nats/templates/service-account.yaml new file mode 100644 index 00000000..6c763bd3 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/service-account.yaml @@ -0,0 +1,6 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.serviceAccount }} +{{- if .enabled }} +{{- include "nats.loadMergePatch" (merge (dict "file" "service-account.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/service.yaml b/packages/system/nats/charts/nats/templates/service.yaml new file mode 100644 index 00000000..04b0b37e --- /dev/null +++ b/packages/system/nats/charts/nats/templates/service.yaml @@ -0,0 +1,6 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.service }} +{{- if .enabled }} +{{- include "nats.loadMergePatch" (merge (dict "file" "service.yaml" "ctx" $) .) }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/stateful-set.yaml b/packages/system/nats/charts/nats/templates/stateful-set.yaml new file mode 100644 index 00000000..bb198323 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/stateful-set.yaml @@ -0,0 +1,4 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.statefulSet }} +{{- include "nats.loadMergePatch" (merge (dict "file" "stateful-set/stateful-set.yaml" "ctx" $) .) }} +{{- end }} diff --git a/packages/system/nats/charts/nats/templates/tests/request-reply.yaml b/packages/system/nats/charts/nats/templates/tests/request-reply.yaml new file mode 100644 index 00000000..3e06edc0 --- /dev/null +++ b/packages/system/nats/charts/nats/templates/tests/request-reply.yaml @@ -0,0 +1,37 @@ +{{- include "nats.defaultValues" . }} +{{- with .Values.natsBox | deepCopy }} +{{- $natsBox := . }} +{{- if .enabled -}} +apiVersion: v1 +kind: Pod +{{- with .container }} +{{- $_ := set . "merge" (dict + "args" (list + "sh" + "-ec" + "nats reply --echo echo & pid=\"$!\"; sleep 1; nats request echo hi > /tmp/resp; kill \"$pid\"; wait; grep -qF hi /tmp/resp" + ) +) }} +{{- $_ := set . "patch" list }} +{{- end }} +{{- with .podTemplate }} +{{- $_ := set . "merge" (dict + "metadata" (dict + "name" (printf "%s-test-request-reply" $.Values.statefulSet.name) + "labels" (dict + "app.kubernetes.io/component" "test-request-reply" + ) + "annotations" (dict + "helm.sh/hook" "test" + "helm.sh/hook-delete-policy" "before-hook-creation,hook-succeeded" + ) + ) + "spec" (dict + "restartPolicy" "Never" + ) +) }} +{{- $_ := set . "patch" list }} +{{ include "nats.loadMergePatch" (merge (dict "file" "nats-box/deployment/pod-template.yaml" "ctx" (merge (dict "Values" (dict "natsBox" $natsBox)) $)) .) }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/nats/charts/nats/values.yaml b/packages/system/nats/charts/nats/values.yaml new file mode 100644 index 00000000..0b14ebd4 --- /dev/null +++ b/packages/system/nats/charts/nats/values.yaml @@ -0,0 +1,669 @@ +################################################################################ +# Global options +################################################################################ +global: + image: + # global image pull policy to use for all container images in the chart + # can be overridden by individual image pullPolicy + pullPolicy: + # global list of secret names to use as image pull secrets for all pod specs in the chart + # secrets must exist in the same namespace + # https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + pullSecretNames: [] + # global registry to use for all container images in the chart + # can be overridden by individual image registry + registry: + + # global labels will be applied to all resources deployed by the chart + labels: {} + +################################################################################ +# Common options +################################################################################ +# override name of the chart +nameOverride: +# override full name of the chart+release +fullnameOverride: +# override the namespace that resources are installed into +namespaceOverride: + +# reference a common CA Certificate or Bundle in all nats config `tls` blocks and nats-box contexts +# note: `tls.verify` still must be set in the appropriate nats config `tls` blocks to require mTLS +tlsCA: + enabled: false + # set configMapName in order to mount an existing configMap to dir + configMapName: + # set secretName in order to mount an existing secretName to dir + secretName: + # directory to mount the configMap or secret to + dir: /etc/nats-ca-cert + # key in the configMap or secret that contains the CA Certificate or Bundle + key: ca.crt + +################################################################################ +# NATS Stateful Set and associated resources +################################################################################ + +############################################################ +# NATS config +############################################################ +config: + cluster: + enabled: false + port: 6222 + # must be 2 or higher when jetstream is enabled + replicas: 3 + + # apply to generated route URLs that connect to other pods in the StatefulSet + routeURLs: + # if both user and password are set, they will be added to route URLs + # and the cluster authorization block + user: + password: + # set to true to use FQDN in route URLs + useFQDN: false + k8sClusterDomain: cluster.local + + tls: + enabled: false + # set secretName in order to mount an existing secret to dir + secretName: + dir: /etc/nats-certs/cluster + cert: tls.crt + key: tls.key + # merge or patch the tls config + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls + merge: {} + patch: [] + + # merge or patch the cluster config + # https://docs.nats.io/running-a-nats-service/configuration/clustering/cluster_config + merge: {} + patch: [] + + jetstream: + enabled: false + + fileStore: + enabled: true + dir: /data + + ############################################################ + # stateful set -> volume claim templates -> jetstream pvc + ############################################################ + pvc: + enabled: true + size: 10Gi + storageClassName: + + # merge or patch the jetstream pvc + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-js" + name: + + # defaults to the PVC size + maxSize: + + memoryStore: + enabled: false + # ensure that container has a sufficient memory limit greater than maxSize + maxSize: 1Gi + + # merge or patch the jetstream config + # https://docs.nats.io/running-a-nats-service/configuration#jetstream + merge: {} + patch: [] + + nats: + port: 4222 + tls: + enabled: false + # set secretName in order to mount an existing secret to dir + secretName: + dir: /etc/nats-certs/nats + cert: tls.crt + key: tls.key + # merge or patch the tls config + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls + merge: {} + patch: [] + + leafnodes: + enabled: false + port: 7422 + tls: + enabled: false + # set secretName in order to mount an existing secret to dir + secretName: + dir: /etc/nats-certs/leafnodes + cert: tls.crt + key: tls.key + # merge or patch the tls config + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls + merge: {} + patch: [] + + # merge or patch the leafnodes config + # https://docs.nats.io/running-a-nats-service/configuration/leafnodes/leafnode_conf + merge: {} + patch: [] + + websocket: + enabled: false + port: 8080 + tls: + enabled: false + # set secretName in order to mount an existing secret to dir + secretName: + dir: /etc/nats-certs/websocket + cert: tls.crt + key: tls.key + # merge or patch the tls config + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls + merge: {} + patch: [] + + ############################################################ + # ingress + ############################################################ + # service must be enabled also + ingress: + enabled: false + # must contain at least 1 host otherwise ingress will not be created + hosts: [] + path: / + pathType: Exact + # sets to the ingress class name + className: + # set to an existing secret name to enable TLS on the ingress; applies to all hosts + tlsSecretName: + + # merge or patch the ingress + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#ingress-v1-networking-k8s-io + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-ws" + name: + + # merge or patch the websocket config + # https://docs.nats.io/running-a-nats-service/configuration/websocket/websocket_conf + merge: {} + patch: [] + + mqtt: + enabled: false + port: 1883 + tls: + enabled: false + # set secretName in order to mount an existing secret to dir + secretName: + dir: /etc/nats-certs/mqtt + cert: tls.crt + key: tls.key + # merge or patch the tls config + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls + merge: {} + patch: [] + + # merge or patch the mqtt config + # https://docs.nats.io/running-a-nats-service/configuration/mqtt/mqtt_config + merge: {} + patch: [] + + gateway: + enabled: false + port: 7222 + tls: + enabled: false + # set secretName in order to mount an existing secret to dir + secretName: + dir: /etc/nats-certs/gateway + cert: tls.crt + key: tls.key + # merge or patch the tls config + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls + merge: {} + patch: [] + + # merge or patch the gateway config + # https://docs.nats.io/running-a-nats-service/configuration/gateways/gateway#gateway-configuration-block + merge: {} + patch: [] + + monitor: + enabled: true + port: 8222 + tls: + # config.nats.tls must be enabled also + # when enabled, monitoring port will use HTTPS with the options from config.nats.tls + enabled: false + + profiling: + enabled: false + port: 65432 + + resolver: + enabled: false + dir: /data/resolver + + ############################################################ + # stateful set -> volume claim templates -> resolver pvc + ############################################################ + pvc: + enabled: true + size: 1Gi + storageClassName: + + # merge or patch the pvc + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-resolver" + name: + + # merge or patch the resolver + # https://docs.nats.io/running-a-nats-service/configuration/securing_nats/auth_intro/jwt/resolver + merge: {} + patch: [] + + # adds a prefix to the server name, which defaults to the pod name + # helpful for ensuring server name is unique in a super cluster + serverNamePrefix: "" + + # merge or patch the nats config + # https://docs.nats.io/running-a-nats-service/configuration + # following special rules apply + # 1. strings that start with << and end with >> will be unquoted + # use this for variables and numbers with units + # 2. keys ending in $include will be switched to include directives + # keys are sorted alphabetically, use prefix before $includes to control includes ordering + # paths should be relative to /etc/nats-config/nats.conf + # example: + # + # merge: + # $include: ./my-config.conf + # zzz$include: ./my-config-last.conf + # server_name: nats + # authorization: + # token: << $TOKEN >> + # jetstream: + # max_memory_store: << 1GB >> + # + # will yield the config: + # { + # include ./my-config.conf; + # "authorization": { + # "token": $TOKEN + # }, + # "jetstream": { + # "max_memory_store": 1GB + # }, + # "server_name": "nats", + # include ./my-config-last.conf; + # } + merge: {} + patch: [] + +############################################################ +# stateful set -> pod template -> nats container +############################################################ +container: + image: + repository: nats + tag: 2.10.17-alpine + pullPolicy: + registry: + + # container port options + # must be enabled in the config section also + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#containerport-v1-core + ports: + nats: {} + leafnodes: {} + websocket: {} + mqtt: {} + cluster: {} + gateway: {} + monitor: {} + profiling: {} + + # map with key as env var name, value can be string or map + # example: + # + # env: + # GOMEMLIMIT: 7GiB + # TOKEN: + # valueFrom: + # secretKeyRef: + # name: nats-auth + # key: token + env: {} + + # merge or patch the container + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core + merge: {} + patch: [] + +############################################################ +# stateful set -> pod template -> reloader container +############################################################ +reloader: + enabled: true + image: + repository: natsio/nats-server-config-reloader + tag: 0.15.0 + pullPolicy: + registry: + + # env var map, see nats.env for an example + env: {} + + # all nats container volume mounts with the following prefixes + # will be mounted into the reloader container + natsVolumeMountPrefixes: + - /etc/ + + # merge or patch the container + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core + merge: {} + patch: [] + +############################################################ +# stateful set -> pod template -> prom-exporter container +############################################################ +# config.monitor must be enabled +promExporter: + enabled: false + image: + repository: natsio/prometheus-nats-exporter + tag: 0.15.0 + pullPolicy: + registry: + + port: 7777 + # env var map, see nats.env for an example + env: {} + + # merge or patch the container + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core + merge: {} + patch: [] + + ############################################################ + # prometheus pod monitor + ############################################################ + podMonitor: + enabled: false + + # merge or patch the pod monitor + # https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.PodMonitor + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}" + name: + + +############################################################ +# service +############################################################ +service: + enabled: true + + # service port options + # additional boolean field enable to control whether port is exposed in the service + # must be enabled in the config section also + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#serviceport-v1-core + ports: + nats: + enabled: true + leafnodes: + enabled: true + websocket: + enabled: true + mqtt: + enabled: true + cluster: + enabled: false + gateway: + enabled: false + monitor: + enabled: false + profiling: + enabled: false + + # merge or patch the service + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}" + name: + +############################################################ +# other nats extension points +############################################################ + +# stateful set +statefulSet: + # merge or patch the stateful set + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#statefulset-v1-apps + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}" + name: + +# stateful set -> pod template +podTemplate: + # adds a hash of the ConfigMap as a pod annotation + # this will cause the StatefulSet to roll when the ConfigMap is updated + configChecksumAnnotation: true + + # map of topologyKey: topologySpreadConstraint + # labelSelector will be added to match StatefulSet pods + # + # topologySpreadConstraints: + # kubernetes.io/hostname: + # maxSkew: 1 + # + topologySpreadConstraints: {} + + # merge or patch the pod template + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core + merge: {} + patch: [] + +# headless service +headlessService: + # merge or patch the headless service + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-headless" + name: + +# config map +configMap: + # merge or patch the config map + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#configmap-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-config" + name: + +# pod disruption budget +podDisruptionBudget: + enabled: true + # merge or patch the pod disruption budget + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#poddisruptionbudget-v1-policy + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}" + name: + +# service account +serviceAccount: + enabled: false + # merge or patch the service account + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#serviceaccount-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}" + name: + + +############################################################ +# natsBox +# +# NATS Box Deployment and associated resources +############################################################ +natsBox: + enabled: true + + ############################################################ + # NATS contexts + ############################################################ + contexts: + default: + creds: + # set contents in order to create a secret with the creds file contents + contents: + # set secretName in order to mount an existing secret to dir + secretName: + # defaults to /etc/nats-creds/ + dir: + key: nats.creds + nkey: + # set contents in order to create a secret with the nkey file contents + contents: + # set secretName in order to mount an existing secret to dir + secretName: + # defaults to /etc/nats-nkeys/ + dir: + key: nats.nk + # used to connect with client certificates + tls: + # set secretName in order to mount an existing secret to dir + secretName: + # defaults to /etc/nats-certs/ + dir: + cert: tls.crt + key: tls.key + + # merge or patch the context + # https://docs.nats.io/using-nats/nats-tools/nats_cli#nats-contexts + merge: {} + patch: [] + + # name of context to select by default + defaultContextName: default + + ############################################################ + # deployment -> pod template -> nats-box container + ############################################################ + container: + image: + repository: natsio/nats-box + tag: 0.14.3 + pullPolicy: + registry: + + # env var map, see nats.env for an example + env: {} + + # merge or patch the container + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core + merge: {} + patch: [] + + ############################################################ + # other nats-box extension points + ############################################################ + + # deployment + deployment: + # merge or patch the deployment + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#deployment-v1-apps + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-box" + name: + + # deployment -> pod template + podTemplate: + # merge or patch the pod template + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core + merge: {} + patch: [] + + # contexts secret + contextsSecret: + # merge or patch the context secret + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-box-contexts" + name: + + # contents secret + contentsSecret: + # merge or patch the contents secret + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-box-contents" + name: + + # service account + serviceAccount: + enabled: false + # merge or patch the service account + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#serviceaccount-v1-core + merge: {} + patch: [] + # defaults to "{{ include "nats.fullname" $ }}-box" + name: + + +################################################################################ +# Extra user-defined resources +################################################################################ +# +# add arbitrary user-generated resources +# example: +# +# config: +# websocket: +# enabled: true +# extraResources: +# - apiVersion: networking.istio.io/v1beta1 +# kind: VirtualService +# metadata: +# name: +# $tplYaml: > +# {{ include "nats.fullname" $ | quote }} +# labels: +# $tplYaml: | +# {{ include "nats.labels" $ }} +# spec: +# hosts: +# - demo.nats.io +# gateways: +# - my-gateway +# http: +# - name: default +# match: +# - name: root +# uri: +# exact: / +# route: +# - destination: +# host: +# $tplYaml: > +# {{ .Values.service.name | quote }} +# port: +# number: +# $tplYaml: > +# {{ .Values.config.websocket.port }} +# +extraResources: [] diff --git a/packages/system/nats/values.yaml b/packages/system/nats/values.yaml new file mode 100644 index 00000000..239b91c4 --- /dev/null +++ b/packages/system/nats/values.yaml @@ -0,0 +1,7 @@ +nats: + statefulSet: + merge: + spec: + persistentVolumeClaimRetentionPolicy: + whenDeleted: Delete + whenScaled: Delete diff --git a/packages/system/snapshot-controller/.helmignore b/packages/system/snapshot-controller/.helmignore new file mode 100644 index 00000000..d5c178e8 --- /dev/null +++ b/packages/system/snapshot-controller/.helmignore @@ -0,0 +1,3 @@ +images +hack +.gitkeep diff --git a/packages/system/snapshot-controller/Chart.yaml b/packages/system/snapshot-controller/Chart.yaml new file mode 100644 index 00000000..1f32123c --- /dev/null +++ b/packages/system/snapshot-controller/Chart.yaml @@ -0,0 +1,3 @@ +apiVersion: v2 +name: cozy-snapshot-controller +version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process diff --git a/packages/system/snapshot-controller/Makefile b/packages/system/snapshot-controller/Makefile new file mode 100644 index 00000000..d06f8967 --- /dev/null +++ b/packages/system/snapshot-controller/Makefile @@ -0,0 +1,10 @@ +export NAME=snapshot-controller +export NAMESPACE=cozy-$(NAME) + +include ../../../scripts/package-system.mk + +update: + rm -rf charts + helm repo add piraeus-charts https://piraeus.io/helm-charts/ + helm repo update piraeus-charts + helm pull piraeus-charts/snapshot-controller --untar --untardir charts \ No newline at end of file diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/.helmignore b/packages/system/snapshot-controller/charts/snapshot-controller/.helmignore new file mode 100644 index 00000000..8c796acd --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-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 +*~ +crds/README.md +Makefile +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/Chart.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/Chart.yaml new file mode 100644 index 00000000..6ca53629 --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/Chart.yaml @@ -0,0 +1,22 @@ +apiVersion: v2 +appVersion: v8.0.1 +description: 'Deploys a Snapshot Controller in a cluster. Snapshot Controllers are + often bundled with the Kubernetes distribution, this chart is meant for cases where + it is not. Also deploys the Snapshot Validation Webhook and configures your cluster + to validate every `VolumeSnapshot` and `VolumeSnapshotContent` resource by sending + it to the webhook. ' +home: https://github.com/piraeusdatastore/helm-charts +icon: https://raw.githubusercontent.com/piraeusdatastore/piraeus/master/artwork/sandbox-artwork/icon/color.svg +keywords: +- storage +- snapshot +- validation +kubeVersion: '>= 1.25.0-0' +maintainers: +- name: The Piraeus Maintainers + url: https://github.com/piraeusdatastore/ +name: snapshot-controller +sources: +- https://github.com/kubernetes-csi/external-snapshotter/ +type: application +version: 3.0.5 diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/LICENSE b/packages/system/snapshot-controller/charts/snapshot-controller/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/LICENSE @@ -0,0 +1,201 @@ + 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 [yyyy] [name of copyright owner] + + 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/packages/system/snapshot-controller/charts/snapshot-controller/README.md b/packages/system/snapshot-controller/charts/snapshot-controller/README.md new file mode 100644 index 00000000..9e6efb45 --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/README.md @@ -0,0 +1,200 @@ +# snapshot-controller + +Deploys the [snapshot-controller](https://github.com/kubernetes-csi/external-snapshotter) and the +[snapshot-validation-webhook](https://github.com/kubernetes-csi/external-snapshotter/#validating-webhook) in a cluster. +The controller is required for CSI snapshotting to work and is not specific to any CSI driver. The webhook is configured +to validate every `VolumeSnapshot` and `VolumeSnapshotContent` resource by sending it to the validation webhook. + +While many Kubernetes distributions already package this controller, some do not. If your cluster does ***NOT*** +have the following CRDs, you likely also do not have a snapshot controller deployed: + +``` +kubectl get crd volumesnapshotclasses.snapshot.storage.k8s.io +kubectl get crd volumesnapshots.snapshot.storage.k8s.io +kubectl get crd volumesnapshotcontents.snapshot.storage.k8s.io +``` + +## Usage + +The *snapshot-controller* should be deployed together with the *snapshot-validation-webhook* which can be done by this +simple Helm commands. See [below](#configuration) for available configuration options. + +``` +helm repo add piraeus-charts https://piraeus.io/helm-charts/ +helm install snapshot-controller piraeus-charts/snapshot-controller +``` + +## Upgrades + +Upgrades can be done using the normal Helm upgrade mechanism + +``` +helm repo update +helm upgrade snapshot-controller piraeus-charts/snapshot-controller +``` + +To enjoy all the latest features of the snapshot controller, you may want to upgrade your CRDs as well: + +``` +kubectl replace -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v5.0.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml +kubectl replace -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v5.0.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml +kubectl replace -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v5.0.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml +``` + +## Upgrade from older CRDs + +In an effort to tighten validation, the CSI project started enforcing stricter requirements on `VolumeSnapshot` and +`VolumeSnapshotContent` resources when switching from `v1beta1` to `v1` CRDs. This validation webhook is part of +enforcing these requirements. When upgrading you [have to ensure non of your resources violate the requirements for `v1`]. + +The upgrade procedure can be summarized by the following steps: + +1. Remove the old snapshot controller, if any (since you are upgrading, you probably already have one deployed manually). +2. Install the snapshot controller and the validation webhook using one of the [`3.x.x` releases]: + + ``` + helm install piraeus-charts/snapshot-controller --set controller.image.tag=v3.0.3 --set webhook.image.tag=v3.0.3 + ``` +3. Ensure that none of the resources are labelled as invalid: + + ``` + kubectl get volumesnapshots --selector=snapshot.storage.kubernetes.io/invalid-snapshot-resource="" --all-namespaces + kubectl get volumesnapshotcontents --selector=snapshot.storage.kubernetes.io/invalid-snapshot-resource="" --all-namespaces + ``` + + If the above commands output any resource, they have to be removed + +4. Upgrade the CRDs + + ``` + kubectl replace -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v5.0.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml + kubectl replace -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v5.0.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml + kubectl replace -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/v5.0.0/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml + ``` + +5. Upgrade to the latest version: + + ``` + helm upgrade piraeus-charts/snapshot-controller --set controller.image.tag=v5.0.0 --set webhook.image.tag=v5.0.0 + ``` + +## Configuration + +### Snapshot controller +The following options are available: + +| Option | Usage | Default | +|------------------------------------------|------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------| +| `controller.enabled` | Toggle to disable the deployment of the snapshot controller. | `true` | +| `controller.fullnameOverride` | Set the base name of deployed resources. Defaults to `snapshot-controller`. | `""` | +| `controller.args` | Arguments to pass to the snapshot controller. Note: Keys will be converted to kebab-case, i.e. `oneArg` -> `--one-arg` | `...` | +| `controller.replicaCount` | Number of replicas to deploy. | `1` | +| `controller.revisionHistoryLimit` | Number of revisions to keep. | `10` | +| `controller.image.repository` | Repository to pull the image from. | `registry.k8s.io/sig-storage/snapshot-controller` | +| `controller.image.pullPolicy` | Pull policy to use. Possible values: `IfNotPresent`, `Always`, `Never` | `IfNotPresent` | +| `controller.image.tag` | Override the tag to pull. If not given, defaults to charts `AppVersion`. | `""` | +| `controller.imagePullSecrets` | Image pull secrets to add to the deployment. | `[]` | +| `controller.podAnnotations` | Annotations to add to every pod in the deployment. | `{}` | +| `controller.podLabels` | Labels to add to every pod in the deployment. | `{}` | +| `controller.podSecurityContext` | Security context to set on the webhook pod. | `{}` | +| `controller.priorityClassName` | Priority Class to set on the deployment pods. | `""` | +| `controller.securityContext` | Configure container security context. Defaults to dropping all capabilties and running as user 1000. | `{capabilities: {drop: [ALL]}, readOnlyRootFilesystem: true, runAsNonRoot: true, runAsUser: 1000}` | +| `controller.resources` | Resources to request and limit on the pod. | `{}` | +| `controller.nodeSelector` | Node selector to add to each webhook pod. | `{}` | +| `controller.tolerations` | Tolerations to add to each webhook pod. | `[]` | +| `controller.topologySpreadConstraints` | Topology spread constraints to set on each pod. | `[]` | +| `controller.affinity` | Affinity to set on each webhook pod. | `{}` | +| `controller.pdb` | PodDisruptionBudget to set on the webhook pod. | `{}` | +| `controller.rbac.create` | Create the necessary roles and bindings for the snapshot controller. | `true` | +| `controller.serviceAccount.create` | Create the service account resource | `true` | +| `controller.serviceAccount.name` | Sets the name of the service account. If left empty, will use the release name as default | `""` | +| `controller.hostNetwork` | Change `hostNetwork` to `true` when you want the pod to share its host's network namespace. | `false` | +| `controller.dnsConfig` | DNS settings for controller pod. | `{}` | +| `controller.dnsPolicy` | DNS Policy for controller pod. For Pods running with hostNetwork, set to `ClusterFirstWithHostNet`. | `ClusterFirst` | + + +### Snapshot Validation Webhook +Webhooks in Kubernetes are required to run on HTTPS. To that end, this charts needs to be configured with one of the +following options: + +* An auto-generated certificate, valid for 10 years. This is the default. If you want to renew the certificate, + set `webhook.tls.renew` to `true` and run an upgrade. + +* A [cert-manager.io](https://cert-manager.io) issuer able to create a certificate for the webhook service. + + To use this method, create an override file like: + ```yaml + webhook: + tls: + certManagerIssuerRef: + name: internal-issuer + kind: ClusterIssuer + ``` + + To apply the override, use `--values `. + +* A pre-existing [`kubernetes.io/tls`] secret and the certificate of the CA used to sign said tls secret. + + To use this method, set `--set webhook.tls.certificateSecret=`. + The secret must be in the same namespace as the deployment and be valid for `..svc`. + +***NOTE:*** When using a custom CNI (such as Weave or Calico) on Amazon EKS, the webhook cannot be reached. + +> Internal error occurred: failed calling webhook "snapshot-validation-webhook.snapshot.storage.k8s.io": failed to call webhook: Post "https://snapshot-validation-webhook.kube-system.svc:443/volumesnapshot?timeout=2s": Address is not allowed + +This happens because the control plane cannot be configured to run on a custom CNI on EKS, so the CNIs +differ between control plane and worker nodes. + +To address this, the webhook can be run in the host network so it can be reached. +```yaml +webhook: + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet +``` + +There are additional options that allow customization outside of HTTPS concerns. This is the full list of options +available. + +| Option | Usage | Default | +|----------------------------------------------|------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------| +| `webhook.enabled` | Toggle to disable the deployment of the snapshot validation webhook. | `true` | +| `webhook.fullnameOverride` | Set the base name of deployed resources. Defaults to `snapshot-validation-webhook`. | `""` | +| `webhook.args` | Arguments to pass to the snapshot controller. Note: Keys will be converted to kebab-case, i.e. `oneArg` -> `--one-arg` | `...` | +| `webhook.replicaCount` | Number of replicas to deploy. | `1` | +| `webhook.revisionHistoryLimit` | Number of revisions to keep. | `10` | +| `webhook.image.repository` | Repository to pull the image from. | `registry.k8s.io/sig-storage/snapshot-validation-webhook` | +| `webhook.image.pullPolicy` | Pull policy to use. Possible values: `IfNotPresent`, `Always`, `Never` | `IfNotPresent` | +| `webhook.image.tag` | Override the tag to pull. If not given, defaults to charts `AppVersion`. | `""` | +| `webhook.webhook.timeoutSeconds` | Timeout to use when contacting webhook server. | `2` | +| `webhook.webhook.failurePolicy` | Policy to apply when webhook is unavailable. Possible values: `Fail`, `Ignore`. | `Fail` | +| `webhook.tls.certificateSecret` | Name of the static tls secret to use for serving the HTTPS endpoint. | `""` | +| `webhook.tls.autogenerate` | Automatically generate the TLS secret for serving the HTTPS endpoint. | `true` | +| `webhook.tls.renew` | Force renewal of certificate when auto-generating. | `false` | +| `webhook.tls.certManagerIssuerRef` | Issuer to use for provisioning the TLS certificate. If this is used, `tls.certificateSecret` can be left empty. | `{}` | +| `webhook.imagePullSecrets` | Image pull secrets to add to the deployment. | `[]` | +| `webhook.podAnnotations` | Annotations to add to every pod in the deployment. | `{}` | +| `webhook.podLabels` | Labels to add to every pod in the deployment. | `{}` | +| `webhook.networkPolicy.enabled` | Should a network policy be created. | `false` | +| `webhook.networkPolicy.ingress` | Additional ingress rules to be added to the network policy. | `{}` | +| `webhook.podDisruptionBudget.enabled` | Should a pod disruption budget be created. | `false` | +| `webhook.podDisruptionBudget.maxUnavailable` | The maximum number of pods that are allowed to be unavailable. | `""` | +| `webhook.podDisruptionBudget.minAvailable` | The minimum number of pods that are required to be available. | `""` | +| `webhook.priorityClassName` | The name of the priority class to assign to the deployment. | `""` | +| `webhook.topologySpreadConstraints` | A list of topology constraints to assign to the deployment. | `[]` | +| `webhook.podSecurityContext` | Security context to set on the webhook pod. | `{}` | +| `webhook.securityContext` | Configure container security context. Defaults to dropping all capabilties and running as user 1000. | `{capabilities: {drop: [ALL]}, readOnlyRootFilesystem: true, runAsNonRoot: true, runAsUser: 1000}` | +| `webhook.resources` | Resources to request and limit on the pod. | `{}` | +| `webhook.nodeSelector` | Node selector to add to each webhook pod. | `{}` | +| `webhook.tolerations` | Tolerations to add to each webhook pod. | `[]` | +| `webhook.affinity` | Affinity to set on each webhook pod. | `{}` | +| `webhook.serviceAccount.create` | Create the service account resource | `true` | +| `webhook.serviceAccount.name` | Sets the name of the service account. If left empty, will use the release name as default | `""` | +| `webhook.tests.nodeSelector` | Node selector to add to each helm test pod. | `{}` | +| `webhook.tests.tolerations` | Tolerations to add to each helm test pod. | `[]` | +| `webhook.tests.affinity` | Affinity to set on each helm test pod. | `{}` | +| `webhook.hostNetwork` | Change `hostNetwork` to `true` when you want the pod to share its host's network namespace. | `false` | +| `webhook.dnsConfig` | DNS settings for webhook pod. | `{}` | +| `webhook.dnsPolicy` | DNS Policy for webhook pod. For Pods running with hostNetwork, set to `ClusterFirstWithHostNet` | `ClusterFirst` | + +[`3.x.x` releases]: https://github.com/kubernetes-csi/external-snapshotter/releases +[have to ensure non of your resources violate the requirements for `v1`]: https://github.com/kubernetes-csi/external-snapshotter#validating-webhook diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/crds/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/crds/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml new file mode 100644 index 00000000..aff3a571 --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/crds/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml @@ -0,0 +1,94 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/814" + controller-gen.kubebuilder.io/version: v0.15.0 + name: volumegroupsnapshotclasses.groupsnapshot.storage.k8s.io +spec: + group: groupsnapshot.storage.k8s.io + names: + kind: VolumeGroupSnapshotClass + listKind: VolumeGroupSnapshotClassList + plural: volumegroupsnapshotclasses + shortNames: + - vgsclass + - vgsclasses + singular: volumegroupsnapshotclass + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .driver + name: Driver + type: string + - description: Determines whether a VolumeGroupSnapshotContent created through + the VolumeGroupSnapshotClass should be deleted when its bound VolumeGroupSnapshot + is deleted. + jsonPath: .deletionPolicy + name: DeletionPolicy + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + VolumeGroupSnapshotClass specifies parameters that a underlying storage system + uses when creating a volume group snapshot. A specific VolumeGroupSnapshotClass + is used by specifying its name in a VolumeGroupSnapshot object. + VolumeGroupSnapshotClasses are non-namespaced. + 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 + deletionPolicy: + description: |- + DeletionPolicy determines whether a VolumeGroupSnapshotContent created + through the VolumeGroupSnapshotClass should be deleted when its bound + VolumeGroupSnapshot is deleted. + Supported values are "Retain" and "Delete". + "Retain" means that the VolumeGroupSnapshotContent and its physical group + snapshot on underlying storage system are kept. + "Delete" means that the VolumeGroupSnapshotContent and its physical group + snapshot on underlying storage system are deleted. + Required. + enum: + - Delete + - Retain + type: string + driver: + description: |- + Driver is the name of the storage driver expected to handle this VolumeGroupSnapshotClass. + Required. + 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 + parameters: + additionalProperties: + type: string + description: |- + Parameters is a key-value map with storage driver specific parameters for + creating group snapshots. + These values are opaque to Kubernetes and are passed directly to the driver. + type: object + required: + - deletionPolicy + - driver + type: object + served: true + storage: true + subresources: {} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/crds/groupsnapshot.storage.k8s.io_volumegroupsnapshotcontents.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/crds/groupsnapshot.storage.k8s.io_volumegroupsnapshotcontents.yaml new file mode 100644 index 00000000..28584e56 --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/crds/groupsnapshot.storage.k8s.io_volumegroupsnapshotcontents.yaml @@ -0,0 +1,335 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1068" + controller-gen.kubebuilder.io/version: v0.15.0 + name: volumegroupsnapshotcontents.groupsnapshot.storage.k8s.io +spec: + group: groupsnapshot.storage.k8s.io + names: + kind: VolumeGroupSnapshotContent + listKind: VolumeGroupSnapshotContentList + plural: volumegroupsnapshotcontents + shortNames: + - vgsc + - vgscs + singular: volumegroupsnapshotcontent + scope: Cluster + versions: + - additionalPrinterColumns: + - description: Indicates if all the individual snapshots in the group are ready + to be used to restore a group of volumes. + jsonPath: .status.readyToUse + name: ReadyToUse + type: boolean + - description: Determines whether this VolumeGroupSnapshotContent and its physical + group snapshot on the underlying storage system should be deleted when its + bound VolumeGroupSnapshot is deleted. + jsonPath: .spec.deletionPolicy + name: DeletionPolicy + type: string + - description: Name of the CSI driver used to create the physical group snapshot + on the underlying storage system. + jsonPath: .spec.driver + name: Driver + type: string + - description: Name of the VolumeGroupSnapshotClass from which this group snapshot + was (or will be) created. + jsonPath: .spec.volumeGroupSnapshotClassName + name: VolumeGroupSnapshotClass + type: string + - description: Namespace of the VolumeGroupSnapshot object to which this VolumeGroupSnapshotContent + object is bound. + jsonPath: .spec.volumeGroupSnapshotRef.namespace + name: VolumeGroupSnapshotNamespace + type: string + - description: Name of the VolumeGroupSnapshot object to which this VolumeGroupSnapshotContent + object is bound. + jsonPath: .spec.volumeGroupSnapshotRef.name + name: VolumeGroupSnapshot + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + VolumeGroupSnapshotContent represents the actual "on-disk" group snapshot object + in the underlying storage system + 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: |- + Spec defines properties of a VolumeGroupSnapshotContent created by the underlying storage system. + Required. + properties: + deletionPolicy: + description: |- + DeletionPolicy determines whether this VolumeGroupSnapshotContent and the + physical group snapshot on the underlying storage system should be deleted + when the bound VolumeGroupSnapshot is deleted. + Supported values are "Retain" and "Delete". + "Retain" means that the VolumeGroupSnapshotContent and its physical group + snapshot on underlying storage system are kept. + "Delete" means that the VolumeGroupSnapshotContent and its physical group + snapshot on underlying storage system are deleted. + For dynamically provisioned group snapshots, this field will automatically + be filled in by the CSI snapshotter sidecar with the "DeletionPolicy" field + defined in the corresponding VolumeGroupSnapshotClass. + For pre-existing snapshots, users MUST specify this field when creating the + VolumeGroupSnapshotContent object. + Required. + enum: + - Delete + - Retain + type: string + driver: + description: |- + Driver is the name of the CSI driver used to create the physical group snapshot on + the underlying storage system. + This MUST be the same as the name returned by the CSI GetPluginName() call for + that driver. + Required. + type: string + source: + description: |- + Source specifies whether the snapshot is (or should be) dynamically provisioned + or already exists, and just requires a Kubernetes object representation. + This field is immutable after creation. + Required. + properties: + groupSnapshotHandles: + description: |- + GroupSnapshotHandles specifies the CSI "group_snapshot_id" of a pre-existing + group snapshot and a list of CSI "snapshot_id" of pre-existing snapshots + on the underlying storage system for which a Kubernetes object + representation was (or should be) created. + This field is immutable. + properties: + volumeGroupSnapshotHandle: + description: |- + VolumeGroupSnapshotHandle specifies the CSI "group_snapshot_id" of a pre-existing + group snapshot on the underlying storage system for which a Kubernetes object + representation was (or should be) created. + This field is immutable. + Required. + type: string + volumeSnapshotHandles: + description: |- + VolumeSnapshotHandles is a list of CSI "snapshot_id" of pre-existing + snapshots on the underlying storage system for which Kubernetes objects + representation were (or should be) created. + This field is immutable. + Required. + items: + type: string + type: array + required: + - volumeGroupSnapshotHandle + - volumeSnapshotHandles + type: object + x-kubernetes-validations: + - message: groupSnapshotHandles is immutable + rule: self == oldSelf + volumeHandles: + description: |- + VolumeHandles is a list of volume handles on the backend to be snapshotted + together. It is specified for dynamic provisioning of the VolumeGroupSnapshot. + This field is immutable. + items: + type: string + type: array + x-kubernetes-validations: + - message: volumeHandles is immutable + rule: self == oldSelf + type: object + x-kubernetes-validations: + - message: volumeHandles is required once set + rule: '!has(oldSelf.volumeHandles) || has(self.volumeHandles)' + - message: groupSnapshotHandles is required once set + rule: '!has(oldSelf.groupSnapshotHandles) || has(self.groupSnapshotHandles)' + - message: exactly one of volumeHandles and groupSnapshotHandles must + be set + rule: (has(self.volumeHandles) && !has(self.groupSnapshotHandles)) + || (!has(self.volumeHandles) && has(self.groupSnapshotHandles)) + volumeGroupSnapshotClassName: + description: |- + VolumeGroupSnapshotClassName is the name of the VolumeGroupSnapshotClass from + which this group snapshot was (or will be) created. + Note that after provisioning, the VolumeGroupSnapshotClass may be deleted or + recreated with different set of values, and as such, should not be referenced + post-snapshot creation. + For dynamic provisioning, this field must be set. + This field may be unset for pre-provisioned snapshots. + type: string + volumeGroupSnapshotRef: + description: |- + VolumeGroupSnapshotRef specifies the VolumeGroupSnapshot object to which this + VolumeGroupSnapshotContent object is bound. + VolumeGroupSnapshot.Spec.VolumeGroupSnapshotContentName field must reference to + this VolumeGroupSnapshotContent's name for the bidirectional binding to be valid. + For a pre-existing VolumeGroupSnapshotContent object, name and namespace of the + VolumeGroupSnapshot object MUST be provided for binding to happen. + This field is immutable after creation. + Required. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + x-kubernetes-validations: + - message: both volumeGroupSnapshotRef.name and volumeGroupSnapshotRef.namespace + must be set + rule: has(self.name) && has(self.__namespace__) + - message: volumeGroupSnapshotRef is immutable + rule: self == oldSelf + required: + - deletionPolicy + - driver + - source + - volumeGroupSnapshotRef + type: object + status: + description: status represents the current information of a group snapshot. + properties: + creationTime: + description: |- + CreationTime is the timestamp when the point-in-time group snapshot is taken + by the underlying storage system. + If not specified, it indicates the creation time is unknown. + If not specified, it means the readiness of a group snapshot is unknown. + The format of this field is a Unix nanoseconds time encoded as an int64. + On Unix, the command date +%s%N returns the current time in nanoseconds + since 1970-01-01 00:00:00 UTC. + format: int64 + type: integer + error: + description: |- + Error is the last observed error during group snapshot creation, if any. + Upon success after retry, this error field will be cleared. + properties: + message: + description: |- + message is a string detailing the encountered error during snapshot + creation if specified. + NOTE: message may be logged, and it should not contain sensitive + information. + type: string + time: + description: time is the timestamp when the error was encountered. + format: date-time + type: string + type: object + pvVolumeSnapshotContentList: + description: |- + PVVolumeSnapshotContentList is the list of pairs of PV and + VolumeSnapshotContent for this group snapshot + The maximum number of allowed snapshots in the group is 100. + items: + description: |- + PVVolumeSnapshotContentPair represent a pair of PV names and + VolumeSnapshotContent names + properties: + persistentVolumeRef: + description: PersistentVolumeRef is a reference to the persistent + volume resource + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid? + type: string + type: object + x-kubernetes-map-type: atomic + volumeSnapshotContentRef: + description: VolumeSnapshotContentRef is a reference to the + volume snapshot content resource + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid? + type: string + type: object + x-kubernetes-map-type: atomic + type: object + type: array + readyToUse: + description: |- + ReadyToUse indicates if all the individual snapshots in the group are ready to be + used to restore a group of volumes. + ReadyToUse becomes true when ReadyToUse of all individual snapshots become true. + type: boolean + volumeGroupSnapshotHandle: + description: |- + VolumeGroupSnapshotHandle is a unique id returned by the CSI driver + to identify the VolumeGroupSnapshot on the storage system. + If a storage system does not provide such an id, the + CSI driver can choose to return the VolumeGroupSnapshot name. + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/crds/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/crds/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml new file mode 100644 index 00000000..3d9a771d --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/crds/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml @@ -0,0 +1,273 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1068" + controller-gen.kubebuilder.io/version: v0.15.0 + name: volumegroupsnapshots.groupsnapshot.storage.k8s.io +spec: + group: groupsnapshot.storage.k8s.io + names: + kind: VolumeGroupSnapshot + listKind: VolumeGroupSnapshotList + plural: volumegroupsnapshots + shortNames: + - vgs + singular: volumegroupsnapshot + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Indicates if all the individual snapshots in the group are ready + to be used to restore a group of volumes. + jsonPath: .status.readyToUse + name: ReadyToUse + type: boolean + - description: The name of the VolumeGroupSnapshotClass requested by the VolumeGroupSnapshot. + jsonPath: .spec.volumeGroupSnapshotClassName + name: VolumeGroupSnapshotClass + type: string + - description: Name of the VolumeGroupSnapshotContent object to which the VolumeGroupSnapshot + object intends to bind to. Please note that verification of binding actually + requires checking both VolumeGroupSnapshot and VolumeGroupSnapshotContent + to ensure both are pointing at each other. Binding MUST be verified prior + to usage of this object. + jsonPath: .status.boundVolumeGroupSnapshotContentName + name: VolumeGroupSnapshotContent + type: string + - description: Timestamp when the point-in-time group snapshot was taken by the + underlying storage system. + jsonPath: .status.creationTime + name: CreationTime + type: date + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + VolumeGroupSnapshot is a user's request for creating either a point-in-time + group snapshot or binding to a pre-existing group snapshot. + 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: |- + Spec defines the desired characteristics of a group snapshot requested by a user. + Required. + properties: + source: + description: |- + Source specifies where a group snapshot will be created from. + This field is immutable after creation. + Required. + properties: + selector: + description: |- + Selector is a label query over persistent volume claims that are to be + grouped together for snapshotting. + This labelSelector will be used to match the label added to a PVC. + If the label is added or removed to a volume after a group snapshot + is created, the existing group snapshots won't be modified. + Once a VolumeGroupSnapshotContent is created and the sidecar starts to process + it, the volume list will not change with retries. + 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 + x-kubernetes-validations: + - message: selector is immutable + rule: self == oldSelf + volumeGroupSnapshotContentName: + description: |- + VolumeGroupSnapshotContentName specifies the name of a pre-existing VolumeGroupSnapshotContent + object representing an existing volume group snapshot. + This field should be set if the volume group snapshot already exists and + only needs a representation in Kubernetes. + This field is immutable. + type: string + x-kubernetes-validations: + - message: volumeGroupSnapshotContentName is immutable + rule: self == oldSelf + type: object + x-kubernetes-validations: + - message: selector is required once set + rule: '!has(oldSelf.selector) || has(self.selector)' + - message: volumeGroupSnapshotContentName is required once set + rule: '!has(oldSelf.volumeGroupSnapshotContentName) || has(self.volumeGroupSnapshotContentName)' + - message: exactly one of selector and volumeGroupSnapshotContentName + must be set + rule: (has(self.selector) && !has(self.volumeGroupSnapshotContentName)) + || (!has(self.selector) && has(self.volumeGroupSnapshotContentName)) + volumeGroupSnapshotClassName: + description: |- + VolumeGroupSnapshotClassName is the name of the VolumeGroupSnapshotClass + requested by the VolumeGroupSnapshot. + VolumeGroupSnapshotClassName may be left nil to indicate that the default + class will be used. + Empty string is not allowed for this field. + type: string + x-kubernetes-validations: + - message: volumeGroupSnapshotClassName must not be the empty string + when set + rule: size(self) > 0 + required: + - source + type: object + status: + description: |- + Status represents the current information of a group snapshot. + Consumers must verify binding between VolumeGroupSnapshot and + VolumeGroupSnapshotContent objects is successful (by validating that both + VolumeGroupSnapshot and VolumeGroupSnapshotContent point to each other) before + using this object. + properties: + boundVolumeGroupSnapshotContentName: + description: |- + BoundVolumeGroupSnapshotContentName is the name of the VolumeGroupSnapshotContent + object to which this VolumeGroupSnapshot object intends to bind to. + If not specified, it indicates that the VolumeGroupSnapshot object has not + been successfully bound to a VolumeGroupSnapshotContent object yet. + NOTE: To avoid possible security issues, consumers must verify binding between + VolumeGroupSnapshot and VolumeGroupSnapshotContent objects is successful + (by validating that both VolumeGroupSnapshot and VolumeGroupSnapshotContent + point at each other) before using this object. + type: string + creationTime: + description: |- + CreationTime is the timestamp when the point-in-time group snapshot is taken + by the underlying storage system. + If not specified, it may indicate that the creation time of the group snapshot + is unknown. + The format of this field is a Unix nanoseconds time encoded as an int64. + On Unix, the command date +%s%N returns the current time in nanoseconds + since 1970-01-01 00:00:00 UTC. + format: date-time + type: string + error: + description: |- + Error is the last observed error during group snapshot creation, if any. + This field could be helpful to upper level controllers (i.e., application + controller) to decide whether they should continue on waiting for the group + snapshot to be created based on the type of error reported. + The snapshot controller will keep retrying when an error occurs during the + group snapshot creation. Upon success, this error field will be cleared. + properties: + message: + description: |- + message is a string detailing the encountered error during snapshot + creation if specified. + NOTE: message may be logged, and it should not contain sensitive + information. + type: string + time: + description: time is the timestamp when the error was encountered. + format: date-time + type: string + type: object + pvcVolumeSnapshotRefList: + description: |- + VolumeSnapshotRefList is the list of PVC and VolumeSnapshot pairs that + is part of this group snapshot. + The maximum number of allowed snapshots in the group is 100. + items: + description: PVCVolumeSnapshotPair defines a pair of a PVC reference + and a Volume Snapshot Reference + properties: + persistentVolumeClaimRef: + description: PersistentVolumeClaimRef is a reference to the + PVC this pair is referring to + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid? + type: string + type: object + x-kubernetes-map-type: atomic + volumeSnapshotRef: + description: VolumeSnapshotRef is a reference to the VolumeSnapshot + this pair is referring to + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid? + type: string + type: object + x-kubernetes-map-type: atomic + type: object + type: array + readyToUse: + description: |- + ReadyToUse indicates if all the individual snapshots in the group are ready + to be used to restore a group of volumes. + ReadyToUse becomes true when ReadyToUse of all individual snapshots become true. + If not specified, it means the readiness of a group snapshot is unknown. + type: boolean + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/crds/snapshot.storage.k8s.io_volumesnapshotclasses.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/crds/snapshot.storage.k8s.io_volumesnapshotclasses.yaml new file mode 100644 index 00000000..8164952a --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/crds/snapshot.storage.k8s.io_volumesnapshotclasses.yaml @@ -0,0 +1,143 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/814" + controller-gen.kubebuilder.io/version: v0.15.0 + name: volumesnapshotclasses.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotClass + listKind: VolumeSnapshotClassList + plural: volumesnapshotclasses + shortNames: + - vsclass + - vsclasses + singular: volumesnapshotclass + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .driver + name: Driver + type: string + - description: Determines whether a VolumeSnapshotContent created through the + VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. + jsonPath: .deletionPolicy + name: DeletionPolicy + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: |- + VolumeSnapshotClass specifies parameters that a underlying storage system uses when + creating a volume snapshot. A specific VolumeSnapshotClass is used by specifying its + name in a VolumeSnapshot object. + VolumeSnapshotClasses are non-namespaced + 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 + deletionPolicy: + description: |- + deletionPolicy determines whether a VolumeSnapshotContent created through + the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. + Supported values are "Retain" and "Delete". + "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. + "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. + Required. + enum: + - Delete + - Retain + type: string + driver: + description: |- + driver is the name of the storage driver that handles this VolumeSnapshotClass. + Required. + 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 + parameters: + additionalProperties: + type: string + description: |- + parameters is a key-value map with storage driver specific parameters for creating snapshots. + These values are opaque to Kubernetes. + type: object + required: + - deletionPolicy + - driver + type: object + served: true + storage: true + subresources: {} + - additionalPrinterColumns: + - jsonPath: .driver + name: Driver + type: string + - description: Determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. + jsonPath: .deletionPolicy + name: DeletionPolicy + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + # This indicates the v1beta1 version of the custom resource is deprecated. + # API requests to this version receive a warning in the server response. + deprecated: true + # This overrides the default warning returned to clients making v1beta1 API requests. + deprecationWarning: "snapshot.storage.k8s.io/v1beta1 VolumeSnapshotClass is deprecated; use snapshot.storage.k8s.io/v1 VolumeSnapshotClass" + schema: + openAPIV3Schema: + description: VolumeSnapshotClass specifies parameters that a underlying storage system uses when creating a volume snapshot. A specific VolumeSnapshotClass is used by specifying its name in a VolumeSnapshot object. VolumeSnapshotClasses are non-namespaced + 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 + deletionPolicy: + description: deletionPolicy determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. Required. + enum: + - Delete + - Retain + type: string + driver: + description: driver is the name of the storage driver that handles this VolumeSnapshotClass. Required. + 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 + parameters: + additionalProperties: + type: string + description: parameters is a key-value map with storage driver specific parameters for creating snapshots. These values are opaque to Kubernetes. + type: object + required: + - deletionPolicy + - driver + type: object + served: false + storage: false + subresources: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/crds/snapshot.storage.k8s.io_volumesnapshotcontents.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/crds/snapshot.storage.k8s.io_volumesnapshotcontents.yaml new file mode 100644 index 00000000..cd0c879f --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/crds/snapshot.storage.k8s.io_volumesnapshotcontents.yaml @@ -0,0 +1,457 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/955" + name: volumesnapshotcontents.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotContent + listKind: VolumeSnapshotContentList + plural: volumesnapshotcontents + shortNames: + - vsc + - vscs + singular: volumesnapshotcontent + scope: Cluster + versions: + - additionalPrinterColumns: + - description: Indicates if the snapshot is ready to be used to restore a volume. + jsonPath: .status.readyToUse + name: ReadyToUse + type: boolean + - description: Represents the complete size of the snapshot in bytes + jsonPath: .status.restoreSize + name: RestoreSize + type: integer + - description: Determines whether this VolumeSnapshotContent and its physical + snapshot on the underlying storage system should be deleted when its bound + VolumeSnapshot is deleted. + jsonPath: .spec.deletionPolicy + name: DeletionPolicy + type: string + - description: Name of the CSI driver used to create the physical snapshot on + the underlying storage system. + jsonPath: .spec.driver + name: Driver + type: string + - description: Name of the VolumeSnapshotClass to which this snapshot belongs. + jsonPath: .spec.volumeSnapshotClassName + name: VolumeSnapshotClass + type: string + - description: Name of the VolumeSnapshot object to which this VolumeSnapshotContent + object is bound. + jsonPath: .spec.volumeSnapshotRef.name + name: VolumeSnapshot + type: string + - description: Namespace of the VolumeSnapshot object to which this VolumeSnapshotContent + object is bound. + jsonPath: .spec.volumeSnapshotRef.namespace + name: VolumeSnapshotNamespace + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: |- + VolumeSnapshotContent represents the actual "on-disk" snapshot object in the + underlying storage system + 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: |- + spec defines properties of a VolumeSnapshotContent created by the underlying storage system. + Required. + properties: + deletionPolicy: + description: |- + deletionPolicy determines whether this VolumeSnapshotContent and its physical snapshot on + the underlying storage system should be deleted when its bound VolumeSnapshot is deleted. + Supported values are "Retain" and "Delete". + "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. + "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. + For dynamically provisioned snapshots, this field will automatically be filled in by the + CSI snapshotter sidecar with the "DeletionPolicy" field defined in the corresponding + VolumeSnapshotClass. + For pre-existing snapshots, users MUST specify this field when creating the + VolumeSnapshotContent object. + Required. + enum: + - Delete + - Retain + type: string + driver: + description: |- + driver is the name of the CSI driver used to create the physical snapshot on + the underlying storage system. + This MUST be the same as the name returned by the CSI GetPluginName() call for + that driver. + Required. + type: string + source: + description: |- + source specifies whether the snapshot is (or should be) dynamically provisioned + or already exists, and just requires a Kubernetes object representation. + This field is immutable after creation. + Required. + properties: + snapshotHandle: + description: |- + snapshotHandle specifies the CSI "snapshot_id" of a pre-existing snapshot on + the underlying storage system for which a Kubernetes object representation + was (or should be) created. + This field is immutable. + type: string + x-kubernetes-validations: + - message: snapshotHandle is immutable + rule: self == oldSelf + volumeHandle: + description: |- + volumeHandle specifies the CSI "volume_id" of the volume from which a snapshot + should be dynamically taken from. + This field is immutable. + type: string + x-kubernetes-validations: + - message: volumeHandle is immutable + rule: self == oldSelf + type: object + x-kubernetes-validations: + - message: volumeHandle is required once set + rule: '!has(oldSelf.volumeHandle) || has(self.volumeHandle)' + - message: snapshotHandle is required once set + rule: '!has(oldSelf.snapshotHandle) || has(self.snapshotHandle)' + - message: exactly one of volumeHandle and snapshotHandle must be + set + rule: (has(self.volumeHandle) && !has(self.snapshotHandle)) || (!has(self.volumeHandle) + && has(self.snapshotHandle)) + sourceVolumeMode: + description: |- + SourceVolumeMode is the mode of the volume whose snapshot is taken. + Can be either “Filesystem” or “Block”. + If not specified, it indicates the source volume's mode is unknown. + This field is immutable. + This field is an alpha field. + type: string + x-kubernetes-validations: + - message: sourceVolumeMode is immutable + rule: self == oldSelf + volumeSnapshotClassName: + description: |- + name of the VolumeSnapshotClass from which this snapshot was (or will be) + created. + Note that after provisioning, the VolumeSnapshotClass may be deleted or + recreated with different set of values, and as such, should not be referenced + post-snapshot creation. + type: string + volumeSnapshotRef: + description: |- + volumeSnapshotRef specifies the VolumeSnapshot object to which this + VolumeSnapshotContent object is bound. + VolumeSnapshot.Spec.VolumeSnapshotContentName field must reference to + this VolumeSnapshotContent's name for the bidirectional binding to be valid. + For a pre-existing VolumeSnapshotContent object, name and namespace of the + VolumeSnapshot object MUST be provided for binding to happen. + This field is immutable after creation. + Required. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + x-kubernetes-validations: + - message: both spec.volumeSnapshotRef.name and spec.volumeSnapshotRef.namespace + must be set + rule: has(self.name) && has(self.__namespace__) + required: + - deletionPolicy + - driver + - source + - volumeSnapshotRef + type: object + x-kubernetes-validations: + - message: sourceVolumeMode is required once set + rule: '!has(oldSelf.sourceVolumeMode) || has(self.sourceVolumeMode)' + status: + description: status represents the current information of a snapshot. + properties: + creationTime: + description: |- + creationTime is the timestamp when the point-in-time snapshot is taken + by the underlying storage system. + In dynamic snapshot creation case, this field will be filled in by the + CSI snapshotter sidecar with the "creation_time" value returned from CSI + "CreateSnapshot" gRPC call. + For a pre-existing snapshot, this field will be filled with the "creation_time" + value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. + If not specified, it indicates the creation time is unknown. + The format of this field is a Unix nanoseconds time encoded as an int64. + On Unix, the command `date +%s%N` returns the current time in nanoseconds + since 1970-01-01 00:00:00 UTC. + format: int64 + type: integer + error: + description: |- + error is the last observed error during snapshot creation, if any. + Upon success after retry, this error field will be cleared. + properties: + message: + description: |- + message is a string detailing the encountered error during snapshot + creation if specified. + NOTE: message may be logged, and it should not contain sensitive + information. + type: string + time: + description: time is the timestamp when the error was encountered. + format: date-time + type: string + type: object + readyToUse: + description: |- + readyToUse indicates if a snapshot is ready to be used to restore a volume. + In dynamic snapshot creation case, this field will be filled in by the + CSI snapshotter sidecar with the "ready_to_use" value returned from CSI + "CreateSnapshot" gRPC call. + For a pre-existing snapshot, this field will be filled with the "ready_to_use" + value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, + otherwise, this field will be set to "True". + If not specified, it means the readiness of a snapshot is unknown. + type: boolean + restoreSize: + description: |- + restoreSize represents the complete size of the snapshot in bytes. + In dynamic snapshot creation case, this field will be filled in by the + CSI snapshotter sidecar with the "size_bytes" value returned from CSI + "CreateSnapshot" gRPC call. + For a pre-existing snapshot, this field will be filled with the "size_bytes" + value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. + When restoring a volume from this snapshot, the size of the volume MUST NOT + be smaller than the restoreSize if it is specified, otherwise the restoration will fail. + If not specified, it indicates that the size is unknown. + format: int64 + minimum: 0 + type: integer + snapshotHandle: + description: |- + snapshotHandle is the CSI "snapshot_id" of a snapshot on the underlying storage system. + If not specified, it indicates that dynamic snapshot creation has either failed + or it is still in progress. + type: string + volumeGroupSnapshotHandle: + description: |- + VolumeGroupSnapshotHandle is the CSI "group_snapshot_id" of a group snapshot + on the underlying storage system. + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - description: Indicates if the snapshot is ready to be used to restore a volume. + jsonPath: .status.readyToUse + name: ReadyToUse + type: boolean + - description: Represents the complete size of the snapshot in bytes + jsonPath: .status.restoreSize + name: RestoreSize + type: integer + - description: Determines whether this VolumeSnapshotContent and its physical snapshot on the underlying storage system should be deleted when its bound VolumeSnapshot is deleted. + jsonPath: .spec.deletionPolicy + name: DeletionPolicy + type: string + - description: Name of the CSI driver used to create the physical snapshot on the underlying storage system. + jsonPath: .spec.driver + name: Driver + type: string + - description: Name of the VolumeSnapshotClass to which this snapshot belongs. + jsonPath: .spec.volumeSnapshotClassName + name: VolumeSnapshotClass + type: string + - description: Name of the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. + jsonPath: .spec.volumeSnapshotRef.name + name: VolumeSnapshot + type: string + - description: Namespace of the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. + jsonPath: .spec.volumeSnapshotRef.namespace + name: VolumeSnapshotNamespace + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + # This indicates the v1beta1 version of the custom resource is deprecated. + # API requests to this version receive a warning in the server response. + deprecated: true + # This overrides the default warning returned to clients making v1beta1 API requests. + deprecationWarning: "snapshot.storage.k8s.io/v1beta1 VolumeSnapshotContent is deprecated; use snapshot.storage.k8s.io/v1 VolumeSnapshotContent" + schema: + openAPIV3Schema: + description: VolumeSnapshotContent represents the actual "on-disk" snapshot object in the underlying storage system + 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 + spec: + description: spec defines properties of a VolumeSnapshotContent created by the underlying storage system. Required. + properties: + deletionPolicy: + description: deletionPolicy determines whether this VolumeSnapshotContent and its physical snapshot on the underlying storage system should be deleted when its bound VolumeSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. For dynamically provisioned snapshots, this field will automatically be filled in by the CSI snapshotter sidecar with the "DeletionPolicy" field defined in the corresponding VolumeSnapshotClass. For pre-existing snapshots, users MUST specify this field when creating the VolumeSnapshotContent object. Required. + enum: + - Delete + - Retain + type: string + driver: + description: driver is the name of the CSI driver used to create the physical snapshot on the underlying storage system. This MUST be the same as the name returned by the CSI GetPluginName() call for that driver. Required. + type: string + source: + description: source specifies whether the snapshot is (or should be) dynamically provisioned or already exists, and just requires a Kubernetes object representation. This field is immutable after creation. Required. + properties: + snapshotHandle: + description: snapshotHandle specifies the CSI "snapshot_id" of a pre-existing snapshot on the underlying storage system for which a Kubernetes object representation was (or should be) created. This field is immutable. + type: string + volumeHandle: + description: volumeHandle specifies the CSI "volume_id" of the volume from which a snapshot should be dynamically taken from. This field is immutable. + type: string + type: object + volumeSnapshotClassName: + description: name of the VolumeSnapshotClass from which this snapshot was (or will be) created. Note that after provisioning, the VolumeSnapshotClass may be deleted or recreated with different set of values, and as such, should not be referenced post-snapshot creation. + type: string + volumeSnapshotRef: + description: volumeSnapshotRef specifies the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. VolumeSnapshot.Spec.VolumeSnapshotContentName field must reference to this VolumeSnapshotContent's name for the bidirectional binding to be valid. For a pre-existing VolumeSnapshotContent object, name and namespace of the VolumeSnapshot object MUST be provided for binding to happen. This field is immutable after creation. Required. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. TODO: this design is not final and this field is subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + required: + - deletionPolicy + - driver + - source + - volumeSnapshotRef + type: object + status: + description: status represents the current information of a snapshot. + properties: + creationTime: + description: creationTime is the timestamp when the point-in-time snapshot is taken by the underlying storage system. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "creation_time" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "creation_time" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. If not specified, it indicates the creation time is unknown. The format of this field is a Unix nanoseconds time encoded as an int64. On Unix, the command `date +%s%N` returns the current time in nanoseconds since 1970-01-01 00:00:00 UTC. + format: int64 + type: integer + error: + description: error is the last observed error during snapshot creation, if any. Upon success after retry, this error field will be cleared. + properties: + message: + description: 'message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information.' + type: string + time: + description: time is the timestamp when the error was encountered. + format: date-time + type: string + type: object + readyToUse: + description: readyToUse indicates if a snapshot is ready to be used to restore a volume. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "ready_to_use" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "ready_to_use" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, this field will be set to "True". If not specified, it means the readiness of a snapshot is unknown. + type: boolean + restoreSize: + description: restoreSize represents the complete size of the snapshot in bytes. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "size_bytes" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "size_bytes" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. When restoring a volume from this snapshot, the size of the volume MUST NOT be smaller than the restoreSize if it is specified, otherwise the restoration will fail. If not specified, it indicates that the size is unknown. + format: int64 + minimum: 0 + type: integer + snapshotHandle: + description: snapshotHandle is the CSI "snapshot_id" of a snapshot on the underlying storage system. If not specified, it indicates that dynamic snapshot creation has either failed or it is still in progress. + type: string + type: object + required: + - spec + type: object + served: false + storage: false + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/crds/snapshot.storage.k8s.io_volumesnapshots.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/crds/snapshot.storage.k8s.io_volumesnapshots.yaml new file mode 100644 index 00000000..6b96d708 --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/crds/snapshot.storage.k8s.io_volumesnapshots.yaml @@ -0,0 +1,351 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/814" + name: volumesnapshots.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshot + listKind: VolumeSnapshotList + plural: volumesnapshots + shortNames: + - vs + singular: volumesnapshot + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Indicates if the snapshot is ready to be used to restore a volume. + jsonPath: .status.readyToUse + name: ReadyToUse + type: boolean + - description: If a new snapshot needs to be created, this contains the name of + the source PVC from which this snapshot was (or will be) created. + jsonPath: .spec.source.persistentVolumeClaimName + name: SourcePVC + type: string + - description: If a snapshot already exists, this contains the name of the existing + VolumeSnapshotContent object representing the existing snapshot. + jsonPath: .spec.source.volumeSnapshotContentName + name: SourceSnapshotContent + type: string + - description: Represents the minimum size of volume required to rehydrate from + this snapshot. + jsonPath: .status.restoreSize + name: RestoreSize + type: string + - description: The name of the VolumeSnapshotClass requested by the VolumeSnapshot. + jsonPath: .spec.volumeSnapshotClassName + name: SnapshotClass + type: string + - description: Name of the VolumeSnapshotContent object to which the VolumeSnapshot + object intends to bind to. Please note that verification of binding actually + requires checking both VolumeSnapshot and VolumeSnapshotContent to ensure + both are pointing at each other. Binding MUST be verified prior to usage of + this object. + jsonPath: .status.boundVolumeSnapshotContentName + name: SnapshotContent + type: string + - description: Timestamp when the point-in-time snapshot was taken by the underlying + storage system. + jsonPath: .status.creationTime + name: CreationTime + type: date + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: |- + VolumeSnapshot is a user's request for either creating a point-in-time + snapshot of a persistent volume, or binding to a pre-existing snapshot. + 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: |- + spec defines the desired characteristics of a snapshot requested by a user. + More info: https://kubernetes.io/docs/concepts/storage/volume-snapshots#volumesnapshots + Required. + properties: + source: + description: |- + source specifies where a snapshot will be created from. + This field is immutable after creation. + Required. + properties: + persistentVolumeClaimName: + description: |- + persistentVolumeClaimName specifies the name of the PersistentVolumeClaim + object representing the volume from which a snapshot should be created. + This PVC is assumed to be in the same namespace as the VolumeSnapshot + object. + This field should be set if the snapshot does not exists, and needs to be + created. + This field is immutable. + type: string + x-kubernetes-validations: + - message: persistentVolumeClaimName is immutable + rule: self == oldSelf + volumeSnapshotContentName: + description: |- + volumeSnapshotContentName specifies the name of a pre-existing VolumeSnapshotContent + object representing an existing volume snapshot. + This field should be set if the snapshot already exists and only needs a representation in Kubernetes. + This field is immutable. + type: string + x-kubernetes-validations: + - message: volumeSnapshotContentName is immutable + rule: self == oldSelf + type: object + x-kubernetes-validations: + - message: persistentVolumeClaimName is required once set + rule: '!has(oldSelf.persistentVolumeClaimName) || has(self.persistentVolumeClaimName)' + - message: volumeSnapshotContentName is required once set + rule: '!has(oldSelf.volumeSnapshotContentName) || has(self.volumeSnapshotContentName)' + - message: exactly one of volumeSnapshotContentName and persistentVolumeClaimName + must be set + rule: (has(self.volumeSnapshotContentName) && !has(self.persistentVolumeClaimName)) + || (!has(self.volumeSnapshotContentName) && has(self.persistentVolumeClaimName)) + volumeSnapshotClassName: + description: |- + VolumeSnapshotClassName is the name of the VolumeSnapshotClass + requested by the VolumeSnapshot. + VolumeSnapshotClassName may be left nil to indicate that the default + SnapshotClass should be used. + A given cluster may have multiple default Volume SnapshotClasses: one + default per CSI Driver. If a VolumeSnapshot does not specify a SnapshotClass, + VolumeSnapshotSource will be checked to figure out what the associated + CSI Driver is, and the default VolumeSnapshotClass associated with that + CSI Driver will be used. If more than one VolumeSnapshotClass exist for + a given CSI Driver and more than one have been marked as default, + CreateSnapshot will fail and generate an event. + Empty string is not allowed for this field. + type: string + x-kubernetes-validations: + - message: volumeSnapshotClassName must not be the empty string when + set + rule: size(self) > 0 + required: + - source + type: object + status: + description: |- + status represents the current information of a snapshot. + Consumers must verify binding between VolumeSnapshot and + VolumeSnapshotContent objects is successful (by validating that both + VolumeSnapshot and VolumeSnapshotContent point at each other) before + using this object. + properties: + boundVolumeSnapshotContentName: + description: |- + boundVolumeSnapshotContentName is the name of the VolumeSnapshotContent + object to which this VolumeSnapshot object intends to bind to. + If not specified, it indicates that the VolumeSnapshot object has not been + successfully bound to a VolumeSnapshotContent object yet. + NOTE: To avoid possible security issues, consumers must verify binding between + VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that + both VolumeSnapshot and VolumeSnapshotContent point at each other) before using + this object. + type: string + creationTime: + description: |- + creationTime is the timestamp when the point-in-time snapshot is taken + by the underlying storage system. + In dynamic snapshot creation case, this field will be filled in by the + snapshot controller with the "creation_time" value returned from CSI + "CreateSnapshot" gRPC call. + For a pre-existing snapshot, this field will be filled with the "creation_time" + value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. + If not specified, it may indicate that the creation time of the snapshot is unknown. + format: date-time + type: string + error: + description: |- + error is the last observed error during snapshot creation, if any. + This field could be helpful to upper level controllers(i.e., application controller) + to decide whether they should continue on waiting for the snapshot to be created + based on the type of error reported. + The snapshot controller will keep retrying when an error occurs during the + snapshot creation. Upon success, this error field will be cleared. + properties: + message: + description: |- + message is a string detailing the encountered error during snapshot + creation if specified. + NOTE: message may be logged, and it should not contain sensitive + information. + type: string + time: + description: time is the timestamp when the error was encountered. + format: date-time + type: string + type: object + readyToUse: + description: |- + readyToUse indicates if the snapshot is ready to be used to restore a volume. + In dynamic snapshot creation case, this field will be filled in by the + snapshot controller with the "ready_to_use" value returned from CSI + "CreateSnapshot" gRPC call. + For a pre-existing snapshot, this field will be filled with the "ready_to_use" + value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, + otherwise, this field will be set to "True". + If not specified, it means the readiness of a snapshot is unknown. + type: boolean + restoreSize: + type: string + description: |- + restoreSize represents the minimum size of volume required to create a volume + from this snapshot. + In dynamic snapshot creation case, this field will be filled in by the + snapshot controller with the "size_bytes" value returned from CSI + "CreateSnapshot" gRPC call. + For a pre-existing snapshot, this field will be filled with the "size_bytes" + value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. + When restoring a volume from this snapshot, the size of the volume MUST NOT + be smaller than the restoreSize if it is specified, otherwise the restoration will fail. + If not specified, it indicates that the size is unknown. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + volumeGroupSnapshotName: + description: |- + VolumeGroupSnapshotName is the name of the VolumeGroupSnapshot of which this + VolumeSnapshot is a part of. + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - description: Indicates if the snapshot is ready to be used to restore a volume. + jsonPath: .status.readyToUse + name: ReadyToUse + type: boolean + - description: If a new snapshot needs to be created, this contains the name of the source PVC from which this snapshot was (or will be) created. + jsonPath: .spec.source.persistentVolumeClaimName + name: SourcePVC + type: string + - description: If a snapshot already exists, this contains the name of the existing VolumeSnapshotContent object representing the existing snapshot. + jsonPath: .spec.source.volumeSnapshotContentName + name: SourceSnapshotContent + type: string + - description: Represents the minimum size of volume required to rehydrate from this snapshot. + jsonPath: .status.restoreSize + name: RestoreSize + type: string + - description: The name of the VolumeSnapshotClass requested by the VolumeSnapshot. + jsonPath: .spec.volumeSnapshotClassName + name: SnapshotClass + type: string + - description: Name of the VolumeSnapshotContent object to which the VolumeSnapshot object intends to bind to. Please note that verification of binding actually requires checking both VolumeSnapshot and VolumeSnapshotContent to ensure both are pointing at each other. Binding MUST be verified prior to usage of this object. + jsonPath: .status.boundVolumeSnapshotContentName + name: SnapshotContent + type: string + - description: Timestamp when the point-in-time snapshot was taken by the underlying storage system. + jsonPath: .status.creationTime + name: CreationTime + type: date + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + # This indicates the v1beta1 version of the custom resource is deprecated. + # API requests to this version receive a warning in the server response. + deprecated: true + # This overrides the default warning returned to clients making v1beta1 API requests. + deprecationWarning: "snapshot.storage.k8s.io/v1beta1 VolumeSnapshot is deprecated; use snapshot.storage.k8s.io/v1 VolumeSnapshot" + schema: + openAPIV3Schema: + description: VolumeSnapshot is a user's request for either creating a point-in-time snapshot of a persistent volume, or binding to a pre-existing snapshot. + 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 + spec: + description: 'spec defines the desired characteristics of a snapshot requested by a user. More info: https://kubernetes.io/docs/concepts/storage/volume-snapshots#volumesnapshots Required.' + properties: + source: + description: source specifies where a snapshot will be created from. This field is immutable after creation. Required. + properties: + persistentVolumeClaimName: + description: persistentVolumeClaimName specifies the name of the PersistentVolumeClaim object representing the volume from which a snapshot should be created. This PVC is assumed to be in the same namespace as the VolumeSnapshot object. This field should be set if the snapshot does not exists, and needs to be created. This field is immutable. + type: string + volumeSnapshotContentName: + description: volumeSnapshotContentName specifies the name of a pre-existing VolumeSnapshotContent object representing an existing volume snapshot. This field should be set if the snapshot already exists and only needs a representation in Kubernetes. This field is immutable. + type: string + type: object + volumeSnapshotClassName: + description: 'VolumeSnapshotClassName is the name of the VolumeSnapshotClass requested by the VolumeSnapshot. VolumeSnapshotClassName may be left nil to indicate that the default SnapshotClass should be used. A given cluster may have multiple default Volume SnapshotClasses: one default per CSI Driver. If a VolumeSnapshot does not specify a SnapshotClass, VolumeSnapshotSource will be checked to figure out what the associated CSI Driver is, and the default VolumeSnapshotClass associated with that CSI Driver will be used. If more than one VolumeSnapshotClass exist for a given CSI Driver and more than one have been marked as default, CreateSnapshot will fail and generate an event. Empty string is not allowed for this field.' + type: string + required: + - source + type: object + status: + description: status represents the current information of a snapshot. Consumers must verify binding between VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that both VolumeSnapshot and VolumeSnapshotContent point at each other) before using this object. + properties: + boundVolumeSnapshotContentName: + description: 'boundVolumeSnapshotContentName is the name of the VolumeSnapshotContent object to which this VolumeSnapshot object intends to bind to. If not specified, it indicates that the VolumeSnapshot object has not been successfully bound to a VolumeSnapshotContent object yet. NOTE: To avoid possible security issues, consumers must verify binding between VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that both VolumeSnapshot and VolumeSnapshotContent point at each other) before using this object.' + type: string + creationTime: + description: creationTime is the timestamp when the point-in-time snapshot is taken by the underlying storage system. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "creation_time" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "creation_time" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. If not specified, it may indicate that the creation time of the snapshot is unknown. + format: date-time + type: string + error: + description: error is the last observed error during snapshot creation, if any. This field could be helpful to upper level controllers(i.e., application controller) to decide whether they should continue on waiting for the snapshot to be created based on the type of error reported. The snapshot controller will keep retrying when an error occurs during the snapshot creation. Upon success, this error field will be cleared. + properties: + message: + description: 'message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information.' + type: string + time: + description: time is the timestamp when the error was encountered. + format: date-time + type: string + type: object + readyToUse: + description: readyToUse indicates if the snapshot is ready to be used to restore a volume. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "ready_to_use" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "ready_to_use" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, this field will be set to "True". If not specified, it means the readiness of a snapshot is unknown. + type: boolean + restoreSize: + type: string + description: restoreSize represents the minimum size of volume required to create a volume from this snapshot. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "size_bytes" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "size_bytes" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. When restoring a volume from this snapshot, the size of the volume MUST NOT be smaller than the restoreSize if it is specified, otherwise the restoration will fail. If not specified, it indicates that the size is unknown. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - spec + type: object + served: false + storage: false + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/NOTES.txt b/packages/system/snapshot-controller/charts/snapshot-controller/templates/NOTES.txt new file mode 100644 index 00000000..5880eb7e --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/NOTES.txt @@ -0,0 +1,30 @@ +{{- if .Values.controller.enabled }} +Volume Snapshot Controller installed. +{{- end }} +{{- if .Values.webhook.enabled }} +Validation for VolumeSnapshots installed. +{{- end }} + +{{- if and (not (.Capabilities.APIVersions.Has "snapshot.storage.k8s.io/v1")) (not (.Capabilities.APIVersions.Has "snapshot.storage.k8s.io/v1beta") ) }} +Please install the snapshot CRDs, otherwise the controller will not run. + +kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/{{ .Chart.AppVersion }}/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/{{ .Chart.AppVersion }}/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml +kubectl apply -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/{{ .Chart.AppVersion }}/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml +{{- else if .Release.IsUpgrade }} +It looks like you are upgrading from a previous release. Helm currently does not support upgrading CRDs, so to ensure +you have the latest CRDs applied, you can run the following commands: + +kubectl replace -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/{{ .Chart.AppVersion }}/client/config/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml +kubectl replace -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/{{ .Chart.AppVersion }}/client/config/crd/snapshot.storage.k8s.io_volumesnapshots.yaml +kubectl replace -f https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/{{ .Chart.AppVersion }}/client/config/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml +{{- end }} + +If you already have volume snapshots deployed using a CRDs before v1, you should +verify that the existing snapshots are upgradable to v1 CRDs. The snapshot controller (>= v3.0.0) +will label any invalid snapshots it can find. Use the following commands to find any invalid snapshot + +kubectl get volumesnapshots --selector=snapshot.storage.kubernetes.io/invalid-snapshot-resource="" --all-namespaces +kubectl get volumesnapshotcontents --selector=snapshot.storage.kubernetes.io/invalid-snapshot-resource="" --all-namespaces + +If the above commands return any items, you need to remove them before upgrading to the newer v1 CRDs. diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/_helpers.tpl b/packages/system/snapshot-controller/charts/snapshot-controller/templates/_helpers.tpl new file mode 100644 index 00000000..5b2fcd1f --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/_helpers.tpl @@ -0,0 +1,134 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "snapshot-controller.name" -}} +{{- .Chart.Name | 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 "snapshot-controller.fullname" -}} +{{- if .Values.controller.fullnameOverride -}} +{{- .Values.controller.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- if contains .Chart.Name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "snapshot-controller.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "snapshot-controller.labels" -}} +helm.sh/chart: {{ include "snapshot-controller.chart" . }} +{{ include "snapshot-controller.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "snapshot-controller.selectorLabels" -}} +app.kubernetes.io/name: {{ include "snapshot-controller.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "snapshot-controller.serviceAccountName" -}} +{{- if .Values.controller.serviceAccount.create -}} + {{ default (include "snapshot-controller.fullname" .) .Values.controller.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.controller.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "snapshot-validation-webhook.name" -}} +{{- "snapshot-validation-webhook" | 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 "snapshot-validation-webhook.fullname" -}} +{{- if .Values.webhook.fullnameOverride -}} +{{- .Values.webhook.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- if contains .Chart.Name .Release.Name }} +{{- "snapshot-validation-webhook" }} +{{- else }} +{{- printf "%s-%s" .Release.Name "snapshot-validation-webhook" | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "snapshot-validation-webhook.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "snapshot-validation-webhook.labels" -}} +helm.sh/chart: {{ include "snapshot-validation-webhook.chart" . }} +{{ include "snapshot-validation-webhook.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "snapshot-validation-webhook.selectorLabels" -}} +app.kubernetes.io/name: {{ include "snapshot-validation-webhook.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "snapshot-validation-webhook.serviceAccountName" -}} +{{- if .Values.webhook.serviceAccount.create -}} + {{ default (include "snapshot-validation-webhook.fullname" .) .Values.webhook.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.webhook.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Certificate secret name +*/}} +{{- define "snapshot-validation-webhook.certifcateName" -}} +{{- if .Values.webhook.tls.certificateSecret }} +{{- .Values.webhook.tls.certificateSecret }} +{{- else }} +{{- include "snapshot-validation-webhook.fullname" . }}-tls +{{- end }} +{{- end }} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/deployment_controller.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/templates/deployment_controller.yaml new file mode 100644 index 00000000..4fa022a7 --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/deployment_controller.yaml @@ -0,0 +1,89 @@ +{{- if .Values.controller.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "snapshot-controller.fullname" . }} + labels: + {{- include "snapshot-controller.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.controller.replicaCount }} + revisionHistoryLimit: {{ .Values.controller.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "snapshot-controller.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.controller.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "snapshot-controller.selectorLabels" . | nindent 8 }} + {{- with .Values.controller.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.controller.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "snapshot-controller.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.controller.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.controller.securityContext | nindent 12 }} + image: "{{ .Values.controller.image.repository }}:{{ .Values.controller.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.controller.image.pullPolicy }} + args: + {{- range $flag, $val := .Values.controller.args }} + - --{{ $flag | kebabcase }}={{ $val }} + {{- end }} + ports: + - name: http + containerPort: 8080 + protocol: TCP + readinessProbe: + httpGet: + port: http + path: /healthz/leader-election + scheme: HTTP + livenessProbe: + httpGet: + port: http + path: /healthz/leader-election + scheme: HTTP + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + resources: + {{- toYaml .Values.controller.resources | nindent 12 }} + {{- with .Values.controller.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.controller.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.controller.priorityClassName }} + priorityClassName: {{ .Values.controller.priorityClassName }} + {{- end }} + hostNetwork: {{ .Values.controller.hostNetwork }} + {{- with .Values.controller.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + dnsPolicy: {{ .Values.controller.dnsPolicy }} +{{- end }} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/deployment_validation_webhook.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/templates/deployment_validation_webhook.yaml new file mode 100644 index 00000000..ad24b32b --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/deployment_validation_webhook.yaml @@ -0,0 +1,91 @@ +{{- if .Values.webhook.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "snapshot-validation-webhook.fullname" . }} + labels: + {{- include "snapshot-validation-webhook.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.webhook.replicaCount }} + revisionHistoryLimit: {{ .Values.webhook.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "snapshot-validation-webhook.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.webhook.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "snapshot-validation-webhook.selectorLabels" . | nindent 8 }} + {{- with .Values.webhook.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.webhook.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "snapshot-validation-webhook.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.webhook.podSecurityContext | nindent 8 }} + {{- with .Values.webhook.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + containers: + - name: {{ include "snapshot-validation-webhook.name" . }} + securityContext: + {{- toYaml .Values.webhook.securityContext | nindent 12 }} + image: "{{ .Values.webhook.image.repository }}:{{ .Values.webhook.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.webhook.image.pullPolicy }} + args: + {{- range $flag, $val := .Values.webhook.args }} + - --{{ $flag | kebabcase }}={{ $val }} + {{- end }} + ports: + - name: https + containerPort: {{ .Values.webhook.args.port | default 8443 }} + protocol: TCP + volumeMounts: + - mountPath: /etc/snapshot-validation + name: tls-config + livenessProbe: + httpGet: + path: /readyz + port: https + scheme: HTTPS + readinessProbe: + httpGet: + path: /readyz + port: https + scheme: HTTPS + resources: + {{- toYaml .Values.webhook.resources | nindent 12 }} + volumes: + - name: tls-config + secret: + secretName: {{ include "snapshot-validation-webhook.certifcateName" . }} + {{- with .Values.webhook.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.webhook.topologySpreadConstraints }} + topologySpreadConstraints: + {{- toYaml .Values.webhook.topologySpreadConstraints | nindent 8 }} + {{- end }} + {{- with .Values.webhook.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + hostNetwork: {{ .Values.webhook.hostNetwork }} + {{- with .Values.webhook.dnsConfig }} + dnsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + dnsPolicy: {{ .Values.webhook.dnsPolicy }} +{{- end }} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/networkpolicy.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/templates/networkpolicy.yaml new file mode 100644 index 00000000..49c8049f --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/networkpolicy.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.webhook.enabled .Values.webhook.networkPolicy.enabled -}} +kind: NetworkPolicy +apiVersion: networking.k8s.io/v1 +metadata: + name: {{ include "snapshot-validation-webhook.fullname" . }} + labels: + {{- include "snapshot-validation-webhook.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "snapshot-validation-webhook.selectorLabels" . | nindent 6 }} + ingress: + - from: + - podSelector: + matchLabels: + {{- include "snapshot-validation-webhook.selectorLabels" . | nindent 12 }} + {{- with .Values.webhook.networkPolicy.ingress }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end -}} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/poddisruptionbudget_controller.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/templates/poddisruptionbudget_controller.yaml new file mode 100644 index 00000000..88fa179f --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/poddisruptionbudget_controller.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.controller.enabled .Values.controller.pdb }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "snapshot-controller.fullname" . }} + labels: + {{- include "snapshot-controller.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "snapshot-controller.selectorLabels" . | nindent 6 }} +{{ toYaml .Values.controller.pdb | indent 2 }} +{{- end }} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/poddisruptionbudget_validation_webhook.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/templates/poddisruptionbudget_validation_webhook.yaml new file mode 100644 index 00000000..af4a0cce --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/poddisruptionbudget_validation_webhook.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.webhook.enabled .Values.webhook.pdb -}} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "snapshot-validation-webhook.fullname" . }} + labels: + {{- include "snapshot-validation-webhook.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "snapshot-validation-webhook.selectorLabels" . | nindent 6 }} +{{ toYaml .Values.webhook.pdb | indent 2 }} +{{- end -}} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/service_controller.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/templates/service_controller.yaml new file mode 100644 index 00000000..4581dc18 --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/service_controller.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.controller.enabled .Values.controller.serviceMonitor.create }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "snapshot-controller.fullname" . }} + labels: + {{- include "snapshot-controller.labels" . | nindent 4 }} +spec: + clusterIP: None + ports: + - port: {{ (.Values.controller.args.httpEndpoint | split ":")._1 }} + targetPort: {{ (.Values.controller.args.httpEndpoint | split ":")._1 }} + name: http + selector: + {{- include "snapshot-controller.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/service_validation_webhook.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/templates/service_validation_webhook.yaml new file mode 100644 index 00000000..bf73511a --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/service_validation_webhook.yaml @@ -0,0 +1,17 @@ +{{- if .Values.webhook.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "snapshot-validation-webhook.fullname" . }} + labels: + {{- include "snapshot-validation-webhook.labels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: 443 + targetPort: https + protocol: TCP + name: https + selector: + {{- include "snapshot-validation-webhook.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/serviceaccount_controller.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/templates/serviceaccount_controller.yaml new file mode 100644 index 00000000..07b2bf3c --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/serviceaccount_controller.yaml @@ -0,0 +1,96 @@ +{{- if .Values.controller.enabled }} +{{- if .Values.controller.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "snapshot-controller.serviceAccountName" . }} + labels: + {{- include "snapshot-controller.labels" . | nindent 4 }} +{{- end }} +--- +{{- if .Values.controller.rbac.create }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "snapshot-controller.fullname" . }} +rules: + - apiGroups: [""] + resources: ["persistentvolumes"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["persistentvolumeclaims"] + verbs: ["get", "list", "watch", "update"] + - apiGroups: [""] + resources: ["events"] + verbs: ["list", "watch", "create", "update", "patch"] + - 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: ["patch"] + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshots"] + verbs: ["get", "list", "watch", "update", "patch", "delete"] + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshots/status"] + verbs: ["update", "patch"] + - apiGroups: ["groupsnapshot.storage.k8s.io"] + resources: ["volumegroupsnapshotclasses"] + verbs: ["get", "list", "watch"] + - apiGroups: ["groupsnapshot.storage.k8s.io"] + resources: ["volumegroupsnapshotcontents"] + verbs: ["create", "get", "list", "watch", "update", "delete", "patch"] + - apiGroups: ["groupsnapshot.storage.k8s.io"] + resources: ["volumegroupsnapshotcontents/status"] + verbs: ["patch"] + - apiGroups: ["groupsnapshot.storage.k8s.io"] + resources: ["volumegroupsnapshots"] + verbs: ["get", "list", "watch", "update", "patch"] + - apiGroups: ["groupsnapshot.storage.k8s.io"] + resources: ["volumegroupsnapshots/status"] + verbs: ["update", "patch"] + {{- if get .Values.controller.args "enableDistributedSnapshotting" }} + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] + {{- end }} +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "snapshot-controller.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "snapshot-controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ include "snapshot-controller.fullname" . }} + apiGroup: rbac.authorization.k8s.io +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "snapshot-controller.fullname" . }} +rules: + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "watch", "list", "delete", "update", "create"] +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "snapshot-controller.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "snapshot-controller.serviceAccountName" . }} +roleRef: + kind: Role + name: {{ include "snapshot-controller.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} +{{- end }} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/serviceaccount_validation_webhook.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/templates/serviceaccount_validation_webhook.yaml new file mode 100644 index 00000000..f1bbebe0 --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/serviceaccount_validation_webhook.yaml @@ -0,0 +1,38 @@ +{{- if .Values.webhook.enabled }} +{{- if .Values.webhook.serviceAccount.create }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "snapshot-validation-webhook.serviceAccountName" . }} + labels: + {{- include "snapshot-validation-webhook.labels" . | nindent 4 }} +{{- end }} +{{- if .Values.webhook.rbac.create }} +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "snapshot-validation-webhook.fullname" . }} +rules: + - apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshotclasses"] + verbs: ["get", "list", "watch"] + - apiGroups: ["groupsnapshot.storage.k8s.io"] + resources: ["volumegroupsnapshotclasses"] + verbs: ["get", "list", "watch"] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "snapshot-validation-webhook.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "snapshot-validation-webhook.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ include "snapshot-validation-webhook.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} +{{- end }} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/servicemonitor.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/templates/servicemonitor.yaml new file mode 100644 index 00000000..54a7f293 --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/servicemonitor.yaml @@ -0,0 +1,15 @@ +{{- if and .Values.controller.enabled .Values.controller.serviceMonitor.create }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "snapshot-controller.fullname" . }} + labels: + {{- include "snapshot-controller.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "snapshot-controller.selectorLabels" . | nindent 6 }} + endpoints: + - port: http + path: /metrics +{{- end }} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/volumesnapshotclass.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/templates/volumesnapshotclass.yaml new file mode 100644 index 00000000..a88f7e8e --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/volumesnapshotclass.yaml @@ -0,0 +1,22 @@ +{{- if .Values.controller.enabled }} +{{- range .Values.controller.volumeSnapshotClasses }} +--- +kind: VolumeSnapshotClass +apiVersion: snapshot.storage.k8s.io/v1 +metadata: + name: {{ .name }} +{{- with .annotations }} + annotations: {{- . | toYaml | trim | nindent 4 }} +{{- end }} + labels: + {{- include "snapshot-controller.labels" $ | nindent 4 }} +{{- with .labels }} + {{- . | toYaml | trim | nindent 4 }} +{{- end }} +driver: {{ .driver }} +deletionPolicy: {{ .deletionPolicy }} +{{- with .parameters }} +parameters: {{- . | toYaml | trim | nindent 2 }} +{{- end }} +{{- end }} +{{- end }} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/templates/webhook.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/templates/webhook.yaml new file mode 100644 index 00000000..d18b1480 --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/templates/webhook.yaml @@ -0,0 +1,112 @@ +{{- if .Values.webhook.enabled }} +# Check if the TLS secret already exists and initialize variables for later use at the top level +{{- $secret := lookup "v1" "Secret" .Release.Namespace (include "snapshot-validation-webhook.certifcateName" .) }} +{{ $ca := "" }} +{{ $key := "" }} +{{ $crt := "" }} +--- +{{- if .Values.webhook.tls.certManagerIssuerRef }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ include "snapshot-validation-webhook.fullname" . }} + labels: + {{- include "snapshot-validation-webhook.labels" . | nindent 4 }} +spec: + secretName: {{ include "snapshot-validation-webhook.certifcateName" . }} + dnsNames: + - {{ include "snapshot-validation-webhook.fullname" . }}.{{ .Release.Namespace }}.svc + issuerRef: + {{- toYaml .Values.webhook.tls.certManagerIssuerRef | nindent 4 }} + privateKey: + rotationPolicy: Always +--- +{{- else if .Values.webhook.tls.autogenerate }} + {{- if and $secret (not .Values.webhook.tls.renew) }} + {{- $ca = get $secret.data "ca.crt" }} + {{- $key = get $secret.data "tls.key" }} + {{- $crt = get $secret.data "tls.crt" }} + {{- else }} + {{- $serviceName := (printf "%s.%s.svc" (include "snapshot-validation-webhook.fullname" .) .Release.Namespace)}} + {{- $cert := genSelfSignedCert $serviceName nil (list $serviceName) 3650 }} + {{- $ca = b64enc $cert.Cert }} + {{- $key = b64enc $cert.Key }} + {{- $crt = b64enc $cert.Cert }} + {{- end }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "snapshot-validation-webhook.certifcateName" . }} + labels: + {{- include "snapshot-validation-webhook.labels" . | nindent 4 }} +type: kubernetes.io/tls +data: + ca.crt: {{ $ca }} + tls.key: {{ $key }} + tls.crt: {{ $crt }} +--- +{{- end }} +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ include "snapshot-validation-webhook.fullname" . }} + labels: + {{- include "snapshot-validation-webhook.labels" . | nindent 4 }} + {{- if .Values.webhook.tls.certManagerIssuerRef }} + annotations: + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "snapshot-validation-webhook.fullname" . }} + {{- end }} +webhooks: + - name: {{ include "snapshot-validation-webhook.name" . }}.snapshot.storage.k8s.io + rules: + - apiGroups: + - snapshot.storage.k8s.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - volumesnapshotclasses + scope: "*" + clientConfig: + service: + namespace: {{ .Release.Namespace }} + name: {{ include "snapshot-validation-webhook.fullname" . }} + path: "/volumesnapshot" + {{- if not .Values.webhook.tls.certManagerIssuerRef }} + caBundle: {{ $ca }} + {{- end }} + admissionReviewVersions: + - v1 + - v1beta1 + sideEffects: None + failurePolicy: {{ .Values.webhook.webhook.failurePolicy }} + timeoutSeconds: {{ .Values.webhook.webhook.timeoutSeconds }} + - name: {{ include "snapshot-validation-webhook.name" . }}.groupsnapshot.storage.k8s.io + rules: + - apiGroups: + - groupsnapshot.storage.k8s.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - volumegroupsnapshotclasses + scope: "*" + clientConfig: + service: + namespace: {{ .Release.Namespace }} + name: {{ include "snapshot-validation-webhook.fullname" . }} + path: "/volumegroupsnapshot" + {{- if not .Values.webhook.tls.certManagerIssuerRef }} + caBundle: {{ $ca }} + {{- end }} + admissionReviewVersions: + - v1 + - v1beta1 + sideEffects: None + failurePolicy: {{ .Values.webhook.webhook.failurePolicy }} + timeoutSeconds: {{ .Values.webhook.webhook.timeoutSeconds }} +{{- end }} diff --git a/packages/system/snapshot-controller/charts/snapshot-controller/values.yaml b/packages/system/snapshot-controller/charts/snapshot-controller/values.yaml new file mode 100644 index 00000000..38acb2b5 --- /dev/null +++ b/packages/system/snapshot-controller/charts/snapshot-controller/values.yaml @@ -0,0 +1,180 @@ +controller: + enabled: true + + replicaCount: 1 + + revisionHistoryLimit: 10 + + args: + leaderElection: true + leaderElectionNamespace: "$(NAMESPACE)" + httpEndpoint: ":8080" + + image: + repository: registry.k8s.io/sig-storage/snapshot-controller + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + + imagePullSecrets: [] + + podAnnotations: {} + + podLabels: {} + + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + + resources: {} + + nodeSelector: {} + + tolerations: [] + + affinity: {} + + ## Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + ## + pdb: {} + + topologySpreadConstraints: [] + + rbac: + # Specifies whether RBAC resources should be created + create: true + + serviceAccount: + # Specifies whether a ServiceAccount should be created + create: true + name: "" + + serviceMonitor: + # Specifies whether a ServiceMonitor should be created + create: false + + volumeSnapshotClasses: [] +# - name: linstor-csi-delete +# annotations: +# snapshot.storage.kubernetes.io/is-default-class: "true" +# labels: +# velero.io/csi-volumesnapshot-class: "true" +# driver: linstor.csi.linbit.com +# deletionPolicy: Delete + + priorityClassName: "" + # Specifies wether a Priority Class should be attached to deployment pods + + # Change `hostNetwork` to `true` when you want the pod to share its host's network namespace. + hostNetwork: false + + # DNS settings for the controller pod. https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config + dnsConfig: {} + # DNS Policy for controller pod. For Pods running with hostNetwork, set to `ClusterFirstWithHostNet` + # For further reference: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy. + dnsPolicy: ClusterFirst + +webhook: + enabled: true + + replicaCount: 1 + + revisionHistoryLimit: 10 + + args: + tlsPrivateKeyFile: /etc/snapshot-validation/tls.key + tlsCertFile: /etc/snapshot-validation/tls.crt + port: 8443 + # enableVolumeGroupSnapshotWebhook: true + + image: + repository: registry.k8s.io/sig-storage/snapshot-validation-webhook + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + + webhook: + timeoutSeconds: 2 + failurePolicy: Fail + + tls: + certificateSecret: "" + autogenerate: true + renew: false + certManagerIssuerRef: {} + + imagePullSecrets: [] + podAnnotations: {} + podLabels: {} + + networkPolicy: + enabled: false + ingress: {} + # - from: + # - ipBlock: + # cidr: 0.0.0.0/0 + + ## Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ + ## + pdb: {} + + priorityClassName: + + ## Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/ + ## + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: topology.kubernetes.io/zone + # whenUnsatisfiable: ScheduleAnyway + # labelSelector: + # matchLabels: + # app.kubernetes.io/instance: snapshot-validation-webhook + + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + + resources: {} + + nodeSelector: {} + + tolerations: [] + + affinity: {} + + serviceAccount: + create: true + name: "" + + rbac: + create: true + + # Change `hostNetwork` to `true` when you want the pod to share its host's network namespace. + hostNetwork: false + + # DNS settings for the webhook pod. https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config + dnsConfig: {} + # DNS Policy for webhook pod. For Pods running with hostNetwork, set to `ClusterFirstWithHostNet` + # For further reference: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy. + dnsPolicy: ClusterFirst + + tests: + nodeSelector: { } + + tolerations: [ ] + + affinity: { } diff --git a/packages/system/snapshot-controller/values.yaml b/packages/system/snapshot-controller/values.yaml new file mode 100644 index 00000000..667d7a9e --- /dev/null +++ b/packages/system/snapshot-controller/values.yaml @@ -0,0 +1,13 @@ +snapshot-controller: + controller: + replicaCount: 2 + revisionHistoryLimit: 10 + webhook: + replicaCount: 2 + revisionHistoryLimit: 10 + hostNetwork: false + dnsPolicy: ClusterFirst + tls: + certManagerIssuerRef: + name: selfsigned-cluster-issuer + kind: ClusterIssuer