From 732fd26820ef8a643ee38b5a61e2871c93fe9011 Mon Sep 17 00:00:00 2001 From: Samuel Attwood Date: Thu, 16 Jun 2022 15:08:11 -0400 Subject: [PATCH] Updating assets, charts, and index.yaml --- assets/dkube/dkube-deployer-1.0.601.tgz | Bin 0 -> 9790 bytes .../external-secrets-0.5.600.tgz | Bin 0 -> 39791 bytes .../k8s-triliovault-operator-2.9.300.tgz | Bin 0 -> 97439 bytes .../portworx-essentials-2.9.100.tgz | Bin 0 -> 25977 bytes assets/portworx/portworx-2.9.101.tgz | Bin 0 -> 25613 bytes .../dkube/dkube-deployer/1.0.601/.helmignore | 23 + .../dkube/dkube-deployer/1.0.601/Chart.yaml | 19 + .../dkube-deployer/1.0.601/app-readme.md | 25 + .../dkube-deployer/1.0.601/questions.yaml | 326 +++ .../1.0.601/templates/NOTES.txt | 7 + .../1.0.601/templates/_helpers.tpl | 53 + .../1.0.601/templates/config-map.yaml | 167 ++ .../1.0.601/templates/hooks/uninstall.yaml | 47 + .../1.0.601/templates/hooks/upgrade.yaml | 67 + .../1.0.601/templates/install.yaml | 41 + .../1.0.601/templates/secrets.yaml | 10 + .../1.0.601/templates/serviceaccount.yaml | 136 ++ .../dkube-deployer/1.0.601/values.schema.json | 205 ++ .../dkube/dkube-deployer/1.0.601/values.yaml | 182 ++ .../external-secrets/0.5.600/.helmignore | 26 + .../external-secrets/0.5.600/Chart.yaml | 19 + .../external-secrets/0.5.600/README.md | 146 ++ .../external-secrets/0.5.600/README.md.gotmpl | 36 + .../external-secrets/0.5.600/app-readme.md | 7 + .../0.5.600/ci/main-values.yaml | 2 + .../external-secrets/0.5.600/questions.yaml | 8 + .../0.5.600/templates/NOTES.txt | 13 + .../0.5.600/templates/_helpers.tpl | 110 + .../templates/cert-controller-deployment.yaml | 94 + .../cert-controller-poddisruptionbudget.yaml | 19 + .../templates/cert-controller-rbac.yaml | 69 + .../templates/cert-controller-service.yaml | 20 + .../cert-controller-serviceaccount.yaml | 13 + .../cert-controller-servicemonitor.yaml | 38 + .../templates/crds/clusterexternalsecret.yaml | 333 +++ .../templates/crds/clustersecretstore.yaml | 2163 ++++++++++++++++ .../templates/crds/externalsecret.yaml | 508 ++++ .../0.5.600/templates/crds/secretstore.yaml | 2166 +++++++++++++++++ .../0.5.600/templates/deployment.yaml | 107 + .../templates/poddisruptionbudget.yaml | 19 + .../0.5.600/templates/rbac.yaml | 227 ++ .../0.5.600/templates/service.yaml | 21 + .../0.5.600/templates/serviceaccount.yaml | 13 + .../0.5.600/templates/servicemonitor.yaml | 39 + .../0.5.600/templates/validatingwebhook.yaml | 64 + .../0.5.600/templates/webhook-deployment.yaml | 105 + .../webhook-poddisruptionbudget.yaml | 20 + .../0.5.600/templates/webhook-secret.yaml | 14 + .../0.5.600/templates/webhook-service.yaml | 31 + .../templates/webhook-serviceaccount.yaml | 13 + .../templates/webhook-servicemonitor.yaml | 38 + .../external-secrets/0.5.600/values.yaml | 313 +++ .../2.9.300/.helmignore | 23 + .../2.9.300/Chart.yaml | 22 + .../k8s-triliovault-operator/2.9.300/LICENSE | 1 + .../2.9.300/README.md | 202 ++ .../2.9.300/charts/observability/Chart.yaml | 21 + .../observability/charts/logging/Chart.yaml | 18 + .../charts/logging/charts/loki/Chart.yaml | 13 + .../logging/charts/loki/templates/NOTES.txt | 3 + .../charts/loki/templates/_helpers.tpl | 75 + .../loki/templates/configmap-alert.yaml | 17 + .../charts/loki/templates/ingress.yaml | 55 + .../charts/loki/templates/networkpolicy.yaml | 26 + .../logging/charts/loki/templates/pdb.yaml | 17 + .../loki/templates/podsecuritypolicy.yaml | 41 + .../charts/loki/templates/prometheusrule.yaml | 23 + .../logging/charts/loki/templates/role.yaml | 20 + .../charts/loki/templates/rolebinding.yaml | 20 + .../logging/charts/loki/templates/secret.yaml | 14 + .../loki/templates/service-headless.yaml | 26 + .../charts/loki/templates/service.yaml | 45 + .../charts/loki/templates/serviceaccount.yaml | 16 + .../charts/loki/templates/servicemonitor.yaml | 38 + .../charts/loki/templates/statefulset.yaml | 160 ++ .../charts/logging/charts/loki/values.yaml | 325 +++ .../charts/logging/charts/promtail/Chart.yaml | 16 + .../charts/promtail/templates/NOTES.txt | 10 + .../charts/promtail/templates/_helpers.tpl | 81 + .../promtail/templates/clusterrole.yaml | 21 + .../templates/clusterrolebinding.yaml | 16 + .../charts/promtail/templates/daemonset.yaml | 132 + .../promtail/templates/extra-manifests.yaml | 4 + .../promtail/templates/networkpolicy.yaml | 126 + .../promtail/templates/podsecuritypolicy.yaml | 10 + .../charts/promtail/templates/role.yaml | 18 + .../promtail/templates/rolebinding.yaml | 16 + .../charts/promtail/templates/secret.yaml | 10 + .../promtail/templates/service-extra.yaml | 52 + .../promtail/templates/service-metrics.yaml | 18 + .../promtail/templates/serviceaccount.yaml | 17 + .../promtail/templates/servicemonitor.yaml | 40 + .../logging/charts/promtail/values.yaml | 430 ++++ .../charts/logging/templates/_helpers.tpl | 50 + .../charts/logging/templates/datasources.yaml | 24 + .../charts/monitoring/Chart.yaml | 16 + .../monitoring/charts/prometheus/Chart.yaml | 22 + .../charts/kube-state-metrics/Chart.yaml | 17 + .../kube-state-metrics/templates/NOTES.txt | 10 + .../kube-state-metrics/templates/_helpers.tpl | 82 + .../templates/clusterrolebinding.yaml | 20 + .../templates/deployment.yaml | 156 ++ .../templates/kubeconfig-secret.yaml | 12 + .../kube-state-metrics/templates/pdb.yaml | 14 + .../templates/podsecuritypolicy.yaml | 39 + .../templates/psp-clusterrole.yaml | 19 + .../templates/psp-clusterrolebinding.yaml | 16 + .../kube-state-metrics/templates/role.yaml | 187 ++ .../templates/rolebinding.yaml | 24 + .../kube-state-metrics/templates/service.yaml | 38 + .../templates/serviceaccount.yaml | 15 + .../templates/servicemonitor.yaml | 66 + .../templates/stsdiscovery-role.yaml | 26 + .../templates/stsdiscovery-rolebinding.yaml | 17 + .../charts/kube-state-metrics/values.yaml | 232 ++ .../charts/prometheus/templates/NOTES.txt | 112 + .../charts/prometheus/templates/_helpers.tpl | 288 +++ .../templates/alertmanager/clusterrole.yaml | 21 + .../alertmanager/clusterrolebinding.yaml | 20 + .../prometheus/templates/alertmanager/cm.yaml | 19 + .../templates/alertmanager/deploy.yaml | 208 ++ .../templates/alertmanager/headless-svc.yaml | 31 + .../templates/alertmanager/ingress.yaml | 57 + .../templates/alertmanager/netpol.yaml | 20 + .../templates/alertmanager/pdb.yaml | 14 + .../templates/alertmanager/psp.yaml | 46 + .../templates/alertmanager/pvc.yaml | 37 + .../templates/alertmanager/role.yaml | 24 + .../templates/alertmanager/rolebinding.yaml | 23 + .../templates/alertmanager/service.yaml | 53 + .../alertmanager/serviceaccount.yaml | 11 + .../templates/alertmanager/sts.yaml | 188 ++ .../templates/node-exporter/daemonset.yaml | 150 ++ .../templates/node-exporter/psp.yaml | 55 + .../templates/node-exporter/role.yaml | 17 + .../templates/node-exporter/rolebinding.yaml | 19 + .../node-exporter/serviceaccount.yaml | 11 + .../templates/node-exporter/svc.yaml | 47 + .../templates/pushgateway/clusterrole.yaml | 21 + .../pushgateway/clusterrolebinding.yaml | 16 + .../templates/pushgateway/deploy.yaml | 119 + .../templates/pushgateway/ingress.yaml | 54 + .../templates/pushgateway/netpol.yaml | 20 + .../prometheus/templates/pushgateway/pdb.yaml | 14 + .../prometheus/templates/pushgateway/psp.yaml | 42 + .../prometheus/templates/pushgateway/pvc.yaml | 31 + .../templates/pushgateway/service.yaml | 41 + .../templates/pushgateway/serviceaccount.yaml | 11 + .../prometheus/templates/pushgateway/vpa.yaml | 20 + .../templates/server/clusterrole.yaml | 48 + .../templates/server/clusterrolebinding.yaml | 16 + .../prometheus/templates/server/cm.yaml | 85 + .../prometheus/templates/server/deploy.yaml | 324 +++ .../templates/server/extra-manifests.yaml | 4 + .../templates/server/headless-svc.yaml | 37 + .../prometheus/templates/server/ingress.yaml | 59 + .../prometheus/templates/server/netpol.yaml | 18 + .../prometheus/templates/server/pdb.yaml | 14 + .../prometheus/templates/server/psp.yaml | 51 + .../prometheus/templates/server/pvc.yaml | 39 + .../templates/server/rolebinding.yaml | 20 + .../prometheus/templates/server/service.yaml | 60 + .../templates/server/serviceaccount.yaml | 13 + .../prometheus/templates/server/sts.yaml | 302 +++ .../prometheus/templates/server/vpa.yaml | 24 + .../monitoring/charts/prometheus/values.yaml | 1855 ++++++++++++++ .../charts/monitoring/templates/_helpers.tpl | 40 + .../monitoring/templates/datasources.yaml | 25 + .../charts/visualization/Chart.yaml | 16 + .../visualization/charts/grafana/Chart.yaml | 14 + .../grafana/dashboards/backup-detail.json | 956 ++++++++ .../grafana/dashboards/backup-overview.json | 762 ++++++ .../grafana/dashboards/backupplan-detail.json | 965 ++++++++ .../dashboards/backupplan-overview.json | 786 ++++++ .../grafana/dashboards/metadata-detail.json | 889 +++++++ .../charts/grafana/dashboards/overview.json | 1093 +++++++++ .../grafana/dashboards/restore-detail.json | 933 +++++++ .../grafana/dashboards/restore-overview.json | 762 ++++++ .../grafana/dashboards/target-detail.json | 1164 +++++++++ .../charts/grafana/templates/NOTES.txt | 54 + .../charts/grafana/templates/_helpers.tpl | 165 ++ .../charts/grafana/templates/_pod.tpl | 748 ++++++ .../charts/grafana/templates/clusterrole.yaml | 25 + .../grafana/templates/clusterrolebinding.yaml | 24 + .../configmap-dashboard-provider.yaml | 29 + .../charts/grafana/templates/configmap.yaml | 88 + .../templates/dashboards-json-configmap.yaml | 36 + .../charts/grafana/templates/deployment.yaml | 50 + .../grafana/templates/extra-manifests.yaml | 4 + .../grafana/templates/headless-service.yaml | 22 + .../charts/grafana/templates/hpa.yaml | 20 + .../templates/image-renderer-deployment.yaml | 121 + .../image-renderer-network-policy.yaml | 76 + .../templates/image-renderer-service.yaml | 30 + .../charts/grafana/templates/ingress.yaml | 78 + .../grafana/templates/networkpolicy.yaml | 37 + .../templates/poddisruptionbudget.yaml | 22 + .../grafana/templates/podsecuritypolicy.yaml | 49 + .../charts/grafana/templates/pvc.yaml | 33 + .../charts/grafana/templates/role.yaml | 32 + .../charts/grafana/templates/rolebinding.yaml | 25 + .../charts/grafana/templates/secret-env.yaml | 14 + .../charts/grafana/templates/secret.yaml | 26 + .../charts/grafana/templates/service.yaml | 51 + .../grafana/templates/serviceaccount.yaml | 14 + .../grafana/templates/servicemonitor.yaml | 44 + .../charts/grafana/templates/statefulset.yaml | 52 + .../visualization/charts/grafana/values.yaml | 919 +++++++ ...iovault.trilio.io_triliovaultmanagers.yaml | 1216 +++++++++ .../2.9.300/questions.yaml | 120 + .../2.9.300/templates/NOTES.txt | 59 + .../2.9.300/templates/TVMCustomResource.yaml | 53 + .../2.9.300/templates/_helpers.tpl | 85 + .../2.9.300/templates/clusterrole.yaml | 133 + .../templates/clusterrole_binding.yaml | 17 + .../2.9.300/templates/deployment.yaml | 200 ++ .../2.9.300/templates/mutating-webhook.yaml | 31 + .../templates/ns-validating-webhook.yaml | 37 + .../preflight_job_preinstall_hook.yaml | 191 ++ .../2.9.300/templates/proxyConfig.yaml | 21 + .../2.9.300/templates/secret.yaml | 11 + .../2.9.300/templates/serviceAccount.yaml | 14 + .../2.9.300/templates/validating-webhook.yaml | 31 + .../2.9.300/templates/webhook-service.yaml | 19 + .../2.9.300/values.yaml | 123 + .../portworx-essentials/2.9.100/Chart.yaml | 34 + .../portworx-essentials/2.9.100/README.md | 57 + .../portworx-essentials/2.9.100/app-readme.md | 26 + .../2.9.100/ci/test-values.yaml | 1 + .../portworx-essentials/2.9.100/questions.yml | 841 +++++++ .../2.9.100/templates/NOTES.txt | 13 + .../2.9.100/templates/_helpers.tpl | 443 ++++ .../px-postdelete-unlabelnode.yaml | 40 + .../pre-delete/px-predelete-nodelabel.yaml | 40 + .../templates/portworx-controller.yaml | 128 + .../2.9.100/templates/portworx-crd.yaml | 1146 +++++++++ .../2.9.100/templates/portworx-csi.yaml | 195 ++ .../2.9.100/templates/portworx-ds.yaml | 477 ++++ .../2.9.100/templates/portworx-essential.yaml | 19 + .../templates/portworx-rbac-config.yaml | 56 + .../2.9.100/templates/portworx-service.yaml | 54 + .../templates/portworx-storageclasses.yaml | 56 + .../2.9.100/templates/portworx-stork.yaml | 645 +++++ .../templates/serviceaccount-hook.yaml | 42 + .../portworx-essentials/2.9.100/values.yaml | 151 ++ charts/portworx/portworx/2.9.101/Chart.yaml | 32 + charts/portworx/portworx/2.9.101/README.md | 76 + .../portworx/portworx/2.9.101/app-readme.md | 8 + .../portworx/2.9.101/ci/test-values.yaml | 1 + .../portworx/portworx/2.9.101/questions.yml | 915 +++++++ .../portworx/2.9.101/templates/NOTES.txt | 13 + .../portworx/2.9.101/templates/_helpers.tpl | 443 ++++ .../px-postdelete-unlabelnode.yaml | 40 + .../pre-delete/px-predelete-nodelabel.yaml | 40 + .../templates/portworx-controller.yaml | 128 + .../2.9.101/templates/portworx-crd.yaml | 1146 +++++++++ .../2.9.101/templates/portworx-csi.yaml | 195 ++ .../2.9.101/templates/portworx-ds.yaml | 472 ++++ .../templates/portworx-rbac-config.yaml | 68 + .../2.9.101/templates/portworx-service.yaml | 54 + .../templates/portworx-storageclasses.yaml | 56 + .../2.9.101/templates/portworx-stork.yaml | 645 +++++ .../templates/serviceaccount-hook.yaml | 42 + charts/portworx/portworx/2.9.101/values.yaml | 149 ++ index.yaml | 148 ++ 265 files changed, 39080 insertions(+) create mode 100644 assets/dkube/dkube-deployer-1.0.601.tgz create mode 100644 assets/external-secrets-operator/external-secrets-0.5.600.tgz create mode 100644 assets/k8s-triliovault-operator/k8s-triliovault-operator-2.9.300.tgz create mode 100644 assets/portworx-essentials/portworx-essentials-2.9.100.tgz create mode 100644 assets/portworx/portworx-2.9.101.tgz create mode 100644 charts/dkube/dkube-deployer/1.0.601/.helmignore create mode 100644 charts/dkube/dkube-deployer/1.0.601/Chart.yaml create mode 100644 charts/dkube/dkube-deployer/1.0.601/app-readme.md create mode 100644 charts/dkube/dkube-deployer/1.0.601/questions.yaml create mode 100644 charts/dkube/dkube-deployer/1.0.601/templates/NOTES.txt create mode 100644 charts/dkube/dkube-deployer/1.0.601/templates/_helpers.tpl create mode 100644 charts/dkube/dkube-deployer/1.0.601/templates/config-map.yaml create mode 100644 charts/dkube/dkube-deployer/1.0.601/templates/hooks/uninstall.yaml create mode 100644 charts/dkube/dkube-deployer/1.0.601/templates/hooks/upgrade.yaml create mode 100644 charts/dkube/dkube-deployer/1.0.601/templates/install.yaml create mode 100644 charts/dkube/dkube-deployer/1.0.601/templates/secrets.yaml create mode 100644 charts/dkube/dkube-deployer/1.0.601/templates/serviceaccount.yaml create mode 100644 charts/dkube/dkube-deployer/1.0.601/values.schema.json create mode 100644 charts/dkube/dkube-deployer/1.0.601/values.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/.helmignore create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/Chart.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/README.md create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/README.md.gotmpl create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/app-readme.md create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/ci/main-values.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/questions.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/NOTES.txt create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/_helpers.tpl create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-deployment.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-poddisruptionbudget.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-rbac.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-service.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-serviceaccount.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-servicemonitor.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/clusterexternalsecret.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/clustersecretstore.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/externalsecret.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/secretstore.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/deployment.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/poddisruptionbudget.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/rbac.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/service.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/serviceaccount.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/servicemonitor.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/validatingwebhook.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-deployment.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-poddisruptionbudget.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-secret.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-service.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-serviceaccount.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-servicemonitor.yaml create mode 100644 charts/external-secrets-operator/external-secrets/0.5.600/values.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/.helmignore create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/Chart.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/LICENSE create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/README.md create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/Chart.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/Chart.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/Chart.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/NOTES.txt create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/_helpers.tpl create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/configmap-alert.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/ingress.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/networkpolicy.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/pdb.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/podsecuritypolicy.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/prometheusrule.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/role.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/rolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/secret.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/service-headless.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/service.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/serviceaccount.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/servicemonitor.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/statefulset.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/values.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/Chart.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/NOTES.txt create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/_helpers.tpl create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/clusterrole.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/clusterrolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/daemonset.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/extra-manifests.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/networkpolicy.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/podsecuritypolicy.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/role.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/rolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/secret.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/service-extra.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/service-metrics.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/serviceaccount.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/servicemonitor.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/values.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/templates/_helpers.tpl create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/templates/datasources.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/Chart.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/Chart.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/Chart.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/NOTES.txt create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/_helpers.tpl create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/clusterrolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/deployment.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/kubeconfig-secret.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/pdb.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/podsecuritypolicy.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrole.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/role.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/rolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/service.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/serviceaccount.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/servicemonitor.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-role.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/values.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/NOTES.txt create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/_helpers.tpl create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/clusterrole.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/clusterrolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/cm.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/deploy.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/headless-svc.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/ingress.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/netpol.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/pdb.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/psp.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/pvc.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/role.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/rolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/service.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/serviceaccount.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/sts.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/daemonset.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/psp.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/role.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/rolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/serviceaccount.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/svc.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/clusterrole.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/clusterrolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/deploy.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/ingress.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/netpol.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/pdb.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/psp.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/pvc.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/service.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/serviceaccount.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/vpa.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/clusterrole.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/clusterrolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/cm.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/deploy.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/extra-manifests.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/headless-svc.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/ingress.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/netpol.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/pdb.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/psp.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/pvc.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/rolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/service.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/serviceaccount.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/sts.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/vpa.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/values.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/templates/_helpers.tpl create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/templates/datasources.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/Chart.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/Chart.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backup-detail.json create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backup-overview.json create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backupplan-detail.json create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backupplan-overview.json create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/metadata-detail.json create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/overview.json create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/restore-detail.json create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/restore-overview.json create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/target-detail.json create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/NOTES.txt create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/_helpers.tpl create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/_pod.tpl create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/clusterrole.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/clusterrolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/configmap-dashboard-provider.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/configmap.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/dashboards-json-configmap.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/deployment.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/extra-manifests.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/headless-service.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/hpa.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/image-renderer-deployment.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/image-renderer-network-policy.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/image-renderer-service.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/ingress.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/networkpolicy.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/poddisruptionbudget.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/podsecuritypolicy.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/pvc.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/role.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/rolebinding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/secret-env.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/secret.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/service.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/serviceaccount.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/servicemonitor.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/statefulset.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/values.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/crds/triliovault.trilio.io_triliovaultmanagers.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/questions.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/NOTES.txt create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/TVMCustomResource.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/_helpers.tpl create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/clusterrole.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/clusterrole_binding.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/deployment.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/mutating-webhook.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/ns-validating-webhook.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/preflight_job_preinstall_hook.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/proxyConfig.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/secret.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/serviceAccount.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/validating-webhook.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/webhook-service.yaml create mode 100644 charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/values.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/Chart.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/README.md create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/app-readme.md create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/ci/test-values.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/questions.yml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/NOTES.txt create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/_helpers.tpl create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/hooks/post-delete/px-postdelete-unlabelnode.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/hooks/pre-delete/px-predelete-nodelabel.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-controller.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-crd.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-csi.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-ds.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-essential.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-rbac-config.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-service.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-storageclasses.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-stork.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/templates/serviceaccount-hook.yaml create mode 100644 charts/portworx-essentials/portworx-essentials/2.9.100/values.yaml create mode 100644 charts/portworx/portworx/2.9.101/Chart.yaml create mode 100644 charts/portworx/portworx/2.9.101/README.md create mode 100644 charts/portworx/portworx/2.9.101/app-readme.md create mode 100644 charts/portworx/portworx/2.9.101/ci/test-values.yaml create mode 100644 charts/portworx/portworx/2.9.101/questions.yml create mode 100644 charts/portworx/portworx/2.9.101/templates/NOTES.txt create mode 100644 charts/portworx/portworx/2.9.101/templates/_helpers.tpl create mode 100644 charts/portworx/portworx/2.9.101/templates/hooks/post-delete/px-postdelete-unlabelnode.yaml create mode 100644 charts/portworx/portworx/2.9.101/templates/hooks/pre-delete/px-predelete-nodelabel.yaml create mode 100644 charts/portworx/portworx/2.9.101/templates/portworx-controller.yaml create mode 100644 charts/portworx/portworx/2.9.101/templates/portworx-crd.yaml create mode 100644 charts/portworx/portworx/2.9.101/templates/portworx-csi.yaml create mode 100644 charts/portworx/portworx/2.9.101/templates/portworx-ds.yaml create mode 100644 charts/portworx/portworx/2.9.101/templates/portworx-rbac-config.yaml create mode 100644 charts/portworx/portworx/2.9.101/templates/portworx-service.yaml create mode 100644 charts/portworx/portworx/2.9.101/templates/portworx-storageclasses.yaml create mode 100644 charts/portworx/portworx/2.9.101/templates/portworx-stork.yaml create mode 100644 charts/portworx/portworx/2.9.101/templates/serviceaccount-hook.yaml create mode 100644 charts/portworx/portworx/2.9.101/values.yaml diff --git a/assets/dkube/dkube-deployer-1.0.601.tgz b/assets/dkube/dkube-deployer-1.0.601.tgz new file mode 100644 index 0000000000000000000000000000000000000000..eb60aa6d6bde00422cd6e01b973088464db1f158 GIT binary patch literal 9790 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 YdY+!A=YgO97XSeN|F`rdxd7Av0AGA9v;Y7A literal 0 HcmV?d00001 diff --git a/assets/external-secrets-operator/external-secrets-0.5.600.tgz b/assets/external-secrets-operator/external-secrets-0.5.600.tgz new file mode 100644 index 0000000000000000000000000000000000000000..fb93c7fa5732106a617ce9d2434d58e8becfbac9 GIT binary patch literal 39791 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 literal 0 HcmV?d00001 diff --git a/assets/k8s-triliovault-operator/k8s-triliovault-operator-2.9.300.tgz b/assets/k8s-triliovault-operator/k8s-triliovault-operator-2.9.300.tgz new file mode 100644 index 0000000000000000000000000000000000000000..c49a93cc4c457b02a8efad0e2c08ad77008a5009 GIT binary patch literal 97439 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± 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 Az5oCK literal 0 HcmV?d00001 diff --git a/assets/portworx-essentials/portworx-essentials-2.9.100.tgz b/assets/portworx-essentials/portworx-essentials-2.9.100.tgz new file mode 100644 index 0000000000000000000000000000000000000000..bcc71a116b4ef1223b1332bb391d3c59f0fc9792 GIT binary patch literal 25977 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:role/'" + type: string + label: IAMRole +# Node Affinity +- variable: optional.nodeAffinity.dkubeNodesLabel + default: "" + description: "Nodes identified by labels on which the dkube pods must be scheduled.. Say management nodes. Unfilled means no binding. When filled there needs to be minimum of 3nodes in case of HA and one node in case of non-HA. Example: DKUBE_NODES_LABEL: key1=value1. Please refer to section Node Affinity of installation guide. https://dkube.io/install/install3_x/Install-Advanced.html#node-affinity" + type: string + label: DKUBE_NODES_LABEL + group: "NodeAffinity" + show_if: "EULA=yes" +- variable: optional.nodeAffinity.dkubeNodesTaints + default: "" + description: "Nodes to be tolerated by dkube control plane pods so that only they can be scheduled on the nodes. Example: DKUBE_NODES_TAINTS: key1=value1:NoSchedule,key2=value2:NoSchedule" + type: string + label: DKUBE_NODES_TAINTS + group: "NodeAffinity" + show_if: "EULA=yes" +- variable: optional.nodeAffinity.gpuWorkloadTaints + default: "" + description: "Taints of the nodes where gpu workloads must be scheduled. Example: GPU_WORKLOADS_TAINTS: key1=value1:NoSchedule,key2=value2:NoSchedule" + type: string + label: GPU_WORKLOADS_TAINTS + group: "NodeAffinity" + show_if: "EULA=yes" +- variable: optional.nodeAffinity.productionWorkloadTaints + default: "" + description: "Taints of the nodes where production workloads must be scheduled. Example: PRODUCTION_WORKLOADS_TAINTS: key1=value1:NoSchedule,key2=value2:NoSchedule" + type: string + label: PRODUCTION_WORKLOADS_TAINTS + group: "NodeAffinity" + show_if: "EULA=yes" +- variable: optional.dkubeDockerhubCredentialsSecret + default: "" + description: "Dockerhub Secrets for OCDR images. If you don't create, this will be auto-created with default values." + type: string + label: DKUBE DOCKERHUB CREDENTIALS SECRET + group: "General" + show_if: "EULA=yes" +- variable: optional.IAMRole + default: "" + description: "AWS IAM role. Valid only if KUBE_PROVIDER=eks. This will be set as an annotation in few deployments. Format should be like: IAMRole: ': ' eg: IAMRole: 'iam.amazonaws.com/role: arn:aws:iam::123456789012:role/myrole'" + type: string + label: IAMRole + group: "General" + show_if: "EULA=yes&&provider=eks" diff --git a/charts/dkube/dkube-deployer/1.0.601/templates/NOTES.txt b/charts/dkube/dkube-deployer/1.0.601/templates/NOTES.txt new file mode 100644 index 000000000..1e25c33a3 --- /dev/null +++ b/charts/dkube/dkube-deployer/1.0.601/templates/NOTES.txt @@ -0,0 +1,7 @@ +Installing Dkube {{ .Values.version }} + +DKube Installation has started. Please use the commands below to view the installation progress. The commands are for installation only. Do not use them for upgrade. + +kubectl wait --for=condition=ready --timeout=5m pod -l job-name=dkube-helm-installer + +kubectl logs -l job-name=dkube-helm-installer --follow --tail=-1 && kubectl wait --for=condition=complete --timeout=30m job/dkube-helm-installer \ No newline at end of file diff --git a/charts/dkube/dkube-deployer/1.0.601/templates/_helpers.tpl b/charts/dkube/dkube-deployer/1.0.601/templates/_helpers.tpl new file mode 100644 index 000000000..8453df294 --- /dev/null +++ b/charts/dkube/dkube-deployer/1.0.601/templates/_helpers.tpl @@ -0,0 +1,53 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "dkube-deployer.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "dkube-deployer.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "dkube-deployer.labels" -}} +helm.sh/chart: {{ include "dkube-deployer.chart" . }} +{{ include "dkube-deployer.selectorLabels" . }} +app.kubernetes.io/version: {{ .Values.version | quote }} +app.kubernetes.io/managed-by: "dkube.io" +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "dkube-deployer.selectorLabels" -}} +app.kubernetes.io/name: {{ include "dkube-deployer.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + + +{{/* +Image pull secret +*/}} +{{- define "dkube-deployer.imagePullSecretData" -}} +{{- with .Values.registry }} +{{- printf "{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\",\"email\":\"ocdlgit@oneconvergence.com\",\"auth\":\"%s\"}}}" .name .username .password (printf "%s:%s" .username .password | b64enc) | b64enc }} +{{- end }} +{{- end }} + + +{{/* +model catalog enable flag +*/}} +{{- define "dkube-deployer.modelCatalog" -}} +{{- if hasPrefix "2.1" .Values.version }} +{{- printf "false" }} +{{- else }} +{{- printf "true" }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/dkube/dkube-deployer/1.0.601/templates/config-map.yaml b/charts/dkube/dkube-deployer/1.0.601/templates/config-map.yaml new file mode 100644 index 000000000..c30026eaf --- /dev/null +++ b/charts/dkube/dkube-deployer/1.0.601/templates/config-map.yaml @@ -0,0 +1,167 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: dkube-config + namespace: {{ .Release.Namespace }} + labels: + {{- include "dkube-deployer.labels" . | nindent 4 }} +data: + dkube.ini: | + ################################################################# + # # + # DKUBE CONFIG FILE # + # # + ################################################################# + + [REQUIRED] + # Choose one of dkube/gke/okd/eks/ntnx + KUBE_PROVIDER={{ .Values.provider }} + # When HA=true k8s cluster must have min 3 schedulable nodes + HA={{ .Values.ha }} + # Operator's Local Sign In Details + # Username cannot be same as that of a namespace's name. + # Also, following names are restricted- dkube, monitoring, kubeflow + # '$' is not supported + USERNAME={{ .Values.username }} + PASSWORD={{ .Values.password }} + # To wipe dkube storage + # Accepted values: yes/no + WIPEDATA={{ .Values.wipedata }} + # To install minimal version of dkube + # Accepted values: yes/no + MINIMAL={{ .Values.minimal }} + # To install air-gapped version of dkube + # Accepted values: yes/no + AIRGAP={{ .Values.airgap }} + + + [NODE-AFFINITY] + # Nodes identified by labels on which the dkube pods must be scheduled.. Say management nodes. Unfilled means no binding. When filled there needs to be minimum of 3nodes in case of HA and one node in case of non-HA + # Example: DKUBE_NODES_LABEL: key1=value1 + DKUBE_NODES_LABEL: {{ .Values.optional.nodeAffinity.dkubeNodesLabel }} + # Nodes to be tolerated by dkube control plane pods so that only they can be scheduled on the nodes + # Example: DKUBE_NODES_TAINTS: key1=value1:NoSchedule,key2=value2:NoSchedule + DKUBE_NODES_TAINTS: {{ .Values.optional.nodeAffinity.dkubeNodesTaints }} + # Taints of the nodes where gpu workloads must be scheduled. + # Example: GPU_WORKLOADS_TAINTS: key1=value1:NoSchedule,key2=value2:NoSchedule + GPU_WORKLOADS_TAINTS: {{ .Values.optional.nodeAffinity.gpuWorkloadTaints }} + # Taints of the nodes where production workloads must be scheduled. + # Example: PRODUCTION_WORKLOADS_TAINTS: key1=value1:NoSchedule,key2=value2:NoSchedule + PRODUCTION_WORKLOADS_TAINTS: {{ .Values.optional.nodeAffinity.productionWorkloadTaints }} + + [OPTIONAL] + # version of dkube installer to be used + DKUBE_INSTALLER_VERSION={{ .Values.version }} + # version of dkube to be installed + DKUBE_VERSION={{ .Values.version }} + # Dockerhub Secrets for OCDR images + # If you don't create, this will be auto-created with default values. + DKUBE_DOCKERHUB_CREDENTIALS_SECRET={{ .Values.optional.dkubeDockerhubCredentialsSecret }} + # TLS Secret of Operator's Certificate & Private Key + # If you don't create, place your certificate and private key in $HOME/.dkube + DKUBE_OPERATOR_CERTIFICATE= + # Repository from where Dkube images can be picked. + # Format: registry/[repo] + DKUBE_REGISTRY={{ .Values.registry.name }} + # Container registry username + REGISTRY_UNAME={{ .Values.registry.username }} + # Container registry password + REGISTRY_PASSWD={{ .Values.registry.password }} + # AWS IAM role + # Valid only if KUBE_PROVIDER=eks + # This will be set as an annotation in few deployments + # Format should be like: + # IAM_ROLE=: + # eg: IAM_ROLE=iam.amazonaws.com/role: arn:aws:iam::123456789012:role/myrole + # Note: Don't enclose with quotes + IAM_ROLE={{ .Values.optional.IAMRole }} + + [EXTERNAL] + # Type of dkube proxy service, possible values are nodeport and loadbalancer + ACCESS={{ .Values.optional.loadbalancer.access }} + # 'true' - to install MetalLB Loadbalancer + # Must fill LB_VIP_POOL if true + INSTALL_LOADBALANCER={{ .Values.optional.loadbalancer.metallb }} + # Only CIDR notation is allowed. E.g: 192.168.2.0/24 + # Valid only if INSTALL_LOADBALANCER=true + LB_VIP_POOL={{ .Values.optional.loadbalancer.vipPool }} + + [STORAGE] + # Type of storage + # Possible values: disk, pv, sc, nfs + # Following are required fields for corresponding storage type + # ------------------------------------------------------- + # STORAGE_TYPE REQUIRED_FIELDS + # ------------------------------------------------------- + # disk STORAGE_DISK_NODE and STORAGE_DISK_PATH + # pv STORAGE_PV + # sc STORAGE_SC + # nfs STORAGE_NFS_SERVER and STORAGE_NFS_PATH + # ceph STORAGE_CEPH_MONITORS and STORAGE_CEPH_SECRET + # For 2.2.1.12 and later + # ceph STORAGE_CEPH_FILESYSTEM and STORAGE_CEPH_NAMESPACE + + STORAGE_TYPE={{ .Values.optional.storage.type }} + # Localpath on the storage node + STORAGE_DISK_PATH={{ .Values.optional.storage.path }} + # Nodename of the storage node + # Possible values: AUTO/ + # AUTO - Master node will be chosen for storage if KUBE_PROVIDER=dkube + STORAGE_DISK_NODE={{ .Values.optional.storage.node }} + # Name of persistent volume + STORAGE_PV={{ .Values.optional.storage.persistentVolume }} + # Name of storage class name + # Make sure dynamic provisioner is running for the storage class name + STORAGE_SC={{ .Values.optional.storage.storageClass }} + # NFS server ip + STORAGE_NFS_SERVER={{ .Values.optional.storage.nfsServer }} + # NFS path (Make sure the path exists) + STORAGE_NFS_PATH={{ .Values.optional.storage.nfsPath }} + # Comma separated IPs of ceph monitors + STORAGE_CEPH_MONITORS={{ .Values.optional.storage.cephMonitors }} + # Ceph secret + STORAGE_CEPH_SECRET={{ .Values.optional.storage.cephSecret }} + # Name of the ceph filesystem + # E.g: dkubefs + STORAGE_CEPH_FILESYSTEM={{ .Values.optional.storage.cephFilesystem }} + # Name of the namespace where ceph is installed + # E.g: rook-ceph + STORAGE_CEPH_NAMESPACE={{ .Values.optional.storage.cephNamespace }} + + # Internal Ceph + # Internal ceph is installed when HA=true and STORAGE_TYPE is not in ("nfs", "ceph") + # Both the following fields are compulsory + # Configuration path for internal ceph + STORAGE_CEPH_PATH={{ .Values.optional.storage.cephPath }} + # Disk name for internal ceph storage + # It should be a raw formatted disk + # E.g: sdb + STORAGE_CEPH_DISK={{ .Values.optional.storage.cephDisk }} + [MODELMONITOR] + #To enable modelmonitor in dkube. (true / false) + ENABLED={{ .Values.optional.modelmonitor.enabled }} + [CICD] + #To enable tekton cicd with dkube. (true / false) + ENABLED={{ .Values.optional.CICD.enabled }} + #Docker registry where CICD built images will be saved. + #For DockerHub, enter docker.io/ + DOCKER_REGISTRY={{ .Values.optional.CICD.registryName }} + REGISTRY_USERNAME={{ .Values.optional.CICD.registryUsername }} + REGISTRY_PASSWORD={{ .Values.optional.CICD.registryPassword }} + + #For AWS ECR on EKS K8S cluster, enter registry as aws_account_id.dkr.ecr.region.amazonaws.com. + #DOCKER_REGISTRY=aws_account_id.dkr.ecr.region.amazonaws.com + #Worker nodes should either have AmazonEC2ContainerRegistryFullAccess or if you are using KIAM + #based IAM control, provide an IAM role which has AmazonEC2ContainerRegistryFullAccess + IAM_ROLE={{ .Values.optional.CICD.IAMRole }} + [MODEL-CATALOG] + #To enable model catalog with dkube. (true / false) + ENABLED={{ template "dkube-deployer.modelCatalog" . }} + + #To configure external database for dkube + [DBAAS] + #Supported mysql, sqlserver(mssql) + #Empty will pickup default sql db installed with dkube. + DATABASE={{ .Values.optional.DBAAS.database }} + #Syntaxes here can be followed to specify dsn https://gorm.io/docs/connecting_to_the_database.html + DSN={{ .Values.optional.DBAAS.dsn }} diff --git a/charts/dkube/dkube-deployer/1.0.601/templates/hooks/uninstall.yaml b/charts/dkube/dkube-deployer/1.0.601/templates/hooks/uninstall.yaml new file mode 100644 index 000000000..edf812368 --- /dev/null +++ b/charts/dkube/dkube-deployer/1.0.601/templates/hooks/uninstall.yaml @@ -0,0 +1,47 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: "dkube-uninstaller-hook" + namespace: {{ .Release.Namespace }} + labels: + {{- include "dkube-deployer.labels" . | nindent 4 }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": pre-delete + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation +spec: + backoffLimit: 0 + template: + metadata: + name: "dkube-uninstaller-hook" + labels: + {{- include "dkube-deployer.selectorLabels" . | nindent 8 }} + spec: + hostPID: true + restartPolicy: Never + imagePullSecrets: + - name: dkube-dockerhub-secret + containers: + - name: dkube-uninstaller-hook + image: {{ .Values.registry.name }}/dkubeadm:{{ .Values.version }} + imagePullPolicy: Always + securityContext: + privileged: true + volumeMounts: + - + mountPath: /root/.dkube/dkube.ini + name: dkube-config + subPath: dkube.ini + {{- if eq .Values.wipedata "yes" }} + command: ["/opt/dkubeadm/dkubeadm.sh", "dkube", "uninstall", "--wipe-data"] + {{- else }} + command: ["/opt/dkubeadm/dkubeadm.sh", "dkube", "uninstall"] + {{- end }} + serviceAccountName: dkube-deployer-sa + volumes: + - + configMap: + name: dkube-config + name: dkube-config diff --git a/charts/dkube/dkube-deployer/1.0.601/templates/hooks/upgrade.yaml b/charts/dkube/dkube-deployer/1.0.601/templates/hooks/upgrade.yaml new file mode 100644 index 000000000..246787b71 --- /dev/null +++ b/charts/dkube/dkube-deployer/1.0.601/templates/hooks/upgrade.yaml @@ -0,0 +1,67 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: "dkube-upgrade-hook" + namespace: {{ .Release.Namespace }} + labels: + {{- include "dkube-deployer.labels" . | nindent 4 }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": post-upgrade + "helm.sh/hook-weight": "-1" + "helm.sh/hook-delete-policy": before-hook-creation +spec: + backoffLimit: 0 + template: + metadata: + name: "dkube-upgrade-hook" + labels: + {{- include "dkube-deployer.selectorLabels" . | nindent 8 }} + spec: + restartPolicy: Never + imagePullSecrets: + - name: dkube-dockerhub-secret + containers: + - name: dkube-upgrade-hook + image: {{ .Values.registry.name }}/dkubeadm:{{ .Values.version }} + imagePullPolicy: Always + securityContext: + privileged: true + command: ["/opt/dkubeadm/dkubeadm.sh", "dkube", "upgrade", {{ .Values.version | quote}}] + serviceAccountName: dkube-deployer-sa +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: "dkube-installer-job-cleanup-hook" + namespace: {{ .Release.Namespace }} + labels: + {{- include "dkube-deployer.labels" . | nindent 4 }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": pre-upgrade,post-upgrade + "helm.sh/hook-weight": "-2" + "helm.sh/hook-delete-policy": before-hook-creation +spec: + backoffLimit: 0 + template: + metadata: + name: "dkube-installer-job-cleanup-hook" + labels: + {{- include "dkube-deployer.selectorLabels" . | nindent 8 }} + spec: + restartPolicy: Never + imagePullSecrets: + - name: dkube-dockerhub-secret + containers: + - name: dkube-installer-job-cleanup-hook + image: {{ .Values.registry.name }}/dkubeadm:{{ .Values.version }} + imagePullPolicy: Always + securityContext: + privileged: true + command: ["/bin/sh", "-c"] + args: + - kubectl delete job dkube-helm-installer --ignore-not-found=true + serviceAccountName: dkube-deployer-sa \ No newline at end of file diff --git a/charts/dkube/dkube-deployer/1.0.601/templates/install.yaml b/charts/dkube/dkube-deployer/1.0.601/templates/install.yaml new file mode 100644 index 000000000..667928ae7 --- /dev/null +++ b/charts/dkube/dkube-deployer/1.0.601/templates/install.yaml @@ -0,0 +1,41 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: "dkube-helm-installer" + namespace: {{ .Release.Namespace }} + labels: + {{- include "dkube-deployer.labels" . | nindent 4 }} +spec: + backoffLimit: 0 + template: + metadata: + name: "dkube-helm-installer" + labels: + {{- include "dkube-deployer.selectorLabels" . | nindent 8 }} + spec: + hostPID: true + restartPolicy: Never + imagePullSecrets: + - name: dkube-dockerhub-secret + containers: + - name: dkube-helm-installer + image: {{ .Values.registry.name }}/dkubeadm:{{ .Values.version }} + imagePullPolicy: Always + securityContext: + privileged: true + volumeMounts: + - + mountPath: /root/.dkube/dkube.ini + name: dkube-config + subPath: dkube.ini + {{- if eq .Values.wipedata "yes" }} + command: ["/opt/dkubeadm/dkubeadm.sh", "dkube", "install", "--accept-eula=yes", "--wipe-data"] + {{- else }} + command: ["/opt/dkubeadm/dkubeadm.sh", "dkube", "install", "--accept-eula={{ .Values.EULA }}"] + {{- end }} + serviceAccountName: dkube-deployer-sa + volumes: + - + configMap: + name: dkube-config + name: dkube-config diff --git a/charts/dkube/dkube-deployer/1.0.601/templates/secrets.yaml b/charts/dkube/dkube-deployer/1.0.601/templates/secrets.yaml new file mode 100644 index 000000000..d46b7098a --- /dev/null +++ b/charts/dkube/dkube-deployer/1.0.601/templates/secrets.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: dkube-dockerhub-secret + namespace: {{ .Release.Namespace }} + labels: + {{- include "dkube-deployer.labels" . | nindent 4 }} +type: kubernetes.io/dockerconfigjson +data: + .dockerconfigjson: {{ template "dkube-deployer.imagePullSecretData" . }} \ No newline at end of file diff --git a/charts/dkube/dkube-deployer/1.0.601/templates/serviceaccount.yaml b/charts/dkube/dkube-deployer/1.0.601/templates/serviceaccount.yaml new file mode 100644 index 000000000..6c1146f8b --- /dev/null +++ b/charts/dkube/dkube-deployer/1.0.601/templates/serviceaccount.yaml @@ -0,0 +1,136 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dkube-deployer-binding + labels: + {{- include "dkube-deployer.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: dkube-deployer-sa + namespace: {{ .Release.Namespace }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: dkube-deployer-sa + namespace: {{ .Release.Namespace }} + labels: + {{- include "dkube-deployer.labels" . | nindent 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: dkube-deployer-clusterrole + namespace: {{ .Release.Namespace }} + labels: + {{- include "dkube-deployer.labels" . | nindent 4 }} +rules: +- apiGroups: + - "" + resources: + - pods + - pods/exec + - pods/portforward + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - argoproj.io + resources: + - workflows + verbs: + - get + - list + - watch + - update + - patch + - create + - delete +- apiGroups: + - kubeflow.org + resources: + - tfjobs + verbs: + - '*' +- apiGroups: + - kubeflow.org + resources: + - mpijobs + verbs: + - '*' +- apiGroups: + - '*' + resources: + - replicasets + verbs: + - '*' +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - '*' +- apiGroups: + - "" + resources: + - events + verbs: + - list +- apiGroups: + - "" + resources: + - persistentvolumes + - persistentvolumeclaims + - services + - endpoints + - configmaps + verbs: + - '*' +- apiGroups: + - apps + - extensions + resources: + - deployments + - daemonsets + - statefulsets + verbs: + - '*' +- apiGroups: + - "" + resources: + - namespaces + - nodes + verbs: + - '*' +- apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + - rolebindings + - clusterroles + - clusterrolebindings + verbs: + - '*' +- apiGroups: + - "" + resources: + - serviceaccounts + - secrets + verbs: + - '*' +- apiGroups: + - batch + resources: + - jobs + - cronjobs + verbs: + - '*' diff --git a/charts/dkube/dkube-deployer/1.0.601/values.schema.json b/charts/dkube/dkube-deployer/1.0.601/values.schema.json new file mode 100644 index 000000000..e0a6265d4 --- /dev/null +++ b/charts/dkube/dkube-deployer/1.0.601/values.schema.json @@ -0,0 +1,205 @@ +{ + "$schema":"http://json-schema.org/draft-07/schema", + "type":"object", + "title":"The root schema", + "description":"The root schema comprises the entire JSON document.", + "required":[ + "EULA", + "username", + "password", + "version", + "provider", + "ha", + "wipedata", + "registry", + "optional" + ], + "properties":{ + "provider":{ + "$id":"#/properties/provider", + "enum": ["dkube", "gke", "okd", "eks", "ntnx", "tanzu"] + }, + "username":{ + "$id":"#/properties/username", + "type":"string", + "minLength":1 + }, + "password":{ + "$id":"#/properties/password", + "type":"string", + "minLength":1 + }, + "EULA":{ + "$id":"#/properties/EULA", + "type":"string", + "enum": ["yes"] + }, + "ha":{ + "$id":"#/properties/ha", + "type":"boolean" + }, + "wipedata":{ + "$id":"#/properties/wipedata", + "type":"string", + "enum": ["yes", "no"] + }, + "registry":{ + "$id":"#/properties/registry", + "type":"object", + "required": [ + "name", + "username", + "password" + ], + "properties":{ + "name":{ + "$id":"#/properties/registry/properties/name", + "type":"string", + "minLength":1 + }, + "username":{ + "$id":"#/properties/registry/properties/username", + "type":"string", + "minLength":1 + }, + "password":{ + "$id":"#/properties/registry/properties/password", + "type":"string", + "minLength":1 + } + } + }, + "optional":{ + "$id":"#/properties/optional", + "type":"object", + "required": [ + "storage" + ], + "properties":{ + "storage":{ + "$id":"#/properties/optional/properties/storage", + "type":"object", + "properties": { + "type": { + "enum": ["disk", "pv", "sc", "nfs", "ceph"] + } + }, + "allOf":[ + { + "if": { + "properties": {"type": {"const": "disk"}} + }, + "then": { + "$ref": "#/properties/optional/definitions/disk" + } + }, + { + "if": { + "properties": {"type": {"const": "pv"}} + }, + "then": { + "$ref": "#/properties/optional/definitions/pv" + } + }, + { + "if": { + "properties": {"type": {"const": "sc"}} + }, + "then": { + "$ref": "#/properties/optional/definitions/sc" + } + }, + { + "if": { + "properties": {"type": {"const": "nfs"}} + }, + "then": { + "$ref": "#/properties/optional/definitions/nfs" + } + }, + { + "if": { + "properties": {"type": {"const": "ceph"}} + }, + "then": { + "$ref": "#/properties/optional/definitions/ceph" + } + } + ] + } + }, + "definitions":{ + "disk":{ + "properties":{ + "path":{ + "type":"string", + "pattern":"^(/[^/ ]*)+/?$" + }, + "node":{ + "type":"string", + "minLength": 1 + } + }, + "required":[ + "path", + "node" + ] + }, + "pv":{ + "properties":{ + "persistentVolume":{ + "type":"string", + "minLength": 1 + } + }, + "required":[ + "persistentVolume" + ] + }, + "sc":{ + "properties":{ + "storageClass":{ + "type":"string", + "minLength": 1 + } + }, + "required":[ + "storageClass" + ] + }, + "nfs":{ + "properties":{ + "nfsPath":{ + "type":"string", + "pattern":"^(/[^/ ]*)+/?$" + }, + "nfsServer":{ + "type":"string", + "minLength": 1 + } + }, + "required":[ + "nfsPath", + "nfsServer" + ] + }, + "ceph":{ + "properties":{ + "cephMonitors":{ + "type":"string" + }, + "cephSecret":{ + "type":"string" + }, + "cephFilesystem":{ + "type":"string" + }, + "cephNamespace":{ + "type":"string" + } + } + } + } + } + } +} diff --git a/charts/dkube/dkube-deployer/1.0.601/values.yaml b/charts/dkube/dkube-deployer/1.0.601/values.yaml new file mode 100644 index 000000000..1ec6d7852 --- /dev/null +++ b/charts/dkube/dkube-deployer/1.0.601/values.yaml @@ -0,0 +1,182 @@ +# The DKube EULA is available at: www.oneconvergence.com/EULA/One-Convergence-EULA.pdf +# By accepting this license agreement you acknowledge that you agree to the terms and conditions. +# The installation will only proceed if the EULA is accepted by defining the EULA value as "yes". +EULA: "" + +# Operator's Local Sign In Details. +# Username cannot be same as that of a kubernetes namespace's name. +# Names like dkube, monitoring, kubeflow are restricted. +username: "" +password: "" + +# dkube version +version: "3.2.0.1" + +# Choose one of dkube/gke/okd/eks/ntnx/tanzu kube provider +provider: "dkube" + +# For ha deployment, k8s cluster must have min 3 schedulable nodes +ha: false + +# Wipe dkube data during helm operation install/uninstall. +# Choose one of yes/no +wipedata: "" + +# To install minimal version of dkube +# Accepted values: yes/no +minimal: "no" + +# To install air-gapped version of dkube +# Accepted values: yes/no +airgap: "no" + +# Docker registry for DKube installation +registry: + # Format: registry/[repo] + name: "docker.io/ocdr" + + # Container registry username + username: "" + + # Container registry password + password: "" + +optional: + storage: + # Type of storage + # Possible values: disk, pv, sc, nfs, ceph + # Following are required fields for corresponding storage type + # ------------------------------------------------------- + # STORAGE_TYPE REQUIRED_FIELDS + # ------------------------------------------------------- + # disk node and path + # pv persistentVolume + # sc storageClass + # nfs nfsServer and nfsPath + # ceph cephMonitors and cephSecret + # For release 2.2.1.12 and later + # ceph cephFilesystem and cephNamespace + type: "disk" + + # Localpath on the storage node + path: "/var/dkube" + + # Nodename of the storage node + # Possible values: AUTO/ + # AUTO - Master node will be chosen for storage if KUBE_PROVIDER=dkube + node: "" + + # Name of persistent volume + persistentVolume: "" + + # Name of storage class name + # Make sure dynamic provisioner is running for the storage class name + storageClass: "" + + # NFS server ip + nfsServer: "" + + # NFS path (Make sure the path exists) + nfsPath: "" + + # Only for external ceph before release 2.2.1.12 + # Comma separated IPs of ceph monitors + cephMonitors: "" + + # Only for external ceph before release 2.2.1.12 + # Ceph secret + cephSecret: "" + + # Only for external ceph from release 2.2.1.12 + # Name of the ceph filesystem + # E.g: dkubefs + cephFilesystem: "" + + # Only for external ceph from release 2.2.1.12 + # Name of the namespace where ceph is installed + # E.g: rook-ceph + cephNamespace: "" + + # Internal Ceph + # Internal ceph is installed when HA=true and STORAGE_TYPE is not in ("nfs", "ceph") + + # Configuration path for internal ceph + cephPath: "/var/lib/rook" + + # Only for internal ceph from release 2.2.1.12 + # Disk name for internal ceph storage + # It should be a raw formatted disk + # E.g: sdb + cephDisk: "" + + loadbalancer: + # Type of dkube proxy service, possible values are nodeport and loadbalancer + # Please use loadbalancer if kubeProvider is gke. + access: "nodeport" + + # 'true' - to install MetalLB Loadbalancer + # Must fill LB_VIP_POOL if true + metallb: "false" + + # Only CIDR notation is allowed. E.g: 192.168.2.0/24 + # Valid only if installLoadbalancer is true + vipPool: "" + + modelmonitor: + #To enable modelmonitor in dkube. (true / false) + enabled: false + + DBAAS: + # To configure external database for dkube + # Supported mysql, sqlserver(mssql) + # Empty will pickup default sql db installed with dkube + database: "" + + # Syntaxes here can be followed to specify dsn https://gorm.io/docs/connecting_to_the_database.html + dsn: "" + + CICD: + #To enable tekton cicd with dkube. (true / false) + enabled: false + + #Docker registry where CICD built images will be saved. + registryName: "docker.io/ocdr" + registryUsername: "" + registryPassword: "" + + #For AWS ECR on EKS K8S cluster, enter registry as aws_account_id.dkr.ecr.region.amazonaws.com. + #registryName: "aws_account_id.dkr.ecr.region.amazonaws.com" + #Worker nodes should either have AmazonEC2ContainerRegistryFullAccess or if you are using KIAM + #based IAM control, provide an IAM role which has AmazonEC2ContainerRegistryFullAccess + #IAMRole: "arn:aws:iam:::role/" + IAMRole: "" + + nodeAffinity: + # Nodes identified by labels on which the dkube pods must be scheduled.. Say management nodes. Unfilled means no binding. When filled there needs to be minimum of 3nodes in case of HA and one node in case of non-HA + # Example: DKUBE_NODES_LABEL: key1=value1 + dkubeNodesLabel: "" + + # Nodes to be tolerated by dkube control plane pods so that only they can be scheduled on the nodes + # Example: DKUBE_NODES_TAINTS: key1=value1:NoSchedule,key2=value2:NoSchedule + dkubeNodesTaints: "" + + # Taints of the nodes where gpu workloads must be scheduled. + # Example: GPU_WORKLOADS_TAINTS: key1=value1:NoSchedule,key2=value2:NoSchedule + gpuWorkloadTaints: "" + + # Taints of the nodes where production workloads must be scheduled. + # Example: PRODUCTION_WORKLOADS_TAINTS: key1=value1:NoSchedule,key2=value2:NoSchedule + productionWorkloadTaints: "" + + # Dockerhub Secrets for OCDR images + # If you don't create, this will be auto-created with default values. + dkubeDockerhubCredentialsSecret: "dkube-dockerhub-secret" + + # AWS IAM role + # Valid only if KUBE_PROVIDER=eks + # This will be set as an annotation in few deployments + # Format should be like: + # IAMRole: ": " + # eg: IAMRole: "iam.amazonaws.com/role: arn:aws:iam::123456789012:role/myrole" + IAMRole: "" + diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/.helmignore b/charts/external-secrets-operator/external-secrets/0.5.600/.helmignore new file mode 100644 index 000000000..855edc3fb --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/.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/ + +# CRD README.md +templates/crds/README.md diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/Chart.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/Chart.yaml new file mode 100644 index 000000000..46c3d0902 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/Chart.yaml @@ -0,0 +1,19 @@ +annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: External Secrets Operator + catalog.cattle.io/release-name: external-secrets-operator +apiVersion: v2 +appVersion: v0.5.6 +description: External secret management for Kubernetes +home: https://github.com/external-secrets/external-secrets +icon: https://raw.githubusercontent.com/external-secrets/external-secrets/main/assets/eso-logo-large.png +keywords: +- kubernetes-external-secrets +- secrets +kubeVersion: '>= 1.19.0-0' +maintainers: +- email: kellinmcavoy@gmail.com + name: mcavoyk +name: external-secrets +type: application +version: 0.5.600 diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/README.md b/charts/external-secrets-operator/external-secrets/0.5.600/README.md new file mode 100644 index 000000000..68df0c03b --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/README.md @@ -0,0 +1,146 @@ +# External Secrets + +

+ +[//]: # (README.md generated by gotmpl. DO NOT EDIT.) + +![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![Version: 0.5.6](https://img.shields.io/badge/Version-0.5.6-informational?style=flat-square) + +External secret management for Kubernetes + +## TL;DR +```bash +helm repo add external-secrets https://charts.external-secrets.io +helm install external-secrets/external-secrets +``` + +## Installing the Chart +To install the chart with the release name `external-secrets`: +```bash +helm install external-secrets external-secrets/external-secrets +``` + +### Custom Resources +By default, the chart will install external-secrets CRDs, this can be controlled with `installCRDs` value. + +## Uninstalling the Chart +To uninstall the `external-secrets` deployment: +```bash +helm uninstall external-secrets +``` +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| certController.affinity | object | `{}` | | +| certController.create | bool | `true` | Specifies whether a certificate controller deployment be created. | +| certController.deploymentAnnotations | object | `{}` | Annotations to add to Deployment | +| certController.extraArgs | object | `{}` | | +| certController.extraEnv | list | `[]` | | +| certController.fullnameOverride | string | `""` | | +| certController.image.pullPolicy | string | `"IfNotPresent"` | | +| certController.image.repository | string | `"ghcr.io/external-secrets/external-secrets"` | | +| certController.image.tag | string | `""` | | +| certController.imagePullSecrets | list | `[]` | | +| certController.nameOverride | string | `""` | | +| certController.nodeSelector | object | `{}` | | +| certController.podAnnotations | object | `{}` | Annotations to add to Pod | +| certController.podDisruptionBudget | object | `{"enabled":false,"minAvailable":1}` | Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| certController.podLabels | object | `{}` | | +| certController.podSecurityContext | object | `{}` | | +| certController.priorityClassName | string | `""` | Pod priority class name. | +| certController.prometheus.enabled | bool | `false` | deprecated. will be removed with 0.7.0, use serviceMonitor instead | +| certController.prometheus.service.port | int | `8080` | deprecated. will be removed with 0.7.0, use serviceMonitor instead | +| certController.rbac.create | bool | `true` | Specifies whether role and rolebinding resources should be created. | +| certController.replicaCount | int | `1` | | +| certController.requeueInterval | string | `"5m"` | | +| certController.resources | object | `{}` | | +| certController.securityContext | object | `{}` | | +| certController.serviceAccount.annotations | object | `{}` | Annotations to add to the service account. | +| certController.serviceAccount.create | bool | `true` | Specifies whether a service account should be created. | +| certController.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. | +| certController.serviceMonitor.additionalLabels | object | `{}` | Additional labels | +| certController.serviceMonitor.enabled | bool | `false` | Specifies whether to create a ServiceMonitor resource for collecting Prometheus metrics | +| certController.serviceMonitor.interval | string | `"30s"` | Interval to scrape metrics | +| certController.serviceMonitor.scrapeTimeout | string | `"25s"` | Timeout if metrics can't be retrieved in given time interval | +| certController.tolerations | list | `[]` | | +| concurrent | int | `1` | Specifies the number of concurrent ExternalSecret Reconciles external-secret executes at a time. | +| controllerClass | string | `""` | If set external secrets will filter matching Secret Stores with the appropriate controller values. | +| crds.createClusterExternalSecret | bool | `true` | If true, create CRDs for Cluster External Secret. | +| crds.createClusterSecretStore | bool | `true` | If true, create CRDs for Cluster Secret Store. | +| createOperator | bool | `true` | Specifies whether an external secret operator deployment be created. | +| deploymentAnnotations | object | `{}` | Annotations to add to Deployment | +| extraArgs | object | `{}` | | +| extraEnv | list | `[]` | | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.repository | string | `"ghcr.io/external-secrets/external-secrets"` | | +| image.tag | string | `""` | The image tag to use. The default is the chart appVersion. | +| imagePullSecrets | list | `[]` | | +| installCRDs | bool | `true` | If set, install and upgrade CRDs through helm chart. | +| leaderElect | bool | `false` | If true, external-secrets will perform leader election between instances to ensure no more than one instance of external-secrets operates at a time. | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | Annotations to add to Pod | +| podDisruptionBudget | object | `{"enabled":false,"minAvailable":1}` | Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| podLabels | object | `{}` | | +| podSecurityContext | object | `{}` | | +| priorityClassName | string | `""` | Pod priority class name. | +| processClusterExternalSecret | bool | `true` | if true, the operator will process cluster external secret. Else, it will ignore them. | +| processClusterStore | bool | `true` | if true, the operator will process cluster store. Else, it will ignore them. | +| prometheus.enabled | bool | `false` | deprecated. will be removed with 0.7.0, use serviceMonitor instead. | +| prometheus.service.port | int | `8080` | deprecated. will be removed with 0.7.0, use serviceMonitor instead. | +| rbac.create | bool | `true` | Specifies whether role and rolebinding resources should be created. | +| replicaCount | int | `1` | | +| resources | object | `{}` | | +| scopedNamespace | string | `""` | If set external secrets are only reconciled in the provided namespace | +| scopedRBAC | bool | `false` | Must be used with scopedNamespace. If true, create scoped RBAC roles under the scoped namespace and implicitly disable cluster stores and cluster external secrets | +| securityContext | object | `{}` | | +| serviceAccount.annotations | object | `{}` | Annotations to add to the service account. | +| serviceAccount.create | bool | `true` | Specifies whether a service account should be created. | +| serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. | +| serviceMonitor.additionalLabels | object | `{}` | Additional labels | +| serviceMonitor.enabled | bool | `false` | Specifies whether to create a ServiceMonitor resource for collecting Prometheus metrics | +| serviceMonitor.interval | string | `"30s"` | Interval to scrape metrics | +| serviceMonitor.scrapeTimeout | string | `"25s"` | Timeout if metrics can't be retrieved in given time interval | +| tolerations | list | `[]` | | +| webhook.affinity | object | `{}` | | +| webhook.certCheckInterval | string | `"5m"` | | +| webhook.certDir | string | `"/tmp/certs"` | | +| webhook.create | bool | `true` | Specifies whether a webhook deployment be created. | +| webhook.deploymentAnnotations | object | `{}` | Annotations to add to Deployment | +| webhook.extraArgs | object | `{}` | | +| webhook.extraEnv | list | `[]` | | +| webhook.failurePolicy | string | `"Fail"` | specifies whether validating webhooks should be created with failurePolicy: Fail or Ignore | +| webhook.fullnameOverride | string | `""` | | +| webhook.hostNetwork | bool | `false` | Specifies if webhook pod should use hostNetwork or not. | +| webhook.image.pullPolicy | string | `"IfNotPresent"` | | +| webhook.image.repository | string | `"ghcr.io/external-secrets/external-secrets"` | | +| webhook.image.tag | string | `""` | The image tag to use. The default is the chart appVersion. | +| webhook.imagePullSecrets | list | `[]` | | +| webhook.nameOverride | string | `""` | | +| webhook.nodeSelector | object | `{}` | | +| webhook.podAnnotations | object | `{}` | Annotations to add to Pod | +| webhook.podDisruptionBudget | object | `{"enabled":false,"minAvailable":1}` | Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ | +| webhook.podLabels | object | `{}` | | +| webhook.podSecurityContext | object | `{}` | | +| webhook.port | int | `10250` | The port the webhook will listen to | +| webhook.priorityClassName | string | `""` | Pod priority class name. | +| webhook.prometheus.enabled | bool | `false` | deprecated. will be removed with 0.7.0, use serviceMonitor instead | +| webhook.prometheus.service.port | int | `8080` | deprecated. will be removed with 0.7.0, use serviceMonitor instead | +| webhook.rbac.create | bool | `true` | Specifies whether role and rolebinding resources should be created. | +| webhook.replicaCount | int | `1` | | +| webhook.resources | object | `{}` | | +| webhook.secretAnnotations | object | `{}` | Annotations to add to Secret | +| webhook.securityContext | object | `{}` | | +| webhook.serviceAccount.annotations | object | `{}` | Annotations to add to the service account. | +| webhook.serviceAccount.create | bool | `true` | Specifies whether a service account should be created. | +| webhook.serviceAccount.name | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template. | +| webhook.serviceMonitor.additionalLabels | object | `{}` | Additional labels | +| webhook.serviceMonitor.enabled | bool | `false` | Specifies whether to create a ServiceMonitor resource for collecting Prometheus metrics | +| webhook.serviceMonitor.interval | string | `"30s"` | Interval to scrape metrics | +| webhook.serviceMonitor.scrapeTimeout | string | `"25s"` | Timeout if metrics can't be retrieved in given time interval | +| webhook.tolerations | list | `[]` | | diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/README.md.gotmpl b/charts/external-secrets-operator/external-secrets/0.5.600/README.md.gotmpl new file mode 100644 index 000000000..7e7d15500 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/README.md.gotmpl @@ -0,0 +1,36 @@ +{{- $valuesYAML := "https://github.com/external-secrets/external-secrets/blob/master/deploy/charts/external-secrets/values.yaml" -}} +{{- $chartRepo := "https://charts.external-secrets.io" -}} +{{- $org := "external-secrets" -}} +# External Secrets + +

+ +[//]: # (README.md generated by gotmpl. DO NOT EDIT.) + +{{ template "chart.typeBadge" . }}{{ template "chart.versionBadge" . }} + +{{ template "chart.description" . }} + +## TL;DR +```bash +helm repo add {{ $org }} {{ $chartRepo }} +helm install {{ $org }}/{{ template "chart.name" . }} +``` + +## Installing the Chart +To install the chart with the release name `{{ template "chart.name" . }}`: +```bash +helm install {{ template "chart.name" . }} {{ $org }}/{{ template "chart.name" . }} +``` + +### Custom Resources +By default, the chart will install external-secrets CRDs, this can be controlled with `installCRDs` value. + +## Uninstalling the Chart +To uninstall the `{{ template "chart.name" . }}` deployment: +```bash +helm uninstall {{ template "chart.name" . }} +``` +The command removes all the Kubernetes components associated with the chart and deletes the release. + +{{ template "chart.valuesSection" . }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/app-readme.md b/charts/external-secrets-operator/external-secrets/0.5.600/app-readme.md new file mode 100644 index 000000000..2a28bc399 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/app-readme.md @@ -0,0 +1,7 @@ +**External Secrets Operator** is a Kubernetes operator that integrates external secret management systems like [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/), [HashiCorp Vault](https://www.vaultproject.io/), [Google Secrets Manager](https://cloud.google.com/secret-manager), [Azure Key Vault](https://azure.microsoft.com/en-us/services/key-vault/) and many more. +The operator reads information from external APIs and automatically injects the values into a [Kubernetes Secret](https://kubernetes.io/docs/concepts/configuration/secret/). + +### What is the goal of External Secrets Operator? + +The goal of External Secrets Operator is to synchronize secrets from external APIs into Kubernetes. ESO is a collection of custom API resources - `ExternalSecret`, `SecretStore` and `ClusterSecretStore` that provide a user-friendly abstraction for the external API that stores and manages the lifecycle of the secrets for you. + diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/ci/main-values.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/ci/main-values.yaml new file mode 100644 index 000000000..75eb234e3 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/ci/main-values.yaml @@ -0,0 +1,2 @@ +image: + tag: main diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/questions.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/questions.yaml new file mode 100644 index 000000000..31008999d --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/questions.yaml @@ -0,0 +1,8 @@ +questions: +- variable: installCRDs + default: false + required: true + description: "If true, Install and upgrade CRDs through helm chart" + type: boolean + label: Install CRDs + diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/NOTES.txt b/charts/external-secrets-operator/external-secrets/0.5.600/templates/NOTES.txt new file mode 100644 index 000000000..a4bd27e0b --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/NOTES.txt @@ -0,0 +1,13 @@ +external-secrets has been deployed successfully! + +In order to begin using ExternalSecrets, you will need to set up a SecretStore +or ClusterSecretStore resource (for example, by creating a 'vault' SecretStore). + +More information on the different types of SecretStores and how to configure them +can be found in our Github: {{ .Chart.Home }} + +{{ if .Values.prometheus.enabled -}} +deprecation warning: +> The flag `prometheus.enabled` is deprecated and will be removed in the next release. + Please migrate to using servicemonitor instead. +{{ end }} \ No newline at end of file diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/_helpers.tpl b/charts/external-secrets-operator/external-secrets/0.5.600/templates/_helpers.tpl new file mode 100644 index 000000000..48c9ed979 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/_helpers.tpl @@ -0,0 +1,110 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "external-secrets.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "external-secrets.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "external-secrets.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "external-secrets.labels" -}} +helm.sh/chart: {{ include "external-secrets.chart" . }} +{{ include "external-secrets.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{- define "external-secrets-webhook.labels" -}} +helm.sh/chart: {{ include "external-secrets.chart" . }} +{{ include "external-secrets-webhook.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{- define "external-secrets-cert-controller.labels" -}} +helm.sh/chart: {{ include "external-secrets.chart" . }} +{{ include "external-secrets-cert-controller.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "external-secrets.selectorLabels" -}} +app.kubernetes.io/name: {{ include "external-secrets.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{- define "external-secrets-webhook.selectorLabels" -}} +app.kubernetes.io/name: {{ include "external-secrets.name" . }}-webhook +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{- define "external-secrets-cert-controller.selectorLabels" -}} +app.kubernetes.io/name: {{ include "external-secrets.name" . }}-cert-controller +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} +{{/* +Create the name of the service account to use +*/}} +{{- define "external-secrets.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "external-secrets.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "external-secrets-webhook.serviceAccountName" -}} +{{- if .Values.webhook.serviceAccount.create }} +{{- default "external-secrets-webhook" .Values.webhook.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.webhook.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "external-secrets-cert-controller.serviceAccountName" -}} +{{- if .Values.certController.serviceAccount.create }} +{{- default "external-secrets-cert-controller" .Values.certController.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.certController.serviceAccount.name }} +{{- end }} +{{- end }} + diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-deployment.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-deployment.yaml new file mode 100644 index 000000000..155e69f34 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-deployment.yaml @@ -0,0 +1,94 @@ +{{- if .Values.certController.create }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} + {{- with .Values.certController.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.certController.replicaCount }} + selector: + matchLabels: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.certController.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 8 }} + {{- with .Values.certController.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.certController.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "external-secrets-cert-controller.serviceAccountName" . }} + {{- with .Values.certController.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: cert-controller + {{- with .Values.certController.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.certController.image.repository }}:{{ .Values.certController.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.certController.image.pullPolicy }} + args: + - certcontroller + - --crd-requeue-interval={{ .Values.certController.requeueInterval }} + - --service-name={{ include "external-secrets.fullname" . }}-webhook + - --service-namespace={{ .Release.Namespace }} + - --secret-name={{ include "external-secrets.fullname" . }}-webhook + - --secret-namespace={{ .Release.Namespace }} + {{- range $key, $value := .Values.certController.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.certController.prometheus.service.port }} + protocol: TCP + name: metrics + readinessProbe: + httpGet: + port: 8081 + path: /readyz + initialDelaySeconds: 20 + periodSeconds: 5 + {{- with .Values.certController.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.certController.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.certController.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.certController.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.certController.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.certController.priorityClassName }} + priorityClassName: {{ .Values.certController.priorityClassName }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-poddisruptionbudget.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-poddisruptionbudget.yaml new file mode 100644 index 000000000..99e88c28e --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-poddisruptionbudget.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.certController.create .Values.certController.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller-pdb + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +spec: + {{- if .Values.certController.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.certController.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.certController.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.certController.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 6 }} +{{- end }} \ No newline at end of file diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-rbac.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-rbac.yaml new file mode 100644 index 000000000..df37edeb7 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-rbac.yaml @@ -0,0 +1,69 @@ +{{- if and .Values.certController.create .Values.certController.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +rules: + - apiGroups: + - "apiextensions.k8s.io" + resources: + - "customresourcedefinitions" + verbs: + - "get" + - "list" + - "watch" + - "update" + - "patch" + - apiGroups: + - "admissionregistration.k8s.io" + resources: + - "validatingwebhookconfigurations" + verbs: + - "get" + - "list" + - "watch" + - "update" + - "patch" + - apiGroups: + - "" + resources: + - "endpoints" + verbs: + - "list" + - "get" + - "watch" + - apiGroups: + - "" + resources: + - "events" + verbs: + - "create" + - "patch" + - apiGroups: + - "" + resources: + - "secrets" + verbs: + - "get" + - "list" + - "watch" + - "update" + - "patch" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "external-secrets.fullname" . }}-cert-controller +subjects: + - name: {{ include "external-secrets-cert-controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + kind: ServiceAccount +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-service.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-service.yaml new file mode 100644 index 000000000..833b2c9fa --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-service.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.certController.create .Values.certController.prometheus.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + annotations: + prometheus.io/path: "/metrics" + prometheus.io/scrape: "true" + prometheus.io/port: {{ .Values.certController.prometheus.service.port | quote }} +spec: + type: ClusterIP + ports: + - port: {{ .Values.certController.prometheus.service.port }} + protocol: TCP + name: metrics + selector: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-serviceaccount.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-serviceaccount.yaml new file mode 100644 index 000000000..acf7d6dea --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.certController.create .Values.certController.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "external-secrets-cert-controller.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} + {{- with .Values.certController.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-servicemonitor.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-servicemonitor.yaml new file mode 100644 index 000000000..78e2388c8 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/cert-controller-servicemonitor.yaml @@ -0,0 +1,38 @@ +{{- if and .Values.certController.create .Values.certController.serviceMonitor.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics + labels: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: 8080 + protocol: TCP + name: metrics + selector: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 4 }} +--- +apiVersion: "monitoring.coreos.com/v1" +kind: ServiceMonitor +metadata: + labels: + {{- include "external-secrets-cert-controller.labels" . | nindent 4 }} +{{- if .Values.certController.serviceMonitor.additionalLabels }} +{{ toYaml .Values.certController.serviceMonitor.additionalLabels | indent 4 }} +{{- end }} + name: {{ include "external-secrets.fullname" . }}-cert-controller-metrics + namespace: {{ .Release.Namespace | quote }} +spec: + selector: + matchLabels: + {{- include "external-secrets-cert-controller.selectorLabels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} + endpoints: + - port: metrics + interval: {{ .Values.certController.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.certController.serviceMonitor.scrapeTimeout }} +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/clusterexternalsecret.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/clusterexternalsecret.yaml new file mode 100644 index 000000000..f10d1589e --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/clusterexternalsecret.yaml @@ -0,0 +1,333 @@ +{{- if and (.Values.installCRDs) (.Values.crds.createClusterExternalSecret) }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.0 + creationTimestamp: null + name: clusterexternalsecrets.external-secrets.io +spec: + group: external-secrets.io + names: + categories: + - externalsecrets + kind: ClusterExternalSecret + listKind: ClusterExternalSecretList + plural: clusterexternalsecrets + shortNames: + - ces + singular: clusterexternalsecret + scope: Cluster + versions: + - name: v1beta1 + schema: + openAPIV3Schema: + description: ClusterExternalSecret is the Schema for the clusterexternalsecrets API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ClusterExternalSecretSpec defines the desired state of ClusterExternalSecret. + properties: + externalSecretName: + description: The name of the external secrets to be created defaults to the name of the ClusterExternalSecret + type: string + externalSecretSpec: + description: The spec for the ExternalSecrets to be created + properties: + data: + description: Data defines the connection between the Kubernetes Secret keys and the Provider data + items: + description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. + properties: + remoteRef: + description: ExternalSecretDataRemoteRef defines Provider data location. + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string + key: + description: Key is the key used in the Provider, mandatory + type: string + metadataPolicy: + description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None + type: string + property: + description: Used to select a specific property of the Provider value (if a map), if supported + type: string + version: + description: Used to select a specific version of the Provider value, if supported + type: string + required: + - key + type: object + secretKey: + type: string + required: + - remoteRef + - secretKey + type: object + type: array + dataFrom: + description: DataFrom is used to fetch all properties from a specific Provider data If multiple entries are specified, the Secret keys are merged in the specified order + items: + maxProperties: 1 + minProperties: 1 + properties: + extract: + description: Used to extract multiple key/value pairs from one secret + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string + key: + description: Key is the key used in the Provider, mandatory + type: string + metadataPolicy: + description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None + type: string + property: + description: Used to select a specific property of the Provider value (if a map), if supported + type: string + version: + description: Used to select a specific version of the Provider value, if supported + type: string + required: + - key + type: object + find: + description: Used to find secrets based on tags or regular expressions + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string + name: + description: Finds secrets based on the name. + properties: + regexp: + description: Finds secrets base + type: string + type: object + path: + description: A root path to start the find operations. + type: string + tags: + additionalProperties: + type: string + description: Find secrets based on tags. + type: object + type: object + type: object + type: array + refreshInterval: + default: 1h + description: RefreshInterval is the amount of time before the values are read again from the SecretStore provider Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" May be set to zero to fetch and create it once. Defaults to 1h. + type: string + secretStoreRef: + description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. + properties: + kind: + description: Kind of the SecretStore resource (SecretStore or ClusterSecretStore) Defaults to `SecretStore` + type: string + name: + description: Name of the SecretStore resource + type: string + required: + - name + type: object + target: + description: ExternalSecretTarget defines the Kubernetes Secret to be created There can be only one target per ExternalSecret. + properties: + creationPolicy: + default: Owner + description: CreationPolicy defines rules on how to create the resulting Secret Defaults to 'Owner' + enum: + - Owner + - Orphan + - Merge + - None + type: string + deletionPolicy: + default: Retain + description: DeletionPolicy defines rules on how to delete the resulting Secret Defaults to 'Retain' + enum: + - Delete + - Merge + - Retain + type: string + immutable: + description: Immutable defines if the final secret will be immutable + type: boolean + name: + description: Name defines the name of the Secret resource to be managed This field is immutable Defaults to the .metadata.name of the ExternalSecret resource + type: string + template: + description: Template defines a blueprint for the created Secret resource. + properties: + data: + additionalProperties: + type: string + type: object + engineVersion: + default: v2 + type: string + metadata: + description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + templateFrom: + items: + maxProperties: 1 + minProperties: 1 + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + type: object + type: array + type: + type: string + type: object + type: object + required: + - secretStoreRef + type: object + namespaceSelector: + description: The labels to select by to find the Namespaces to create the ExternalSecrets in. + 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 + required: + - key + - operator + type: object + type: array + 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 + refreshTime: + description: The time in which the controller should reconcile it's objects and recheck namespaces for labels. + type: string + required: + - externalSecretSpec + - namespaceSelector + type: object + status: + description: ClusterExternalSecretStatus defines the observed state of ClusterExternalSecret. + properties: + conditions: + items: + properties: + message: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + failedNamespaces: + description: Failed namespaces are the namespaces that failed to apply an ExternalSecret + items: + description: ClusterExternalSecretNamespaceFailure represents a failed namespace deployment and it's reason. + properties: + namespace: + description: Namespace is the namespace that failed when trying to apply an ExternalSecret + type: string + reason: + description: Reason is why the ExternalSecret failed to apply to the namespace + type: string + required: + - namespace + type: object + type: array + provisionedNamespaces: + description: ProvisionedNamespaces are the namespaces where the ClusterExternalSecret has secrets + items: + type: string + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/clustersecretstore.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/clustersecretstore.yaml new file mode 100644 index 000000000..89601d12e --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/clustersecretstore.yaml @@ -0,0 +1,2163 @@ +{{- if and (.Values.installCRDs) (.Values.crds.createClusterSecretStore) }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.0 + creationTimestamp: null + name: clustersecretstores.external-secrets.io +spec: + group: external-secrets.io + names: + categories: + - externalsecrets + kind: ClusterSecretStore + listKind: ClusterSecretStoreList + plural: clustersecretstores + shortNames: + - css + singular: clustersecretstore + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + deprecated: true + name: v1alpha1 + schema: + openAPIV3Schema: + description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: SecretStoreSpec defines the desired state of SecretStore. + properties: + controller: + description: 'Used to select the correct KES controller (think: ingress.ingressClassName) The KES controller is instantiated with a specific controller name and filters ES based on this property' + type: string + provider: + description: Used to configure the provider. Only one provider may be set + maxProperties: 1 + minProperties: 1 + properties: + akeyless: + description: Akeyless configures this store to sync secrets using Akeyless Vault provider + properties: + akeylessGWApiURL: + description: Akeyless GW API Url from which the secrets to be fetched from. + type: string + authSecretRef: + description: Auth configures how the operator authenticates with Akeyless. + properties: + secretRef: + description: 'AkeylessAuthSecretRef AKEYLESS_ACCESS_TYPE_PARAM: AZURE_OBJ_ID OR GCP_AUDIENCE OR ACCESS_KEY OR KUB_CONFIG_NAME.' + properties: + accessID: + description: The SecretAccessID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessType: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessTypeParam: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + required: + - akeylessGWApiURL + - authSecretRef + type: object + alibaba: + description: Alibaba configures this store to sync secrets using Alibaba Cloud provider + properties: + auth: + description: AlibabaAuth contains a secretRef for credentials. + properties: + secretRef: + description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessKeySecretSecretRef: + description: The AccessKeySecret is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - accessKeyIDSecretRef + - accessKeySecretSecretRef + type: object + required: + - secretRef + type: object + endpoint: + type: string + regionID: + description: Alibaba Region to be used for the provider + type: string + required: + - auth + - regionID + type: object + aws: + description: AWS configures this store to sync secrets using AWS Secret Manager provider + properties: + auth: + description: 'Auth defines the information necessary to authenticate against AWS if not set aws sdk will infer credentials from your environment see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + properties: + jwt: + description: Authenticate against AWS using service account tokens. + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + type: object + secretRef: + description: AWSAuthSecretRef holds secret references for AWS credentials both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + region: + description: AWS Region to be used for the provider + type: string + role: + description: Role is a Role ARN which the SecretManager provider will assume + type: string + service: + description: Service defines which service should be used to fetch the secrets + enum: + - SecretsManager + - ParameterStore + type: string + required: + - region + - service + type: object + azurekv: + description: AzureKV configures this store to sync secrets using Azure Key Vault provider + properties: + authSecretRef: + description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. + properties: + clientId: + description: The Azure clientId of the service principle used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientSecret: + description: The Azure ClientSecret of the service principle used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + authType: + default: ServicePrincipal + description: 'Auth type defines how to authenticate to the keyvault service. Valid values are: - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity)' + enum: + - ServicePrincipal + - ManagedIdentity + - WorkloadIdentity + type: string + identityId: + description: If multiple Managed Identity is assigned to the pod, you can select the one to be used + type: string + serviceAccountRef: + description: ServiceAccountRef specified the service account that should be used when authenticating with WorkloadIdentity. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + tenantId: + description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. + type: string + vaultUrl: + description: Vault Url from which the secrets to be fetched from. + type: string + required: + - vaultUrl + type: object + fake: + description: Fake configures a store with static key/value pairs + properties: + data: + items: + properties: + key: + type: string + value: + type: string + valueMap: + additionalProperties: + type: string + type: object + version: + type: string + required: + - key + type: object + type: array + required: + - data + type: object + gcpsm: + description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider + properties: + auth: + description: Auth defines the information necessary to authenticate against GCP + properties: + secretRef: + properties: + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + workloadIdentity: + properties: + clusterLocation: + type: string + clusterName: + type: string + clusterProjectID: + type: string + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - clusterLocation + - clusterName + - serviceAccountRef + type: object + type: object + projectID: + description: ProjectID project where secret is located + type: string + type: object + gitlab: + description: Gitlab configures this store to sync secrets using Gitlab Variables provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a GitLab instance. + properties: + SecretRef: + properties: + accessToken: + description: AccessToken is used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - SecretRef + type: object + projectID: + description: ProjectID specifies a project where secrets are located. + type: string + url: + description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. + type: string + required: + - auth + type: object + ibm: + description: IBM configures this store to sync secrets using IBM Cloud provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the IBM secrets manager. + properties: + secretRef: + properties: + secretApiKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + serviceUrl: + description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance + type: string + required: + - auth + type: object + kubernetes: + description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Kubernetes instance. + maxProperties: 1 + minProperties: 1 + properties: + cert: + description: has both clientCert and clientKey as secretKeySelector + properties: + clientCert: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientKey: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + serviceAccount: + description: points to a service account that should be used for authentication + properties: + serviceAccount: + description: A reference to a ServiceAccount resource. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + type: object + token: + description: use static token to authenticate with + properties: + bearerToken: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + remoteNamespace: + default: default + description: Remote namespace to fetch the secrets from + type: string + server: + description: configures the Kubernetes server Address. + properties: + caBundle: + description: CABundle is a base64-encoded CA certificate + format: byte + type: string + caProvider: + description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + url: + default: kubernetes.default + description: configures the Kubernetes server Address. + type: string + type: object + required: + - auth + type: object + oracle: + description: Oracle configures this store to sync secrets using Oracle Vault provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Oracle Vault. If empty, use the instance principal, otherwise the user credentials specified in Auth. + properties: + secretRef: + description: SecretRef to pass through sensitive information. + properties: + fingerprint: + description: Fingerprint is the fingerprint of the API private key. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + privatekey: + description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - fingerprint + - privatekey + type: object + tenancy: + description: Tenancy is the tenancy OCID where user is located. + type: string + user: + description: User is an access OCID specific to the account. + type: string + required: + - secretRef + - tenancy + - user + type: object + region: + description: Region is the region where vault is located. + type: string + vault: + description: Vault is the vault's OCID of the specific vault where secret is located. + type: string + required: + - region + - vault + type: object + vault: + description: Vault configures this store to sync secrets using Hashi provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Vault server. + properties: + appRole: + description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + properties: + path: + default: approle + description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + type: string + roleId: + description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + type: string + secretRef: + description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + - roleId + - secretRef + type: object + cert: + description: Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate Cert authentication method + properties: + clientCert: + description: ClientCert is a certificate to authenticate using the Cert Vault authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretRef: + description: SecretRef to a key in a Secret resource containing client private key to authenticate with Vault using the Cert authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + jwt: + description: Jwt authenticates with Vault by passing role and JWT token using the JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: Optional ServiceAccountToken specifies the Kubernetes service account for which to request a token for with the `TokenRequest` API. + properties: + audiences: + description: Optional audiences field that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to a single audience `vault` it not specified. + items: + type: string + type: array + expirationSeconds: + description: Optional expiration time in seconds that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to 10 minutes. + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the name of a kubernetes ServiceAccount. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: 'Path where the JWT authentication backend is mounted in Vault, e.g: "jwt"' + type: string + role: + description: Role is a JWT role to authenticate using the JWT/OIDC Vault authentication method + type: string + secretRef: + description: Optional SecretRef that refers to a key in a Secret resource containing JWT token to authenticate with Vault using the JWT/OIDC authentication method. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + properties: + mountPath: + default: kubernetes + description: 'Path where the Kubernetes authentication backend is mounted in Vault, e.g: "kubernetes"' + type: string + role: + description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: Optional secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. If a name is specified without a key, `token` is the default. If one is not specified, the one bound to the controller will be used. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Vault. If the service account selector is not supplied, the secretRef will be used instead. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: Ldap authenticates with Vault by passing username/password pair using the LDAP authentication method + properties: + path: + default: ldap + description: 'Path where the LDAP authentication backend is mounted in Vault, e.g: "ldap"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the LDAP user used to authenticate with Vault using the LDAP authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a LDAP user name used to authenticate using the LDAP Vault authentication method + type: string + required: + - path + - username + type: object + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caBundle: + description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Vault server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: ForwardInconsistent tells Vault to forward read-after-write requests to the Vault leader instead of simply retrying within a loop. This can increase performance if the option is enabled serverside. https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1". More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + type: string + path: + description: 'Path is the mount path of the Vault KV backend endpoint, e.g: "secret". The v2 KV secret engine version specific "/data" path suffix for fetching secrets from Vault is optional and will be appended if not present in specified path.' + type: string + readYourWrites: + description: ReadYourWrites ensures isolated read-after-write semantics by providing discovered cluster replication states in each request. More information about eventual consistency in Vault can be found here https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + version: + default: v2 + description: Version is the Vault KV secret engine version. This can be either "v1" or "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + webhook: + description: Webhook configures this store to sync secrets using a generic templated webhook + properties: + body: + description: Body + type: string + caBundle: + description: PEM encoded CA bundle used to validate webhook server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate webhook server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + headers: + additionalProperties: + type: string + description: Headers + type: object + method: + description: Webhook Method + type: string + result: + description: Result formatting + properties: + jsonPath: + description: Json path of return value + type: string + type: object + secrets: + description: Secrets to fill in templates These secrets will be passed to the templating function as key value pairs under the given name + items: + properties: + name: + description: Name of this secret in templates + type: string + secretRef: + description: Secret ref to fill in credentials + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - name + - secretRef + type: object + type: array + timeout: + description: Timeout + type: string + url: + description: Webhook url to call + type: string + required: + - result + - url + type: object + yandexlockbox: + description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Lockbox + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + type: object + retrySettings: + description: Used to configure http retries if failed + properties: + maxRetries: + format: int32 + type: integer + retryInterval: + type: string + type: object + required: + - provider + type: object + status: + description: SecretStoreStatus defines the observed state of the SecretStore. + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: ClusterSecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: SecretStoreSpec defines the desired state of SecretStore. + properties: + controller: + description: 'Used to select the correct KES controller (think: ingress.ingressClassName) The KES controller is instantiated with a specific controller name and filters ES based on this property' + type: string + provider: + description: Used to configure the provider. Only one provider may be set + maxProperties: 1 + minProperties: 1 + properties: + akeyless: + description: Akeyless configures this store to sync secrets using Akeyless Vault provider + properties: + akeylessGWApiURL: + description: Akeyless GW API Url from which the secrets to be fetched from. + type: string + authSecretRef: + description: Auth configures how the operator authenticates with Akeyless. + properties: + secretRef: + description: 'AkeylessAuthSecretRef AKEYLESS_ACCESS_TYPE_PARAM: AZURE_OBJ_ID OR GCP_AUDIENCE OR ACCESS_KEY OR KUB_CONFIG_NAME.' + properties: + accessID: + description: The SecretAccessID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessType: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessTypeParam: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + required: + - akeylessGWApiURL + - authSecretRef + type: object + alibaba: + description: Alibaba configures this store to sync secrets using Alibaba Cloud provider + properties: + auth: + description: AlibabaAuth contains a secretRef for credentials. + properties: + secretRef: + description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessKeySecretSecretRef: + description: The AccessKeySecret is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - accessKeyIDSecretRef + - accessKeySecretSecretRef + type: object + required: + - secretRef + type: object + endpoint: + type: string + regionID: + description: Alibaba Region to be used for the provider + type: string + required: + - auth + - regionID + type: object + aws: + description: AWS configures this store to sync secrets using AWS Secret Manager provider + properties: + auth: + description: 'Auth defines the information necessary to authenticate against AWS if not set aws sdk will infer credentials from your environment see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + properties: + jwt: + description: Authenticate against AWS using service account tokens. + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + type: object + secretRef: + description: AWSAuthSecretRef holds secret references for AWS credentials both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + region: + description: AWS Region to be used for the provider + type: string + role: + description: Role is a Role ARN which the SecretManager provider will assume + type: string + service: + description: Service defines which service should be used to fetch the secrets + enum: + - SecretsManager + - ParameterStore + type: string + required: + - region + - service + type: object + azurekv: + description: AzureKV configures this store to sync secrets using Azure Key Vault provider + properties: + authSecretRef: + description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. + properties: + clientId: + description: The Azure clientId of the service principle used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientSecret: + description: The Azure ClientSecret of the service principle used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + authType: + default: ServicePrincipal + description: 'Auth type defines how to authenticate to the keyvault service. Valid values are: - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity)' + enum: + - ServicePrincipal + - ManagedIdentity + - WorkloadIdentity + type: string + identityId: + description: If multiple Managed Identity is assigned to the pod, you can select the one to be used + type: string + serviceAccountRef: + description: ServiceAccountRef specified the service account that should be used when authenticating with WorkloadIdentity. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + tenantId: + description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. + type: string + vaultUrl: + description: Vault Url from which the secrets to be fetched from. + type: string + required: + - vaultUrl + type: object + fake: + description: Fake configures a store with static key/value pairs + properties: + data: + items: + properties: + key: + type: string + value: + type: string + valueMap: + additionalProperties: + type: string + type: object + version: + type: string + required: + - key + type: object + type: array + required: + - data + type: object + gcpsm: + description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider + properties: + auth: + description: Auth defines the information necessary to authenticate against GCP + properties: + secretRef: + properties: + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + workloadIdentity: + properties: + clusterLocation: + type: string + clusterName: + type: string + clusterProjectID: + type: string + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - clusterLocation + - clusterName + - serviceAccountRef + type: object + type: object + projectID: + description: ProjectID project where secret is located + type: string + type: object + gitlab: + description: Gitlab configures this store to sync secrets using Gitlab Variables provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a GitLab instance. + properties: + SecretRef: + properties: + accessToken: + description: AccessToken is used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - SecretRef + type: object + projectID: + description: ProjectID specifies a project where secrets are located. + type: string + url: + description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. + type: string + required: + - auth + type: object + ibm: + description: IBM configures this store to sync secrets using IBM Cloud provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the IBM secrets manager. + properties: + secretRef: + properties: + secretApiKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + serviceUrl: + description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance + type: string + required: + - auth + type: object + kubernetes: + description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Kubernetes instance. + maxProperties: 1 + minProperties: 1 + properties: + cert: + description: has both clientCert and clientKey as secretKeySelector + properties: + clientCert: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientKey: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + serviceAccount: + description: points to a service account that should be used for authentication + properties: + serviceAccount: + description: A reference to a ServiceAccount resource. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + type: object + token: + description: use static token to authenticate with + properties: + bearerToken: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + remoteNamespace: + default: default + description: Remote namespace to fetch the secrets from + type: string + server: + description: configures the Kubernetes server Address. + properties: + caBundle: + description: CABundle is a base64-encoded CA certificate + format: byte + type: string + caProvider: + description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + url: + default: kubernetes.default + description: configures the Kubernetes server Address. + type: string + type: object + required: + - auth + type: object + onepassword: + description: OnePassword configures this store to sync secrets using the 1Password Cloud provider + properties: + auth: + description: Auth defines the information necessary to authenticate against OnePassword Connect Server + properties: + secretRef: + description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. + properties: + connectTokenSecretRef: + description: The ConnectToken is used for authentication to a 1Password Connect Server. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - connectTokenSecretRef + type: object + required: + - secretRef + type: object + connectHost: + description: ConnectHost defines the OnePassword Connect Server to connect to + type: string + vaults: + additionalProperties: + type: integer + description: Vaults defines which OnePassword vaults to search in which order + type: object + required: + - auth + - connectHost + - vaults + type: object + oracle: + description: Oracle configures this store to sync secrets using Oracle Vault provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Oracle Vault. If empty, use the instance principal, otherwise the user credentials specified in Auth. + properties: + secretRef: + description: SecretRef to pass through sensitive information. + properties: + fingerprint: + description: Fingerprint is the fingerprint of the API private key. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + privatekey: + description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - fingerprint + - privatekey + type: object + tenancy: + description: Tenancy is the tenancy OCID where user is located. + type: string + user: + description: User is an access OCID specific to the account. + type: string + required: + - secretRef + - tenancy + - user + type: object + region: + description: Region is the region where vault is located. + type: string + vault: + description: Vault is the vault's OCID of the specific vault where secret is located. + type: string + required: + - region + - vault + type: object + senhasegura: + description: Senhasegura configures this store to sync secrets using senhasegura provider + properties: + auth: + description: Auth defines parameters to authenticate in senhasegura + properties: + clientId: + type: string + clientSecretSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecretSecretRef + type: object + ignoreSslCertificate: + default: false + description: IgnoreSslCertificate defines if SSL certificate must be ignored + type: boolean + module: + description: Module defines which senhasegura module should be used to get secrets + type: string + url: + description: URL of senhasegura + type: string + required: + - auth + - module + - url + type: object + vault: + description: Vault configures this store to sync secrets using Hashi provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Vault server. + properties: + appRole: + description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + properties: + path: + default: approle + description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + type: string + roleId: + description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + type: string + secretRef: + description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + - roleId + - secretRef + type: object + cert: + description: Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate Cert authentication method + properties: + clientCert: + description: ClientCert is a certificate to authenticate using the Cert Vault authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretRef: + description: SecretRef to a key in a Secret resource containing client private key to authenticate with Vault using the Cert authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + jwt: + description: Jwt authenticates with Vault by passing role and JWT token using the JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: Optional ServiceAccountToken specifies the Kubernetes service account for which to request a token for with the `TokenRequest` API. + properties: + audiences: + description: Optional audiences field that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to a single audience `vault` it not specified. + items: + type: string + type: array + expirationSeconds: + description: Optional expiration time in seconds that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to 10 minutes. + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the name of a kubernetes ServiceAccount. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: 'Path where the JWT authentication backend is mounted in Vault, e.g: "jwt"' + type: string + role: + description: Role is a JWT role to authenticate using the JWT/OIDC Vault authentication method + type: string + secretRef: + description: Optional SecretRef that refers to a key in a Secret resource containing JWT token to authenticate with Vault using the JWT/OIDC authentication method. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + properties: + mountPath: + default: kubernetes + description: 'Path where the Kubernetes authentication backend is mounted in Vault, e.g: "kubernetes"' + type: string + role: + description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: Optional secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. If a name is specified without a key, `token` is the default. If one is not specified, the one bound to the controller will be used. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Vault. If the service account selector is not supplied, the secretRef will be used instead. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: Ldap authenticates with Vault by passing username/password pair using the LDAP authentication method + properties: + path: + default: ldap + description: 'Path where the LDAP authentication backend is mounted in Vault, e.g: "ldap"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the LDAP user used to authenticate with Vault using the LDAP authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a LDAP user name used to authenticate using the LDAP Vault authentication method + type: string + required: + - path + - username + type: object + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caBundle: + description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Vault server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: ForwardInconsistent tells Vault to forward read-after-write requests to the Vault leader instead of simply retrying within a loop. This can increase performance if the option is enabled serverside. https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1". More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + type: string + path: + description: 'Path is the mount path of the Vault KV backend endpoint, e.g: "secret". The v2 KV secret engine version specific "/data" path suffix for fetching secrets from Vault is optional and will be appended if not present in specified path.' + type: string + readYourWrites: + description: ReadYourWrites ensures isolated read-after-write semantics by providing discovered cluster replication states in each request. More information about eventual consistency in Vault can be found here https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + version: + default: v2 + description: Version is the Vault KV secret engine version. This can be either "v1" or "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + webhook: + description: Webhook configures this store to sync secrets using a generic templated webhook + properties: + body: + description: Body + type: string + caBundle: + description: PEM encoded CA bundle used to validate webhook server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate webhook server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + headers: + additionalProperties: + type: string + description: Headers + type: object + method: + description: Webhook Method + type: string + result: + description: Result formatting + properties: + jsonPath: + description: Json path of return value + type: string + type: object + secrets: + description: Secrets to fill in templates These secrets will be passed to the templating function as key value pairs under the given name + items: + properties: + name: + description: Name of this secret in templates + type: string + secretRef: + description: Secret ref to fill in credentials + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - name + - secretRef + type: object + type: array + timeout: + description: Timeout + type: string + url: + description: Webhook url to call + type: string + required: + - result + - url + type: object + yandexcertificatemanager: + description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Certificate Manager + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + yandexlockbox: + description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Lockbox + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + type: object + refreshInterval: + description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. + type: integer + retrySettings: + description: Used to configure http retries if failed + properties: + maxRetries: + format: int32 + type: integer + retryInterval: + type: string + type: object + required: + - provider + type: object + status: + description: SecretStoreStatus defines the observed state of the SecretStore. + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/externalsecret.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/externalsecret.yaml new file mode 100644 index 000000000..a1254ffee --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/externalsecret.yaml @@ -0,0 +1,508 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.0 + creationTimestamp: null + name: externalsecrets.external-secrets.io +spec: + group: external-secrets.io + names: + categories: + - externalsecrets + kind: ExternalSecret + listKind: ExternalSecretList + plural: externalsecrets + shortNames: + - es + singular: externalsecret + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.secretStoreRef.name + name: Store + type: string + - jsonPath: .spec.refreshInterval + name: Refresh Interval + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + deprecated: true + name: v1alpha1 + schema: + openAPIV3Schema: + description: ExternalSecret is the Schema for the external-secrets API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ExternalSecretSpec defines the desired state of ExternalSecret. + properties: + data: + description: Data defines the connection between the Kubernetes Secret keys and the Provider data + items: + description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. + properties: + remoteRef: + description: ExternalSecretDataRemoteRef defines Provider data location. + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string + key: + description: Key is the key used in the Provider, mandatory + type: string + property: + description: Used to select a specific property of the Provider value (if a map), if supported + type: string + version: + description: Used to select a specific version of the Provider value, if supported + type: string + required: + - key + type: object + secretKey: + type: string + required: + - remoteRef + - secretKey + type: object + type: array + dataFrom: + description: DataFrom is used to fetch all properties from a specific Provider data If multiple entries are specified, the Secret keys are merged in the specified order + items: + description: ExternalSecretDataRemoteRef defines Provider data location. + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string + key: + description: Key is the key used in the Provider, mandatory + type: string + property: + description: Used to select a specific property of the Provider value (if a map), if supported + type: string + version: + description: Used to select a specific version of the Provider value, if supported + type: string + required: + - key + type: object + type: array + refreshInterval: + default: 1h + description: RefreshInterval is the amount of time before the values are read again from the SecretStore provider Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" May be set to zero to fetch and create it once. Defaults to 1h. + type: string + secretStoreRef: + description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. + properties: + kind: + description: Kind of the SecretStore resource (SecretStore or ClusterSecretStore) Defaults to `SecretStore` + type: string + name: + description: Name of the SecretStore resource + type: string + required: + - name + type: object + target: + description: ExternalSecretTarget defines the Kubernetes Secret to be created There can be only one target per ExternalSecret. + properties: + creationPolicy: + default: Owner + description: CreationPolicy defines rules on how to create the resulting Secret Defaults to 'Owner' + type: string + immutable: + description: Immutable defines if the final secret will be immutable + type: boolean + name: + description: Name defines the name of the Secret resource to be managed This field is immutable Defaults to the .metadata.name of the ExternalSecret resource + type: string + template: + description: Template defines a blueprint for the created Secret resource. + properties: + data: + additionalProperties: + type: string + type: object + engineVersion: + default: v1 + description: EngineVersion specifies the template engine version that should be used to compile/execute the template specified in .data and .templateFrom[]. + type: string + metadata: + description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + templateFrom: + items: + maxProperties: 1 + minProperties: 1 + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + type: object + type: array + type: + type: string + type: object + type: object + required: + - secretStoreRef + - target + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + refreshTime: + description: refreshTime is the time and date the external secret was fetched and the target secret updated + format: date-time + nullable: true + type: string + syncedResourceVersion: + description: SyncedResourceVersion keeps track of the last synced version + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.secretStoreRef.name + name: Store + type: string + - jsonPath: .spec.refreshInterval + name: Refresh Interval + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: ExternalSecret is the Schema for the external-secrets API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ExternalSecretSpec defines the desired state of ExternalSecret. + properties: + data: + description: Data defines the connection between the Kubernetes Secret keys and the Provider data + items: + description: ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.) and the Provider data. + properties: + remoteRef: + description: ExternalSecretDataRemoteRef defines Provider data location. + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string + key: + description: Key is the key used in the Provider, mandatory + type: string + metadataPolicy: + description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None + type: string + property: + description: Used to select a specific property of the Provider value (if a map), if supported + type: string + version: + description: Used to select a specific version of the Provider value, if supported + type: string + required: + - key + type: object + secretKey: + type: string + required: + - remoteRef + - secretKey + type: object + type: array + dataFrom: + description: DataFrom is used to fetch all properties from a specific Provider data If multiple entries are specified, the Secret keys are merged in the specified order + items: + maxProperties: 1 + minProperties: 1 + properties: + extract: + description: Used to extract multiple key/value pairs from one secret + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string + key: + description: Key is the key used in the Provider, mandatory + type: string + metadataPolicy: + description: Policy for fetching tags/labels from provider secrets, possible options are Fetch, None. Defaults to None + type: string + property: + description: Used to select a specific property of the Provider value (if a map), if supported + type: string + version: + description: Used to select a specific version of the Provider value, if supported + type: string + required: + - key + type: object + find: + description: Used to find secrets based on tags or regular expressions + properties: + conversionStrategy: + default: Default + description: Used to define a conversion Strategy + type: string + name: + description: Finds secrets based on the name. + properties: + regexp: + description: Finds secrets base + type: string + type: object + path: + description: A root path to start the find operations. + type: string + tags: + additionalProperties: + type: string + description: Find secrets based on tags. + type: object + type: object + type: object + type: array + refreshInterval: + default: 1h + description: RefreshInterval is the amount of time before the values are read again from the SecretStore provider Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h" May be set to zero to fetch and create it once. Defaults to 1h. + type: string + secretStoreRef: + description: SecretStoreRef defines which SecretStore to fetch the ExternalSecret data. + properties: + kind: + description: Kind of the SecretStore resource (SecretStore or ClusterSecretStore) Defaults to `SecretStore` + type: string + name: + description: Name of the SecretStore resource + type: string + required: + - name + type: object + target: + description: ExternalSecretTarget defines the Kubernetes Secret to be created There can be only one target per ExternalSecret. + properties: + creationPolicy: + default: Owner + description: CreationPolicy defines rules on how to create the resulting Secret Defaults to 'Owner' + enum: + - Owner + - Orphan + - Merge + - None + type: string + deletionPolicy: + default: Retain + description: DeletionPolicy defines rules on how to delete the resulting Secret Defaults to 'Retain' + enum: + - Delete + - Merge + - Retain + type: string + immutable: + description: Immutable defines if the final secret will be immutable + type: boolean + name: + description: Name defines the name of the Secret resource to be managed This field is immutable Defaults to the .metadata.name of the ExternalSecret resource + type: string + template: + description: Template defines a blueprint for the created Secret resource. + properties: + data: + additionalProperties: + type: string + type: object + engineVersion: + default: v2 + type: string + metadata: + description: ExternalSecretTemplateMetadata defines metadata fields for the Secret blueprint. + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + templateFrom: + items: + maxProperties: 1 + minProperties: 1 + properties: + configMap: + properties: + items: + items: + properties: + key: + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + required: + - key + type: object + type: array + name: + type: string + required: + - items + - name + type: object + type: object + type: array + type: + type: string + type: object + type: object + required: + - secretStoreRef + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + refreshTime: + description: refreshTime is the time and date the external secret was fetched and the target secret updated + format: date-time + nullable: true + type: string + syncedResourceVersion: + description: SyncedResourceVersion keeps track of the last synced version + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/secretstore.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/secretstore.yaml new file mode 100644 index 000000000..df387c704 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/crds/secretstore.yaml @@ -0,0 +1,2166 @@ +{{- if .Values.installCRDs }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.0 + creationTimestamp: null + name: secretstores.external-secrets.io +spec: + group: external-secrets.io + names: + categories: + - externalsecrets + kind: SecretStore + listKind: SecretStoreList + plural: secretstores + shortNames: + - ss + singular: secretstore + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + deprecated: true + name: v1alpha1 + schema: + openAPIV3Schema: + description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: SecretStoreSpec defines the desired state of SecretStore. + properties: + controller: + description: 'Used to select the correct KES controller (think: ingress.ingressClassName) The KES controller is instantiated with a specific controller name and filters ES based on this property' + type: string + provider: + description: Used to configure the provider. Only one provider may be set + maxProperties: 1 + minProperties: 1 + properties: + akeyless: + description: Akeyless configures this store to sync secrets using Akeyless Vault provider + properties: + akeylessGWApiURL: + description: Akeyless GW API Url from which the secrets to be fetched from. + type: string + authSecretRef: + description: Auth configures how the operator authenticates with Akeyless. + properties: + secretRef: + description: 'AkeylessAuthSecretRef AKEYLESS_ACCESS_TYPE_PARAM: AZURE_OBJ_ID OR GCP_AUDIENCE OR ACCESS_KEY OR KUB_CONFIG_NAME.' + properties: + accessID: + description: The SecretAccessID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessType: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessTypeParam: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + required: + - akeylessGWApiURL + - authSecretRef + type: object + alibaba: + description: Alibaba configures this store to sync secrets using Alibaba Cloud provider + properties: + auth: + description: AlibabaAuth contains a secretRef for credentials. + properties: + secretRef: + description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessKeySecretSecretRef: + description: The AccessKeySecret is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - accessKeyIDSecretRef + - accessKeySecretSecretRef + type: object + required: + - secretRef + type: object + endpoint: + type: string + regionID: + description: Alibaba Region to be used for the provider + type: string + required: + - auth + - regionID + type: object + aws: + description: AWS configures this store to sync secrets using AWS Secret Manager provider + properties: + auth: + description: 'Auth defines the information necessary to authenticate against AWS if not set aws sdk will infer credentials from your environment see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + properties: + jwt: + description: Authenticate against AWS using service account tokens. + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + type: object + secretRef: + description: AWSAuthSecretRef holds secret references for AWS credentials both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + region: + description: AWS Region to be used for the provider + type: string + role: + description: Role is a Role ARN which the SecretManager provider will assume + type: string + service: + description: Service defines which service should be used to fetch the secrets + enum: + - SecretsManager + - ParameterStore + type: string + required: + - region + - service + type: object + azurekv: + description: AzureKV configures this store to sync secrets using Azure Key Vault provider + properties: + authSecretRef: + description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. + properties: + clientId: + description: The Azure clientId of the service principle used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientSecret: + description: The Azure ClientSecret of the service principle used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + authType: + default: ServicePrincipal + description: 'Auth type defines how to authenticate to the keyvault service. Valid values are: - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity)' + enum: + - ServicePrincipal + - ManagedIdentity + - WorkloadIdentity + type: string + identityId: + description: If multiple Managed Identity is assigned to the pod, you can select the one to be used + type: string + serviceAccountRef: + description: ServiceAccountRef specified the service account that should be used when authenticating with WorkloadIdentity. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + tenantId: + description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. + type: string + vaultUrl: + description: Vault Url from which the secrets to be fetched from. + type: string + required: + - vaultUrl + type: object + fake: + description: Fake configures a store with static key/value pairs + properties: + data: + items: + properties: + key: + type: string + value: + type: string + valueMap: + additionalProperties: + type: string + type: object + version: + type: string + required: + - key + type: object + type: array + required: + - data + type: object + gcpsm: + description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider + properties: + auth: + description: Auth defines the information necessary to authenticate against GCP + properties: + secretRef: + properties: + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + workloadIdentity: + properties: + clusterLocation: + type: string + clusterName: + type: string + clusterProjectID: + type: string + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - clusterLocation + - clusterName + - serviceAccountRef + type: object + type: object + projectID: + description: ProjectID project where secret is located + type: string + type: object + gitlab: + description: Gitlab configures this store to sync secrets using Gitlab Variables provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a GitLab instance. + properties: + SecretRef: + properties: + accessToken: + description: AccessToken is used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - SecretRef + type: object + projectID: + description: ProjectID specifies a project where secrets are located. + type: string + url: + description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. + type: string + required: + - auth + type: object + ibm: + description: IBM configures this store to sync secrets using IBM Cloud provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the IBM secrets manager. + properties: + secretRef: + properties: + secretApiKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + serviceUrl: + description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance + type: string + required: + - auth + type: object + kubernetes: + description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Kubernetes instance. + maxProperties: 1 + minProperties: 1 + properties: + cert: + description: has both clientCert and clientKey as secretKeySelector + properties: + clientCert: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientKey: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + serviceAccount: + description: points to a service account that should be used for authentication + properties: + serviceAccount: + description: A reference to a ServiceAccount resource. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + type: object + token: + description: use static token to authenticate with + properties: + bearerToken: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + remoteNamespace: + default: default + description: Remote namespace to fetch the secrets from + type: string + server: + description: configures the Kubernetes server Address. + properties: + caBundle: + description: CABundle is a base64-encoded CA certificate + format: byte + type: string + caProvider: + description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + url: + default: kubernetes.default + description: configures the Kubernetes server Address. + type: string + type: object + required: + - auth + type: object + oracle: + description: Oracle configures this store to sync secrets using Oracle Vault provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Oracle Vault. If empty, use the instance principal, otherwise the user credentials specified in Auth. + properties: + secretRef: + description: SecretRef to pass through sensitive information. + properties: + fingerprint: + description: Fingerprint is the fingerprint of the API private key. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + privatekey: + description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - fingerprint + - privatekey + type: object + tenancy: + description: Tenancy is the tenancy OCID where user is located. + type: string + user: + description: User is an access OCID specific to the account. + type: string + required: + - secretRef + - tenancy + - user + type: object + region: + description: Region is the region where vault is located. + type: string + vault: + description: Vault is the vault's OCID of the specific vault where secret is located. + type: string + required: + - region + - vault + type: object + vault: + description: Vault configures this store to sync secrets using Hashi provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Vault server. + properties: + appRole: + description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + properties: + path: + default: approle + description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + type: string + roleId: + description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + type: string + secretRef: + description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + - roleId + - secretRef + type: object + cert: + description: Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate Cert authentication method + properties: + clientCert: + description: ClientCert is a certificate to authenticate using the Cert Vault authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretRef: + description: SecretRef to a key in a Secret resource containing client private key to authenticate with Vault using the Cert authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + jwt: + description: Jwt authenticates with Vault by passing role and JWT token using the JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: Optional ServiceAccountToken specifies the Kubernetes service account for which to request a token for with the `TokenRequest` API. + properties: + audiences: + description: Optional audiences field that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to a single audience `vault` it not specified. + items: + type: string + type: array + expirationSeconds: + description: Optional expiration time in seconds that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to 10 minutes. + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the name of a kubernetes ServiceAccount. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: 'Path where the JWT authentication backend is mounted in Vault, e.g: "jwt"' + type: string + role: + description: Role is a JWT role to authenticate using the JWT/OIDC Vault authentication method + type: string + secretRef: + description: Optional SecretRef that refers to a key in a Secret resource containing JWT token to authenticate with Vault using the JWT/OIDC authentication method. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + properties: + mountPath: + default: kubernetes + description: 'Path where the Kubernetes authentication backend is mounted in Vault, e.g: "kubernetes"' + type: string + role: + description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: Optional secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. If a name is specified without a key, `token` is the default. If one is not specified, the one bound to the controller will be used. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Vault. If the service account selector is not supplied, the secretRef will be used instead. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: Ldap authenticates with Vault by passing username/password pair using the LDAP authentication method + properties: + path: + default: ldap + description: 'Path where the LDAP authentication backend is mounted in Vault, e.g: "ldap"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the LDAP user used to authenticate with Vault using the LDAP authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a LDAP user name used to authenticate using the LDAP Vault authentication method + type: string + required: + - path + - username + type: object + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caBundle: + description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Vault server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: ForwardInconsistent tells Vault to forward read-after-write requests to the Vault leader instead of simply retrying within a loop. This can increase performance if the option is enabled serverside. https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1". More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + type: string + path: + description: 'Path is the mount path of the Vault KV backend endpoint, e.g: "secret". The v2 KV secret engine version specific "/data" path suffix for fetching secrets from Vault is optional and will be appended if not present in specified path.' + type: string + readYourWrites: + description: ReadYourWrites ensures isolated read-after-write semantics by providing discovered cluster replication states in each request. More information about eventual consistency in Vault can be found here https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + version: + default: v2 + description: Version is the Vault KV secret engine version. This can be either "v1" or "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + webhook: + description: Webhook configures this store to sync secrets using a generic templated webhook + properties: + body: + description: Body + type: string + caBundle: + description: PEM encoded CA bundle used to validate webhook server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate webhook server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + headers: + additionalProperties: + type: string + description: Headers + type: object + method: + description: Webhook Method + type: string + result: + description: Result formatting + properties: + jsonPath: + description: Json path of return value + type: string + type: object + secrets: + description: Secrets to fill in templates These secrets will be passed to the templating function as key value pairs under the given name + items: + properties: + name: + description: Name of this secret in templates + type: string + secretRef: + description: Secret ref to fill in credentials + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - name + - secretRef + type: object + type: array + timeout: + description: Timeout + type: string + url: + description: Webhook url to call + type: string + required: + - result + - url + type: object + yandexlockbox: + description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Lockbox + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + type: object + retrySettings: + description: Used to configure http retries if failed + properties: + maxRetries: + format: int32 + type: integer + retryInterval: + type: string + type: object + required: + - provider + type: object + status: + description: SecretStoreStatus defines the observed state of the SecretStore. + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].reason + name: Status + type: string + name: v1beta1 + schema: + openAPIV3Schema: + description: SecretStore represents a secure external location for storing secrets, which can be referenced as part of `storeRef` fields. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: SecretStoreSpec defines the desired state of SecretStore. + properties: + controller: + description: 'Used to select the correct KES controller (think: ingress.ingressClassName) The KES controller is instantiated with a specific controller name and filters ES based on this property' + type: string + provider: + description: Used to configure the provider. Only one provider may be set + maxProperties: 1 + minProperties: 1 + properties: + akeyless: + description: Akeyless configures this store to sync secrets using Akeyless Vault provider + properties: + akeylessGWApiURL: + description: Akeyless GW API Url from which the secrets to be fetched from. + type: string + authSecretRef: + description: Auth configures how the operator authenticates with Akeyless. + properties: + secretRef: + description: 'AkeylessAuthSecretRef AKEYLESS_ACCESS_TYPE_PARAM: AZURE_OBJ_ID OR GCP_AUDIENCE OR ACCESS_KEY OR KUB_CONFIG_NAME.' + properties: + accessID: + description: The SecretAccessID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessType: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessTypeParam: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + required: + - akeylessGWApiURL + - authSecretRef + type: object + alibaba: + description: Alibaba configures this store to sync secrets using Alibaba Cloud provider + properties: + auth: + description: AlibabaAuth contains a secretRef for credentials. + properties: + secretRef: + description: AlibabaAuthSecretRef holds secret references for Alibaba credentials. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + accessKeySecretSecretRef: + description: The AccessKeySecret is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - accessKeyIDSecretRef + - accessKeySecretSecretRef + type: object + required: + - secretRef + type: object + endpoint: + type: string + regionID: + description: Alibaba Region to be used for the provider + type: string + required: + - auth + - regionID + type: object + aws: + description: AWS configures this store to sync secrets using AWS Secret Manager provider + properties: + auth: + description: 'Auth defines the information necessary to authenticate against AWS if not set aws sdk will infer credentials from your environment see: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials' + properties: + jwt: + description: Authenticate against AWS using service account tokens. + properties: + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + type: object + secretRef: + description: AWSAuthSecretRef holds secret references for AWS credentials both AccessKeyID and SecretAccessKey must be defined in order to properly authenticate. + properties: + accessKeyIDSecretRef: + description: The AccessKeyID is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + region: + description: AWS Region to be used for the provider + type: string + role: + description: Role is a Role ARN which the SecretManager provider will assume + type: string + service: + description: Service defines which service should be used to fetch the secrets + enum: + - SecretsManager + - ParameterStore + type: string + required: + - region + - service + type: object + azurekv: + description: AzureKV configures this store to sync secrets using Azure Key Vault provider + properties: + authSecretRef: + description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. + properties: + clientId: + description: The Azure clientId of the service principle used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientSecret: + description: The Azure ClientSecret of the service principle used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + authType: + default: ServicePrincipal + description: 'Auth type defines how to authenticate to the keyvault service. Valid values are: - "ServicePrincipal" (default): Using a service principal (tenantId, clientId, clientSecret) - "ManagedIdentity": Using Managed Identity assigned to the pod (see aad-pod-identity)' + enum: + - ServicePrincipal + - ManagedIdentity + - WorkloadIdentity + type: string + identityId: + description: If multiple Managed Identity is assigned to the pod, you can select the one to be used + type: string + serviceAccountRef: + description: ServiceAccountRef specified the service account that should be used when authenticating with WorkloadIdentity. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + tenantId: + description: TenantID configures the Azure Tenant to send requests to. Required for ServicePrincipal auth type. + type: string + vaultUrl: + description: Vault Url from which the secrets to be fetched from. + type: string + required: + - vaultUrl + type: object + fake: + description: Fake configures a store with static key/value pairs + properties: + data: + items: + properties: + key: + type: string + value: + type: string + valueMap: + additionalProperties: + type: string + type: object + version: + type: string + required: + - key + type: object + type: array + required: + - data + type: object + gcpsm: + description: GCPSM configures this store to sync secrets using Google Cloud Platform Secret Manager provider + properties: + auth: + description: Auth defines the information necessary to authenticate against GCP + properties: + secretRef: + properties: + secretAccessKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + workloadIdentity: + properties: + clusterLocation: + type: string + clusterName: + type: string + clusterProjectID: + type: string + serviceAccountRef: + description: A reference to a ServiceAccount resource. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - clusterLocation + - clusterName + - serviceAccountRef + type: object + type: object + projectID: + description: ProjectID project where secret is located + type: string + type: object + gitlab: + description: Gitlab configures this store to sync secrets using Gitlab Variables provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a GitLab instance. + properties: + SecretRef: + properties: + accessToken: + description: AccessToken is used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - SecretRef + type: object + projectID: + description: ProjectID specifies a project where secrets are located. + type: string + url: + description: URL configures the GitLab instance URL. Defaults to https://gitlab.com/. + type: string + required: + - auth + type: object + ibm: + description: IBM configures this store to sync secrets using IBM Cloud provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the IBM secrets manager. + properties: + secretRef: + properties: + secretApiKeySecretRef: + description: The SecretAccessKey is used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + serviceUrl: + description: ServiceURL is the Endpoint URL that is specific to the Secrets Manager service instance + type: string + required: + - auth + type: object + kubernetes: + description: Kubernetes configures this store to sync secrets using a Kubernetes cluster provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Kubernetes instance. + maxProperties: 1 + minProperties: 1 + properties: + cert: + description: has both clientCert and clientKey as secretKeySelector + properties: + clientCert: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + clientKey: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + serviceAccount: + description: points to a service account that should be used for authentication + properties: + serviceAccount: + description: A reference to a ServiceAccount resource. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + type: object + token: + description: use static token to authenticate with + properties: + bearerToken: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + type: object + remoteNamespace: + default: default + description: Remote namespace to fetch the secrets from + type: string + server: + description: configures the Kubernetes server Address. + properties: + caBundle: + description: CABundle is a base64-encoded CA certificate + format: byte + type: string + caProvider: + description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider' + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + url: + default: kubernetes.default + description: configures the Kubernetes server Address. + type: string + type: object + required: + - auth + type: object + onepassword: + description: OnePassword configures this store to sync secrets using the 1Password Cloud provider + properties: + auth: + description: Auth defines the information necessary to authenticate against OnePassword Connect Server + properties: + secretRef: + description: OnePasswordAuthSecretRef holds secret references for 1Password credentials. + properties: + connectTokenSecretRef: + description: The ConnectToken is used for authentication to a 1Password Connect Server. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - connectTokenSecretRef + type: object + required: + - secretRef + type: object + connectHost: + description: ConnectHost defines the OnePassword Connect Server to connect to + type: string + vaults: + additionalProperties: + type: integer + description: Vaults defines which OnePassword vaults to search in which order + type: object + required: + - auth + - connectHost + - vaults + type: object + oracle: + description: Oracle configures this store to sync secrets using Oracle Vault provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Oracle Vault. If empty, use the instance principal, otherwise the user credentials specified in Auth. + properties: + secretRef: + description: SecretRef to pass through sensitive information. + properties: + fingerprint: + description: Fingerprint is the fingerprint of the API private key. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + privatekey: + description: PrivateKey is the user's API Signing Key in PEM format, used for authentication. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - fingerprint + - privatekey + type: object + tenancy: + description: Tenancy is the tenancy OCID where user is located. + type: string + user: + description: User is an access OCID specific to the account. + type: string + required: + - secretRef + - tenancy + - user + type: object + region: + description: Region is the region where vault is located. + type: string + vault: + description: Vault is the vault's OCID of the specific vault where secret is located. + type: string + required: + - region + - vault + type: object + senhasegura: + description: Senhasegura configures this store to sync secrets using senhasegura provider + properties: + auth: + description: Auth defines parameters to authenticate in senhasegura + properties: + clientId: + type: string + clientSecretSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecretSecretRef + type: object + ignoreSslCertificate: + default: false + description: IgnoreSslCertificate defines if SSL certificate must be ignored + type: boolean + module: + description: Module defines which senhasegura module should be used to get secrets + type: string + url: + description: URL of senhasegura + type: string + required: + - auth + - module + - url + type: object + vault: + description: Vault configures this store to sync secrets using Hashi provider + properties: + auth: + description: Auth configures how secret-manager authenticates with the Vault server. + properties: + appRole: + description: AppRole authenticates with Vault using the App Role auth mechanism, with the role and secret stored in a Kubernetes Secret resource. + properties: + path: + default: approle + description: 'Path where the App Role authentication backend is mounted in Vault, e.g: "approle"' + type: string + roleId: + description: RoleID configured in the App Role authentication backend when setting up the authentication backend in Vault. + type: string + secretRef: + description: Reference to a key in a Secret that contains the App Role secret used to authenticate with Vault. The `key` field must be specified and denotes which entry within the Secret resource is used as the app role secret. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + - roleId + - secretRef + type: object + cert: + description: Cert authenticates with TLS Certificates by passing client certificate, private key and ca certificate Cert authentication method + properties: + clientCert: + description: ClientCert is a certificate to authenticate using the Cert Vault authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + secretRef: + description: SecretRef to a key in a Secret resource containing client private key to authenticate with Vault using the Cert authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + jwt: + description: Jwt authenticates with Vault by passing role and JWT token using the JWT/OIDC authentication method + properties: + kubernetesServiceAccountToken: + description: Optional ServiceAccountToken specifies the Kubernetes service account for which to request a token for with the `TokenRequest` API. + properties: + audiences: + description: Optional audiences field that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to a single audience `vault` it not specified. + items: + type: string + type: array + expirationSeconds: + description: Optional expiration time in seconds that will be used to request a temporary Kubernetes service account token for the service account referenced by `serviceAccountRef`. Defaults to 10 minutes. + format: int64 + type: integer + serviceAccountRef: + description: Service account field containing the name of a kubernetes ServiceAccount. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - serviceAccountRef + type: object + path: + default: jwt + description: 'Path where the JWT authentication backend is mounted in Vault, e.g: "jwt"' + type: string + role: + description: Role is a JWT role to authenticate using the JWT/OIDC Vault authentication method + type: string + secretRef: + description: Optional SecretRef that refers to a key in a Secret resource containing JWT token to authenticate with Vault using the JWT/OIDC authentication method. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - path + type: object + kubernetes: + description: Kubernetes authenticates with Vault by passing the ServiceAccount token stored in the named Secret resource to the Vault server. + properties: + mountPath: + default: kubernetes + description: 'Path where the Kubernetes authentication backend is mounted in Vault, e.g: "kubernetes"' + type: string + role: + description: A required field containing the Vault Role to assume. A Role binds a Kubernetes ServiceAccount with a set of Vault policies. + type: string + secretRef: + description: Optional secret field containing a Kubernetes ServiceAccount JWT used for authenticating with Vault. If a name is specified without a key, `token` is the default. If one is not specified, the one bound to the controller will be used. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + serviceAccountRef: + description: Optional service account field containing the name of a kubernetes ServiceAccount. If the service account is specified, the service account secret token JWT will be used for authenticating with Vault. If the service account selector is not supplied, the secretRef will be used instead. + properties: + name: + description: The name of the ServiceAccount resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + required: + - name + type: object + required: + - mountPath + - role + type: object + ldap: + description: Ldap authenticates with Vault by passing username/password pair using the LDAP authentication method + properties: + path: + default: ldap + description: 'Path where the LDAP authentication backend is mounted in Vault, e.g: "ldap"' + type: string + secretRef: + description: SecretRef to a key in a Secret resource containing password for the LDAP user used to authenticate with Vault using the LDAP authentication method + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + username: + description: Username is a LDAP user name used to authenticate using the LDAP Vault authentication method + type: string + required: + - path + - username + type: object + tokenSecretRef: + description: TokenSecretRef authenticates with Vault by presenting a token. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caBundle: + description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate Vault server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + forwardInconsistent: + description: ForwardInconsistent tells Vault to forward read-after-write requests to the Vault leader instead of simply retrying within a loop. This can increase performance if the option is enabled serverside. https://www.vaultproject.io/docs/configuration/replication#allow_forwarding_via_header + type: boolean + namespace: + description: 'Name of the vault namespace. Namespaces is a set of features within Vault Enterprise that allows Vault environments to support Secure Multi-tenancy. e.g: "ns1". More about namespaces can be found here https://www.vaultproject.io/docs/enterprise/namespaces' + type: string + path: + description: 'Path is the mount path of the Vault KV backend endpoint, e.g: "secret". The v2 KV secret engine version specific "/data" path suffix for fetching secrets from Vault is optional and will be appended if not present in specified path.' + type: string + readYourWrites: + description: ReadYourWrites ensures isolated read-after-write semantics by providing discovered cluster replication states in each request. More information about eventual consistency in Vault can be found here https://www.vaultproject.io/docs/enterprise/consistency + type: boolean + server: + description: 'Server is the connection address for the Vault server, e.g: "https://vault.example.com:8200".' + type: string + version: + default: v2 + description: Version is the Vault KV secret engine version. This can be either "v1" or "v2". Version defaults to "v2". + enum: + - v1 + - v2 + type: string + required: + - auth + - server + type: object + webhook: + description: Webhook configures this store to sync secrets using a generic templated webhook + properties: + body: + description: Body + type: string + caBundle: + description: PEM encoded CA bundle used to validate webhook server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection. + format: byte + type: string + caProvider: + description: The provider for the CA bundle to use to validate webhook server certificate. + properties: + key: + description: The key the value inside of the provider type to use, only used with "Secret" type + type: string + name: + description: The name of the object located at the provider type. + type: string + namespace: + description: The namespace the Provider type is in. + type: string + type: + description: The type of provider to use such as "Secret", or "ConfigMap". + enum: + - Secret + - ConfigMap + type: string + required: + - name + - type + type: object + headers: + additionalProperties: + type: string + description: Headers + type: object + method: + description: Webhook Method + type: string + result: + description: Result formatting + properties: + jsonPath: + description: Json path of return value + type: string + type: object + secrets: + description: Secrets to fill in templates These secrets will be passed to the templating function as key value pairs under the given name + items: + properties: + name: + description: Name of this secret in templates + type: string + secretRef: + description: Secret ref to fill in credentials + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + required: + - name + - secretRef + type: object + type: array + timeout: + description: Timeout + type: string + url: + description: Webhook url to call + type: string + required: + - result + - url + type: object + yandexcertificatemanager: + description: YandexCertificateManager configures this store to sync secrets using Yandex Certificate Manager provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Certificate Manager + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + yandexlockbox: + description: YandexLockbox configures this store to sync secrets using Yandex Lockbox provider + properties: + apiEndpoint: + description: Yandex.Cloud API endpoint (e.g. 'api.cloud.yandex.net:443') + type: string + auth: + description: Auth defines the information necessary to authenticate against Yandex Lockbox + properties: + authorizedKeySecretRef: + description: The authorized key used for authentication + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + caProvider: + description: The provider for the CA bundle to use to validate Yandex.Cloud server certificate. + properties: + certSecretRef: + description: A reference to a specific 'key' within a Secret resource, In some instances, `key` is a required field. + properties: + key: + description: The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults to the namespace of the referent. + type: string + type: object + type: object + required: + - auth + type: object + type: object + refreshInterval: + description: Used to configure store refresh interval in seconds. Empty or 0 will default to the controller config. + type: integer + retrySettings: + description: Used to configure http retries if failed + properties: + maxRetries: + format: int32 + type: integer + retryInterval: + type: string + type: object + required: + - provider + type: object + status: + description: SecretStoreStatus defines the observed state of the SecretStore. + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: + - v1 + clientConfig: + service: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + path: /convert +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/deployment.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/deployment.yaml new file mode 100644 index 000000000..4ee8eaaac --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/deployment.yaml @@ -0,0 +1,107 @@ +{{- if .Values.createOperator }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "external-secrets.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + {{- with .Values.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "external-secrets.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "external-secrets.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "external-secrets.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if or (.Values.leaderElect) (.Values.scopedNamespace) (.Values.processClusterStore) (.Values.processClusterExternalSecret) (.Values.concurrent) (.Values.extraArgs) }} + args: + {{- if .Values.leaderElect }} + - --enable-leader-election=true + {{- end }} + {{- if .Values.scopedNamespace }} + - --namespace={{ .Values.scopedNamespace }} + {{- end }} + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + - --enable-cluster-store-reconciler=false + - --enable-cluster-external-secret-reconciler=false + {{- else }} + {{- if not .Values.processClusterStore }} + - --enable-cluster-store-reconciler=false + {{- end }} + {{- if not .Values.processClusterExternalSecret }} + - --enable-cluster-external-secret-reconciler=false + {{- end }} + {{- end }} + {{- if .Values.controllerClass }} + - --controller-class={{ .Values.controllerClass }} + {{- end }} + {{- if .Values.concurrent }} + - --concurrent={{ .Values.concurrent }} + {{- end }} + {{- range $key, $value := .Values.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.prometheus.service.port }} + protocol: TCP + name: metrics + {{- with .Values.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/poddisruptionbudget.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/poddisruptionbudget.yaml new file mode 100644 index 000000000..abe51d337 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/poddisruptionbudget.yaml @@ -0,0 +1,19 @@ +{{- if .Values.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "external-secrets.fullname" . }}-pdb + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +spec: + {{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "external-secrets.selectorLabels" . | nindent 6 }} +{{- end }} \ No newline at end of file diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/rbac.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/rbac.yaml new file mode 100644 index 000000000..3a37931ca --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/rbac.yaml @@ -0,0 +1,227 @@ +{{- if .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + name: {{ include "external-secrets.fullname" . }}-controller + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +rules: + - apiGroups: + - "external-secrets.io" + resources: + - "secretstores" + - "clustersecretstores" + - "externalsecrets" + - "clusterexternalsecrets" + verbs: + - "get" + - "list" + - "watch" + - apiGroups: + - "external-secrets.io" + resources: + - "externalsecrets" + - "externalsecrets/status" + - "externalsecrets/finalizers" + - "secretstores" + - "secretstores/status" + - "secretstores/finalizers" + - "clustersecretstores" + - "clustersecretstores/status" + - "clustersecretstores/finalizers" + - "clusterexternalsecrets" + - "clusterexternalsecrets/status" + - "clusterexternalsecrets/finalizers" + verbs: + - "update" + - "patch" + - apiGroups: + - "" + resources: + - "serviceaccounts" + - "namespaces" + verbs: + - "get" + - "list" + - "watch" + - apiGroups: + - "" + resources: + - "configmaps" + verbs: + - "get" + - "list" + - "watch" + - apiGroups: + - "" + resources: + - "secrets" + verbs: + - "get" + - "list" + - "watch" + - "create" + - "update" + - "delete" + - "patch" + - apiGroups: + - "" + resources: + - "serviceaccounts/token" + verbs: + - "create" + - apiGroups: + - "" + resources: + - "events" + verbs: + - "create" + - "patch" + - apiGroups: + - "external-secrets.io" + resources: + - "externalsecrets" + verbs: + - "create" + - "update" +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + name: {{ include "external-secrets.fullname" . }}-view + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-view: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: + - apiGroups: + - "external-secrets.io" + resources: + - "externalsecrets" + - "secretstores" + - "clustersecretstores" + verbs: + - "get" + - "watch" + - "list" +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + name: {{ include "external-secrets.fullname" . }}-edit + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-admin: "true" +rules: + - apiGroups: + - "external-secrets.io" + resources: + - "externalsecrets" + - "secretstores" + - "clustersecretstores" + verbs: + - "create" + - "delete" + - "deletecollection" + - "patch" + - "update" +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{- if and .Values.scopedNamespace .Values.scopedRBAC }} +kind: RoleBinding +{{- else }} +kind: ClusterRoleBinding +{{- end }} +metadata: + name: {{ include "external-secrets.fullname" . }}-controller + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + namespace: {{ .Values.scopedNamespace | quote }} + {{- end }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + {{- if and .Values.scopedNamespace .Values.scopedRBAC }} + kind: Role + {{- else }} + kind: ClusterRole + {{- end }} + name: {{ include "external-secrets.fullname" . }}-controller +subjects: + - name: {{ include "external-secrets.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + kind: ServiceAccount +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "external-secrets.fullname" . }}-leaderelection + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - "configmaps" + resourceNames: + - "external-secrets-controller" + verbs: + - "get" + - "update" + - "patch" + - apiGroups: + - "" + resources: + - "configmaps" + verbs: + - "create" + - apiGroups: + - "coordination.k8s.io" + resources: + - "leases" + verbs: + - "get" + - "create" + - "update" + - "patch" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "external-secrets.fullname" . }}-leaderelection + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "external-secrets.fullname" . }}-leaderelection +subjects: + - kind: ServiceAccount + name: {{ include "external-secrets.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/service.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/service.yaml new file mode 100644 index 000000000..de2d462d4 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/service.yaml @@ -0,0 +1,21 @@ +{{- if .Values.prometheus.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-metrics + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + annotations: + prometheus.io/path: "/metrics" + prometheus.io/scrape: "true" + prometheus.io/port: {{ .Values.prometheus.service.port | quote }} +spec: + type: ClusterIP + ports: + - port: {{ .Values.prometheus.service.port }} + protocol: TCP + name: metrics + selector: + {{- include "external-secrets.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/serviceaccount.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/serviceaccount.yaml new file mode 100644 index 000000000..d3e58f78b --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "external-secrets.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/servicemonitor.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/servicemonitor.yaml new file mode 100644 index 000000000..950507ccc --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/servicemonitor.yaml @@ -0,0 +1,39 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-metrics + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets.selectorLabels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: 8080 + protocol: TCP + name: metrics + selector: + {{- include "external-secrets.selectorLabels" . | nindent 4 }} +--- +apiVersion: "monitoring.coreos.com/v1" +kind: ServiceMonitor +metadata: + labels: + {{- include "external-secrets.labels" . | nindent 4 }} +{{- if .Values.serviceMonitor.additionalLabels }} +{{ toYaml .Values.serviceMonitor.additionalLabels | indent 4 }} +{{- end }} + name: {{ include "external-secrets.fullname" . }}-metrics + namespace: {{ .Release.Namespace | quote }} +spec: + selector: + matchLabels: + {{- include "external-secrets.selectorLabels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} + endpoints: + - port: metrics + interval: {{ .Values.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/validatingwebhook.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/validatingwebhook.yaml new file mode 100644 index 000000000..d1bc2efac --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/validatingwebhook.yaml @@ -0,0 +1,64 @@ +{{- if .Values.webhook.create }} +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: secretstore-validate + labels: + external-secrets.io/component: webhook +webhooks: +- name: "validate.secretstore.external-secrets.io" + rules: + - apiGroups: ["external-secrets.io"] + apiVersions: ["v1beta1"] + operations: ["CREATE", "UPDATE", "DELETE"] + resources: ["secretstores"] + scope: "Namespaced" + clientConfig: + service: + namespace: {{ .Release.Namespace | quote }} + name: {{ include "external-secrets.fullname" . }}-webhook + path: /validate-external-secrets-io-v1beta1-secretstore + admissionReviewVersions: ["v1", "v1beta1"] + sideEffects: None + timeoutSeconds: 5 + +- name: "validate.clustersecretstore.external-secrets.io" + rules: + - apiGroups: ["external-secrets.io"] + apiVersions: ["v1beta1"] + operations: ["CREATE", "UPDATE", "DELETE"] + resources: ["clustersecretstores"] + scope: "Cluster" + clientConfig: + service: + namespace: {{ .Release.Namespace | quote }} + name: {{ include "external-secrets.fullname" . }}-webhook + path: /validate-external-secrets-io-v1beta1-clustersecretstore + admissionReviewVersions: ["v1", "v1beta1"] + sideEffects: None + timeoutSeconds: 5 +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: externalsecret-validate + labels: + external-secrets.io/component: webhook +webhooks: +- name: "validate.externalsecret.external-secrets.io" + rules: + - apiGroups: ["external-secrets.io"] + apiVersions: ["v1beta1"] + operations: ["CREATE", "UPDATE", "DELETE"] + resources: ["externalsecrets"] + scope: "Namespaced" + clientConfig: + service: + namespace: {{ .Release.Namespace | quote }} + name: {{ include "external-secrets.fullname" . }}-webhook + path: /validate-external-secrets-io-v1beta1-externalsecret + admissionReviewVersions: ["v1", "v1beta1"] + sideEffects: None + timeoutSeconds: 5 + failurePolicy: {{ .Values.webhook.failurePolicy}} +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-deployment.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-deployment.yaml new file mode 100644 index 000000000..135bdc288 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-deployment.yaml @@ -0,0 +1,105 @@ +{{- if .Values.webhook.create }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + {{- with .Values.webhook.deploymentAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.webhook.replicaCount }} + selector: + matchLabels: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.webhook.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 8 }} + {{- with .Values.webhook.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.webhook.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + hostNetwork: {{ .Values.webhook.hostNetwork}} + serviceAccountName: {{ include "external-secrets-webhook.serviceAccountName" . }} + {{- with .Values.webhook.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: webhook + {{- with .Values.webhook.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.webhook.image.repository }}:{{ .Values.webhook.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.webhook.image.pullPolicy }} + args: + - webhook + - --port={{ .Values.webhook.port }} + - --dns-name={{ include "external-secrets.fullname" . }}-webhook.{{ .Release.Namespace }}.svc + - --cert-dir={{ .Values.webhook.certDir }} + - --check-interval={{ .Values.webhook.certCheckInterval }} + {{- range $key, $value := .Values.webhook.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + ports: + - containerPort: {{ .Values.webhook.prometheus.service.port }} + protocol: TCP + name: metrics + - containerPort: {{ .Values.webhook.port }} + protocol: TCP + name: webhook + readinessProbe: + httpGet: + port: 8081 + path: /readyz + initialDelaySeconds: 20 + periodSeconds: 5 + {{- with .Values.webhook.extraEnv }} + env: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.webhook.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: certs + mountPath: {{ .Values.webhook.certDir }} + readOnly: true + volumes: + - name: certs + secret: + secretName: {{ include "external-secrets.fullname" . }}-webhook + {{- with .Values.webhook.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.webhook.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.webhook.priorityClassName }} + priorityClassName: {{ .Values.webhook.priorityClassName }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-poddisruptionbudget.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-poddisruptionbudget.yaml new file mode 100644 index 000000000..279a6c5ba --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-poddisruptionbudget.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.webhook.create .Values.webhook.podDisruptionBudget.enabled }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook-pdb + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + external-secrets.io/component : webhook +spec: + {{- if .Values.webhook.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.webhook.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if .Values.webhook.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.webhook.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 6 }} +{{- end }} \ No newline at end of file diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-secret.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-secret.yaml new file mode 100644 index 000000000..47dbab915 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-secret.yaml @@ -0,0 +1,14 @@ +{{- if .Values.webhook.create }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + external-secrets.io/component : webhook + {{- with .Values.webhook.secretAnnotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-service.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-service.yaml new file mode 100644 index 000000000..36f13a1e4 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-service.yaml @@ -0,0 +1,31 @@ +{{- if .Values.webhook.create }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + external-secrets.io/component : webhook + {{- if .Values.webhook.prometheus.enabled}} + annotations: + prometheus.io/path: "/metrics" + prometheus.io/scrape: "true" + prometheus.io/port: {{ .Values.prometheus.service.port | quote }} + {{- end }} +spec: + type: ClusterIP + ports: + - port: 443 + targetPort: {{ .Values.webhook.port }} + protocol: TCP + name: webhook + {{- if .Values.webhook.prometheus.enabled}} + - port: {{ .Values.webhook.prometheus.service.port}} + targetPort: {{ .Values.webhook.prometheus.service.port}} + protocol: TCP + name: metrics + {{- end }} + selector: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-serviceaccount.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-serviceaccount.yaml new file mode 100644 index 000000000..5a8b95917 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if and .Values.webhook.create .Values.webhook.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "external-secrets-webhook.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} + {{- with .Values.webhook.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-servicemonitor.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-servicemonitor.yaml new file mode 100644 index 000000000..4843406b2 --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/templates/webhook-servicemonitor.yaml @@ -0,0 +1,38 @@ +{{- if and .Values.webhook.create .Values.webhook.serviceMonitor.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "external-secrets.fullname" . }}-webhook-metrics + labels: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }} +spec: + type: ClusterIP + ports: + - port: 8080 + protocol: TCP + name: metrics + selector: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 4 }} +--- +apiVersion: "monitoring.coreos.com/v1" +kind: ServiceMonitor +metadata: + labels: + {{- include "external-secrets-webhook.labels" . | nindent 4 }} +{{- if .Values.webhook.serviceMonitor.additionalLabels }} +{{ toYaml .Values.webhook.serviceMonitor.additionalLabels | indent 4 }} +{{- end }} + name: {{ include "external-secrets.fullname" . }}-webhook-metrics + namespace: {{ .Release.Namespace | quote }} +spec: + selector: + matchLabels: + {{- include "external-secrets-webhook.selectorLabels" . | nindent 6 }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} + endpoints: + - port: metrics + interval: {{ .Values.webhook.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.webhook.serviceMonitor.scrapeTimeout }} +{{- end }} diff --git a/charts/external-secrets-operator/external-secrets/0.5.600/values.yaml b/charts/external-secrets-operator/external-secrets/0.5.600/values.yaml new file mode 100644 index 000000000..455551b6e --- /dev/null +++ b/charts/external-secrets-operator/external-secrets/0.5.600/values.yaml @@ -0,0 +1,313 @@ +replicaCount: 1 + +image: + repository: ghcr.io/external-secrets/external-secrets + pullPolicy: IfNotPresent + # -- The image tag to use. The default is the chart appVersion. + tag: "" + +# -- If set, install and upgrade CRDs through helm chart. +installCRDs: true + +crds: + # -- If true, create CRDs for Cluster External Secret. + createClusterExternalSecret: true + # -- If true, create CRDs for Cluster Secret Store. + createClusterSecretStore: true + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +# -- If true, external-secrets will perform leader election between instances to ensure no more +# than one instance of external-secrets operates at a time. +leaderElect: false + +# -- If set external secrets will filter matching +# Secret Stores with the appropriate controller values. +controllerClass: "" + +# -- If set external secrets are only reconciled in the +# provided namespace +scopedNamespace: "" + +# -- Must be used with scopedNamespace. If true, create scoped RBAC roles under the scoped namespace +# and implicitly disable cluster stores and cluster external secrets +scopedRBAC: false + +# -- if true, the operator will process cluster external secret. Else, it will ignore them. +processClusterExternalSecret: true + +# -- if true, the operator will process cluster store. Else, it will ignore them. +processClusterStore: true + +# -- Specifies whether an external secret operator deployment be created. +createOperator: true + +# -- Specifies the number of concurrent ExternalSecret Reconciles external-secret executes at +# a time. +concurrent: 1 + +serviceAccount: + # -- Specifies whether a service account should be created. + create: true + # -- Annotations to add to the service account. + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + name: "" + +rbac: + # -- Specifies whether role and rolebinding resources should be created. + create: true + +## -- Extra environment variables to add to container. +extraEnv: [] + +## -- Map of extra arguments to pass to container. +extraArgs: {} + +# -- Annotations to add to Deployment +deploymentAnnotations: {} + +# -- Annotations to add to Pod +podAnnotations: {} + +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + +prometheus: + # -- deprecated. will be removed with 0.7.0, use serviceMonitor instead. + enabled: false + service: + # -- deprecated. will be removed with 0.7.0, use serviceMonitor instead. + port: 8080 + +serviceMonitor: + # -- Specifies whether to create a ServiceMonitor resource for collecting Prometheus metrics + enabled: false + + # -- Additional labels + additionalLabels: {} + + # -- Interval to scrape metrics + interval: 30s + + # -- Timeout if metrics can't be retrieved in given time interval + scrapeTimeout: 25s + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +# -- Pod priority class name. +priorityClassName: "" + +# -- Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ +podDisruptionBudget: + enabled: false + minAvailable: 1 + # maxUnavailable: 1 + +webhook: + # -- Specifies whether a webhook deployment be created. + create: true + certCheckInterval: "5m" + replicaCount: 1 + certDir: /tmp/certs + # -- specifies whether validating webhooks should be created with failurePolicy: Fail or Ignore + failurePolicy: Fail + # -- Specifies if webhook pod should use hostNetwork or not. + hostNetwork: false + image: + repository: ghcr.io/external-secrets/external-secrets + pullPolicy: IfNotPresent + # -- The image tag to use. The default is the chart appVersion. + tag: "" + imagePullSecrets: [] + nameOverride: "" + fullnameOverride: "" + # -- The port the webhook will listen to + port: 10250 + rbac: + # -- Specifies whether role and rolebinding resources should be created. + create: true + serviceAccount: + # -- Specifies whether a service account should be created. + create: true + # -- Annotations to add to the service account. + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + name: "" + nodeSelector: {} + + tolerations: [] + + affinity: {} + + # -- Pod priority class name. + priorityClassName: "" + + # -- Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + podDisruptionBudget: + enabled: false + minAvailable: 1 + # maxUnavailable: 1 + prometheus: + # -- deprecated. will be removed with 0.7.0, use serviceMonitor instead + enabled: false + service: + # -- deprecated. will be removed with 0.7.0, use serviceMonitor instead + port: 8080 + + serviceMonitor: + # -- Specifies whether to create a ServiceMonitor resource for collecting Prometheus metrics + enabled: false + + # -- Additional labels + additionalLabels: {} + + # -- Interval to scrape metrics + interval: 30s + + # -- Timeout if metrics can't be retrieved in given time interval + scrapeTimeout: 25s + + ## -- Extra environment variables to add to container. + extraEnv: [] + + ## -- Map of extra arguments to pass to container. + extraArgs: {} + + # -- Annotations to add to Secret + secretAnnotations: {} + + # -- Annotations to add to Deployment + deploymentAnnotations: {} + + # -- Annotations to add to Pod + podAnnotations: {} + + podLabels: {} + + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + + resources: {} + # requests: + # cpu: 10m + # memory: 32Mi + +certController: + # -- Specifies whether a certificate controller deployment be created. + create: true + requeueInterval: "5m" + replicaCount: 1 + image: + repository: ghcr.io/external-secrets/external-secrets + pullPolicy: IfNotPresent + tag: "" + imagePullSecrets: [] + nameOverride: "" + fullnameOverride: "" + rbac: + # -- Specifies whether role and rolebinding resources should be created. + create: true + serviceAccount: + # -- Specifies whether a service account should be created. + create: true + # -- Annotations to add to the service account. + annotations: {} + # -- The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template. + name: "" + nodeSelector: {} + + tolerations: [] + + affinity: {} + + # -- Pod priority class name. + priorityClassName: "" + + # -- Pod disruption budget - for more details see https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + podDisruptionBudget: + enabled: false + minAvailable: 1 + # maxUnavailable: 1 + + prometheus: + # -- deprecated. will be removed with 0.7.0, use serviceMonitor instead + enabled: false + service: + # -- deprecated. will be removed with 0.7.0, use serviceMonitor instead + port: 8080 + + serviceMonitor: + # -- Specifies whether to create a ServiceMonitor resource for collecting Prometheus metrics + enabled: false + + # -- Additional labels + additionalLabels: {} + + # -- Interval to scrape metrics + interval: 30s + + # -- Timeout if metrics can't be retrieved in given time interval + scrapeTimeout: 25s + + ## -- Extra environment variables to add to container. + extraEnv: [] + + ## -- Map of extra arguments to pass to container. + extraArgs: {} + + # -- Annotations to add to Deployment + deploymentAnnotations: {} + + # -- Annotations to add to Pod + podAnnotations: {} + + podLabels: {} + + podSecurityContext: {} + # fsGroup: 2000 + + securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + + resources: {} + # requests: + # cpu: 10m + # memory: 32Mi diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/.helmignore b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/.helmignore new file mode 100644 index 000000000..be86b789d --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj +# Helm files +OWNERS diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/Chart.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/Chart.yaml new file mode 100644 index 000000000..55302dee9 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/Chart.yaml @@ -0,0 +1,22 @@ +annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: TrilioVault for Kubernetes Operator + catalog.cattle.io/release-name: k8s-triliovault-operator +apiVersion: v2 +appVersion: 2.9.3 +dependencies: +- condition: observability.enabled + name: observability + repository: file://./charts/observability +description: K8s-TrilioVault-Operator is an operator designed to manage the K8s-TrilioVault + Application Lifecycle. +home: https://github.com/trilioData/k8s-triliovault-operator +icon: https://www.trilio.io/wp-content/uploads/2021/01/Trilio-2020-logo-RGB-gray-green.png +kubeVersion: '>=1.19.0-0' +maintainers: +- email: prafull.ladha@trilio.io + name: prafull11 +name: k8s-triliovault-operator +sources: +- https://github.com/trilioData/k8s-triliovault-operator +version: 2.9.300 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/LICENSE b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/LICENSE new file mode 100644 index 000000000..76b559d3b --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/LICENSE @@ -0,0 +1 @@ +# Placeholder for the License if we decide to provide one diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/README.md b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/README.md new file mode 100644 index 000000000..5f5eb92e1 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/README.md @@ -0,0 +1,202 @@ +# K8s-TrilioVault-Operator +This operator is to manage the lifecycle of TrilioVault Backup/Recovery solution. This operator install, updates and manage the TrilioVault application. + +## Introduction + +## Prerequisites + +- Kubernetes 1.19+ +- PV provisioner support +- CSI driver should be installed + +### One Click Installation + +In one click install for upstream operator, a cluster scope TVM custom resource `triliovault-manager` is created. + +```shell script +helm repo add trilio-vault-operator https://charts.k8strilio.net/trilio-stable/k8s-triliovault-operator +helm install tvm trilio-vault-operator/k8s-triliovault-operator +``` + +#### One click install with preflight Configuration + +The following table lists the configuration parameter of the upstream operator one click install feature as well as preflight check flags, their default values and usage. + +| Parameter | Description | Default | Example | +|--------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|------------|-------------------------| +| `installTVK.enabled` | 1 click install feature is enabled | true | | +| `installTVK.applicationScope` | scope of TVK application created | Cluster | | +| `installTVK.tvkInstanceName` | tvk instance name | "" | "tvk-instance" | +| `installTVK.ingressConfig.host` | host of the ingress resource created | "" | | +| `installTVK.ingressConfig.tlsSecretName` | tls secret name which contains ingress certs | "" | | +| `installTVK.ingressConfig.annotations` | annotations to be added on ingress resource | "" | | +| `installTVK.ingressConfig.ingressClass` | ingress class name for the ingress resource | "" | | +| `installTVK.ComponentConfiguration.ingressController.enabled` | TVK ingress controller should be deployed | true | | +| `installTVK.ComponentConfiguration.ingressController.service.type` | TVK ingress controller service type | "NodePort" | | +| `preflight.enabled` | enables preflight check for tvk | false | | +| `preflight.storageClass` | Name of storage class to use for preflight checks (Required) | "" | | +| `preflight.cleanupOnFailure` | Cleanup the resources on cluster if preflight checks fail (Optional) | false | | +| `preflight.imagePullSecret` | Name of the secret for authentication while pulling the images from the local registry (Optional) | "" | | +| `preflight.limits` | Pod memory and cpu resource limits for DNS and volume snapshot preflight check (Optional) | "" | "cpu=600m,memory=256Mi" | +| `preflight.localRegistry` | Name of the local registry from where the images will be pulled (Optional) | "" | | +| `preflight.nodeSelector` | Node selector labels for pods to schedule on a specific nodes of cluster (Optional) | "" | "key=value" | +| `preflight.pvcStorageRequest` | PVC storage request for volume snapshot preflight check (Optional) | "" | "2Gi" | +| `preflight.requests` | Pod memory and cpu resource requests for DNS and volume snapshot preflight check (Optional) | "" | "cpu=300m,memory=128Mi" | +| `preflight.volumeSnapshotClass` | Name of volume snapshot class to use for preflight checks (Optional) | "" | | +| `preflight.logLevel` | Log Level for the preflight run (Default: "INFO") | "" | | +| `preflight.imageTag` | Image tag to use for the preflight image (Default: latest) | "" | | + +Check the TVM CR configuration by running following command: + +``` +kubectl get triliovaultmanagers.triliovault.trilio.io triliovault-manager -o yaml +``` + +Once the operator pod is in running state, the TVK pods getting spawned. Confirm the [TVK pods are up](#Check-TVK-Install). + +#### Note: + +If preflight check is enabled and helm install fails, check pre-install helm hook pod logs for any failure in preflight check. Do the following steps: + +First, run this command: +``` +kubectl get pods -n +``` + +The pod name should start with `-preflight-job-preinstall-hook`. Check the logs of the pod by the following command: +``` +kubectl logs -f -n +``` + +#### The failed preflight job is not cleaned up automatically right after failure. If the user cluster version is 1.21 and above, the job will be cleaned up after 1 hour so user should collect any failure logs within 1 hr of job failure. For cluster version below 1.21, user has to clean up failed preflight job manually. + +To delete the job manually, run the following command: +``` +kubectl delete job -f -n +``` + +where job name should also start with `-preflight-job-preinstall-hook` + +Also, due to a bug at helm side where auto deletion of resources upon failure doesn't work, user needs to clean the following resources left behind to be able to run preflight again, until the bug is fixed from their side, after which this step will be handled automatically. Run the following command to clean up the temporary resources: + +1. Cleanup Service Account: + ``` + kubectl delete sa -preflight-service-account -n + ``` +2. Cleanup Cluster Role Binding: + ``` + kubectl delete clusterrolebinding --preflight-rolebinding + ``` +3. Cleanup Cluster Role: + ``` + kubectl delete clusterrole --preflight-role + ``` + +## Manual Installation + +To install the operator on local setup just run the latest helm charts inside this repo + +```shell script +helm repo add trilio-vault-operator https://charts.k8strilio.net/trilio-stable/k8s-triliovault-operator +helm install tvm trilio-vault-operator/k8s-triliovault-operator +``` + +Now, create a TrilioVaultManager CR to install the TrilioVault for Kubernetes. You can provide the custom configurations for the TVK resources as follows: + +``` +apiVersion: triliovault.trilio.io/v1 +kind: TrilioVaultManager +metadata: + labels: + triliovault: k8s + name: tvk +spec: + trilioVaultAppVersion: latest + applicationScope: Cluster + # User can configure tvk instance name + tvkInstanceName: tvk-instance + # User can configure the ingress hosts, annotations and TLS secret through the ingressConfig section + ingressConfig: + host: "trilio.co.in" + tlsSecretName: "secret-name" + # TVK components configuration, currently supports control-plane, web, exporter, web-backend, ingress-controller, admission-webhook. + # User can configure resources for all componentes and can configure service type and host for the ingress-controller + componentConfiguration: + web-backend: + resources: + requests: + memory: "400Mi" + cpu: "200m" + limits: + memory: "2584Mi" + cpu: "1000m" + ingress-controller: + enabled: true + service: + type: LoadBalancer +``` + +### Apply the Custom Resource + +Apply `TVM.yaml`: + +```shell +kubectl create -f TVM.yaml +``` + +### Check TVK Install + +Check that the pods were created: + +``` +kubectl get pods +``` + +``` +NAME READY STATUS RESTARTS AGE +k8s-triliovault-admission-webhook-6ff5f98c8-qwmfc 1/1 Running 0 81s +k8s-triliovault-backend-6f66b6b8d5-gxtmz 1/1 Running 0 81s +k8s-triliovault-control-plane-6c464c5d78-ftk6g 1/1 Running 0 81s +k8s-triliovault-exporter-59566f97dd-gs4xc 1/1 Running 0 81s +k8s-triliovault-ingress-nginx-controller-867c764cd5-qhpx6 1/1 Running 0 18s +k8s-triliovault-web-967c8475-m7pc6 1/1 Running 0 81s +tvm-k8s-triliovault-operator-66bd7d86d5-dvhzb 1/1 Running 0 6m48s +``` + +Check that ingress controller service is of type LoadBalancer: +``` +NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +k8s-triliovault-admission-webhook ClusterIP 10.7.243.24 443/TCP 129m +k8s-triliovault-ingress-nginx-controller LoadBalancer 10.7.246.193 35.203.155.148 80:30362/TCP,443:32327/TCP 129m +k8s-triliovault-ingress-nginx-controller-admission ClusterIP 10.7.250.31 443/TCP 129m +k8s-triliovault-web ClusterIP 10.7.254.41 80/TCP 129m +k8s-triliovault-web-backend ClusterIP 10.7.252.146 80/TCP 129m +tvm-k8s-triliovault-operator-webhook-service ClusterIP 10.7.248.163 443/TCP 130m 123m +``` + +Check that ingress resources has the host defined by the user: +``` +NAME CLASS HOSTS ADDRESS PORTS AGE +k8s-triliovault k8s-triliovault-default-nginx * 35.203.155.148 80 129m +``` + +You can access the TVK UI by hitting this address in your browser: https://35.203.155.148 + +## Delete + +```shell +kubectl delete -f TVM.yaml +``` + +## Uninstall + +To uninstall/delete the operator helm chart : + +```bash +helm uninstall tvm +``` + +## TrilioVaultManager compatibility + +We maintain the version parity between the TrilioVaultManager(upstream operator) and TrilioVault for Kubernetes. Whenever +user wants to upgrade to the new version, should use the same version for upstream operator and Triliovault for Kubernetes. diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/Chart.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/Chart.yaml new file mode 100644 index 000000000..4df538147 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/Chart.yaml @@ -0,0 +1,21 @@ +apiVersion: v2 +appVersion: 0.1.0 +dependencies: +- name: visualization + repository: file://charts/visualization + version: ^0.1.0 +- name: logging + repository: file://charts/logging + version: ^0.1.0 +- name: monitoring + repository: file://charts/monitoring + version: ^0.1.0 +description: Observability Stack is designed to manage the K8s-TrilioVault Application's + Logging, Monitoring and Visualization. +icon: https://www.trilio.io/wp-content/uploads/2021/01/Trilio-2020-logo-RGB-gray-green.png +kubeVersion: '>=1.19.0-0' +maintainers: +- email: support@trilio.io + name: Trilio +name: observability +version: 0.1.0 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/Chart.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/Chart.yaml new file mode 100644 index 000000000..2745b9dbf --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +appVersion: 0.1.0 +dependencies: +- condition: loki.enabled + name: loki + repository: https://grafana.github.io/helm-charts + version: ^2.11.1 +- condition: promtail.enabled + name: promtail + repository: https://grafana.github.io/helm-charts + version: ^4.2.0 +description: Logging Stack designed to manage the K8s-TrilioVault Application's Logs. +icon: https://www.trilio.io/wp-content/uploads/2021/01/Trilio-2020-logo-RGB-gray-green.png +maintainers: +- email: support@trilio.io + name: Trilio +name: logging +version: 0.1.0 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/Chart.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/Chart.yaml new file mode 100644 index 000000000..1ad366c62 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/Chart.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +appVersion: v2.5.0 +description: 'Loki: like Prometheus, but for logs.' +home: https://grafana.com/loki +icon: https://raw.githubusercontent.com/grafana/loki/master/docs/sources/logo.png +kubeVersion: ^1.10.0-0 +maintainers: +- email: support@trilio.io + name: Trilio +name: loki +sources: +- https://github.com/grafana/loki +version: 2.11.1 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/NOTES.txt b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/NOTES.txt new file mode 100644 index 000000000..abe023a70 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/NOTES.txt @@ -0,0 +1,3 @@ +Verify the application is working by running these commands: + kubectl --namespace {{ .Release.Namespace }} port-forward service/{{ include "loki.fullname" . }} {{ .Values.service.port }} + curl http://127.0.0.1:{{ .Values.service.port }}/api/prom/label diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/_helpers.tpl b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/_helpers.tpl new file mode 100644 index 000000000..d873a0fea --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/_helpers.tpl @@ -0,0 +1,75 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "loki.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 "loki.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 "loki.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the service account +*/}} +{{- define "loki.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "loki.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the app name of loki clients. Defaults to the same logic as "loki.fullname", and default client expects "promtail". +*/}} +{{- define "client.name" -}} +{{- if .Values.client.name -}} +{{- .Values.client.name -}} +{{- else if .Values.client.fullnameOverride -}} +{{- .Values.client.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default "promtail" .Values.client.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Generate a right Ingress apiVersion +*/}} +{{- define "ingress.apiVersion" -}} +{{- if semverCompare ">=1.20-0" .Capabilities.KubeVersion.GitVersion -}} +networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +networking.k8s.io/v1beta1 +{{- else -}} +extensions/v1 +{{- end }} +{{- end -}} + diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/configmap-alert.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/configmap-alert.yaml new file mode 100644 index 000000000..07fab47a6 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/configmap-alert.yaml @@ -0,0 +1,17 @@ +{{- if or (.Values.useExistingAlertingGroup.enabled) (gt (len .Values.alerting_groups) 0) }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "loki.fullname" . }}-alerting-rules + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +data: + {{ template "loki.fullname" . }}-alerting-rules.yaml: |- + groups: + {{- toYaml .Values.alerting_groups | nindent 6 }} +{{- end }} \ No newline at end of file diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/ingress.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/ingress.yaml new file mode 100644 index 000000000..2a0314ea1 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/ingress.yaml @@ -0,0 +1,55 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "loki.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- $apiVersion := include "ingress.apiVersion" . -}} +apiVersion: {{ $apiVersion }} +kind: Ingress +metadata: + name: {{ $fullName }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Values.ingress.ingressClassName }} + ingressClassName: {{ .Values.ingress.ingressClassName }} +{{- end }} +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ . }} + {{- if eq $apiVersion "networking.k8s.io/v1" }} + pathType: Prefix + {{- end }} + backend: + {{- if eq $apiVersion "networking.k8s.io/v1" }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/networkpolicy.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/networkpolicy.yaml new file mode 100644 index 000000000..5d7383229 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/networkpolicy.yaml @@ -0,0 +1,26 @@ +{{- if .Values.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "loki.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + podSelector: + matchLabels: + name: {{ template "loki.fullname" . }} + app: {{ template "loki.name" . }} + release: {{ .Release.Name }} + ingress: + - from: + - podSelector: + matchLabels: + app: {{ template "client.name" . }} + release: {{ .Release.Name }} + - ports: + - port: {{ .Values.service.port }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/pdb.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/pdb.yaml new file mode 100644 index 000000000..c64ad507e --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/pdb.yaml @@ -0,0 +1,17 @@ +{{- if .Values.podDisruptionBudget -}} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ template "loki.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "loki.name" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + chart: {{ template "loki.chart" . }} +spec: + selector: + matchLabels: + app: {{ template "loki.name" . }} +{{ toYaml .Values.podDisruptionBudget | indent 2 }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/podsecuritypolicy.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/podsecuritypolicy.yaml new file mode 100644 index 000000000..ce1c1c109 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/podsecuritypolicy.yaml @@ -0,0 +1,41 @@ +{{- if .Values.rbac.pspEnabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "loki.fullname" . }} + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} +spec: + privileged: false + allowPrivilegeEscalation: false + volumes: + - 'configMap' + - 'emptyDir' + - 'persistentVolumeClaim' + - 'secret' + - 'projected' + - 'downwardAPI' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAsNonRoot' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: true + requiredDropCapabilities: + - ALL +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/prometheusrule.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/prometheusrule.yaml new file mode 100644 index 000000000..effe6f152 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/prometheusrule.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.serviceMonitor.enabled .Values.serviceMonitor.prometheusRule.enabled -}} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "loki.fullname" . }} +{{- if .Values.serviceMonitor.prometheusRule.namespace }} + namespace: {{ .Values.serviceMonitor.prometheusRule.namespace | quote }} +{{- end }} + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + {{- if .Values.serviceMonitor.prometheusRule.additionalLabels }} + {{- toYaml .Values.serviceMonitor.prometheusRule.additionalLabels | nindent 4 }} + {{- end }} +spec: +{{- if .Values.serviceMonitor.prometheusRule.rules }} + groups: + - name: {{ template "loki.fullname" . }} + rules: {{- toYaml .Values.serviceMonitor.prometheusRule.rules | nindent 4 }} +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/role.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/role.yaml new file mode 100644 index 000000000..b7bfb29d6 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/role.yaml @@ -0,0 +1,20 @@ +{{- if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "loki.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} +{{- if .Values.rbac.pspEnabled }} +rules: +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ template "loki.fullname" . }}] +{{- end }} +{{- end }} + diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/rolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/rolebinding.yaml new file mode 100644 index 000000000..41fc5039f --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/rolebinding.yaml @@ -0,0 +1,20 @@ +{{- if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "loki.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "loki.fullname" . }} +subjects: +- kind: ServiceAccount + name: {{ template "loki.serviceAccountName" . }} +{{- end }} + diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/secret.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/secret.yaml new file mode 100644 index 000000000..1f6db2d84 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/secret.yaml @@ -0,0 +1,14 @@ +{{- if not .Values.config.existingSecret -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "loki.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +data: + loki.yaml: {{ tpl (toYaml .Values.config) . | b64enc}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/service-headless.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/service-headless.yaml new file mode 100644 index 000000000..871629bad --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/service-headless.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "loki.fullname" . }}-headless + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + app.kubernetes.io/instance: {{ template "loki.name" . }} + {{- include "k8s-triliovault-operator.labels" . | nindent 4 }} + variant: headless +spec: + clusterIP: None + ports: + - port: {{ .Values.service.port }} + protocol: TCP + name: http-metrics + targetPort: {{ .Values.service.targetPort }} +{{- if .Values.extraPorts }} +{{ toYaml .Values.extraPorts | indent 4}} +{{- end }} + selector: + app: {{ template "loki.name" . }} + release: {{ .Release.Name }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/service.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/service.yaml new file mode 100644 index 000000000..42bf51b6e --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/service.yaml @@ -0,0 +1,45 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "loki.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + app.kubernetes.io/instance: {{ template "loki.name" . }} + {{- include "k8s-triliovault-operator.labels" . | nindent 4 }} + {{- with .Values.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- toYaml .Values.service.annotations | nindent 4 }} +spec: + type: {{ .Values.service.type }} +{{- if (and (eq .Values.service.type "ClusterIP") (not (empty .Values.service.clusterIP))) }} + clusterIP: {{ .Values.service.clusterIP }} +{{- end }} +{{- if (and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP))) }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} +{{- end }} +{{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} + ports: + - port: {{ .Values.service.port }} + protocol: TCP + name: http-metrics + targetPort: {{ .Values.service.targetPort }} +{{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} + nodePort: {{ .Values.service.nodePort }} +{{- end }} +{{- if .Values.extraPorts }} +{{ toYaml .Values.extraPorts | indent 4}} +{{- end }} + selector: + app: {{ template "loki.name" . }} + release: {{ .Release.Name }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/serviceaccount.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/serviceaccount.yaml new file mode 100644 index 000000000..510972c6a --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/serviceaccount.yaml @@ -0,0 +1,16 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + annotations: + {{- toYaml .Values.serviceAccount.annotations | nindent 4 }} + name: {{ template "loki.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- end }} + diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/servicemonitor.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/servicemonitor.yaml new file mode 100644 index 000000000..0a4867294 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/servicemonitor.yaml @@ -0,0 +1,38 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "loki.fullname" . }} + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- if .Values.serviceMonitor.additionalLabels }} +{{ toYaml .Values.serviceMonitor.additionalLabels | indent 4 }} + {{- end }} + {{- if .Values.serviceMonitor.annotations }} + annotations: +{{ toYaml .Values.serviceMonitor.annotations | indent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app: {{ template "loki.name" . }} + release: {{ .Release.Name | quote }} + variant: headless + namespaceSelector: + matchNames: + - {{ .Release.Namespace | quote }} + endpoints: + - port: http-metrics + {{- if .Values.serviceMonitor.interval }} + interval: {{ .Values.serviceMonitor.interval }} + {{- end }} + {{- if .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.serviceMonitor.path }} + path: {{ .Values.serviceMonitor.path }} + {{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/statefulset.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/statefulset.yaml new file mode 100644 index 000000000..96220c48f --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/templates/statefulset.yaml @@ -0,0 +1,160 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ template "loki.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "loki.name" . }} + chart: {{ template "loki.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- include "k8s-triliovault-operator.labels" . | nindent 4 }} + annotations: + {{- toYaml .Values.annotations | nindent 4 }} +spec: + podManagementPolicy: {{ .Values.podManagementPolicy }} + replicas: {{ .Values.replicas }} + selector: + matchLabels: + app: {{ template "loki.name" . }} + release: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- include "k8s-triliovault-operator.labels" . | nindent 6 }} + serviceName: {{ template "loki.fullname" . }}-headless + updateStrategy: + {{- toYaml .Values.updateStrategy | nindent 4 }} + template: + metadata: + labels: + app: {{ template "loki.name" . }} + name: {{ template "loki.fullname" . }} + release: {{ .Release.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + {{- include "k8s-triliovault-operator.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + {{- if not .Values.config.existingSecret }} + checksum/config: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- end }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ template "loki.serviceAccountName" . }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + securityContext: + {{- toYaml .Values.securityContext | nindent 8 }} + initContainers: + {{- toYaml .Values.initContainers | nindent 8 }} + {{- if .Values.image.pullSecrets }} + imagePullSecrets: + {{- range .Values.image.pullSecrets }} + - name: {{ . }} + {{- end}} + {{- end }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - "-config.file=/etc/loki/loki.yaml" + {{- range $key, $value := .Values.extraArgs }} + - "-{{ $key }}={{ $value }}" + {{- end }} + volumeMounts: + - name: tmp + mountPath: /tmp + {{- if .Values.extraVolumeMounts }} + {{ toYaml .Values.extraVolumeMounts | nindent 12}} + {{- end }} + - name: config + mountPath: /etc/loki + - name: storage + mountPath: "/data" + subPath: {{ .Values.persistence.subPath }} + {{- if or (.Values.useExistingAlertingGroup.enabled) (gt (len .Values.alerting_groups) 0) }} + - name: rules + mountPath: /rules/fake + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.config.server.http_listen_port }} + protocol: TCP + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + securityContext: + readOnlyRootFilesystem: true + env: + {{- if .Values.env }} + {{- toYaml .Values.env | nindent 12 }} + {{- end }} + {{- if .Values.tracing.jaegerAgentHost }} + - name: JAEGER_AGENT_HOST + value: "{{ .Values.tracing.jaegerAgentHost }}" + {{- end }} +{{- if .Values.extraContainers }} +{{ toYaml .Values.extraContainers | indent 8}} +{{- end }} + nodeSelector: + {{- toYaml .Values.nodeSelector | nindent 8 }} + affinity: + {{- toYaml .Values.affinity | nindent 8 }} + tolerations: + {{- toYaml .Values.tolerations | nindent 8 }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + volumes: + - name: tmp + emptyDir: {} + {{- if or (.Values.useExistingAlertingGroup.enabled) (gt (len .Values.alerting_groups) 0) }} + - name: rules + configMap: + {{- if .Values.useExistingAlertingGroup.enabled }} + name: {{ .Values.useExistingAlertingGroup.configmapName }} + {{- else }} + name: {{ template "loki.fullname" . }}-alerting-rules + {{- end }} + {{- end }} + - name: config + secret: + {{- if .Values.config.existingSecret }} + secretName: {{ .Values.config.existingSecret }} + {{- else }} + secretName: {{ template "loki.fullname" . }} + {{- end }} +{{- if .Values.extraVolumes }} +{{ toYaml .Values.extraVolumes | indent 8}} +{{- end }} + {{- if not .Values.persistence.enabled }} + - name: storage + emptyDir: {} + {{- else if .Values.persistence.existingClaim }} + - name: storage + persistentVolumeClaim: + claimName: {{ .Values.persistence.existingClaim }} + {{- else }} + volumeClaimTemplates: + - metadata: + name: storage + annotations: + {{- toYaml .Values.persistence.annotations | nindent 8 }} + spec: + accessModes: + {{- toYaml .Values.persistence.accessModes | nindent 8 }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + storageClassName: {{ .Values.persistence.storageClassName }} + {{- if .Values.persistence.selector }} + selector: + {{- toYaml .Values.persistence.selector | nindent 8 }} + {{- end }} + {{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/values.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/values.yaml new file mode 100644 index 000000000..66ccb0f51 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/loki/values.yaml @@ -0,0 +1,325 @@ +image: + repository: grafana/loki + tag: 2.5.0 + pullPolicy: IfNotPresent + + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## + # pullSecrets: + # - myRegistryKeySecretName + +ingress: + enabled: false + # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName + # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress + # ingressClassName: nginx + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: [] + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +## Affinity for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +affinity: {} +# podAntiAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# - labelSelector: +# matchExpressions: +# - key: app +# operator: In +# values: +# - loki +# topologyKey: "kubernetes.io/hostname" + +## StatefulSet annotations +annotations: {} + +# enable tracing for debug, need install jaeger and specify right jaeger_agent_host +tracing: + jaegerAgentHost: + +config: + # existingSecret: + auth_enabled: false + ingester: + chunk_idle_period: 3m + chunk_block_size: 262144 + chunk_retain_period: 1m + max_transfer_retries: 0 + wal: + dir: /data/loki/wal + lifecycler: + ring: + kvstore: + store: inmemory + replication_factor: 1 + + ## Different ring configs can be used. E.g. Consul + # ring: + # store: consul + # replication_factor: 1 + # consul: + # host: "consul:8500" + # prefix: "" + # http_client_timeout: "20s" + # consistent_reads: true + limits_config: + enforce_metric_name: false + reject_old_samples: true + reject_old_samples_max_age: 168h + max_entries_limit_per_query: 5000 + schema_config: + configs: + - from: 2020-10-24 + store: boltdb-shipper + object_store: filesystem + schema: v11 + index: + prefix: index_ + period: 24h + server: + http_listen_port: 3100 + storage_config: + boltdb_shipper: + active_index_directory: /data/loki/boltdb-shipper-active + cache_location: /data/loki/boltdb-shipper-cache + cache_ttl: 24h # Can be increased for faster performance over longer query periods, uses more disk space + shared_store: filesystem + filesystem: + directory: /data/loki/chunks + chunk_store_config: + max_look_back_period: 0s + table_manager: + retention_deletes_enabled: false + retention_period: 0s + compactor: + working_directory: /data/loki/boltdb-shipper-compactor + shared_store: filesystem +# Needed for Alerting: https://grafana.com/docs/loki/latest/rules/ +# This is just a simple example, for more details: https://grafana.com/docs/loki/latest/configuration/#ruler_config +# ruler: +# storage: +# type: local +# local: +# directory: /rules +# rule_path: /tmp/scratch +# alertmanager_url: http://alertmanager.svc.namespace:9093 +# ring: +# kvstore: +# store: inmemory +# enable_api: true + +## Additional Loki container arguments, e.g. log level (debug, info, warn, error) +extraArgs: {} + # log.level: debug + +livenessProbe: + httpGet: + path: /ready + port: http-metrics + initialDelaySeconds: 45 + +## ref: https://kubernetes.io/docs/concepts/services-networking/network-policies/ +networkPolicy: + enabled: false + +## The app name of loki clients +client: {} + # name: + +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ +nodeSelector: {} + +## ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/ +## If you set enabled as "True", you need : +## - create a pv which above 10Gi and has same namespace with loki +## - keep storageClassName same with below setting +persistence: + enabled: false + accessModes: + - ReadWriteOnce + size: 10Gi + annotations: {} + # selector: + # matchLabels: + # app.kubernetes.io/name: loki + # subPath: "" + # existingClaim: + +## Pod Labels +podLabels: {} + +## Pod Annotations +podAnnotations: + prometheus.io/scrape: "true" + prometheus.io/port: "http-metrics" + +podManagementPolicy: OrderedReady + +## Assign a PriorityClassName to pods if set +# priorityClassName: + +rbac: + create: true + pspEnabled: false + +readinessProbe: + httpGet: + path: /ready + port: http-metrics + initialDelaySeconds: 45 + +replicas: 1 + +resources: + limits: + cpu: 1000m + memory: 500Mi + requests: + cpu: 500m + memory: 256Mi + +securityContext: + fsGroup: 10001 + runAsGroup: 10001 + runAsNonRoot: true + runAsUser: 10001 + +service: + type: ClusterIP + nodePort: + port: 3100 + annotations: {} + labels: {} + targetPort: http-metrics + +serviceAccount: + create: true + name: + annotations: {} + automountServiceAccountToken: true + +terminationGracePeriodSeconds: 4800 + +## Tolerations for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +tolerations: [] + +# The values to set in the PodDisruptionBudget spec +# If not set then a PodDisruptionBudget will not be created +podDisruptionBudget: {} +# minAvailable: 1 +# maxUnavailable: 1 + +updateStrategy: + type: RollingUpdate + +serviceMonitor: + enabled: false + interval: "" + additionalLabels: {} + annotations: {} + # scrapeTimeout: 10s + # path: /metrics + prometheusRule: + enabled: false + additionalLabels: {} + # namespace: + rules: [] + # Some examples from https://awesome-prometheus-alerts.grep.to/rules.html#loki + # - alert: LokiProcessTooManyRestarts + # expr: changes(process_start_time_seconds{job=~"loki"}[15m]) > 2 + # for: 0m + # labels: + # severity: warning + # annotations: + # summary: Loki process too many restarts (instance {{ $labels.instance }}) + # description: "A loki process had too many restarts (target {{ $labels.instance }})\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" + # - alert: LokiRequestErrors + # expr: 100 * sum(rate(loki_request_duration_seconds_count{status_code=~"5.."}[1m])) by (namespace, job, route) / sum(rate(loki_request_duration_seconds_count[1m])) by (namespace, job, route) > 10 + # for: 15m + # labels: + # severity: critical + # annotations: + # summary: Loki request errors (instance {{ $labels.instance }}) + # description: "The {{ $labels.job }} and {{ $labels.route }} are experiencing errors\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" + # - alert: LokiRequestPanic + # expr: sum(increase(loki_panic_total[10m])) by (namespace, job) > 0 + # for: 5m + # labels: + # severity: critical + # annotations: + # summary: Loki request panic (instance {{ $labels.instance }}) + # description: "The {{ $labels.job }} is experiencing {{ printf \"%.2f\" $value }}% increase of panics\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" + # - alert: LokiRequestLatency + # expr: (histogram_quantile(0.99, sum(rate(loki_request_duration_seconds_bucket{route!~"(?i).*tail.*"}[5m])) by (le))) > 1 + # for: 5m + # labels: + # severity: critical + # annotations: + # summary: Loki request latency (instance {{ $labels.instance }}) + # description: "The {{ $labels.job }} {{ $labels.route }} is experiencing {{ printf \"%.2f\" $value }}s 99th percentile latency\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" + + +initContainers: [] +## Init containers to be added to the loki pod. +# - name: my-init-container +# image: busybox:latest +# command: ['sh', '-c', 'echo hello'] + +extraContainers: [] +## Additional containers to be added to the loki pod. +# - name: reverse-proxy +# image: angelbarrera92/basic-auth-reverse-proxy:dev +# args: +# - "serve" +# - "--upstream=http://localhost:3100" +# - "--auth-config=/etc/reverse-proxy-conf/authn.yaml" +# ports: +# - name: http +# containerPort: 11811 +# protocol: TCP +# volumeMounts: +# - name: reverse-proxy-auth-config +# mountPath: /etc/reverse-proxy-conf + + +extraVolumes: [] +## Additional volumes to the loki pod. +# - name: reverse-proxy-auth-config +# secret: +# secretName: reverse-proxy-auth-config + +## Extra volume mounts that will be added to the loki container +extraVolumeMounts: [] + +extraPorts: [] +## Additional ports to the loki services. Useful to expose extra container ports. +# - port: 11811 +# protocol: TCP +# name: http +# targetPort: http + +# Extra env variables to pass to the loki container +env: [] + +# Specify Loki Alerting rules based on this documentation: https://grafana.com/docs/loki/latest/rules/ +# When specified, you also need to add a ruler config section above. An example is shown in the alerting docs. +alerting_groups: [] +# - name: example +# rules: +# - alert: HighThroughputLogStreams +# expr: sum by(container) (rate({job=~"loki-dev/.*"}[1m])) > 1000 +# for: 2m + +useExistingAlertingGroup: + enabled: false + configmapName: "" diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/Chart.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/Chart.yaml new file mode 100644 index 000000000..48d7ba243 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/Chart.yaml @@ -0,0 +1,16 @@ +apiVersion: v2 +appVersion: 2.5.0 +description: Promtail is an agent which ships the contents of local logs to a Loki + instance +home: https://grafana.com/loki +icon: https://raw.githubusercontent.com/grafana/loki/master/docs/sources/logo.png +maintainers: +- email: support@trilio.io + name: Trilio +name: promtail +sources: +- https://github.com/grafana/loki +- https://grafana.com/oss/loki/ +- https://grafana.com/docs/loki/latest/ +type: application +version: 4.2.0 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/NOTES.txt b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/NOTES.txt new file mode 100644 index 000000000..df740448d --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/NOTES.txt @@ -0,0 +1,10 @@ +*********************************************************************** + Welcome to Grafana Promtail + Chart version: {{ .Chart.Version }} + Promtail version: {{ .Values.image.tag | default .Chart.AppVersion }} +*********************************************************************** + +Verify the application is working by running these commands: + +* kubectl --namespace {{ .Release.Namespace }} port-forward daemonset/{{ include "promtail.fullname" . }} {{ .Values.config.serverPort }} +* curl http://127.0.0.1:{{ .Values.config.serverPort }}/metrics diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/_helpers.tpl b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/_helpers.tpl new file mode 100644 index 000000000..25069d58e --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/_helpers.tpl @@ -0,0 +1,81 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "promtail.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 "promtail.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 "promtail.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "promtail.labels" -}} +helm.sh/chart: {{ include "promtail.chart" . }} +{{ include "promtail.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "promtail.selectorLabels" -}} +app.kubernetes.io/name: {{ include "promtail.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{ include "k8s-triliovault-operator.labels" .}} +{{- end }} + +{{/* +Create the name of the service account +*/}} +{{- define "promtail.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "promtail.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +The service name to connect to Loki. Defaults to the same logic as "loki.fullname" +*/}} +{{- define "loki.serviceName" -}} +{{- if .Values.loki.serviceName -}} +{{- .Values.loki.serviceName -}} +{{- else if .Values.loki.fullnameOverride -}} +{{- .Values.loki.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default "loki" .Values.loki.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/clusterrole.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/clusterrole.yaml new file mode 100644 index 000000000..4702e60d0 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/clusterrole.yaml @@ -0,0 +1,21 @@ +{{- if .Values.rbac.create }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "promtail.fullname" . }} + labels: + {{- include "promtail.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - nodes + - nodes/proxy + - services + - endpoints + - pods + verbs: + - get + - watch + - list +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/clusterrolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..06054e3a5 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if .Values.rbac.create }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "promtail.fullname" . }} + labels: + {{- include "promtail.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "promtail.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ include "promtail.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/daemonset.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/daemonset.yaml new file mode 100644 index 000000000..f55c16221 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/daemonset.yaml @@ -0,0 +1,132 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ include "promtail.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "promtail.labels" . | nindent 4 }} + {{- with .Values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "promtail.selectorLabels" . | nindent 6 }} + updateStrategy: + {{- toYaml .Values.updateStrategy | nindent 4 }} + template: + metadata: + labels: + {{- include "promtail.selectorLabels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + annotations: + checksum/config: {{ include (print .Template.BasePath "/secret.yaml") . | sha256sum }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "promtail.serviceAccountName" . }} + {{- with .Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + {{- if .Values.initContainer.enabled }} + initContainers: + - name: init + image: "{{ .Values.initContainer.image.registry }}/{{ .Values.initContainer.image.repository }}:{{ .Values.initContainer.image.tag }}" + imagePullPolicy: {{ .Values.initContainer.image.pullPolicy }} + command: + - sh + - -c + - sysctl -w fs.inotify.max_user_instances={{ .Values.initContainer.fsInotifyMaxUserInstances }} + securityContext: + privileged: true + {{- end }} + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: promtail + image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - "-config.file=/etc/promtail/promtail.yaml" + {{- with .Values.extraArgs }} + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: config + mountPath: /etc/promtail + - name: run + mountPath: /run/promtail + {{- with .Values.defaultVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: HOSTNAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + {{- with .Values.extraEnv }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.extraEnvFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http-metrics + containerPort: {{ .Values.config.serverPort }} + protocol: TCP + {{- range $key, $values := .Values.extraPorts }} + - name: {{ .name | default $key }} + containerPort: {{ $values.containerPort }} + protocol: {{ $values.protocol | default "TCP" }} + {{- end }} + securityContext: + {{- toYaml .Values.containerSecurityContext | nindent 12 }} + {{- with .Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: config + secret: + secretName: {{ include "promtail.fullname" . }} + - name: run + hostPath: + path: /run/promtail + {{- with .Values.defaultVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/extra-manifests.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/extra-manifests.yaml new file mode 100644 index 000000000..a9bb3b6ba --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{ range .Values.extraObjects }} +--- +{{ tpl (toYaml .) $ }} +{{ end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/networkpolicy.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/networkpolicy.yaml new file mode 100644 index 000000000..103dcc139 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/networkpolicy.yaml @@ -0,0 +1,126 @@ +{{- if .Values.networkPolicy.enabled }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "promtail.name" . }}-namespace-only + namespace: {{ .Release.Namespace }} + labels: + {{- include "promtail.labels" . | nindent 4 }} +spec: + podSelector: {} + policyTypes: + - Ingress + - Egress + egress: + - to: + - podSelector: {} + ingress: + - from: + - podSelector: {} + + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "promtail.name" . }}-egress-dns + namespace: {{ .Release.Namespace }} + labels: + {{- include "promtail.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "promtail.selectorLabels" . | nindent 6 }} + policyTypes: + - Egress + egress: + - ports: + - port: 53 + protocol: UDP + to: + - namespaceSelector: {} + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "promtail.name" . }}-egress-k8s-api + namespace: {{ .Release.Namespace }} + labels: + {{- include "promtail.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "promtail.selectorLabels" . | nindent 6 }} + policyTypes: + - Egress + egress: + - ports: + - port: {{ .Values.networkPolicy.k8sApi.port }} + protocol: TCP + {{- if len .Values.networkPolicy.k8sApi.cidrs }} + to: + {{- range $cidr := .Values.networkPolicy.k8sApi.cidrs }} + - ipBlock: + cidr: {{ $cidr }} + {{- end }} + {{- end }} + +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "promtail.name" . }}-ingress-metrics + namespace: {{ .Release.Namespace }} + labels: + {{- include "promtail.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "promtail.selectorLabels" . | nindent 6 }} + policyTypes: + - Ingress + ingress: + - ports: + - port: http-metrics + protocol: TCP + {{- if len .Values.networkPolicy.metrics.cidrs }} + from: + {{- range $cidr := .Values.networkPolicy.metrics.cidrs }} + - ipBlock: + cidr: {{ $cidr }} + {{- end }} + {{- if .Values.networkPolicy.metrics.namespaceSelector }} + - namespaceSelector: + {{- toYaml .Values.networkPolicy.metrics.namespaceSelector | nindent 12 }} + {{- if .Values.networkPolicy.metrics.podSelector }} + podSelector: + {{- toYaml .Values.networkPolicy.metrics.podSelector | nindent 12 }} + {{- end }} + {{- end }} + {{- end }} + +{{- if .Values.extraPorts }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "promtail.name" . }}-egress-extra-ports + namespace: {{ .Release.Namespace }} + labels: + {{- include "promtail.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "promtail.selectorLabels" . | nindent 6 }} + policyTypes: + - Egress + egress: + - ports: + {{- range $extraPortConfig := .Values.extraPorts }} + - port: {{ $extraPortConfig.containerPort }} + protocol: {{ $extraPortConfig.protocol }} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/podsecuritypolicy.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/podsecuritypolicy.yaml new file mode 100644 index 000000000..b8287cdcc --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/podsecuritypolicy.yaml @@ -0,0 +1,10 @@ +{{- if and .Values.rbac.create .Values.rbac.pspEnabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ include "promtail.fullname" . }} + labels: + {{- include "promtail.labels" . | nindent 4 }} +spec: + {{- toYaml .Values.podSecurityPolicy | nindent 2 }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/role.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/role.yaml new file mode 100644 index 000000000..02b4a1a1b --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/role.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.rbac.create .Values.rbac.pspEnabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ include "promtail.fullname" . }}-psp + namespace: {{ .Release.Namespace }} + labels: + {{- include "promtail.labels" . | nindent 4 }} +rules: + - apiGroups: + - policy + resources: + - podsecuritypolicies + verbs: + - use + resourceNames: + - {{ include "promtail.fullname" . }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/rolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/rolebinding.yaml new file mode 100644 index 000000000..1fdda9699 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/rolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.rbac.create .Values.rbac.pspEnabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "promtail.fullname" . }}-psp + namespace: {{ .Release.Namespace }} + labels: + {{- include "promtail.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ include "promtail.fullname" . }}-psp +subjects: + - kind: ServiceAccount + name: {{ include "promtail.serviceAccountName" . }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/secret.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/secret.yaml new file mode 100644 index 000000000..aa519d1cc --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "promtail.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "promtail.labels" . | nindent 4 }} +stringData: + promtail.yaml: | + {{- tpl .Values.config.file . | nindent 4 }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/service-extra.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/service-extra.yaml new file mode 100644 index 000000000..1287d1f67 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/service-extra.yaml @@ -0,0 +1,52 @@ +{{- range $key, $values := .Values.extraPorts }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "promtail.fullname" $ }}-{{ $key | lower }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "promtail.labels" $ | nindent 4 }} + {{- with .labels }} + {{- toYaml $ | nindent 4 }} + {{- end }} + {{- with .annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with $values.service }} + type: {{ .type | default "ClusterIP" }} + {{- with .clusterIP }} + clusterIP: {{ . }} + {{- end }} + {{- with .loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- with .loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- toYaml . | nindent 4 }} + {{- end -}} + {{- with .externalIPs }} + externalIPs: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .externalTrafficPolicy }} + externalTrafficPolicy: {{ . }} + {{- end }} + {{- end }} + ports: + - name: {{ .name | default $key }} + targetPort: {{ .name | default $key }} + protocol: TCP + {{- if $values.service }} + port: {{ $values.service.port | default $values.containerPort }} + {{- if $values.service.nodePort }} + nodePort: {{ $values.service.nodePort }} + {{- end }} + {{- else }} + port: {{ $values.containerPort }} + {{- end }} + selector: + {{- include "promtail.selectorLabels" $ | nindent 4 }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/service-metrics.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/service-metrics.yaml new file mode 100644 index 000000000..bc29a8121 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/service-metrics.yaml @@ -0,0 +1,18 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "promtail.fullname" . }}-metrics + namespace: {{ .Release.Namespace }} + labels: + {{- include "promtail.labels" . | nindent 4 }} +spec: + clusterIP: None + ports: + - name: http-metrics + port: {{ .Values.config.serverPort }} + targetPort: http-metrics + protocol: TCP + selector: + {{- include "promtail.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/serviceaccount.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/serviceaccount.yaml new file mode 100644 index 000000000..d566aecab --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/serviceaccount.yaml @@ -0,0 +1,17 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "promtail.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "promtail.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- with .Values.serviceAccount.imagePullSecrets }} +imagePullSecrets: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/servicemonitor.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/servicemonitor.yaml new file mode 100644 index 000000000..06235f49b --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/templates/servicemonitor.yaml @@ -0,0 +1,40 @@ +{{- if .Values.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "promtail.fullname" $ }} + {{- if .Values.serviceMonitor.namespace }} + namespace: {{ .Values.serviceMonitor.namespace }} + {{- else }} + namespace: {{ .Release.Namespace }} + {{- end }} + {{- with .Values.serviceMonitor.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + {{- include "promtail.labels" $ | nindent 4 }} + {{- with .Values.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.serviceMonitor.namespaceSelector }} + namespaceSelector: + {{- toYaml . | nindent 4 }} + {{- end }} + selector: + matchLabels: + {{- include "promtail.selectorLabels" . | nindent 6 }} + endpoints: + - port: http-metrics + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/values.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/values.yaml new file mode 100644 index 000000000..ff69dfed4 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/charts/promtail/values.yaml @@ -0,0 +1,430 @@ +# -- Overrides the chart's name +nameOverride: null + +# -- Overrides the chart's computed fullname +fullnameOverride: null + +initContainer: + # -- Specifies whether the init container for setting inotify max user instances is to be enabled + enabled: false + image: + # -- The Docker registry for the init container + registry: docker.io + # -- Docker image repository for the init container + repository: busybox + # -- Docker tag for the init container + tag: 1.33 + # -- Docker image pull policy for the init container image + pullPolicy: IfNotPresent + # -- The inotify max user instances to configure + fsInotifyMaxUserInstances: 128 + +image: + # -- The Docker registry + registry: docker.io + # -- Docker image repository + repository: grafana/promtail + # -- Overrides the image tag whose default is the chart's appVersion + tag: null + # -- Docker image pull policy + pullPolicy: IfNotPresent + +# -- Image pull secrets for Docker images +imagePullSecrets: [] + +# -- Annotations for the DaemonSet +annotations: + ignore-check.kube-linter.io/run-as-non-root: "This deployment needs to run as root user to modify log files" + ignore-check.kube-linter.io/writable-host-mount: "This deployment needs writable volume mount on host to capture logs" + +# -- The update strategy for the DaemonSet +updateStrategy: + type: RollingUpdate + +# -- Pod labels +podLabels: {} + +# -- Pod annotations +podAnnotations: {} +# prometheus.io/scrape: "true" +# prometheus.io/port: "http-metrics" + +# -- The name of the PriorityClass +priorityClassName: null + +# -- Liveness probe +livenessProbe: {} + +# -- Readiness probe +# @default -- See `values.yaml` +readinessProbe: + failureThreshold: 5 + httpGet: + path: /ready + port: http-metrics + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + +# -- Resource requests and limits +resources: + limits: + cpu: 1000m + memory: 500Mi + requests: + cpu: 500m + memory: 256Mi + +# -- The security context for pods +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +# -- The security context for containers +containerSecurityContext: + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + allowPrivilegeEscalation: false + +rbac: + # -- Specifies whether RBAC resources are to be created + create: true + # -- Specifies whether a PodSecurityPolicy is to be created + pspEnabled: false + +serviceAccount: + # -- Specifies whether a ServiceAccount should be created + create: true + # -- The name of the ServiceAccount to use. + # If not set and `create` is true, a name is generated using the fullname template + name: null + # -- Image pull secrets for the service account + imagePullSecrets: [] + # -- Annotations for the service account + annotations: {} + +# -- Node selector for pods +nodeSelector: {} + +# -- Affinity configuration for pods +affinity: {} + +# -- Tolerations for pods. By default, pods will be scheduled on master/control-plane nodes. +tolerations: + - key: node-role.kubernetes.io/master + operator: Exists + effect: NoSchedule + - key: node-role.kubernetes.io/control-plane + operator: Exists + effect: NoSchedule + +# -- Default volumes that are mounted into pods. In most cases, these should not be changed. +# Use `extraVolumes`/`extraVolumeMounts` for additional custom volumes. +# @default -- See `values.yaml` +defaultVolumes: + - name: containers + hostPath: + path: /var/lib/docker/containers + - name: pods + hostPath: + path: /var/log/pods + +# -- Default volume mounts. Corresponds to `volumes`. +# @default -- See `values.yaml` +defaultVolumeMounts: + - name: containers + mountPath: /var/lib/docker/containers + readOnly: true + - name: pods + mountPath: /var/log/pods + readOnly: true + +# Extra volumes to be added in addition to those specified under `defaultVolumes`. +extraVolumes: [] + +# Extra volume mounts together. Corresponds to `extraVolumes`. +extraVolumeMounts: [] + +# Extra args for the Promtail container. +extraArgs: [] +# -- Example: +# -- extraArgs: +# -- - -client.external-labels=hostname=$(HOSTNAME) + +# -- Extra environment variables +extraEnv: [] + +# -- Extra environment variables from secrets or configmaps +extraEnvFrom: [] + +# ServiceMonitor configuration +serviceMonitor: + # -- If enabled, ServiceMonitor resources for Prometheus Operator are created + enabled: false + # -- Alternative namespace for ServiceMonitor resources + namespace: null + # -- Namespace selector for ServiceMonitor resources + namespaceSelector: {} + # -- ServiceMonitor annotations + annotations: {} + # -- Additional ServiceMonitor labels + labels: {} + # -- ServiceMonitor scrape interval + interval: null + # -- ServiceMonitor scrape timeout in Go duration format (e.g. 15s) + scrapeTimeout: null + # -- ServiceMonitor relabel configs to apply to samples before scraping + # https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#relabelconfig + relabelings: [] + +# -- Configure additional ports and services. For each configured port, a corresponding service is created. +# See values.yaml for details +extraPorts: {} +# syslog: +# name: tcp-syslog +# containerPort: 1514 +# protocol: TCP +# service: +# type: ClusterIP +# clusterIP: null +# port: 1514 +# externalIPs: [] +# nodePort: null +# annotations: {} +# labels: {} +# loadBalancerIP: null +# loadBalancerSourceRanges: [] +# externalTrafficPolicy: null + +# -- PodSecurityPolicy configuration. +# @default -- See `values.yaml` +podSecurityPolicy: + privileged: true + allowPrivilegeEscalation: true + volumes: + - 'secret' + - 'hostPath' + - 'downwardAPI' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' + readOnlyRootFilesystem: true + requiredDropCapabilities: + - ALL + +# -- Section for crafting Promtails config file. The only directly relevant value is `config.file` +# which is a templated string that references the other values and snippets below this key. +# @default -- See `values.yaml` +config: + # -- The log level of the Promtail server + # Must be reference in `config.file` to configure `server.log_level` + # See default config in `values.yaml` + logLevel: info + # -- The port of the Promtail server + # Must be reference in `config.file` to configure `server.http_listen_port` + # See default config in `values.yaml` + serverPort: 3101 + # -- The Loki address to post logs to. + # Must be reference in `config.file` to configure `client.url`. + # See default config in `values.yaml` + lokiAddress: http://{{ .Release.Name }}-loki:3100/loki/api/v1/push + # -- A section of reusable snippets that can be reference in `config.file`. + # Custom snippets may be added in order to reduce redundancy. + # This is especially helpful when multiple `kubernetes_sd_configs` are use which usually have large parts in common. + # @default -- See `values.yaml` + snippets: + pipelineStages: + - cri: {} + - match: + selector: '{app="k8s-triliovault"}' + stages: + - json: + expressions: + file: file + func: func + level: level + msg: msg + tvk_version: tvk_version + tvk_instance_id: tvk_instance_id + service_id: service_id + service_type: service_type + transaction_id: transaction_id + transaction_type: transaction_type + transaction_resource_name: transaction_resource_name + transaction_resource_namespace: transaction_resource_namespace + child_transaction_type: child_transaction_type + child_transaction_id: child_transaction_id + child_transaction_resource_name: child_transaction_resource_name + child_transaction_resource_namespace: child_transaction_resource_namespace + - labels: + file: + func: + level: + msg: + tvk_version: + tvk_instance_id: + service_id: + service_type: + transaction_id: + transaction_type: + transaction_resource_name: + transaction_resource_namespace: + child_transaction_type: + child_transaction_id: + child_transaction_resource_name: + child_transaction_resource_namespace: + common: + - action: replace + source_labels: + - __meta_kubernetes_pod_node_name + target_label: node_name + - action: replace + source_labels: + - __meta_kubernetes_namespace + target_label: namespace + - action: replace + replacement: $1 + separator: / + source_labels: + - namespace + - app + target_label: job + - action: replace + source_labels: + - __meta_kubernetes_pod_name + target_label: pod + - action: replace + source_labels: + - __meta_kubernetes_pod_container_name + target_label: container + - action: replace + replacement: /var/log/pods/*$1/*.log + separator: / + source_labels: + - __meta_kubernetes_pod_uid + - __meta_kubernetes_pod_container_name + target_label: __path__ + - action: replace + replacement: /var/log/pods/*$1/*.log + regex: true/(.*) + separator: / + source_labels: + - __meta_kubernetes_pod_annotationpresent_kubernetes_io_config_hash + - __meta_kubernetes_pod_annotation_kubernetes_io_config_hash + - __meta_kubernetes_pod_container_name + target_label: __path__ + + # If set to true, adds an additional label for the scrape job. + # This helps debug the Promtail config. + addScrapeJobLabel: false + + # -- You can put here any keys that will be directly added to the config file's 'client' block. + # @default -- empty + extraClientConfigs: [] + + # -- You can put here any additional scrape configs you want to add to the config file. + # @default -- empty + extraScrapeConfigs: "" + + # -- You can put here any additional relabel_configs to "kubernetes-pods" job + extraRelabelConfigs: [] + + scrapeConfigs: | + # See also https://github.com/grafana/loki/blob/master/production/ksonnet/promtail/scrape_config.libsonnet for reference + - job_name: kubernetes-pods + pipeline_stages: + {{- toYaml .Values.config.snippets.pipelineStages | nindent 4 }} + kubernetes_sd_configs: + - role: pod + relabel_configs: + - source_labels: + - __meta_kubernetes_pod_controller_name + regex: ([0-9a-z-.]+?)(-[0-9a-f]{8,10})? + action: replace + target_label: __tmp_controller_name + - source_labels: + - __meta_kubernetes_pod_label_app_kubernetes_io_name + - __meta_kubernetes_pod_label_app + - __tmp_controller_name + - __meta_kubernetes_pod_name + regex: ^;*([^;]+)(;.*)?$ + action: replace + target_label: app + - source_labels: + - __meta_kubernetes_pod_label_app_kubernetes_io_component + - __meta_kubernetes_pod_label_component + regex: ^;*([^;]+)(;.*)?$ + action: replace + target_label: component + {{- if .Values.config.snippets.addScrapeJobLabel }} + - replacement: kubernetes-pods + target_label: scrape_job + {{- end }} + {{- toYaml .Values.config.snippets.common | nindent 4 }} + {{- with .Values.config.snippets.extraRelabelConfigs }} + {{- toYaml . | nindent 4 }} + {{- end }} + + # -- Config file contents for Promtail. + # Must be configured as string. + # It is templated so it can be assembled from reusable snippets in order to avoid redundancy. + # @default -- See `values.yaml` + file: | + server: + log_level: {{ .Values.config.logLevel }} + http_listen_port: {{ .Values.config.serverPort }} + + clients: + - url: {{ tpl .Values.config.lokiAddress . }} + {{- with .Values.config.snippets.extraClientConfigs }} + {{- toYaml . | nindent 2 }} + {{- end }} + + positions: + filename: /run/promtail/positions.yaml + + scrape_configs: + {{- tpl .Values.config.snippets.scrapeConfigs . | nindent 2 }} + {{- tpl .Values.config.snippets.extraScrapeConfigs . | nindent 2 }} + +networkPolicy: + # -- Specifies whether Network Policies should be created + enabled: false + metrics: + # -- Specifies the Pods which are allowed to access the metrics port. + # As this is cross-namespace communication, you also neeed the namespaceSelector. + podSelector: {} + # -- Specifies the namespaces which are allowed to access the metrics port + namespaceSelector: {} + # -- Specifies specific network CIDRs which are allowed to access the metrics port. + # In case you use namespaceSelector, you also have to specify your kubelet networks here. + # The metrics ports are also used for probes. + cidrs: [] + k8sApi: + # -- Specify the k8s API endpoint port + port: 8443 + # -- Specifies specific network CIDRs you want to limit access to + cidrs: [] + +# -- Extra K8s manifests to deploy +extraObjects: [] + # - apiVersion: "kubernetes-client.io/v1" + # kind: ExternalSecret + # metadata: + # name: promtail-secrets + # spec: + # backendType: gcpSecretsManager + # data: + # - key: promtail-oauth2-creds + # name: client_secret diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/templates/_helpers.tpl b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/templates/_helpers.tpl new file mode 100644 index 000000000..9fb468f83 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/templates/_helpers.tpl @@ -0,0 +1,50 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "logging.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 "logging.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 "logging.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +The service name to connect to Loki. Defaults to the same logic as "loki.fullname" +*/}} +{{- define "loki.serviceName" -}} +{{- if .Values.loki.serviceName -}} +{{- .Values.loki.serviceName -}} +{{- else if .Values.loki.fullnameOverride -}} +{{- .Values.loki.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default "loki" .Values.loki.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/templates/datasources.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/templates/datasources.yaml new file mode 100644 index 000000000..d54ec60c9 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/logging/templates/datasources.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "logging.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "logging.name" . }} + chart: {{ template "logging.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + app.kubernetes.io/instance: {{ template "logging.name" . }} + {{- include "k8s-triliovault-operator.labels" . | nindent 4 }} + grafana_datasource: "1" +data: + logging-datasource.yaml: |- + apiVersion: 1 + datasources: +{{- if .Values.loki.enabled }} + - name: Loki + type: loki + access: proxy + url: http://{{(include "loki.serviceName" .)}}:{{ .Values.loki.service.port }} + version: 1 +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/Chart.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/Chart.yaml new file mode 100644 index 000000000..13ffa6d15 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/Chart.yaml @@ -0,0 +1,16 @@ +apiVersion: v2 +appVersion: 0.1.0 +dependencies: +- condition: prometheus.enabled + name: prometheus + repository: https://prometheus-community.github.io/helm-charts + version: ^15.8.7 +description: Monitoring Stack designed to manage the K8s-TrilioVault Application's + Monitoring. +icon: https://www.trilio.io/wp-content/uploads/2021/01/Trilio-2020-logo-RGB-gray-green.png +kubeVersion: '>=1.19.0-0' +maintainers: +- email: support@trilio.io + name: Trilio +name: monitoring +version: 0.1.0 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/Chart.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/Chart.yaml new file mode 100644 index 000000000..609fb7386 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/Chart.yaml @@ -0,0 +1,22 @@ +apiVersion: v2 +appVersion: 2.34.0 +dependencies: +- condition: kubeStateMetrics.enabled + name: kube-state-metrics + repository: https://prometheus-community.github.io/helm-charts + version: 4.7.* +description: Prometheus is a monitoring system and time series database. +home: https://prometheus.io/ +icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png +maintainers: +- email: support@trilio.io + name: Trilio +name: prometheus +sources: +- https://github.com/prometheus/alertmanager +- https://github.com/prometheus/prometheus +- https://github.com/prometheus/pushgateway +- https://github.com/prometheus/node_exporter +- https://github.com/kubernetes/kube-state-metrics +type: application +version: 15.8.7 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/Chart.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/Chart.yaml new file mode 100644 index 000000000..83d0685a1 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/Chart.yaml @@ -0,0 +1,17 @@ +apiVersion: v2 +appVersion: 2.4.1 +description: Install kube-state-metrics to generate and expose cluster-level metrics +home: https://github.com/kubernetes/kube-state-metrics/ +keywords: +- metric +- monitoring +- prometheus +- kubernetes +maintainers: +- email: support@trilio.io + name: Trilio +name: kube-state-metrics +sources: +- https://github.com/kubernetes/kube-state-metrics/ +type: application +version: 4.7.0 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/NOTES.txt b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/NOTES.txt new file mode 100644 index 000000000..5a646e0cc --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/NOTES.txt @@ -0,0 +1,10 @@ +kube-state-metrics is a simple service that listens to the Kubernetes API server and generates metrics about the state of the objects. +The exposed metrics can be found here: +https://github.com/kubernetes/kube-state-metrics/blob/master/docs/README.md#exposed-metrics + +The metrics are exported on the HTTP endpoint /metrics on the listening port. +In your case, {{ template "kube-state-metrics.fullname" . }}.{{ template "kube-state-metrics.namespace" . }}.svc.cluster.local:{{ .Values.service.port }}/metrics + +They are served either as plaintext or protobuf depending on the Accept header. +They are designed to be consumed either by Prometheus itself or by a scraper that is compatible with scraping a Prometheus client endpoint. + diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/_helpers.tpl b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/_helpers.tpl new file mode 100644 index 000000000..976b27337 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/_helpers.tpl @@ -0,0 +1,82 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "kube-state-metrics.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 "kube-state-metrics.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "kube-state-metrics.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "kube-state-metrics.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "kube-state-metrics.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "kube-state-metrics.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Generate basic labels +*/}} +{{- define "kube-state-metrics.labels" }} +helm.sh/chart: {{ template "kube-state-metrics.chart" . }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/component: metrics +app.kubernetes.io/part-of: {{ template "kube-state-metrics.name" . }} +{{- include "kube-state-metrics.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +{{- if .Values.customLabels }} +{{ toYaml .Values.customLabels }} +{{- end }} +{{- if .Values.releaseLabel }} +release: {{ .Release.Name }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "kube-state-metrics.selectorLabels" }} +app.kubernetes.io/name: {{ include "kube-state-metrics.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/clusterrolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..cf9f628d0 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/clusterrolebinding.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.rbac.create .Values.rbac.useClusterRole -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: {{ template "kube-state-metrics.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole +{{- if .Values.rbac.useExistingRole }} + name: {{ .Values.rbac.useExistingRole }} +{{- else }} + name: {{ template "kube-state-metrics.fullname" . }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "kube-state-metrics.serviceAccountName" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/deployment.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/deployment.yaml new file mode 100644 index 000000000..450e8e059 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/deployment.yaml @@ -0,0 +1,156 @@ +apiVersion: apps/v1 +{{- if .Values.autosharding.enabled }} +kind: StatefulSet +{{- else }} +kind: Deployment +{{- end }} +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +spec: + selector: + matchLabels: + {{- include "kube-state-metrics.selectorLabels" . | indent 6 }} + replicas: {{ .Values.replicas }} + {{- if .Values.autosharding.enabled }} + serviceName: {{ template "kube-state-metrics.fullname" . }} + updateStrategy: + type: RollingUpdate + volumeClaimTemplates: [] + {{- else }} + strategy: + type: RollingUpdate + {{- end }} + template: + metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 8 }} + {{- if .Values.podAnnotations }} + annotations: +{{ toYaml .Values.podAnnotations | indent 8 }} + {{- end }} + spec: + hostNetwork: {{ .Values.hostNetwork }} + serviceAccountName: {{ template "kube-state-metrics.serviceAccountName" . }} + {{- if .Values.securityContext.enabled }} + securityContext: + fsGroup: {{ .Values.securityContext.fsGroup }} + runAsGroup: {{ .Values.securityContext.runAsGroup }} + runAsUser: {{ .Values.securityContext.runAsUser }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + {{- if .Values.autosharding.enabled }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- end }} + args: + {{- if .Values.extraArgs }} + {{- range .Values.extraArgs }} + - {{ . }} + {{- end }} + {{- end }} + {{- if .Values.service.port }} + - --port={{ .Values.service.port | default 8080}} + {{- end }} + {{- if .Values.collectors }} + - --resources={{ .Values.collectors | join "," }} + {{- end }} + {{- if .Values.metricLabelsAllowlist }} + - --metric-labels-allowlist={{ .Values.metricLabelsAllowlist | join "," }} + {{- end }} + {{- if .Values.metricAnnotationsAllowList }} + - --metric-annotations-allowlist={{ .Values.metricAnnotationsAllowList | join "," }} + {{- end }} + {{- if .Values.metricAllowlist }} + - --metric-allowlist={{ .Values.metricAllowlist | join "," }} + {{- end }} + {{- if .Values.metricDenylist }} + - --metric-denylist={{ .Values.metricDenylist | join "," }} + {{- end }} + {{- if .Values.namespaces }} + - --namespaces={{ tpl (.Values.namespaces | join ",") $ }} + {{- end }} + {{- if .Values.namespacesDenylist }} + - --namespaces-denylist={{ tpl (.Values.namespacesDenylist | join ",") $ }} + {{- end }} + {{- if .Values.autosharding.enabled }} + - --pod=$(POD_NAME) + - --pod-namespace=$(POD_NAMESPACE) + {{- end }} + {{- if .Values.kubeconfig.enabled }} + - --kubeconfig=/opt/k8s/.kube/config + {{- end }} + {{- if .Values.selfMonitor.telemetryHost }} + - --telemetry-host={{ .Values.selfMonitor.telemetryHost }} + {{- end }} + - --telemetry-port={{ .Values.selfMonitor.telemetryPort | default 8081 }} + {{- if .Values.kubeconfig.enabled }} + volumeMounts: + - name: kubeconfig + mountPath: /opt/k8s/.kube/ + readOnly: true + {{- end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + ports: + - containerPort: {{ .Values.service.port | default 8080}} + name: "http" + {{- if .Values.selfMonitor.enabled }} + - containerPort: {{ .Values.selfMonitor.telemetryPort | default 8081 }} + name: "metrics" + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: {{ .Values.service.port | default 8080}} + initialDelaySeconds: 5 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: / + port: {{ .Values.service.port | default 8080}} + initialDelaySeconds: 5 + timeoutSeconds: 5 + {{- if .Values.resources }} + resources: +{{ toYaml .Values.resources | indent 10 }} +{{- end }} +{{- if .Values.containerSecurityContext }} + securityContext: +{{ toYaml .Values.containerSecurityContext | indent 10 }} +{{- end }} +{{- if .Values.imagePullSecrets }} + imagePullSecrets: +{{ toYaml .Values.imagePullSecrets | indent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: +{{ toYaml .Values.affinity | indent 8 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: +{{ toYaml .Values.tolerations | indent 8 }} + {{- end }} + {{- if .Values.kubeconfig.enabled}} + volumes: + - name: kubeconfig + secret: + secretName: {{ template "kube-state-metrics.fullname" . }}-kubeconfig + {{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/kubeconfig-secret.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/kubeconfig-secret.yaml new file mode 100644 index 000000000..6af008450 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/kubeconfig-secret.yaml @@ -0,0 +1,12 @@ +{{- if .Values.kubeconfig.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "kube-state-metrics.fullname" . }}-kubeconfig + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +type: Opaque +data: + config: '{{ .Values.kubeconfig.secret }}' +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/pdb.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/pdb.yaml new file mode 100644 index 000000000..cbcf3a37e --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/pdb.yaml @@ -0,0 +1,14 @@ +{{- if .Values.podDisruptionBudget -}} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ template "kube-state-metrics.name" . }} +{{ toYaml .Values.podDisruptionBudget | indent 2 }} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/podsecuritypolicy.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/podsecuritypolicy.yaml new file mode 100644 index 000000000..3299056ab --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/podsecuritypolicy.yaml @@ -0,0 +1,39 @@ +{{- if .Values.podSecurityPolicy.enabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +{{- if .Values.podSecurityPolicy.annotations }} + annotations: +{{ toYaml .Values.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +spec: + privileged: false + volumes: + - 'secret' +{{- if .Values.podSecurityPolicy.additionalVolumes }} +{{ toYaml .Values.podSecurityPolicy.additionalVolumes | indent 4 }} +{{- end }} + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'MustRunAsNonRoot' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrole.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrole.yaml new file mode 100644 index 000000000..69047d4ff --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrole.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.podSecurityPolicy.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: psp-{{ template "kube-state-metrics.fullname" . }} +rules: +{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }} +{{- if semverCompare "> 1.15.0-0" $kubeTargetVersion }} +- apiGroups: ['policy'] +{{- else }} +- apiGroups: ['extensions'] +{{- end }} + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "kube-state-metrics.fullname" . }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml new file mode 100644 index 000000000..03c56d575 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/psp-clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.podSecurityPolicy.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: psp-{{ template "kube-state-metrics.fullname" . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: psp-{{ template "kube-state-metrics.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "kube-state-metrics.serviceAccountName" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/role.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/role.yaml new file mode 100644 index 000000000..e514e3c01 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/role.yaml @@ -0,0 +1,187 @@ +{{- if and (eq .Values.rbac.create true) (not .Values.rbac.useExistingRole) -}} +{{- range (ternary (split "," .Values.namespaces) (list "") (eq $.Values.rbac.useClusterRole false)) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{- if eq $.Values.rbac.useClusterRole false }} +kind: Role +{{- else }} +kind: ClusterRole +{{- end }} +metadata: + labels: + {{- include "kube-state-metrics.labels" $ | indent 4 }} + name: {{ template "kube-state-metrics.fullname" $ }} +{{- if eq $.Values.rbac.useClusterRole false }} + namespace: {{ . }} +{{- end }} +rules: +{{ if has "certificatesigningrequests" $.Values.collectors }} +- apiGroups: ["certificates.k8s.io"] + resources: + - certificatesigningrequests + verbs: ["list", "watch"] +{{ end -}} +{{ if has "configmaps" $.Values.collectors }} +- apiGroups: [""] + resources: + - configmaps + verbs: ["list", "watch"] +{{ end -}} +{{ if has "cronjobs" $.Values.collectors }} +- apiGroups: ["batch"] + resources: + - cronjobs + verbs: ["list", "watch"] +{{ end -}} +{{ if has "daemonsets" $.Values.collectors }} +- apiGroups: ["extensions", "apps"] + resources: + - daemonsets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "deployments" $.Values.collectors }} +- apiGroups: ["extensions", "apps"] + resources: + - deployments + verbs: ["list", "watch"] +{{ end -}} +{{ if has "endpoints" $.Values.collectors }} +- apiGroups: [""] + resources: + - endpoints + verbs: ["list", "watch"] +{{ end -}} +{{ if has "horizontalpodautoscalers" $.Values.collectors }} +- apiGroups: ["autoscaling"] + resources: + - horizontalpodautoscalers + verbs: ["list", "watch"] +{{ end -}} +{{ if has "ingresses" $.Values.collectors }} +- apiGroups: ["extensions", "networking.k8s.io"] + resources: + - ingresses + verbs: ["list", "watch"] +{{ end -}} +{{ if has "jobs" $.Values.collectors }} +- apiGroups: ["batch"] + resources: + - jobs + verbs: ["list", "watch"] +{{ end -}} +{{ if has "limitranges" $.Values.collectors }} +- apiGroups: [""] + resources: + - limitranges + verbs: ["list", "watch"] +{{ end -}} +{{ if has "mutatingwebhookconfigurations" $.Values.collectors }} +- apiGroups: ["admissionregistration.k8s.io"] + resources: + - mutatingwebhookconfigurations + verbs: ["list", "watch"] +{{ end -}} +{{ if has "namespaces" $.Values.collectors }} +- apiGroups: [""] + resources: + - namespaces + verbs: ["list", "watch"] +{{ end -}} +{{ if has "networkpolicies" $.Values.collectors }} +- apiGroups: ["networking.k8s.io"] + resources: + - networkpolicies + verbs: ["list", "watch"] +{{ end -}} +{{ if has "nodes" $.Values.collectors }} +- apiGroups: [""] + resources: + - nodes + verbs: ["list", "watch"] +{{ end -}} +{{ if has "persistentvolumeclaims" $.Values.collectors }} +- apiGroups: [""] + resources: + - persistentvolumeclaims + verbs: ["list", "watch"] +{{ end -}} +{{ if has "persistentvolumes" $.Values.collectors }} +- apiGroups: [""] + resources: + - persistentvolumes + verbs: ["list", "watch"] +{{ end -}} +{{ if has "poddisruptionbudgets" $.Values.collectors }} +- apiGroups: ["policy"] + resources: + - poddisruptionbudgets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "pods" $.Values.collectors }} +- apiGroups: [""] + resources: + - pods + verbs: ["list", "watch"] +{{ end -}} +{{ if has "replicasets" $.Values.collectors }} +- apiGroups: ["extensions", "apps"] + resources: + - replicasets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "replicationcontrollers" $.Values.collectors }} +- apiGroups: [""] + resources: + - replicationcontrollers + verbs: ["list", "watch"] +{{ end -}} +{{ if has "resourcequotas" $.Values.collectors }} +- apiGroups: [""] + resources: + - resourcequotas + verbs: ["list", "watch"] +{{ end -}} +{{ if has "secrets" $.Values.collectors }} +- apiGroups: [""] + resources: + - secrets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "services" $.Values.collectors }} +- apiGroups: [""] + resources: + - services + verbs: ["list", "watch"] +{{ end -}} +{{ if has "statefulsets" $.Values.collectors }} +- apiGroups: ["apps"] + resources: + - statefulsets + verbs: ["list", "watch"] +{{ end -}} +{{ if has "storageclasses" $.Values.collectors }} +- apiGroups: ["storage.k8s.io"] + resources: + - storageclasses + verbs: ["list", "watch"] +{{ end -}} +{{ if has "validatingwebhookconfigurations" $.Values.collectors }} +- apiGroups: ["admissionregistration.k8s.io"] + resources: + - validatingwebhookconfigurations + verbs: ["list", "watch"] +{{ end -}} +{{ if has "volumeattachments" $.Values.collectors }} +- apiGroups: ["storage.k8s.io"] + resources: + - volumeattachments + verbs: ["list", "watch"] +{{ end -}} +{{ if has "verticalpodautoscalers" $.Values.collectors }} +- apiGroups: ["autoscaling.k8s.io"] + resources: + - verticalpodautoscalers + verbs: ["list", "watch"] +{{ end -}} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/rolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/rolebinding.yaml new file mode 100644 index 000000000..135094f7b --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/rolebinding.yaml @@ -0,0 +1,24 @@ +{{- if and (eq .Values.rbac.create true) (eq .Values.rbac.useClusterRole false) -}} +{{- range (split "," $.Values.namespaces) }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + {{- include "kube-state-metrics.labels" $ | indent 4 }} + name: {{ template "kube-state-metrics.fullname" $ }} + namespace: {{ . }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role +{{- if (not $.Values.rbac.useExistingRole) }} + name: {{ template "kube-state-metrics.fullname" $ }} +{{- else }} + name: {{ $.Values.rbac.useExistingRole }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "kube-state-metrics.serviceAccountName" $ }} + namespace: {{ template "kube-state-metrics.namespace" $ }} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/service.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/service.yaml new file mode 100644 index 000000000..5a2d8eab0 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/service.yaml @@ -0,0 +1,38 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + annotations: + {{- if .Values.prometheusScrape }} + prometheus.io/scrape: '{{ .Values.prometheusScrape }}' + {{- end }} + {{- if .Values.service.annotations }} + {{- toYaml .Values.service.annotations | nindent 4 }} + {{- end }} +spec: + type: "{{ .Values.service.type }}" + ports: + - name: "http" + protocol: TCP + port: {{ .Values.service.port | default 8080}} + {{- if .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + targetPort: {{ .Values.service.port | default 8080}} + {{ if .Values.selfMonitor.enabled }} + - name: "metrics" + protocol: TCP + port: {{ .Values.selfMonitor.telemetryPort | default 8081 }} + targetPort: {{ .Values.selfMonitor.telemetryPort | default 8081 }} + {{ end }} +{{- if .Values.service.loadBalancerIP }} + loadBalancerIP: "{{ .Values.service.loadBalancerIP }}" +{{- end }} +{{- if .Values.service.clusterIP }} + clusterIP: "{{ .Values.service.clusterIP }}" +{{- end }} + selector: + {{- include "kube-state-metrics.selectorLabels" . | indent 4 }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/serviceaccount.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/serviceaccount.yaml new file mode 100644 index 000000000..e1229eb95 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + name: {{ template "kube-state-metrics.serviceAccountName" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- if .Values.serviceAccount.annotations }} + annotations: +{{ toYaml .Values.serviceAccount.annotations | indent 4 }} +{{- end }} +imagePullSecrets: +{{ toYaml .Values.serviceAccount.imagePullSecrets | indent 2 }} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/servicemonitor.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/servicemonitor.yaml new file mode 100644 index 000000000..93a5870f6 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/servicemonitor.yaml @@ -0,0 +1,66 @@ +{{- if .Values.prometheus.monitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} + {{- with .Values.prometheus.monitor.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ default "app.kubernetes.io/name" .Values.prometheus.monitor.jobLabel }} + selector: + matchLabels: + {{- if .Values.prometheus.monitor.selectorOverride -}} + {{ toYaml .Values.prometheus.monitor.selectorOverride | nindent 6 }} + {{ else }} + {{- include "kube-state-metrics.selectorLabels" . | indent 6 }} + {{- end }} + endpoints: + - port: http + {{- if .Values.prometheus.monitor.interval }} + interval: {{ .Values.prometheus.monitor.interval }} + {{- end }} + {{- if .Values.prometheus.monitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.prometheus.monitor.scrapeTimeout }} + {{- end }} + {{- if .Values.prometheus.monitor.proxyUrl }} + proxyUrl: {{ .Values.prometheus.monitor.proxyUrl}} + {{- end }} + {{- if .Values.prometheus.monitor.honorLabels }} + honorLabels: true + {{- end }} + {{- if .Values.prometheus.monitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.monitor.metricRelabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.monitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.monitor.relabelings | nindent 8 }} + {{- end }} + {{- if .Values.selfMonitor.enabled }} + - port: metrics + {{- if .Values.prometheus.monitor.interval }} + interval: {{ .Values.prometheus.monitor.interval }} + {{- end }} + {{- if .Values.prometheus.monitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.prometheus.monitor.scrapeTimeout }} + {{- end }} + {{- if .Values.prometheus.monitor.proxyUrl }} + proxyUrl: {{ .Values.prometheus.monitor.proxyUrl}} + {{- end }} + {{- if .Values.prometheus.monitor.honorLabels }} + honorLabels: true + {{- end }} + {{- if .Values.prometheus.monitor.metricRelabelings }} + metricRelabelings: + {{- toYaml .Values.prometheus.monitor.metricRelabelings | nindent 8 }} + {{- end }} + {{- if .Values.prometheus.monitor.relabelings }} + relabelings: + {{- toYaml .Values.prometheus.monitor.relabelings | nindent 8 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-role.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-role.yaml new file mode 100644 index 000000000..489de147c --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-role.yaml @@ -0,0 +1,26 @@ +{{- if and .Values.autosharding.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +rules: +- apiGroups: + - "" + resources: + - pods + verbs: + - get +- apiGroups: + - apps + resourceNames: + - {{ template "kube-state-metrics.fullname" . }} + resources: + - statefulsets + verbs: + - get + - list + - watch +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml new file mode 100644 index 000000000..73b37a4f6 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/templates/stsdiscovery-rolebinding.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.autosharding.enabled .Values.rbac.create -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} + labels: + {{- include "kube-state-metrics.labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: stsdiscovery-{{ template "kube-state-metrics.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "kube-state-metrics.serviceAccountName" . }} + namespace: {{ template "kube-state-metrics.namespace" . }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/values.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/values.yaml new file mode 100644 index 000000000..2f0718b15 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/charts/kube-state-metrics/values.yaml @@ -0,0 +1,232 @@ +# Default values for kube-state-metrics. +prometheusScrape: true +image: + repository: k8s.gcr.io/kube-state-metrics/kube-state-metrics + tag: v2.4.1 + pullPolicy: IfNotPresent + +imagePullSecrets: [] +# - name: "image-pull-secret" + +# If set to true, this will deploy kube-state-metrics as a StatefulSet and the data +# will be automatically sharded across <.Values.replicas> pods using the built-in +# autodiscovery feature: https://github.com/kubernetes/kube-state-metrics#automated-sharding +# This is an experimental feature and there are no stability guarantees. +autosharding: + enabled: false + +replicas: 1 + +# List of additional cli arguments to configure kube-state-metrics +# for example: --enable-gzip-encoding, --log-file, etc. +# all the possible args can be found here: https://github.com/kubernetes/kube-state-metrics/blob/master/docs/cli-arguments.md +extraArgs: [] + +service: + port: 8080 + # Default to clusterIP for backward compatibility + type: ClusterIP + nodePort: 0 + loadBalancerIP: "" + clusterIP: "" + annotations: {} + +## Additional labels to add to all resources +customLabels: {} + # app: kube-state-metrics + +## set to true to add the release label so scraping of the servicemonitor with kube-prometheus-stack works out of the box +releaseLabel: false + +hostNetwork: false + +rbac: + # If true, create & use RBAC resources + create: true + + # Set to a rolename to use existing role - skipping role creating - but still doing serviceaccount and rolebinding to it, rolename set here. + # useExistingRole: your-existing-role + + # If set to false - Run without Cluteradmin privs needed - ONLY works if namespace is also set (if useExistingRole is set this name is used as ClusterRole or Role to bind to) + useClusterRole: true + +serviceAccount: + # Specifies whether a ServiceAccount should be created, require rbac true + create: true + # The name of the ServiceAccount to use. + # If not set and create is true, a name is generated using the fullname template + name: + # Reference to one or more secrets to be used when pulling images + # ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + imagePullSecrets: [] + # ServiceAccount annotations. + # Use case: AWS EKS IAM roles for service accounts + # ref: https://docs.aws.amazon.com/eks/latest/userguide/specify-service-account-role.html + annotations: {} + +prometheus: + monitor: + enabled: false + additionalLabels: {} + namespace: "" + jobLabel: "" + interval: "" + scrapeTimeout: "" + proxyUrl: "" + selectorOverride: {} + honorLabels: false + metricRelabelings: [] + relabelings: [] + +## Specify if a Pod Security Policy for kube-state-metrics must be created +## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## +podSecurityPolicy: + enabled: false + annotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + additionalVolumes: [] + +securityContext: + enabled: true + runAsGroup: 65534 + runAsUser: 65534 + fsGroup: 65534 + +## Specify security settings for a Container +## Allows overrides and additional options compared to (Pod) securityContext +## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +containerSecurityContext: {} + +## Node labels for pod assignment +## Ref: https://kubernetes.io/docs/user-guide/node-selection/ +nodeSelector: {} + +## Affinity settings for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ +affinity: {} + +## Tolerations for pod assignment +## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +tolerations: [] + +# Annotations to be added to the pod +podAnnotations: {} + +## Assign a PriorityClassName to pods if set +# priorityClassName: "" + +# Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +podDisruptionBudget: {} + +updateStrategy: + type: RollingUpdate + +# Comma-separated list of metrics to be exposed. +# This list comprises of exact metric names and/or regex patterns. +# The allowlist and denylist are mutually exclusive. +metricAllowlist: [] + +# Comma-separated list of metrics not to be enabled. +# This list comprises of exact metric names and/or regex patterns. +# The allowlist and denylist are mutually exclusive. +metricDenylist: [] + +# Comma-separated list of additional Kubernetes label keys that will be used in the resource's +# labels metric. By default the metric contains only name and namespace labels. +# To include additional labels, provide a list of resource names in their plural form and Kubernetes +# label keys you would like to allow for them (Example: '=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. +# A single '*' can be provided per resource instead to allow any labels, but that has +# severe performance implications (Example: '=pods=[*]'). +metricLabelsAllowlist: [] + # - namespaces=[k8s-label-1,k8s-label-n] + +# Comma-separated list of Kubernetes annotations keys that will be used in the resource' +# labels metric. By default the metric contains only name and namespace labels. +# To include additional annotations provide a list of resource names in their plural form and Kubernetes +# annotation keys you would like to allow for them (Example: '=namespaces=[kubernetes.io/team,...],pods=[kubernetes.io/team],...)'. +# A single '*' can be provided per resource instead to allow any annotations, but that has +# severe performance implications (Example: '=pods=[*]'). +metricAnnotationsAllowList: [] + # - pods=[k8s-annotation-1,k8s-annotation-n] + +# Available collectors for kube-state-metrics. +# By default, all available resources are enabled, comment out to disable. +collectors: + - certificatesigningrequests + - configmaps + - cronjobs + - daemonsets + - deployments + - endpoints + - horizontalpodautoscalers + - ingresses + - jobs + - limitranges + - mutatingwebhookconfigurations + - namespaces + - networkpolicies + - nodes + - persistentvolumeclaims + - persistentvolumes + - poddisruptionbudgets + - pods + - replicasets + - replicationcontrollers + - resourcequotas + - secrets + - services + - statefulsets + - storageclasses + - validatingwebhookconfigurations + - volumeattachments + # - verticalpodautoscalers # not a default resource, see also: https://github.com/kubernetes/kube-state-metrics#enabling-verticalpodautoscalers + +# Enabling kubeconfig will pass the --kubeconfig argument to the container +kubeconfig: + enabled: false + # base64 encoded kube-config file + secret: + +# Comma-separated list of namespaces to be enabled for collecting resources. By default all namespaces are collected. +namespaces: "" + +# Comma-separated list of namespaces not to be enabled. If namespaces and namespaces-denylist are both set, +# only namespaces that are excluded in namespaces-denylist will be used. +namespacesDenylist: "" + +## Override the deployment namespace +## +namespaceOverride: "" + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 100m + memory: 64Mi + +## Provide a k8s version to define apiGroups for podSecurityPolicy Cluster Role. +## For example: kubeTargetVersionOverride: 1.14.9 +## +kubeTargetVersionOverride: "" + +# Enable self metrics configuration for service and Service Monitor +# Default values for telemetry configuration can be overridden +selfMonitor: + enabled: false + # telemetryHost: 0.0.0.0 + # telemetryPort: 8081 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/NOTES.txt b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/NOTES.txt new file mode 100644 index 000000000..0e8868f0b --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/NOTES.txt @@ -0,0 +1,112 @@ +{{- if .Values.server.enabled -}} +The Prometheus server can be accessed via port {{ .Values.server.service.servicePort }} on the following DNS name from within your cluster: +{{ template "prometheus.server.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + +{{ if .Values.server.ingress.enabled -}} +From outside the cluster, the server URL(s) are: +{{- range .Values.server.ingress.hosts }} +http://{{ . }} +{{- end }} +{{- else }} +Get the Prometheus server URL by running these commands in the same shell: +{{- if contains "NodePort" .Values.server.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus.server.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.server.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "prometheus.server.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "prometheus.server.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.server.service.servicePort }} +{{- else if contains "ClusterIP" .Values.server.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "prometheus.name" . }},component={{ .Values.server.name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 9090 +{{- end }} +{{- end }} + +{{- if .Values.server.persistentVolume.enabled }} +{{- else }} +################################################################################# +###### WARNING: Persistence is disabled!!! You will lose your data when ##### +###### the Server pod is terminated. ##### +################################################################################# +{{- end }} +{{- end }} + +{{ if .Values.alertmanager.enabled }} +The Prometheus alertmanager can be accessed via port {{ .Values.alertmanager.service.servicePort }} on the following DNS name from within your cluster: +{{ template "prometheus.alertmanager.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + +{{ if .Values.alertmanager.ingress.enabled -}} +From outside the cluster, the alertmanager URL(s) are: +{{- range .Values.alertmanager.ingress.hosts }} +http://{{ . }} +{{- end }} +{{- else }} +Get the Alertmanager URL by running these commands in the same shell: +{{- if contains "NodePort" .Values.alertmanager.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus.alertmanager.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.alertmanager.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "prometheus.alertmanager.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "prometheus.alertmanager.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.alertmanager.service.servicePort }} +{{- else if contains "ClusterIP" .Values.alertmanager.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "prometheus.name" . }},component={{ .Values.alertmanager.name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 9093 +{{- end }} +{{- end }} + +{{- if .Values.alertmanager.persistentVolume.enabled }} +{{- else }} +################################################################################# +###### WARNING: Persistence is disabled!!! You will lose your data when ##### +###### the AlertManager pod is terminated. ##### +################################################################################# +{{- end }} +{{- end }} + +{{- if .Values.nodeExporter.podSecurityPolicy.enabled }} +{{- else }} +################################################################################# +###### WARNING: Pod Security Policy has been moved to a global property. ##### +###### use .Values.podSecurityPolicy.enabled with pod-based ##### +###### annotations ##### +###### (e.g. .Values.nodeExporter.podSecurityPolicy.annotations) ##### +################################################################################# +{{- end }} + +{{ if .Values.pushgateway.enabled }} +The Prometheus PushGateway can be accessed via port {{ .Values.pushgateway.service.servicePort }} on the following DNS name from within your cluster: +{{ template "prometheus.pushgateway.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local + +{{ if .Values.pushgateway.ingress.enabled -}} +From outside the cluster, the pushgateway URL(s) are: +{{- range .Values.pushgateway.ingress.hosts }} +http://{{ . }} +{{- end }} +{{- else }} +Get the PushGateway URL by running these commands in the same shell: +{{- if contains "NodePort" .Values.pushgateway.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus.pushgateway.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.pushgateway.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "prometheus.pushgateway.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "prometheus.pushgateway.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.pushgateway.service.servicePort }} +{{- else if contains "ClusterIP" .Values.pushgateway.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "prometheus.name" . }},component={{ .Values.pushgateway.name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 9091 +{{- end }} +{{- end }} +{{- end }} + +For more information on running Prometheus, visit: +https://prometheus.io/ diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/_helpers.tpl b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/_helpers.tpl new file mode 100644 index 000000000..af4c3aefa --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/_helpers.tpl @@ -0,0 +1,288 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "prometheus.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "prometheus.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create unified labels for prometheus components +*/}} +{{- define "prometheus.common.matchLabels" -}} +app: {{ template "prometheus.name" . }} +release: {{ .Release.Name }} +{{ include "k8s-triliovault-operator.labels" . }} +{{- end -}} + +{{- define "prometheus.common.metaLabels" -}} +chart: {{ template "prometheus.chart" . }} +heritage: {{ .Release.Service }} +{{ include "k8s-triliovault-operator.labels" . }} +{{- end -}} + +{{- define "prometheus.alertmanager.labels" -}} +{{ include "prometheus.alertmanager.matchLabels" . }} +{{ include "prometheus.common.metaLabels" . }} +{{- end -}} + +{{- define "prometheus.alertmanager.matchLabels" -}} +component: {{ .Values.alertmanager.name | quote }} +app.kubernetes.io/instance: {{ .Values.alertmanager.name | quote }} +{{ include "prometheus.common.matchLabels" . }} +{{- end -}} + +{{- define "prometheus.nodeExporter.labels" -}} +{{ include "prometheus.nodeExporter.matchLabels" . }} +{{ include "prometheus.common.metaLabels" . }} +{{- end -}} + +{{- define "prometheus.nodeExporter.matchLabels" -}} +component: {{ .Values.nodeExporter.name | quote }} +app.kubernetes.io/instance: {{ .Values.nodeExporter.name | quote }} +{{ include "prometheus.common.matchLabels" . }} +{{- end -}} + +{{- define "prometheus.pushgateway.labels" -}} +{{ include "prometheus.pushgateway.matchLabels" . }} +{{ include "prometheus.common.metaLabels" . }} +{{- end -}} + +{{- define "prometheus.pushgateway.matchLabels" -}} +component: {{ .Values.pushgateway.name | quote }} +app.kubernetes.io/instance: {{ .Values.pushgateway.name | quote }} +{{ include "prometheus.common.matchLabels" . }} +{{- end -}} + +{{- define "prometheus.server.labels" -}} +{{ include "prometheus.server.matchLabels" . }} +{{ include "prometheus.common.metaLabels" . }} +{{- end -}} + +{{- define "prometheus.server.matchLabels" -}} +component: {{ .Values.server.name | quote }} +app.kubernetes.io/instance: {{ .Values.server.name | quote }} +{{ include "prometheus.common.matchLabels" . }} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "prometheus.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a fully qualified alertmanager name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} + +{{- define "prometheus.alertmanager.fullname" -}} +{{- if .Values.alertmanager.fullnameOverride -}} +{{- .Values.alertmanager.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-%s" .Release.Name .Values.alertmanager.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-%s" .Release.Name $name .Values.alertmanager.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a fully qualified node-exporter name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "prometheus.nodeExporter.fullname" -}} +{{- if .Values.nodeExporter.fullnameOverride -}} +{{- .Values.nodeExporter.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-%s" .Release.Name .Values.nodeExporter.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-%s" .Release.Name $name .Values.nodeExporter.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a fully qualified Prometheus server name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "prometheus.server.fullname" -}} +{{- if .Values.server.fullnameOverride -}} +{{- .Values.server.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-%s" .Release.Name .Values.server.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-%s" .Release.Name $name .Values.server.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a fully qualified pushgateway name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "prometheus.pushgateway.fullname" -}} +{{- if .Values.pushgateway.fullnameOverride -}} +{{- .Values.pushgateway.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- printf "%s-%s" .Release.Name .Values.pushgateway.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s-%s" .Release.Name $name .Values.pushgateway.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Get KubeVersion removing pre-release information. +*/}} +{{- define "prometheus.kubeVersion" -}} + {{- default .Capabilities.KubeVersion.Version (regexFind "v[0-9]+\\.[0-9]+\\.[0-9]+" .Capabilities.KubeVersion.Version) -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "prometheus.deployment.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} +{{/* +Return the appropriate apiVersion for daemonset. +*/}} +{{- define "prometheus.daemonset.apiVersion" -}} +{{- print "apps/v1" -}} +{{- end -}} +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "prometheus.networkPolicy.apiVersion" -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{/* +Return the appropriate apiVersion for podsecuritypolicy. +*/}} +{{- define "prometheus.podSecurityPolicy.apiVersion" -}} +{{- print "policy/v1beta1" -}} +{{- end -}} +{{/* +Return the appropriate apiVersion for rbac. +*/}} +{{- define "rbac.apiVersion" -}} +{{- if .Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1" }} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- else -}} +{{- print "rbac.authorization.k8s.io/v1beta1" -}} +{{- end -}} +{{- end -}} +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "ingress.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19.x" (include "prometheus.kubeVersion" .)) -}} + {{- print "networking.k8s.io/v1" -}} + {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} + {{- print "networking.k8s.io/v1beta1" -}} + {{- else -}} + {{- print "extensions/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return if ingress is stable. +*/}} +{{- define "ingress.isStable" -}} + {{- eq (include "ingress.apiVersion" .) "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return if ingress supports ingressClassName. +*/}} +{{- define "ingress.supportsIngressClassName" -}} + {{- or (eq (include "ingress.isStable" .) "true") (and (eq (include "ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18.x" (include "prometheus.kubeVersion" .))) -}} +{{- end -}} +{{/* +Return if ingress supports pathType. +*/}} +{{- define "ingress.supportsPathType" -}} + {{- or (eq (include "ingress.isStable" .) "true") (and (eq (include "ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18.x" (include "prometheus.kubeVersion" .))) -}} +{{- end -}} + +{{/* +Create the name of the service account to use for the alertmanager component +*/}} +{{- define "prometheus.serviceAccountName.alertmanager" -}} +{{- if .Values.serviceAccounts.alertmanager.create -}} + {{ default (include "prometheus.alertmanager.fullname" .) .Values.serviceAccounts.alertmanager.name }} +{{- else -}} + {{ default "default" .Values.serviceAccounts.alertmanager.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use for the nodeExporter component +*/}} +{{- define "prometheus.serviceAccountName.nodeExporter" -}} +{{- if .Values.serviceAccounts.nodeExporter.create -}} + {{ default (include "prometheus.nodeExporter.fullname" .) .Values.serviceAccounts.nodeExporter.name }} +{{- else -}} + {{ default "default" .Values.serviceAccounts.nodeExporter.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use for the pushgateway component +*/}} +{{- define "prometheus.serviceAccountName.pushgateway" -}} +{{- if .Values.serviceAccounts.pushgateway.create -}} + {{ default (include "prometheus.pushgateway.fullname" .) .Values.serviceAccounts.pushgateway.name }} +{{- else -}} + {{ default "default" .Values.serviceAccounts.pushgateway.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use for the server component +*/}} +{{- define "prometheus.serviceAccountName.server" -}} +{{- if .Values.serviceAccounts.server.create -}} + {{ default (include "prometheus.server.fullname" .) .Values.serviceAccounts.server.name }} +{{- else -}} + {{ default "default" .Values.serviceAccounts.server.name }} +{{- end -}} +{{- end -}} + +{{/* +Define the prometheus.namespace template if set with forceNamespace or .Release.Namespace is set +*/}} +{{- define "prometheus.namespace" -}} +{{- if .Values.forceNamespace -}} +{{ printf "namespace: %s" .Values.forceNamespace }} +{{- else -}} +{{ printf "namespace: %s" .Release.Namespace }} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/clusterrole.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/clusterrole.yaml new file mode 100644 index 000000000..c732ff4e5 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/clusterrole.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.alertmanager.enabled .Values.rbac.create .Values.alertmanager.useClusterRole (not .Values.alertmanager.useExistingRole) -}} +apiVersion: {{ template "rbac.apiVersion" . }} +kind: ClusterRole +metadata: + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" . }} +rules: +{{- if .Values.podSecurityPolicy.enabled }} + - apiGroups: + - extensions + resources: + - podsecuritypolicies + verbs: + - use + resourceNames: + - {{ template "prometheus.alertmanager.fullname" . }} +{{- else }} + [] +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/clusterrolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/clusterrolebinding.yaml new file mode 100644 index 000000000..6f13e98b5 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/clusterrolebinding.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.alertmanager.enabled .Values.rbac.create .Values.alertmanager.useClusterRole -}} +apiVersion: {{ template "rbac.apiVersion" . }} +kind: ClusterRoleBinding +metadata: + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName.alertmanager" . }} +{{ include "prometheus.namespace" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole +{{- if (not .Values.alertmanager.useExistingRole) }} + name: {{ template "prometheus.alertmanager.fullname" . }} +{{- else }} + name: {{ .Values.alertmanager.useExistingRole }} +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/cm.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/cm.yaml new file mode 100644 index 000000000..cb09bf067 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/cm.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.alertmanager.enabled (and (empty .Values.alertmanager.configMapOverrideName) (empty .Values.alertmanager.configFromSecret)) -}} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +data: +{{- $root := . -}} +{{- range $key, $value := .Values.alertmanagerFiles }} + {{- if $key | regexMatch ".*\\.ya?ml$" }} + {{ $key }}: | +{{ toYaml $value | default "{}" | indent 4 }} + {{- else }} + {{ $key }}: {{ toYaml $value | indent 4 }} + {{- end }} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/deploy.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/deploy.yaml new file mode 100644 index 000000000..86335698a --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/deploy.yaml @@ -0,0 +1,208 @@ +{{- if and .Values.alertmanager.enabled (not .Values.alertmanager.statefulSet.enabled) -}} +apiVersion: {{ template "prometheus.deployment.apiVersion" . }} +kind: Deployment +metadata: +{{- if .Values.alertmanager.deploymentAnnotations }} + annotations: + {{ toYaml .Values.alertmanager.deploymentAnnotations | nindent 4 }} +{{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: + selector: + matchLabels: + {{- include "prometheus.alertmanager.matchLabels" . | nindent 6 }} + replicas: {{ .Values.alertmanager.replicaCount }} + {{- if .Values.alertmanager.strategy }} + strategy: +{{ toYaml .Values.alertmanager.strategy | trim | indent 4 }} + {{ if eq .Values.alertmanager.strategy.type "Recreate" }}rollingUpdate: null{{ end }} +{{- end }} + template: + metadata: + {{- if .Values.alertmanager.podAnnotations }} + annotations: + {{ toYaml .Values.alertmanager.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 8 }} + {{- if .Values.alertmanager.podLabels}} + {{ toYaml .Values.alertmanager.podLabels | nindent 8 }} + {{- end}} + spec: +{{- if .Values.alertmanager.schedulerName }} + schedulerName: "{{ .Values.alertmanager.schedulerName }}" +{{- end }} + serviceAccountName: {{ template "prometheus.serviceAccountName.alertmanager" . }} + {{- if .Values.alertmanager.extraInitContainers }} + initContainers: +{{ toYaml .Values.alertmanager.extraInitContainers | indent 8 }} + {{- end }} +{{- if .Values.alertmanager.priorityClassName }} + priorityClassName: "{{ .Values.alertmanager.priorityClassName }}" +{{- end }} + containers: + - name: {{ template "prometheus.name" . }}-{{ .Values.alertmanager.name }} + image: "{{ .Values.alertmanager.image.repository }}:{{ .Values.alertmanager.image.tag }}" + imagePullPolicy: "{{ .Values.alertmanager.image.pullPolicy }}" + env: + {{- range $key, $value := .Values.alertmanager.extraEnv }} + - name: {{ $key }} + value: {{ $value }} + {{- end }} + - name: POD_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + args: + - --config.file=/etc/config/{{ .Values.alertmanager.configFileName }} + - --storage.path={{ .Values.alertmanager.persistentVolume.mountPath }} + {{- if .Values.alertmanager.service.enableMeshPeer }} + - --cluster.listen-address=0.0.0.0:6783 + - --cluster.advertise-address=[$(POD_IP)]:6783 + {{- else }} + - --cluster.listen-address= + {{- end }} + {{- range $key, $value := .Values.alertmanager.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- if .Values.alertmanager.baseURL }} + - --web.external-url={{ .Values.alertmanager.baseURL }} + {{- end }} + {{- range .Values.alertmanager.clusterPeers }} + - --cluster.peer={{ . }} + {{- end }} + + ports: + - containerPort: 9093 + readinessProbe: + httpGet: + path: {{ .Values.alertmanager.prefixURL }}/-/ready + port: 9093 + {{- if .Values.alertmanager.probeHeaders }} + httpHeaders: + {{- range .Values.alertmanager.probeHeaders }} + - name: {{ .name }} + value: {{ .value }} + {{- end }} + {{- end }} + initialDelaySeconds: 30 + timeoutSeconds: 30 + resources: +{{ toYaml .Values.alertmanager.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + - name: storage-volume + mountPath: "{{ .Values.alertmanager.persistentVolume.mountPath }}" + subPath: "{{ .Values.alertmanager.persistentVolume.subPath }}" + {{- range .Values.alertmanager.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.alertmanager.extraConfigmapMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + + {{- if .Values.configmapReload.alertmanager.enabled }} + - name: {{ template "prometheus.name" . }}-{{ .Values.alertmanager.name }}-{{ .Values.configmapReload.alertmanager.name }} + image: "{{ .Values.configmapReload.alertmanager.image.repository }}:{{ .Values.configmapReload.alertmanager.image.tag }}" + imagePullPolicy: "{{ .Values.configmapReload.alertmanager.image.pullPolicy }}" + args: + - --volume-dir=/etc/config + - --webhook-url=http://127.0.0.1:9093{{ .Values.alertmanager.prefixURL }}/-/reload + {{- range $key, $value := .Values.configmapReload.alertmanager.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- range .Values.configmapReload.alertmanager.extraVolumeDirs }} + - --volume-dir={{ . }} + {{- end }} + {{- if .Values.configmapReload.alertmanager.containerPort }} + ports: + - containerPort: {{ .Values.configmapReload.alertmanager.containerPort }} + {{- end }} + resources: +{{ toYaml .Values.configmapReload.alertmanager.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + {{- range .Values.configmapReload.alertmanager.extraConfigmapMounts }} + - name: {{ $.Values.configmapReload.alertmanager.name }}-{{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: +{{ toYaml .Values.imagePullSecrets | indent 8 }} + {{- end }} + {{- if .Values.alertmanager.nodeSelector }} + nodeSelector: +{{ toYaml .Values.alertmanager.nodeSelector | indent 8 }} + {{- end }} + {{- with .Values.alertmanager.dnsConfig }} + dnsConfig: +{{ toYaml . | indent 8 }} + {{- end }} + {{- if .Values.alertmanager.securityContext }} + securityContext: +{{ toYaml .Values.alertmanager.securityContext | indent 8 }} + {{- end }} + {{- if .Values.alertmanager.tolerations }} + tolerations: +{{ toYaml .Values.alertmanager.tolerations | indent 8 }} + {{- end }} + {{- if .Values.alertmanager.affinity }} + affinity: +{{ toYaml .Values.alertmanager.affinity | indent 8 }} + {{- end }} + volumes: + - name: config-volume + {{- if empty .Values.alertmanager.configFromSecret }} + configMap: + name: {{ if .Values.alertmanager.configMapOverrideName }}{{ .Release.Name }}-{{ .Values.alertmanager.configMapOverrideName }}{{- else }}{{ template "prometheus.alertmanager.fullname" . }}{{- end }} + {{- else }} + secret: + secretName: {{ .Values.alertmanager.configFromSecret }} + {{- end }} + {{- range .Values.alertmanager.extraSecretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + {{- with .optional }} + optional: {{ . }} + {{- end }} + {{- end }} + {{- range .Values.alertmanager.extraConfigmapMounts }} + - name: {{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + {{- range .Values.configmapReload.alertmanager.extraConfigmapMounts }} + - name: {{ $.Values.configmapReload.alertmanager.name }}-{{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + - name: storage-volume + {{- if .Values.alertmanager.persistentVolume.enabled }} + persistentVolumeClaim: + claimName: {{ if .Values.alertmanager.persistentVolume.existingClaim }}{{ .Values.alertmanager.persistentVolume.existingClaim }}{{- else }}{{ template "prometheus.alertmanager.fullname" . }}{{- end }} + {{- else }} + emptyDir: + {{- if .Values.alertmanager.emptyDir.sizeLimit }} + sizeLimit: {{ .Values.alertmanager.emptyDir.sizeLimit }} + {{- else }} + {} + {{- end -}} + {{- end -}} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/headless-svc.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/headless-svc.yaml new file mode 100644 index 000000000..8c402c408 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/headless-svc.yaml @@ -0,0 +1,31 @@ +{{- if and .Values.alertmanager.enabled .Values.alertmanager.statefulSet.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.alertmanager.statefulSet.headless.annotations }} + annotations: +{{ toYaml .Values.alertmanager.statefulSet.headless.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} +{{- if .Values.alertmanager.statefulSet.headless.labels }} +{{ toYaml .Values.alertmanager.statefulSet.headless.labels | indent 4 }} +{{- end }} + name: {{ template "prometheus.alertmanager.fullname" . }}-headless +{{ include "prometheus.namespace" . | indent 2 }} +spec: + clusterIP: None + ports: + - name: http + port: {{ .Values.alertmanager.statefulSet.headless.servicePort }} + protocol: TCP + targetPort: 9093 +{{- if .Values.alertmanager.statefulSet.headless.enableMeshPeer }} + - name: meshpeer + port: 6783 + protocol: TCP + targetPort: 6783 +{{- end }} + selector: + {{- include "prometheus.alertmanager.matchLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/ingress.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/ingress.yaml new file mode 100644 index 000000000..2a7b67c08 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/ingress.yaml @@ -0,0 +1,57 @@ +{{- if and .Values.alertmanager.enabled .Values.alertmanager.ingress.enabled -}} +{{- $ingressApiIsStable := eq (include "ingress.isStable" .) "true" -}} +{{- $ingressSupportsIngressClassName := eq (include "ingress.supportsIngressClassName" .) "true" -}} +{{- $ingressSupportsPathType := eq (include "ingress.supportsPathType" .) "true" -}} +{{- $releaseName := .Release.Name -}} +{{- $serviceName := include "prometheus.alertmanager.fullname" . }} +{{- $servicePort := .Values.alertmanager.service.servicePort -}} +{{- $ingressPath := .Values.alertmanager.ingress.path -}} +{{- $ingressPathType := .Values.alertmanager.ingress.pathType -}} +{{- $extraPaths := .Values.alertmanager.ingress.extraPaths -}} +apiVersion: {{ template "ingress.apiVersion" . }} +kind: Ingress +metadata: +{{- if .Values.alertmanager.ingress.annotations }} + annotations: +{{ toYaml .Values.alertmanager.ingress.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} +{{- range $key, $value := .Values.alertmanager.ingress.extraLabels }} + {{ $key }}: {{ $value }} +{{- end }} + name: {{ template "prometheus.alertmanager.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: + {{- if and $ingressSupportsIngressClassName .Values.alertmanager.ingress.ingressClassName }} + ingressClassName: {{ .Values.alertmanager.ingress.ingressClassName }} + {{- end }} + rules: + {{- range .Values.alertmanager.ingress.hosts }} + {{- $url := splitList "/" . }} + - host: {{ first $url }} + http: + paths: +{{ if $extraPaths }} +{{ toYaml $extraPaths | indent 10 }} +{{- end }} + - path: {{ $ingressPath }} + {{- if $ingressSupportsPathType }} + pathType: {{ $ingressPathType }} + {{- end }} + backend: + {{- if $ingressApiIsStable }} + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} +{{- if .Values.alertmanager.ingress.tls }} + tls: +{{ toYaml .Values.alertmanager.ingress.tls | indent 4 }} + {{- end -}} +{{- end -}} \ No newline at end of file diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/netpol.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/netpol.yaml new file mode 100644 index 000000000..e44ade60e --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/netpol.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.alertmanager.enabled .Values.networkPolicy.enabled -}} +apiVersion: {{ template "prometheus.networkPolicy.apiVersion" . }} +kind: NetworkPolicy +metadata: + name: {{ template "prometheus.alertmanager.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "prometheus.alertmanager.matchLabels" . | nindent 6 }} + ingress: + - from: + - podSelector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 12 }} + - ports: + - port: 9093 +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/pdb.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/pdb.yaml new file mode 100644 index 000000000..41a92f364 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/pdb.yaml @@ -0,0 +1,14 @@ +{{- if .Values.alertmanager.podDisruptionBudget.enabled }} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ template "prometheus.alertmanager.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} +spec: + maxUnavailable: {{ .Values.alertmanager.podDisruptionBudget.maxUnavailable }} + selector: + matchLabels: + {{- include "prometheus.alertmanager.labels" . | nindent 6 }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/psp.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/psp.yaml new file mode 100644 index 000000000..64fb13003 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/psp.yaml @@ -0,0 +1,46 @@ +{{- if and .Values.alertmanager.enabled .Values.rbac.create .Values.podSecurityPolicy.enabled }} +apiVersion: {{ template "prometheus.podSecurityPolicy.apiVersion" . }} +kind: PodSecurityPolicy +metadata: + name: {{ template "prometheus.alertmanager.fullname" . }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + annotations: +{{- if .Values.alertmanager.podSecurityPolicy.annotations }} +{{ toYaml .Values.alertmanager.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL + volumes: + - 'configMap' + - 'persistentVolumeClaim' + - 'emptyDir' + - 'secret' + allowedHostPaths: + - pathPrefix: /etc + readOnly: true + - pathPrefix: {{ .Values.alertmanager.persistentVolume.mountPath }} + hostNetwork: false + hostPID: false + hostIPC: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: true +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/pvc.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/pvc.yaml new file mode 100644 index 000000000..160e296a5 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/pvc.yaml @@ -0,0 +1,37 @@ +{{- if not .Values.alertmanager.statefulSet.enabled -}} +{{- if and .Values.alertmanager.enabled .Values.alertmanager.persistentVolume.enabled -}} +{{- if not .Values.alertmanager.persistentVolume.existingClaim -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + {{- if .Values.alertmanager.persistentVolume.annotations }} + annotations: +{{ toYaml .Values.alertmanager.persistentVolume.annotations | indent 4 }} + {{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: + accessModes: +{{ toYaml .Values.alertmanager.persistentVolume.accessModes | indent 4 }} +{{- if .Values.alertmanager.persistentVolume.storageClass }} +{{- if (eq "-" .Values.alertmanager.persistentVolume.storageClass) }} + storageClassName: "" +{{- else }} + storageClassName: "{{ .Values.alertmanager.persistentVolume.storageClass }}" +{{- end }} +{{- end }} +{{- if .Values.alertmanager.persistentVolume.volumeBindingMode }} + volumeBindingMode: "{{ .Values.alertmanager.persistentVolume.volumeBindingMode }}" +{{- end }} + resources: + requests: + storage: "{{ .Values.alertmanager.persistentVolume.size }}" +{{- if .Values.alertmanager.persistentVolume.selector }} + selector: + {{- toYaml .Values.alertmanager.persistentVolume.selector | nindent 4 }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/role.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/role.yaml new file mode 100644 index 000000000..ce60eaf0a --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/role.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.alertmanager.enabled .Values.rbac.create (eq .Values.alertmanager.useClusterRole false) (not .Values.alertmanager.useExistingRole) -}} +{{- range $.Values.alertmanager.namespaces }} +apiVersion: {{ template "rbac.apiVersion" . }} +kind: Role +metadata: + labels: + {{- include "prometheus.alertmanager.labels" $ | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" $ }} + namespace: {{ . }} +rules: +{{- if $.Values.podSecurityPolicy.enabled }} + - apiGroups: + - extensions + resources: + - podsecuritypolicies + verbs: + - use + resourceNames: + - {{ template "prometheus.alertmanager.fullname" $ }} +{{- else }} + [] +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/rolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/rolebinding.yaml new file mode 100644 index 000000000..906d6522d --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/rolebinding.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.alertmanager.enabled .Values.rbac.create (eq .Values.alertmanager.useClusterRole false) -}} +{{ range $.Values.alertmanager.namespaces }} +apiVersion: {{ template "rbac.apiVersion" . }} +kind: RoleBinding +metadata: + labels: + {{- include "prometheus.alertmanager.labels" $ | nindent 4 }} + name: {{ template "prometheus.alertmanager.fullname" $ }} + namespace: {{ . }} +subjects: + - kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName.alertmanager" $ }} +{{ include "prometheus.namespace" $ | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role +{{- if (not $.Values.alertmanager.useExistingRole) }} + name: {{ template "prometheus.alertmanager.fullname" $ }} +{{- else }} + name: {{ $.Values.alertmanager.useExistingRole }} +{{- end }} +{{- end }} +{{ end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/service.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/service.yaml new file mode 100644 index 000000000..9edc9ac65 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/service.yaml @@ -0,0 +1,53 @@ +{{- if .Values.alertmanager.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.alertmanager.service.annotations }} + annotations: +{{ toYaml .Values.alertmanager.service.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} +{{- if .Values.alertmanager.service.labels }} +{{ toYaml .Values.alertmanager.service.labels | indent 4 }} +{{- end }} + name: {{ template "prometheus.alertmanager.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: +{{- if .Values.alertmanager.service.clusterIP }} + clusterIP: {{ .Values.alertmanager.service.clusterIP }} +{{- end }} +{{- if .Values.alertmanager.service.externalIPs }} + externalIPs: +{{ toYaml .Values.alertmanager.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.alertmanager.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.alertmanager.service.loadBalancerIP }} +{{- end }} +{{- if .Values.alertmanager.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.alertmanager.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} + ports: + - name: http + port: {{ .Values.alertmanager.service.servicePort }} + protocol: TCP + targetPort: 9093 + {{- if .Values.alertmanager.service.nodePort }} + nodePort: {{ .Values.alertmanager.service.nodePort }} + {{- end }} +{{- if .Values.alertmanager.service.enableMeshPeer }} + - name: meshpeer + port: 6783 + protocol: TCP + targetPort: 6783 +{{- end }} + selector: + {{- include "prometheus.alertmanager.matchLabels" . | nindent 4 }} +{{- if .Values.alertmanager.service.sessionAffinity }} + sessionAffinity: {{ .Values.alertmanager.service.sessionAffinity }} +{{- end }} + type: "{{ .Values.alertmanager.service.type }}" +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/serviceaccount.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/serviceaccount.yaml new file mode 100644 index 000000000..a5d996a85 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.alertmanager.enabled .Values.serviceAccounts.alertmanager.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + name: {{ template "prometheus.serviceAccountName.alertmanager" . }} +{{ include "prometheus.namespace" . | indent 2 }} + annotations: +{{ toYaml .Values.serviceAccounts.alertmanager.annotations | indent 4 }} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/sts.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/sts.yaml new file mode 100644 index 000000000..1baef4b75 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/alertmanager/sts.yaml @@ -0,0 +1,188 @@ +{{- if and .Values.alertmanager.enabled .Values.alertmanager.statefulSet.enabled -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: +{{- if .Values.alertmanager.statefulSet.annotations }} + annotations: + {{ toYaml .Values.alertmanager.statefulSet.annotations | nindent 4 }} +{{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 4 }} + {{- if .Values.alertmanager.statefulSet.labels}} + {{ toYaml .Values.alertmanager.statefulSet.labels | nindent 4 }} + {{- end}} + name: {{ template "prometheus.alertmanager.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: + serviceName: {{ template "prometheus.alertmanager.fullname" . }}-headless + selector: + matchLabels: + {{- include "prometheus.alertmanager.matchLabels" . | nindent 6 }} + replicas: {{ .Values.alertmanager.replicaCount }} + podManagementPolicy: {{ .Values.alertmanager.statefulSet.podManagementPolicy }} + template: + metadata: + {{- if .Values.alertmanager.podAnnotations }} + annotations: + {{ toYaml .Values.alertmanager.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "prometheus.alertmanager.labels" . | nindent 8 }} + {{- if .Values.alertmanager.podLabels}} + {{ toYaml .Values.alertmanager.podLabels | nindent 8 }} + {{- end}} + spec: +{{- if .Values.alertmanager.affinity }} + affinity: +{{ toYaml .Values.alertmanager.affinity | indent 8 }} +{{- end }} +{{- if .Values.alertmanager.schedulerName }} + schedulerName: "{{ .Values.alertmanager.schedulerName }}" +{{- end }} + serviceAccountName: {{ template "prometheus.serviceAccountName.alertmanager" . }} +{{- if .Values.alertmanager.priorityClassName }} + priorityClassName: "{{ .Values.alertmanager.priorityClassName }}" +{{- end }} + containers: + - name: {{ template "prometheus.name" . }}-{{ .Values.alertmanager.name }} + image: "{{ .Values.alertmanager.image.repository }}:{{ .Values.alertmanager.image.tag }}" + imagePullPolicy: "{{ .Values.alertmanager.image.pullPolicy }}" + env: + {{- range $key, $value := .Values.alertmanager.extraEnv }} + - name: {{ $key }} + value: {{ $value }} + {{- end }} + - name: POD_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + args: + - --config.file=/etc/config/alertmanager.yml + - --storage.path={{ .Values.alertmanager.persistentVolume.mountPath }} + {{- if .Values.alertmanager.statefulSet.headless.enableMeshPeer }} + - --cluster.advertise-address=[$(POD_IP)]:6783 + - --cluster.listen-address=0.0.0.0:6783 + {{- range $n := until (.Values.alertmanager.replicaCount | int) }} + - --cluster.peer={{ template "prometheus.alertmanager.fullname" $ }}-{{ $n }}.{{ template "prometheus.alertmanager.fullname" $ }}-headless:6783 + {{- end }} + {{- else }} + - --cluster.listen-address= + {{- end }} + {{- range $key, $value := .Values.alertmanager.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- if .Values.alertmanager.baseURL }} + - --web.external-url={{ .Values.alertmanager.baseURL }} + {{- end }} + + ports: + - containerPort: 9093 + {{- if .Values.alertmanager.statefulSet.headless.enableMeshPeer }} + - containerPort: 6783 + {{- end }} + readinessProbe: + httpGet: + path: {{ .Values.alertmanager.prefixURL }}/#/status + port: 9093 + initialDelaySeconds: 30 + timeoutSeconds: 30 + resources: +{{ toYaml .Values.alertmanager.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + - name: storage-volume + mountPath: "{{ .Values.alertmanager.persistentVolume.mountPath }}" + subPath: "{{ .Values.alertmanager.persistentVolume.subPath }}" + {{- range .Values.alertmanager.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- if .Values.configmapReload.alertmanager.enabled }} + - name: {{ template "prometheus.name" . }}-{{ .Values.alertmanager.name }}-{{ .Values.configmapReload.alertmanager.name }} + image: "{{ .Values.configmapReload.alertmanager.image.repository }}:{{ .Values.configmapReload.alertmanager.image.tag }}" + imagePullPolicy: "{{ .Values.configmapReload.alertmanager.image.pullPolicy }}" + args: + - --volume-dir=/etc/config + - --webhook-url=http://localhost:9093{{ .Values.alertmanager.prefixURL }}/-/reload + {{- range $key, $value := .Values.configmapReload.alertmanager.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- if .Values.configmapReload.alertmanager.port }} + ports: + - containerPort: {{ .Values.configmapReload.alertmanager.port }} + {{- end }} + resources: +{{ toYaml .Values.configmapReload.alertmanager.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: +{{ toYaml .Values.imagePullSecrets | indent 8 }} + {{- end }} + {{- if .Values.alertmanager.nodeSelector }} + nodeSelector: +{{ toYaml .Values.alertmanager.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.alertmanager.securityContext }} + securityContext: +{{ toYaml .Values.alertmanager.securityContext | indent 8 }} + {{- end }} + {{- if .Values.alertmanager.tolerations }} + tolerations: +{{ toYaml .Values.alertmanager.tolerations | indent 8 }} + {{- end }} + volumes: + - name: config-volume + {{- if empty .Values.alertmanager.configFromSecret }} + configMap: + name: {{ if .Values.alertmanager.configMapOverrideName }}{{ .Release.Name }}-{{ .Values.alertmanager.configMapOverrideName }}{{- else }}{{ template "prometheus.alertmanager.fullname" . }}{{- end }} + {{- else }} + secret: + secretName: {{ .Values.alertmanager.configFromSecret }} + {{- end }} + {{- range .Values.alertmanager.extraSecretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + {{- with .optional }} + optional: {{ . }} + {{- end }} + {{- end }} +{{- if .Values.alertmanager.persistentVolume.enabled }} + volumeClaimTemplates: + - metadata: + name: storage-volume + {{- if .Values.alertmanager.persistentVolume.annotations }} + annotations: +{{ toYaml .Values.alertmanager.persistentVolume.annotations | indent 10 }} + {{- end }} + spec: + accessModes: +{{ toYaml .Values.alertmanager.persistentVolume.accessModes | indent 10 }} + resources: + requests: + storage: "{{ .Values.alertmanager.persistentVolume.size }}" + {{- if .Values.server.persistentVolume.storageClass }} + {{- if (eq "-" .Values.server.persistentVolume.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.alertmanager.persistentVolume.storageClass }}" + {{- end }} + {{- end }} +{{- else }} + - name: storage-volume + emptyDir: + {{- if .Values.alertmanager.emptyDir.sizeLimit }} + sizeLimit: {{ .Values.alertmanager.emptyDir.sizeLimit }} + {{- else }} + {} + {{- end -}} +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/daemonset.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/daemonset.yaml new file mode 100644 index 000000000..d1d5cf064 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/daemonset.yaml @@ -0,0 +1,150 @@ +{{- if .Values.nodeExporter.enabled -}} +apiVersion: {{ template "prometheus.daemonset.apiVersion" . }} +kind: DaemonSet +metadata: +{{- if .Values.nodeExporter.deploymentAnnotations }} + annotations: +{{ toYaml .Values.nodeExporter.deploymentAnnotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 4 }} + name: {{ template "prometheus.nodeExporter.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: + selector: + matchLabels: + {{- include "prometheus.nodeExporter.matchLabels" . | nindent 6 }} + {{- if .Values.nodeExporter.updateStrategy }} + updateStrategy: +{{ toYaml .Values.nodeExporter.updateStrategy | indent 4 }} + {{- end }} + template: + metadata: + {{- if .Values.nodeExporter.podAnnotations }} + annotations: +{{ toYaml .Values.nodeExporter.podAnnotations | indent 8 }} + {{- end }} + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 8 }} +{{- if .Values.nodeExporter.pod.labels }} +{{ toYaml .Values.nodeExporter.pod.labels | indent 8 }} +{{- end }} + spec: + serviceAccountName: {{ template "prometheus.serviceAccountName.nodeExporter" . }} + {{- if .Values.nodeExporter.extraInitContainers }} + initContainers: +{{ toYaml .Values.nodeExporter.extraInitContainers | indent 8 }} + {{- end }} +{{- if .Values.nodeExporter.priorityClassName }} + priorityClassName: "{{ .Values.nodeExporter.priorityClassName }}" +{{- end }} + containers: + - name: {{ template "prometheus.name" . }}-{{ .Values.nodeExporter.name }} + image: "{{ .Values.nodeExporter.image.repository }}:{{ .Values.nodeExporter.image.tag }}" + imagePullPolicy: "{{ .Values.nodeExporter.image.pullPolicy }}" + args: + - --path.procfs=/host/proc + - --path.sysfs=/host/sys + {{- if .Values.nodeExporter.hostRootfs }} + - --path.rootfs=/host/root + {{- end }} + {{- if .Values.nodeExporter.hostNetwork }} + - --web.listen-address=:{{ .Values.nodeExporter.service.hostPort }} + {{- end }} + {{- range $key, $value := .Values.nodeExporter.extraArgs }} + {{- if $value }} + - --{{ $key }}={{ $value }} + {{- else }} + - --{{ $key }} + {{- end }} + {{- end }} + ports: + - name: metrics + {{- if .Values.nodeExporter.hostNetwork }} + containerPort: {{ .Values.nodeExporter.service.hostPort }} + {{- else }} + containerPort: 9100 + {{- end }} + hostPort: {{ .Values.nodeExporter.service.hostPort }} + resources: +{{ toYaml .Values.nodeExporter.resources | indent 12 }} + {{- if .Values.nodeExporter.container.securityContext }} + securityContext: +{{ toYaml .Values.nodeExporter.container.securityContext | indent 12 }} + {{- end }} + volumeMounts: + - name: proc + mountPath: /host/proc + readOnly: true + - name: sys + mountPath: /host/sys + readOnly: true + {{- if .Values.nodeExporter.hostRootfs }} + - name: root + mountPath: /host/root + mountPropagation: HostToContainer + readOnly: true + {{- end }} + {{- range .Values.nodeExporter.extraHostPathMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- if .mountPropagation }} + mountPropagation: {{ .mountPropagation }} + {{- end }} + {{- end }} + {{- range .Values.nodeExporter.extraConfigmapMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: +{{ toYaml .Values.imagePullSecrets | indent 8 }} + {{- end }} + {{- if .Values.nodeExporter.hostNetwork }} + hostNetwork: true + {{- end }} + {{- if .Values.nodeExporter.hostPID }} + hostPID: true + {{- end }} + {{- if .Values.nodeExporter.tolerations }} + tolerations: +{{ toYaml .Values.nodeExporter.tolerations | indent 8 }} + {{- end }} + {{- if .Values.nodeExporter.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeExporter.nodeSelector | indent 8 }} + {{- end }} + {{- with .Values.nodeExporter.dnsConfig }} + dnsConfig: +{{ toYaml . | indent 8 }} + {{- end }} + {{- if .Values.nodeExporter.securityContext }} + securityContext: +{{ toYaml .Values.nodeExporter.securityContext | indent 8 }} + {{- end }} + volumes: + - name: proc + hostPath: + path: /proc + - name: sys + hostPath: + path: /sys + {{- if .Values.nodeExporter.hostRootfs }} + - name: root + hostPath: + path: / + {{- end }} + {{- range .Values.nodeExporter.extraHostPathMounts }} + - name: {{ .name }} + hostPath: + path: {{ .hostPath }} + {{- end }} + {{- range .Values.nodeExporter.extraConfigmapMounts }} + - name: {{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/psp.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/psp.yaml new file mode 100644 index 000000000..bd9c73bee --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/psp.yaml @@ -0,0 +1,55 @@ +{{- if and .Values.nodeExporter.enabled .Values.rbac.create .Values.podSecurityPolicy.enabled }} +apiVersion: {{ template "prometheus.podSecurityPolicy.apiVersion" . }} +kind: PodSecurityPolicy +metadata: + name: {{ template "prometheus.nodeExporter.fullname" . }} + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 4 }} + annotations: +{{- if .Values.nodeExporter.podSecurityPolicy.annotations }} +{{ toYaml .Values.nodeExporter.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL + volumes: + - 'configMap' + - 'hostPath' + - 'secret' + allowedHostPaths: + - pathPrefix: /proc + readOnly: true + - pathPrefix: /sys + readOnly: true + - pathPrefix: / + readOnly: true + {{- range .Values.nodeExporter.extraHostPathMounts }} + - pathPrefix: {{ .hostPath }} + readOnly: {{ .readOnly }} + {{- end }} + hostNetwork: {{ .Values.nodeExporter.hostNetwork }} + hostPID: {{ .Values.nodeExporter.hostPID }} + hostIPC: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: false + hostPorts: + - min: 1 + max: 65535 +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/role.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/role.yaml new file mode 100644 index 000000000..d8ef3ed90 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/role.yaml @@ -0,0 +1,17 @@ +{{- if and .Values.nodeExporter.enabled .Values.rbac.create }} +{{- if or (default .Values.nodeExporter.podSecurityPolicy.enabled false) (.Values.podSecurityPolicy.enabled) }} +apiVersion: {{ template "rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ template "prometheus.nodeExporter.fullname" . }} + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 4 }} +{{ include "prometheus.namespace" . | indent 2 }} +rules: +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: + - {{ template "prometheus.nodeExporter.fullname" . }} +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/rolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/rolebinding.yaml new file mode 100644 index 000000000..06914b70a --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/rolebinding.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.nodeExporter.enabled .Values.rbac.create }} +{{- if .Values.podSecurityPolicy.enabled }} +apiVersion: {{ template "rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ template "prometheus.nodeExporter.fullname" . }} + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 4 }} +{{ include "prometheus.namespace" . | indent 2 }} +roleRef: + kind: Role + name: {{ template "prometheus.nodeExporter.fullname" . }} + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName.nodeExporter" . }} +{{ include "prometheus.namespace" . | indent 2 }} +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/serviceaccount.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/serviceaccount.yaml new file mode 100644 index 000000000..0cf91afba --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.nodeExporter.enabled .Values.serviceAccounts.nodeExporter.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 4 }} + name: {{ template "prometheus.serviceAccountName.nodeExporter" . }} +{{ include "prometheus.namespace" . | indent 2 }} + annotations: +{{ toYaml .Values.serviceAccounts.nodeExporter.annotations | indent 4 }} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/svc.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/svc.yaml new file mode 100644 index 000000000..26d1eaa21 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/node-exporter/svc.yaml @@ -0,0 +1,47 @@ +{{- if .Values.nodeExporter.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.nodeExporter.service.annotations }} + annotations: +{{ toYaml .Values.nodeExporter.service.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.nodeExporter.labels" . | nindent 4 }} +{{- if .Values.nodeExporter.service.labels }} +{{ toYaml .Values.nodeExporter.service.labels | indent 4 }} +{{- end }} + name: {{ template "prometheus.nodeExporter.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: +{{- if .Values.nodeExporter.service.clusterIP }} + clusterIP: {{ .Values.nodeExporter.service.clusterIP }} +{{- end }} +{{- if .Values.nodeExporter.service.externalIPs }} + externalIPs: +{{ toYaml .Values.nodeExporter.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.nodeExporter.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.nodeExporter.service.loadBalancerIP }} +{{- end }} +{{- if .Values.nodeExporter.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.nodeExporter.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} + ports: + - name: metrics + {{- if .Values.nodeExporter.hostNetwork }} + port: {{ .Values.nodeExporter.service.hostPort }} + protocol: TCP + targetPort: {{ .Values.nodeExporter.service.hostPort }} + {{- else }} + port: {{ .Values.nodeExporter.service.servicePort }} + protocol: TCP + targetPort: 9100 + {{- end }} + selector: + {{- include "prometheus.nodeExporter.matchLabels" . | nindent 4 }} + type: "{{ .Values.nodeExporter.service.type }}" +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/clusterrole.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/clusterrole.yaml new file mode 100644 index 000000000..76ecf053f --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/clusterrole.yaml @@ -0,0 +1,21 @@ +{{- if and .Values.pushgateway.enabled .Values.rbac.create -}} +apiVersion: {{ template "rbac.apiVersion" . }} +kind: ClusterRole +metadata: + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.pushgateway.fullname" . }} +rules: +{{- if .Values.podSecurityPolicy.enabled }} + - apiGroups: + - extensions + resources: + - podsecuritypolicies + verbs: + - use + resourceNames: + - {{ template "prometheus.pushgateway.fullname" . }} +{{- else }} + [] +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/clusterrolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/clusterrolebinding.yaml new file mode 100644 index 000000000..15770ee50 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.pushgateway.enabled .Values.rbac.create -}} +apiVersion: {{ template "rbac.apiVersion" . }} +kind: ClusterRoleBinding +metadata: + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.pushgateway.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName.pushgateway" . }} +{{ include "prometheus.namespace" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "prometheus.pushgateway.fullname" . }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/deploy.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/deploy.yaml new file mode 100644 index 000000000..ffdbfcc42 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/deploy.yaml @@ -0,0 +1,119 @@ +{{- if .Values.pushgateway.enabled -}} +apiVersion: {{ template "prometheus.deployment.apiVersion" . }} +kind: Deployment +metadata: +{{- if .Values.pushgateway.deploymentAnnotations }} + annotations: + {{ toYaml .Values.pushgateway.deploymentAnnotations | nindent 4 }} +{{- end }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.pushgateway.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: + selector: + {{- if .Values.schedulerName }} + schedulerName: "{{ .Values.schedulerName }}" + {{- end }} + matchLabels: + {{- include "prometheus.pushgateway.matchLabels" . | nindent 6 }} + replicas: {{ .Values.pushgateway.replicaCount }} + {{- if .Values.pushgateway.strategy }} + strategy: +{{ toYaml .Values.pushgateway.strategy | trim | indent 4 }} + {{ if eq .Values.pushgateway.strategy.type "Recreate" }}rollingUpdate: null{{ end }} +{{- end }} + template: + metadata: + {{- if .Values.pushgateway.podAnnotations }} + annotations: + {{ toYaml .Values.pushgateway.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 8 }} + {{- if .Values.pushgateway.podLabels }} + {{ toYaml .Values.pushgateway.podLabels | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ template "prometheus.serviceAccountName.pushgateway" . }} + {{- if .Values.pushgateway.extraInitContainers }} + initContainers: +{{ toYaml .Values.pushgateway.extraInitContainers | indent 8 }} + {{- end }} +{{- if .Values.pushgateway.priorityClassName }} + priorityClassName: "{{ .Values.pushgateway.priorityClassName }}" +{{- end }} + containers: + - name: {{ template "prometheus.name" . }}-{{ .Values.pushgateway.name }} + image: "{{ .Values.pushgateway.image.repository }}:{{ .Values.pushgateway.image.tag }}" + imagePullPolicy: "{{ .Values.pushgateway.image.pullPolicy }}" + args: + {{- range $key, $value := .Values.pushgateway.extraArgs }} + {{- $stringvalue := toString $value }} + {{- if eq $stringvalue "true" }} + - --{{ $key }} + {{- else }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- end }} + ports: + - containerPort: 9091 + livenessProbe: + httpGet: + {{- if (index .Values "pushgateway" "extraArgs" "web.route-prefix") }} + path: /{{ index .Values "pushgateway" "extraArgs" "web.route-prefix" }}/-/healthy + {{- else }} + path: /-/healthy + {{- end }} + port: 9091 + initialDelaySeconds: 10 + timeoutSeconds: 10 + readinessProbe: + httpGet: + {{- if (index .Values "pushgateway" "extraArgs" "web.route-prefix") }} + path: /{{ index .Values "pushgateway" "extraArgs" "web.route-prefix" }}/-/ready + {{- else }} + path: /-/ready + {{- end }} + port: 9091 + initialDelaySeconds: 10 + timeoutSeconds: 10 + resources: +{{ toYaml .Values.pushgateway.resources | indent 12 }} + {{- if .Values.pushgateway.persistentVolume.enabled }} + volumeMounts: + - name: storage-volume + mountPath: "{{ .Values.pushgateway.persistentVolume.mountPath }}" + subPath: "{{ .Values.pushgateway.persistentVolume.subPath }}" + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: +{{ toYaml .Values.imagePullSecrets | indent 8 }} + {{- end }} + {{- if .Values.pushgateway.nodeSelector }} + nodeSelector: +{{ toYaml .Values.pushgateway.nodeSelector | indent 8 }} + {{- end }} + {{- with .Values.pushgateway.dnsConfig }} + dnsConfig: +{{ toYaml . | indent 8 }} + {{- end }} + {{- if .Values.pushgateway.securityContext }} + securityContext: +{{ toYaml .Values.pushgateway.securityContext | indent 8 }} + {{- end }} + {{- if .Values.pushgateway.tolerations }} + tolerations: +{{ toYaml .Values.pushgateway.tolerations | indent 8 }} + {{- end }} + {{- if .Values.pushgateway.affinity }} + affinity: +{{ toYaml .Values.pushgateway.affinity | indent 8 }} + {{- end }} + {{- if .Values.pushgateway.persistentVolume.enabled }} + volumes: + - name: storage-volume + persistentVolumeClaim: + claimName: {{ if .Values.pushgateway.persistentVolume.existingClaim }}{{ .Values.pushgateway.persistentVolume.existingClaim }}{{- else }}{{ template "prometheus.pushgateway.fullname" . }}{{- end }} + {{- end -}} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/ingress.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/ingress.yaml new file mode 100644 index 000000000..2ff72abd5 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/ingress.yaml @@ -0,0 +1,54 @@ +{{- if and .Values.pushgateway.enabled .Values.pushgateway.ingress.enabled -}} +{{- $ingressApiIsStable := eq (include "ingress.isStable" .) "true" -}} +{{- $ingressSupportsIngressClassName := eq (include "ingress.supportsIngressClassName" .) "true" -}} +{{- $ingressSupportsPathType := eq (include "ingress.supportsPathType" .) "true" -}} +{{- $releaseName := .Release.Name -}} +{{- $serviceName := include "prometheus.pushgateway.fullname" . }} +{{- $servicePort := .Values.pushgateway.service.servicePort -}} +{{- $ingressPath := .Values.pushgateway.ingress.path -}} +{{- $ingressPathType := .Values.pushgateway.ingress.pathType -}} +{{- $extraPaths := .Values.pushgateway.ingress.extraPaths -}} +apiVersion: {{ template "ingress.apiVersion" . }} +kind: Ingress +metadata: +{{- if .Values.pushgateway.ingress.annotations }} + annotations: +{{ toYaml .Values.pushgateway.ingress.annotations | indent 4}} +{{- end }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.pushgateway.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: + {{- if and $ingressSupportsIngressClassName .Values.pushgateway.ingress.ingressClassName }} + ingressClassName: {{ .Values.pushgateway.ingress.ingressClassName }} + {{- end }} + rules: + {{- range .Values.pushgateway.ingress.hosts }} + {{- $url := splitList "/" . }} + - host: {{ first $url }} + http: + paths: +{{ if $extraPaths }} +{{ toYaml $extraPaths | indent 10 }} +{{- end }} + - path: {{ $ingressPath }} + {{- if $ingressSupportsPathType }} + pathType: {{ $ingressPathType }} + {{- end }} + backend: + {{- if $ingressApiIsStable }} + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} +{{- if .Values.pushgateway.ingress.tls }} + tls: +{{ toYaml .Values.pushgateway.ingress.tls | indent 4 }} + {{- end -}} +{{- end -}} \ No newline at end of file diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/netpol.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/netpol.yaml new file mode 100644 index 000000000..c8d1fb37e --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/netpol.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.pushgateway.enabled .Values.networkPolicy.enabled -}} +apiVersion: {{ template "prometheus.networkPolicy.apiVersion" . }} +kind: NetworkPolicy +metadata: + name: {{ template "prometheus.pushgateway.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "prometheus.pushgateway.matchLabels" . | nindent 6 }} + ingress: + - from: + - podSelector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 12 }} + - ports: + - port: 9091 +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/pdb.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/pdb.yaml new file mode 100644 index 000000000..50beb486d --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/pdb.yaml @@ -0,0 +1,14 @@ +{{- if .Values.pushgateway.podDisruptionBudget.enabled }} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ template "prometheus.pushgateway.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} +spec: + maxUnavailable: {{ .Values.pushgateway.podDisruptionBudget.maxUnavailable }} + selector: + matchLabels: + {{- include "prometheus.pushgateway.labels" . | nindent 6 }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/psp.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/psp.yaml new file mode 100644 index 000000000..1ca3267f8 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/psp.yaml @@ -0,0 +1,42 @@ +{{- if and .Values.pushgateway.enabled .Values.rbac.create .Values.podSecurityPolicy.enabled }} +apiVersion: {{ template "prometheus.podSecurityPolicy.apiVersion" . }} +kind: PodSecurityPolicy +metadata: + name: {{ template "prometheus.pushgateway.fullname" . }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + annotations: +{{- if .Values.pushgateway.podSecurityPolicy.annotations }} +{{ toYaml .Values.pushgateway.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + - ALL + volumes: + - 'persistentVolumeClaim' + - 'secret' + allowedHostPaths: + - pathPrefix: {{ .Values.pushgateway.persistentVolume.mountPath }} + hostNetwork: false + hostPID: false + hostIPC: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: true +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/pvc.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/pvc.yaml new file mode 100644 index 000000000..d5d64ddcc --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/pvc.yaml @@ -0,0 +1,31 @@ +{{- if .Values.pushgateway.persistentVolume.enabled -}} +{{- if not .Values.pushgateway.persistentVolume.existingClaim -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + {{- if .Values.pushgateway.persistentVolume.annotations }} + annotations: +{{ toYaml .Values.pushgateway.persistentVolume.annotations | indent 4 }} + {{- end }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.pushgateway.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: + accessModes: +{{ toYaml .Values.pushgateway.persistentVolume.accessModes | indent 4 }} +{{- if .Values.pushgateway.persistentVolume.storageClass }} +{{- if (eq "-" .Values.pushgateway.persistentVolume.storageClass) }} + storageClassName: "" +{{- else }} + storageClassName: "{{ .Values.pushgateway.persistentVolume.storageClass }}" +{{- end }} +{{- end }} +{{- if .Values.pushgateway.persistentVolume.volumeBindingMode }} + volumeBindingMode: "{{ .Values.pushgateway.persistentVolume.volumeBindingMode }}" +{{- end }} + resources: + requests: + storage: "{{ .Values.pushgateway.persistentVolume.size }}" +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/service.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/service.yaml new file mode 100644 index 000000000..f05f17c42 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/service.yaml @@ -0,0 +1,41 @@ +{{- if .Values.pushgateway.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.pushgateway.service.annotations }} + annotations: +{{ toYaml .Values.pushgateway.service.annotations | indent 4}} +{{- end }} + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} +{{- if .Values.pushgateway.service.labels }} +{{ toYaml .Values.pushgateway.service.labels | indent 4}} +{{- end }} + name: {{ template "prometheus.pushgateway.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: +{{- if .Values.pushgateway.service.clusterIP }} + clusterIP: {{ .Values.pushgateway.service.clusterIP }} +{{- end }} +{{- if .Values.pushgateway.service.externalIPs }} + externalIPs: +{{ toYaml .Values.pushgateway.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.pushgateway.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.pushgateway.service.loadBalancerIP }} +{{- end }} +{{- if .Values.pushgateway.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.pushgateway.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} + ports: + - name: http + port: {{ .Values.pushgateway.service.servicePort }} + protocol: TCP + targetPort: 9091 + selector: + {{- include "prometheus.pushgateway.matchLabels" . | nindent 4 }} + type: "{{ .Values.pushgateway.service.type }}" +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/serviceaccount.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/serviceaccount.yaml new file mode 100644 index 000000000..8c0b876f3 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/serviceaccount.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.pushgateway.enabled .Values.serviceAccounts.pushgateway.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.serviceAccountName.pushgateway" . }} +{{ include "prometheus.namespace" . | indent 2 }} + annotations: +{{ toYaml .Values.serviceAccounts.pushgateway.annotations | indent 4 }} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/vpa.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/vpa.yaml new file mode 100644 index 000000000..0ac54f9fe --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/pushgateway/vpa.yaml @@ -0,0 +1,20 @@ +{{- if .Values.pushgateway.enabled -}} +{{- if .Values.pushgateway.verticalAutoscaler.enabled -}} +apiVersion: autoscaling.k8s.io/v1beta2 +kind: VerticalPodAutoscaler +metadata: + labels: + {{- include "prometheus.pushgateway.labels" . | nindent 4 }} + name: {{ template "prometheus.pushgateway.fullname" . }}-vpa +{{ include "prometheus.namespace" . | indent 2 }} +spec: + targetRef: + apiVersion: "apps/v1" + kind: Deployment + name: {{ template "prometheus.pushgateway.fullname" . }} + updatePolicy: + updateMode: {{ .Values.pushgateway.verticalAutoscaler.updateMode | default "Off" | quote }} + resourcePolicy: + containerPolicies: {{ .Values.pushgateway.verticalAutoscaler.containerPolicies | default list | toYaml | trim | nindent 4 }} +{{- end -}} {{/* if .Values.pushgateway.verticalAutoscaler.enabled */}} +{{- end -}} {{/* .Values.pushgateway.enabled */}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/clusterrole.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/clusterrole.yaml new file mode 100644 index 000000000..2520235ab --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/clusterrole.yaml @@ -0,0 +1,48 @@ +{{- if and .Values.server.enabled .Values.rbac.create (empty .Values.server.useExistingClusterRoleName) -}} +apiVersion: {{ template "rbac.apiVersion" . }} +kind: ClusterRole +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.server.fullname" . }} +rules: +{{- if .Values.podSecurityPolicy.enabled }} + - apiGroups: + - extensions + resources: + - podsecuritypolicies + verbs: + - use + resourceNames: + - {{ template "prometheus.server.fullname" . }} +{{- end }} + - apiGroups: + - "" + resources: + - nodes + - nodes/proxy + - nodes/metrics + - services + - endpoints + - pods + - ingresses + - configmaps + verbs: + - get + - list + - watch + - apiGroups: + - "extensions" + - "networking.k8s.io" + resources: + - ingresses/status + - ingresses + verbs: + - get + - list + - watch + - nonResourceURLs: + - "/metrics" + verbs: + - get +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/clusterrolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/clusterrolebinding.yaml new file mode 100644 index 000000000..5a79611ff --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/clusterrolebinding.yaml @@ -0,0 +1,16 @@ +{{- if and .Values.server.enabled .Values.rbac.create (empty .Values.server.namespaces) (empty .Values.server.useExistingClusterRoleName) -}} +apiVersion: {{ template "rbac.apiVersion" . }} +kind: ClusterRoleBinding +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.server.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName.server" . }} +{{ include "prometheus.namespace" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "prometheus.server.fullname" . }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/cm.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/cm.yaml new file mode 100644 index 000000000..a0a813ae2 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/cm.yaml @@ -0,0 +1,85 @@ +{{- if .Values.server.enabled -}} +{{- if (empty .Values.server.configMapOverrideName) -}} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.server.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +data: +{{- $root := . -}} +{{- range $key, $value := .Values.ruleFiles }} + {{ $key }}: {{- toYaml $value | indent 2 }} +{{- end }} +{{- range $key, $value := .Values.serverFiles }} + {{ $key }}: | +{{- if eq $key "prometheus.yml" }} + global: +{{ $root.Values.server.global | toYaml | trimSuffix "\n" | indent 6 }} +{{- if $root.Values.server.remoteWrite }} + remote_write: +{{ $root.Values.server.remoteWrite | toYaml | indent 4 }} +{{- end }} +{{- if $root.Values.server.remoteRead }} + remote_read: +{{ $root.Values.server.remoteRead | toYaml | indent 4 }} +{{- end }} +{{- end }} +{{- if eq $key "alerts" }} +{{- if and (not (empty $value)) (empty $value.groups) }} + groups: +{{- range $ruleKey, $ruleValue := $value }} + - name: {{ $ruleKey -}}.rules + rules: +{{ $ruleValue | toYaml | trimSuffix "\n" | indent 6 }} +{{- end }} +{{- else }} +{{ toYaml $value | indent 4 }} +{{- end }} +{{- else }} +{{ toYaml $value | default "{}" | indent 4 }} +{{- end }} +{{- if eq $key "prometheus.yml" -}} +{{- if $root.Values.extraScrapeConfigs }} +{{ tpl $root.Values.extraScrapeConfigs $root | indent 4 }} +{{- end -}} +{{- if or ($root.Values.alertmanager.enabled) ($root.Values.server.alertmanagers) }} + alerting: +{{- if $root.Values.alertRelabelConfigs }} +{{ $root.Values.alertRelabelConfigs | toYaml | trimSuffix "\n" | indent 6 }} +{{- end }} + alertmanagers: +{{- if $root.Values.server.alertmanagers }} +{{ toYaml $root.Values.server.alertmanagers | indent 8 }} +{{- else }} + - kubernetes_sd_configs: + - role: pod + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + {{- if $root.Values.alertmanager.prefixURL }} + path_prefix: {{ $root.Values.alertmanager.prefixURL }} + {{- end }} + relabel_configs: + - source_labels: [__meta_kubernetes_namespace] + regex: {{ $root.Release.Namespace }} + action: keep + - source_labels: [__meta_kubernetes_pod_label_app] + regex: {{ template "prometheus.name" $root }} + action: keep + - source_labels: [__meta_kubernetes_pod_label_component] + regex: alertmanager + action: keep + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_probe] + regex: {{ index $root.Values.alertmanager.podAnnotations "prometheus.io/probe" | default ".*" }} + action: keep + - source_labels: [__meta_kubernetes_pod_container_port_number] + regex: "9093" + action: keep +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/deploy.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/deploy.yaml new file mode 100644 index 000000000..eb86e90ab --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/deploy.yaml @@ -0,0 +1,324 @@ +{{- if .Values.server.enabled -}} +{{- if not .Values.server.statefulSet.enabled -}} +apiVersion: {{ template "prometheus.deployment.apiVersion" . }} +kind: Deployment +metadata: +{{- if .Values.server.deploymentAnnotations }} + annotations: + {{ toYaml .Values.server.deploymentAnnotations | nindent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.server.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: + selector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 6 }} + replicas: {{ .Values.server.replicaCount }} + {{- if .Values.server.strategy }} + strategy: +{{ toYaml .Values.server.strategy | trim | indent 4 }} + {{ if eq .Values.server.strategy.type "Recreate" }}rollingUpdate: null{{ end }} +{{- end }} + template: + metadata: + {{- if .Values.server.podAnnotations }} + annotations: + {{ toYaml .Values.server.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 8 }} + {{- if .Values.server.podLabels}} + {{ toYaml .Values.server.podLabels | nindent 8 }} + {{- end}} + spec: +{{- if .Values.server.priorityClassName }} + priorityClassName: "{{ .Values.server.priorityClassName }}" +{{- end }} +{{- if .Values.server.schedulerName }} + schedulerName: "{{ .Values.server.schedulerName }}" +{{- end }} +{{- if semverCompare ">=1.13-0" .Capabilities.KubeVersion.GitVersion }} + {{- if or (.Values.server.enableServiceLinks) (eq (.Values.server.enableServiceLinks | toString) "") }} + enableServiceLinks: true + {{- else }} + enableServiceLinks: false + {{- end }} +{{- end }} + serviceAccountName: {{ template "prometheus.serviceAccountName.server" . }} + {{- if .Values.server.extraInitContainers }} + initContainers: +{{ toYaml .Values.server.extraInitContainers | indent 8 }} + {{- end }} + containers: + {{- if .Values.configmapReload.prometheus.enabled }} + - name: {{ template "prometheus.name" . }}-{{ .Values.server.name }}-{{ .Values.configmapReload.prometheus.name }} + image: "{{ .Values.configmapReload.prometheus.image.repository }}:{{ .Values.configmapReload.prometheus.image.tag }}" + imagePullPolicy: "{{ .Values.configmapReload.prometheus.image.pullPolicy }}" + args: + - --volume-dir=/etc/config + - --webhook-url=http://127.0.0.1:9090{{ .Values.server.prefixURL }}/-/reload + {{- range $key, $value := .Values.configmapReload.prometheus.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraVolumeDirs }} + - --volume-dir={{ . }} + {{- end }} + {{- if .Values.configmapReload.prometheus.containerPort }} + ports: + - containerPort: {{ .Values.configmapReload.prometheus.containerPort }} + {{- end }} + resources: +{{ toYaml .Values.configmapReload.prometheus.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ $.Values.configmapReload.prometheus.name }}-{{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- end }} + + - name: {{ template "prometheus.name" . }}-{{ .Values.server.name }} + image: "{{ .Values.server.image.repository }}:{{ .Values.server.image.tag }}" + imagePullPolicy: "{{ .Values.server.image.pullPolicy }}" + {{- if .Values.server.env }} + env: +{{ toYaml .Values.server.env | indent 12}} + {{- end }} + args: + {{- if .Values.server.defaultFlagsOverride }} + {{ toYaml .Values.server.defaultFlagsOverride | nindent 12}} + {{- else }} + {{- if .Values.server.retention }} + - --storage.tsdb.retention.time={{ .Values.server.retention }} + {{- end }} + - --config.file={{ .Values.server.configPath }} + {{- if .Values.server.storagePath }} + - --storage.tsdb.path={{ .Values.server.storagePath }} + {{- else }} + - --storage.tsdb.path={{ .Values.server.persistentVolume.mountPath }} + {{- end }} + - --web.console.libraries=/etc/prometheus/console_libraries + - --web.console.templates=/etc/prometheus/consoles + {{- range .Values.server.extraFlags }} + - --{{ . }} + {{- end }} + {{- range $key, $value := .Values.server.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- if .Values.server.prefixURL }} + - --web.route-prefix={{ .Values.server.prefixURL }} + {{- end }} + {{- if .Values.server.baseURL }} + - --web.external-url={{ .Values.server.baseURL }} + {{- end }} + {{- end }} + ports: + - containerPort: 9090 + {{- if .Values.server.hostPort }} + hostPort: {{ .Values.server.hostPort }} + {{- end }} + readinessProbe: + {{- if not .Values.server.tcpSocketProbeEnabled }} + httpGet: + path: {{ .Values.server.prefixURL }}/-/ready + port: 9090 + scheme: {{ .Values.server.probeScheme }} + {{- if .Values.server.probeHeaders }} + httpHeaders: + {{- range .Values.server.probeHeaders}} + - name: {{ .name }} + value: {{ .value }} + {{- end }} + {{- end }} + {{- else }} + tcpSocket: + port: 9090 + {{- end }} + initialDelaySeconds: {{ .Values.server.readinessProbeInitialDelay }} + periodSeconds: {{ .Values.server.readinessProbePeriodSeconds }} + timeoutSeconds: {{ .Values.server.readinessProbeTimeout }} + failureThreshold: {{ .Values.server.readinessProbeFailureThreshold }} + successThreshold: {{ .Values.server.readinessProbeSuccessThreshold }} + livenessProbe: + {{- if not .Values.server.tcpSocketProbeEnabled }} + httpGet: + path: {{ .Values.server.prefixURL }}/-/healthy + port: 9090 + scheme: {{ .Values.server.probeScheme }} + {{- if .Values.server.probeHeaders }} + httpHeaders: + {{- range .Values.server.probeHeaders}} + - name: {{ .name }} + value: {{ .value }} + {{- end }} + {{- end }} + {{- else }} + tcpSocket: + port: 9090 + {{- end }} + initialDelaySeconds: {{ .Values.server.livenessProbeInitialDelay }} + periodSeconds: {{ .Values.server.livenessProbePeriodSeconds }} + timeoutSeconds: {{ .Values.server.livenessProbeTimeout }} + failureThreshold: {{ .Values.server.livenessProbeFailureThreshold }} + successThreshold: {{ .Values.server.livenessProbeSuccessThreshold }} + {{- if .Values.server.startupProbe.enabled }} + startupProbe: + {{- if not .Values.server.tcpSocketProbeEnabled }} + httpGet: + path: {{ .Values.server.prefixURL }}/-/healthy + port: 9090 + scheme: {{ .Values.server.probeScheme }} + {{- if .Values.server.probeHeaders }} + httpHeaders: + {{- range .Values.server.probeHeaders}} + - name: {{ .name }} + value: {{ .value }} + {{- end }} + {{- end }} + {{- else }} + tcpSocket: + port: 9090 + {{- end }} + failureThreshold: {{ .Values.server.startupProbe.failureThreshold }} + periodSeconds: {{ .Values.server.startupProbe.periodSeconds }} + timeoutSeconds: {{ .Values.server.startupProbe.timeoutSeconds }} + {{- end }} + resources: +{{ toYaml .Values.server.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + - name: storage-volume + mountPath: {{ .Values.server.persistentVolume.mountPath }} + subPath: "{{ .Values.server.persistentVolume.subPath }}" + {{- range .Values.server.extraHostPathMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.server.extraConfigmapMounts }} + - name: {{ $.Values.server.name }}-{{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.server.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- if .Values.server.extraVolumeMounts }} + {{ toYaml .Values.server.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.server.containerSecurityContext }} + securityContext: + {{- toYaml .Values.server.containerSecurityContext | nindent 12 }} + {{- end }} + {{- if .Values.server.sidecarContainers }} + {{- range $name, $spec := .Values.server.sidecarContainers }} + - name: {{ $name }} + {{- if kindIs "string" $spec }} + {{- tpl $spec $ | nindent 10 }} + {{- else }} + {{- toYaml $spec | nindent 10 }} + {{- end }} + {{- end }} + {{- end }} + hostNetwork: {{ .Values.server.hostNetwork }} + {{- if .Values.server.dnsPolicy }} + dnsPolicy: {{ .Values.server.dnsPolicy }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: +{{ toYaml .Values.imagePullSecrets | indent 8 }} + {{- end }} + {{- if .Values.server.nodeSelector }} + nodeSelector: +{{ toYaml .Values.server.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.server.hostAliases }} + hostAliases: +{{ toYaml .Values.server.hostAliases | indent 8 }} + {{- end }} + {{- if .Values.server.dnsConfig }} + dnsConfig: +{{ toYaml .Values.server.dnsConfig | indent 8 }} + {{- end }} + {{- if .Values.server.securityContext }} + securityContext: +{{ toYaml .Values.server.securityContext | indent 8 }} + {{- end }} + {{- if .Values.server.tolerations }} + tolerations: +{{ toYaml .Values.server.tolerations | indent 8 }} + {{- end }} + {{- if .Values.server.affinity }} + affinity: +{{ toYaml .Values.server.affinity | indent 8 }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.server.terminationGracePeriodSeconds }} + volumes: + - name: config-volume + {{- if empty .Values.server.configFromSecret }} + configMap: + name: {{ if .Values.server.configMapOverrideName }}{{ .Release.Name }}-{{ .Values.server.configMapOverrideName }}{{- else }}{{ template "prometheus.server.fullname" . }}{{- end }} + {{- else }} + secret: + secretName: {{ .Values.server.configFromSecret }} + {{- end }} + {{- range .Values.server.extraHostPathMounts }} + - name: {{ .name }} + hostPath: + path: {{ .hostPath }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ $.Values.configmapReload.prometheus.name }}-{{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + {{- range .Values.server.extraConfigmapMounts }} + - name: {{ $.Values.server.name }}-{{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + {{- range .Values.server.extraSecretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + {{- with .optional }} + optional: {{ . }} + {{- end }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ .name }} + configMap: + name: {{ .configMap }} + {{- with .optional }} + optional: {{ . }} + {{- end }} + {{- end }} +{{- if .Values.server.extraVolumes }} +{{ toYaml .Values.server.extraVolumes | indent 8}} +{{- end }} + - name: storage-volume + {{- if .Values.server.persistentVolume.enabled }} + persistentVolumeClaim: + claimName: {{ if .Values.server.persistentVolume.existingClaim }}{{ .Values.server.persistentVolume.existingClaim }}{{- else }}{{ template "prometheus.server.fullname" . }}{{- end }} + {{- else }} + emptyDir: + {{- if .Values.server.emptyDir.sizeLimit }} + sizeLimit: {{ .Values.server.emptyDir.sizeLimit }} + {{- else }} + {} + {{- end -}} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/extra-manifests.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/extra-manifests.yaml new file mode 100644 index 000000000..e46d4d8b9 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{ range .Values.server.extraObjects }} +--- +{{ tpl (toYaml .) $ }} +{{ end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/headless-svc.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/headless-svc.yaml new file mode 100644 index 000000000..d519f4e0e --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/headless-svc.yaml @@ -0,0 +1,37 @@ +{{- if .Values.server.enabled -}} +{{- if .Values.server.statefulSet.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.server.statefulSet.headless.annotations }} + annotations: +{{ toYaml .Values.server.statefulSet.headless.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +{{- if .Values.server.statefulSet.headless.labels }} +{{ toYaml .Values.server.statefulSet.headless.labels | indent 4 }} +{{- end }} + name: {{ template "prometheus.server.fullname" . }}-headless +{{ include "prometheus.namespace" . | indent 2 }} +spec: + clusterIP: None + ports: + - name: http + port: {{ .Values.server.statefulSet.headless.servicePort }} + protocol: TCP + targetPort: 9090 + {{- if .Values.server.statefulSet.headless.gRPC.enabled }} + - name: grpc + port: {{ .Values.server.statefulSet.headless.gRPC.servicePort }} + protocol: TCP + targetPort: 10901 + {{- if .Values.server.statefulSet.headless.gRPC.nodePort }} + nodePort: {{ .Values.server.statefulSet.headless.gRPC.nodePort }} + {{- end }} + {{- end }} + + selector: + {{- include "prometheus.server.matchLabels" . | nindent 4 }} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/ingress.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/ingress.yaml new file mode 100644 index 000000000..000f39cab --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/ingress.yaml @@ -0,0 +1,59 @@ +{{- if .Values.server.enabled -}} +{{- if .Values.server.ingress.enabled -}} +{{- $ingressApiIsStable := eq (include "ingress.isStable" .) "true" -}} +{{- $ingressSupportsIngressClassName := eq (include "ingress.supportsIngressClassName" .) "true" -}} +{{- $ingressSupportsPathType := eq (include "ingress.supportsPathType" .) "true" -}} +{{- $releaseName := .Release.Name -}} +{{- $serviceName := include "prometheus.server.fullname" . }} +{{- $servicePort := .Values.server.service.servicePort -}} +{{- $ingressPath := .Values.server.ingress.path -}} +{{- $ingressPathType := .Values.server.ingress.pathType -}} +{{- $extraPaths := .Values.server.ingress.extraPaths -}} +apiVersion: {{ template "ingress.apiVersion" . }} +kind: Ingress +metadata: +{{- if .Values.server.ingress.annotations }} + annotations: +{{ toYaml .Values.server.ingress.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +{{- range $key, $value := .Values.server.ingress.extraLabels }} + {{ $key }}: {{ $value }} +{{- end }} + name: {{ template "prometheus.server.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: + {{- if and $ingressSupportsIngressClassName .Values.server.ingress.ingressClassName }} + ingressClassName: {{ .Values.server.ingress.ingressClassName }} + {{- end }} + rules: + {{- range .Values.server.ingress.hosts }} + {{- $url := splitList "/" . }} + - host: {{ first $url }} + http: + paths: +{{ if $extraPaths }} +{{ toYaml $extraPaths | indent 10 }} +{{- end }} + - path: {{ $ingressPath }} + {{- if $ingressSupportsPathType }} + pathType: {{ $ingressPathType }} + {{- end }} + backend: + {{- if $ingressApiIsStable }} + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end -}} +{{- if .Values.server.ingress.tls }} + tls: +{{ toYaml .Values.server.ingress.tls | indent 4 }} + {{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/netpol.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/netpol.yaml new file mode 100644 index 000000000..c8870e9ff --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/netpol.yaml @@ -0,0 +1,18 @@ +{{- if .Values.server.enabled -}} +{{- if .Values.networkPolicy.enabled }} +apiVersion: {{ template "prometheus.networkPolicy.apiVersion" . }} +kind: NetworkPolicy +metadata: + name: {{ template "prometheus.server.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +spec: + podSelector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 6 }} + ingress: + - ports: + - port: 9090 +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/pdb.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/pdb.yaml new file mode 100644 index 000000000..364cb5b49 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/pdb.yaml @@ -0,0 +1,14 @@ +{{- if .Values.server.podDisruptionBudget.enabled }} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ template "prometheus.server.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +spec: + maxUnavailable: {{ .Values.server.podDisruptionBudget.maxUnavailable }} + selector: + matchLabels: + {{- include "prometheus.server.labels" . | nindent 6 }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/psp.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/psp.yaml new file mode 100644 index 000000000..e2b885f16 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/psp.yaml @@ -0,0 +1,51 @@ +{{- if and .Values.server.enabled .Values.rbac.create .Values.podSecurityPolicy.enabled }} +apiVersion: {{ template "prometheus.podSecurityPolicy.apiVersion" . }} +kind: PodSecurityPolicy +metadata: + name: {{ template "prometheus.server.fullname" . }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + annotations: +{{- if .Values.server.podSecurityPolicy.annotations }} +{{ toYaml .Values.server.podSecurityPolicy.annotations | indent 4 }} +{{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + allowedCapabilities: + - 'CHOWN' + volumes: + - 'configMap' + - 'persistentVolumeClaim' + - 'emptyDir' + - 'secret' + - 'hostPath' + allowedHostPaths: + - pathPrefix: /etc + readOnly: true + - pathPrefix: {{ .Values.server.persistentVolume.mountPath }} + {{- range .Values.server.extraHostPathMounts }} + - pathPrefix: {{ .hostPath }} + readOnly: {{ .readOnly }} + {{- end }} + hostNetwork: false + hostPID: false + hostIPC: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/pvc.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/pvc.yaml new file mode 100644 index 000000000..a7355365c --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/pvc.yaml @@ -0,0 +1,39 @@ +{{- if .Values.server.enabled -}} +{{- if not .Values.server.statefulSet.enabled -}} +{{- if .Values.server.persistentVolume.enabled -}} +{{- if not .Values.server.persistentVolume.existingClaim -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + {{- if .Values.server.persistentVolume.annotations }} + annotations: +{{ toYaml .Values.server.persistentVolume.annotations | indent 4 }} + {{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.server.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: + accessModes: +{{ toYaml .Values.server.persistentVolume.accessModes | indent 4 }} +{{- if .Values.server.persistentVolume.storageClass }} +{{- if (eq "-" .Values.server.persistentVolume.storageClass) }} + storageClassName: "" +{{- else }} + storageClassName: "{{ .Values.server.persistentVolume.storageClass }}" +{{- end }} +{{- end }} +{{- if .Values.server.persistentVolume.volumeBindingMode }} + volumeBindingMode: "{{ .Values.server.persistentVolume.volumeBindingMode }}" +{{- end }} + resources: + requests: + storage: "{{ .Values.server.persistentVolume.size }}" +{{- if .Values.server.persistentVolume.selector }} + selector: + {{- toYaml .Values.server.persistentVolume.selector | nindent 4 }} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/rolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/rolebinding.yaml new file mode 100644 index 000000000..93ce3ee13 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/rolebinding.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.server.enabled .Values.rbac.create .Values.server.useExistingClusterRoleName .Values.server.namespaces -}} +{{ range $.Values.server.namespaces -}} +--- +apiVersion: {{ template "rbac.apiVersion" $ }} +kind: RoleBinding +metadata: + labels: + {{- include "prometheus.server.labels" $ | nindent 4 }} + name: {{ template "prometheus.server.fullname" $ }} + namespace: {{ . }} +subjects: + - kind: ServiceAccount + name: {{ template "prometheus.serviceAccountName.server" $ }} +{{ include "prometheus.namespace" $ | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ $.Values.server.useExistingClusterRoleName }} +{{ end -}} +{{ end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/service.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/service.yaml new file mode 100644 index 000000000..01c5a4a8a --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/service.yaml @@ -0,0 +1,60 @@ +{{- if and .Values.server.enabled .Values.server.service.enabled -}} +apiVersion: v1 +kind: Service +metadata: +{{- if .Values.server.service.annotations }} + annotations: +{{ toYaml .Values.server.service.annotations | indent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} +{{- if .Values.server.service.labels }} +{{ toYaml .Values.server.service.labels | indent 4 }} +{{- end }} + name: {{ template "prometheus.server.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: +{{- if .Values.server.service.clusterIP }} + clusterIP: {{ .Values.server.service.clusterIP }} +{{- end }} +{{- if .Values.server.service.externalIPs }} + externalIPs: +{{ toYaml .Values.server.service.externalIPs | indent 4 }} +{{- end }} +{{- if .Values.server.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.server.service.loadBalancerIP }} +{{- end }} +{{- if .Values.server.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: + {{- range $cidr := .Values.server.service.loadBalancerSourceRanges }} + - {{ $cidr }} + {{- end }} +{{- end }} + ports: + - name: http + port: {{ .Values.server.service.servicePort }} + protocol: TCP + targetPort: 9090 + {{- if .Values.server.service.nodePort }} + nodePort: {{ .Values.server.service.nodePort }} + {{- end }} + {{- if .Values.server.service.gRPC.enabled }} + - name: grpc + port: {{ .Values.server.service.gRPC.servicePort }} + protocol: TCP + targetPort: 10901 + {{- if .Values.server.service.gRPC.nodePort }} + nodePort: {{ .Values.server.service.gRPC.nodePort }} + {{- end }} + {{- end }} + selector: + {{- if and .Values.server.statefulSet.enabled .Values.server.service.statefulsetReplica.enabled }} + statefulset.kubernetes.io/pod-name: {{ template "prometheus.server.fullname" . }}-{{ .Values.server.service.statefulsetReplica.replica }} + {{- else -}} + {{- include "prometheus.server.matchLabels" . | nindent 4 }} +{{- if .Values.server.service.sessionAffinity }} + sessionAffinity: {{ .Values.server.service.sessionAffinity }} +{{- end }} + {{- end }} + type: "{{ .Values.server.service.type }}" +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/serviceaccount.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/serviceaccount.yaml new file mode 100644 index 000000000..9c0502ab7 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.server.enabled -}} +{{- if .Values.serviceAccounts.server.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.serviceAccountName.server" . }} +{{ include "prometheus.namespace" . | indent 2 }} + annotations: +{{ toYaml .Values.serviceAccounts.server.annotations | indent 4 }} +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/sts.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/sts.yaml new file mode 100644 index 000000000..24a9d923e --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/sts.yaml @@ -0,0 +1,302 @@ +{{- if .Values.server.enabled -}} +{{- if .Values.server.statefulSet.enabled -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: +{{- if .Values.server.statefulSet.annotations }} + annotations: + {{ toYaml .Values.server.statefulSet.annotations | nindent 4 }} +{{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + {{- if .Values.server.statefulSet.labels}} + {{ toYaml .Values.server.statefulSet.labels | nindent 4 }} + {{- end}} + name: {{ template "prometheus.server.fullname" . }} +{{ include "prometheus.namespace" . | indent 2 }} +spec: + serviceName: {{ template "prometheus.server.fullname" . }}-headless + selector: + matchLabels: + {{- include "prometheus.server.matchLabels" . | nindent 6 }} + replicas: {{ .Values.server.replicaCount }} + podManagementPolicy: {{ .Values.server.statefulSet.podManagementPolicy }} + template: + metadata: + {{- if .Values.server.podAnnotations }} + annotations: + {{ toYaml .Values.server.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "prometheus.server.labels" . | nindent 8 }} + {{- if .Values.server.podLabels}} + {{ toYaml .Values.server.podLabels | nindent 8 }} + {{- end}} + spec: +{{- if .Values.server.priorityClassName }} + priorityClassName: "{{ .Values.server.priorityClassName }}" +{{- end }} +{{- if .Values.server.schedulerName }} + schedulerName: "{{ .Values.server.schedulerName }}" +{{- end }} +{{- if semverCompare ">=1.13-0" .Capabilities.KubeVersion.GitVersion }} + {{- if or (.Values.server.enableServiceLinks) (eq (.Values.server.enableServiceLinks | toString) "") }} + enableServiceLinks: true + {{- else }} + enableServiceLinks: false + {{- end }} +{{- end }} + serviceAccountName: {{ template "prometheus.serviceAccountName.server" . }} + {{- if .Values.server.extraInitContainers }} + initContainers: +{{ toYaml .Values.server.extraInitContainers | indent 8 }} + {{- end }} + containers: + {{- if .Values.configmapReload.prometheus.enabled }} + - name: {{ template "prometheus.name" . }}-{{ .Values.server.name }}-{{ .Values.configmapReload.prometheus.name }} + image: "{{ .Values.configmapReload.prometheus.image.repository }}:{{ .Values.configmapReload.prometheus.image.tag }}" + imagePullPolicy: "{{ .Values.configmapReload.prometheus.image.pullPolicy }}" + args: + - --volume-dir=/etc/config + - --webhook-url=http://127.0.0.1:9090{{ .Values.server.prefixURL }}/-/reload + {{- range $key, $value := .Values.configmapReload.prometheus.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraVolumeDirs }} + - --volume-dir={{ . }} + {{- end }} + {{- if .Values.configmapReload.prometheus.containerPort }} + ports: + - containerPort: {{ .Values.configmapReload.prometheus.containerPort }} + {{- end }} + resources: +{{ toYaml .Values.configmapReload.prometheus.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + readOnly: true + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ $.Values.configmapReload.prometheus.name }}-{{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- end }} + + - name: {{ template "prometheus.name" . }}-{{ .Values.server.name }} + image: "{{ .Values.server.image.repository }}:{{ .Values.server.image.tag }}" + imagePullPolicy: "{{ .Values.server.image.pullPolicy }}" + {{- if .Values.server.env }} + env: +{{ toYaml .Values.server.env | indent 12}} + {{- end }} + args: + {{- if .Values.server.defaultFlagsOverride }} + {{ toYaml .Values.server.defaultFlagsOverride | nindent 12}} + {{- else }} + {{- if .Values.server.prefixURL }} + - --web.route-prefix={{ .Values.server.prefixURL }} + {{- end }} + {{- if .Values.server.retention }} + - --storage.tsdb.retention.time={{ .Values.server.retention }} + {{- end }} + - --config.file={{ .Values.server.configPath }} + {{- if .Values.server.storagePath }} + - --storage.tsdb.path={{ .Values.server.storagePath }} + {{- else }} + - --storage.tsdb.path={{ .Values.server.persistentVolume.mountPath }} + {{- end }} + - --web.console.libraries=/etc/prometheus/console_libraries + - --web.console.templates=/etc/prometheus/consoles + {{- range .Values.server.extraFlags }} + - --{{ . }} + {{- end }} + {{- range $key, $value := .Values.server.extraArgs }} + - --{{ $key }}={{ $value }} + {{- end }} + {{- if .Values.server.baseURL }} + - --web.external-url={{ .Values.server.baseURL }} + {{- end }} + {{- end }} + ports: + - containerPort: 9090 + {{- if .Values.server.hostPort }} + hostPort: {{ .Values.server.hostPort }} + {{- end }} + readinessProbe: + {{- if not .Values.server.tcpSocketProbeEnabled }} + httpGet: + path: {{ .Values.server.prefixURL }}/-/ready + port: 9090 + scheme: {{ .Values.server.probeScheme }} + {{- else }} + tcpSocket: + port: 9090 + {{- end }} + initialDelaySeconds: {{ .Values.server.readinessProbeInitialDelay }} + periodSeconds: {{ .Values.server.readinessProbePeriodSeconds }} + timeoutSeconds: {{ .Values.server.readinessProbeTimeout }} + failureThreshold: {{ .Values.server.readinessProbeFailureThreshold }} + successThreshold: {{ .Values.server.readinessProbeSuccessThreshold }} + livenessProbe: + {{- if not .Values.server.tcpSocketProbeEnabled }} + httpGet: + path: {{ .Values.server.prefixURL }}/-/healthy + port: 9090 + scheme: {{ .Values.server.probeScheme }} + {{- else }} + tcpSocket: + port: 9090 + {{- end }} + initialDelaySeconds: {{ .Values.server.livenessProbeInitialDelay }} + periodSeconds: {{ .Values.server.livenessProbePeriodSeconds }} + timeoutSeconds: {{ .Values.server.livenessProbeTimeout }} + failureThreshold: {{ .Values.server.livenessProbeFailureThreshold }} + successThreshold: {{ .Values.server.livenessProbeSuccessThreshold }} + resources: +{{ toYaml .Values.server.resources | indent 12 }} + volumeMounts: + - name: config-volume + mountPath: /etc/config + - name: storage-volume + mountPath: {{ .Values.server.persistentVolume.mountPath }} + subPath: "{{ .Values.server.persistentVolume.subPath }}" + {{- range .Values.server.extraHostPathMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.server.extraConfigmapMounts }} + - name: {{ $.Values.server.name }}-{{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.server.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath }} + readOnly: {{ .readOnly }} + {{- end }} + {{- if .Values.server.extraVolumeMounts }} + {{ toYaml .Values.server.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.server.sidecarContainers }} + {{- range $name, $spec := .Values.server.sidecarContainers }} + - name: {{ $name }} + {{- if kindIs "string" $spec }} + {{- tpl $spec $ | nindent 10 }} + {{- else }} + {{- toYaml $spec | nindent 10 }} + {{- end }} + {{- end }} + {{- end }} + hostNetwork: {{ .Values.server.hostNetwork }} + {{- if .Values.server.dnsPolicy }} + dnsPolicy: {{ .Values.server.dnsPolicy }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: +{{ toYaml .Values.imagePullSecrets | indent 8 }} + {{- end }} + {{- if .Values.server.nodeSelector }} + nodeSelector: +{{ toYaml .Values.server.nodeSelector | indent 8 }} + {{- end }} + {{- if .Values.server.hostAliases }} + hostAliases: +{{ toYaml .Values.server.hostAliases | indent 8 }} + {{- end }} + {{- if .Values.server.dnsConfig }} + dnsConfig: +{{ toYaml .Values.server.dnsConfig | indent 8 }} + {{- end }} + {{- if .Values.server.securityContext }} + securityContext: +{{ toYaml .Values.server.securityContext | indent 8 }} + {{- end }} + {{- if .Values.server.tolerations }} + tolerations: +{{ toYaml .Values.server.tolerations | indent 8 }} + {{- end }} + {{- if .Values.server.affinity }} + affinity: +{{ toYaml .Values.server.affinity | indent 8 }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.server.terminationGracePeriodSeconds }} + volumes: + - name: config-volume + {{- if empty .Values.server.configFromSecret }} + configMap: + name: {{ if .Values.server.configMapOverrideName }}{{ .Release.Name }}-{{ .Values.server.configMapOverrideName }}{{- else }}{{ template "prometheus.server.fullname" . }}{{- end }} + {{- else }} + secret: + secretName: {{ .Values.server.configFromSecret }} + {{- end }} + {{- range .Values.server.extraHostPathMounts }} + - name: {{ .name }} + hostPath: + path: {{ .hostPath }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ $.Values.configmapReload.prometheus.name }}-{{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + {{- range .Values.server.extraConfigmapMounts }} + - name: {{ $.Values.server.name }}-{{ .name }} + configMap: + name: {{ .configMap }} + {{- end }} + {{- range .Values.server.extraSecretMounts }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + {{- with .optional }} + optional: {{ . }} + {{- end }} + {{- end }} + {{- range .Values.configmapReload.prometheus.extraConfigmapMounts }} + - name: {{ .name }} + configMap: + name: {{ .configMap }} + {{- with .optional }} + optional: {{ . }} + {{- end }} + {{- end }} +{{- if .Values.server.extraVolumes }} +{{ toYaml .Values.server.extraVolumes | indent 8}} +{{- end }} +{{- if .Values.server.persistentVolume.enabled }} + volumeClaimTemplates: + - metadata: + name: storage-volume + {{- if .Values.server.persistentVolume.annotations }} + annotations: +{{ toYaml .Values.server.persistentVolume.annotations | indent 10 }} + {{- end }} + spec: + accessModes: +{{ toYaml .Values.server.persistentVolume.accessModes | indent 10 }} + resources: + requests: + storage: "{{ .Values.server.persistentVolume.size }}" + {{- if .Values.server.persistentVolume.storageClass }} + {{- if (eq "-" .Values.server.persistentVolume.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: "{{ .Values.server.persistentVolume.storageClass }}" + {{- end }} + {{- end }} +{{- else }} + - name: storage-volume + emptyDir: + {{- if .Values.server.emptyDir.sizeLimit }} + sizeLimit: {{ .Values.server.emptyDir.sizeLimit }} + {{- else }} + {} + {{- end -}} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/vpa.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/vpa.yaml new file mode 100644 index 000000000..981a9b485 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/templates/server/vpa.yaml @@ -0,0 +1,24 @@ +{{- if .Values.server.enabled -}} +{{- if .Values.server.verticalAutoscaler.enabled -}} +apiVersion: autoscaling.k8s.io/v1beta2 +kind: VerticalPodAutoscaler +metadata: + labels: + {{- include "prometheus.server.labels" . | nindent 4 }} + name: {{ template "prometheus.server.fullname" . }}-vpa +{{ include "prometheus.namespace" . | indent 2 }} +spec: + targetRef: + apiVersion: "apps/v1" +{{- if .Values.server.statefulSet.enabled }} + kind: StatefulSet +{{- else }} + kind: Deployment +{{- end }} + name: {{ template "prometheus.server.fullname" . }} + updatePolicy: + updateMode: {{ .Values.server.verticalAutoscaler.updateMode | default "Off" | quote }} + resourcePolicy: + containerPolicies: {{ .Values.server.verticalAutoscaler.containerPolicies | default list | toYaml | trim | nindent 4 }} +{{- end -}} {{/* if .Values.server.verticalAutoscaler.enabled */}} +{{- end -}} {{/* .Values.server.enabled */}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/values.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/values.yaml new file mode 100644 index 000000000..f04b0e87a --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/charts/prometheus/values.yaml @@ -0,0 +1,1855 @@ +rbac: + create: true + +podSecurityPolicy: + enabled: false + +imagePullSecrets: +# - name: "image-pull-secret" + +## Define serviceAccount names for components. Defaults to component's fully qualified name. +## +serviceAccounts: + alertmanager: + create: false + name: + annotations: {} + nodeExporter: + create: false + name: + annotations: {} + pushgateway: + create: false + name: + annotations: {} + server: + create: true + name: + annotations: {} + +alertmanager: + ## If false, alertmanager will not be installed + ## + enabled: true + + ## Use a ClusterRole (and ClusterRoleBinding) + ## - If set to false - we define a Role and RoleBinding in the defined namespaces ONLY + ## This makes alertmanager work - for users who do not have ClusterAdmin privs, but wants alertmanager to operate on their own namespaces, instead of clusterwide. + useClusterRole: true + + ## Set to a rolename to use existing role - skipping role creating - but still doing serviceaccount and rolebinding to the rolename set here. + useExistingRole: false + + ## alertmanager container name + ## + name: alertmanager + + ## alertmanager container image + ## + image: + repository: quay.io/prometheus/alertmanager + tag: v0.23.0 + pullPolicy: IfNotPresent + + ## alertmanager priorityClassName + ## + priorityClassName: "" + + ## Custom HTTP headers for Readiness Probe + ## + ## Useful for providing HTTP Basic Auth to healthchecks + probeHeaders: [] + + ## Additional alertmanager container arguments + ## + extraArgs: {} + + ## Additional InitContainers to initialize the pod + ## + extraInitContainers: [] + + ## The URL prefix at which the container can be accessed. Useful in the case the '-web.external-url' includes a slug + ## so that the various internal URLs are still able to access as they are in the default case. + ## (Optional) + prefixURL: "" + + ## External URL which can access alertmanager + baseURL: "http://localhost:9093" + + ## Additional alertmanager container environment variable + ## For instance to add a http_proxy + ## + extraEnv: {} + + ## Additional alertmanager Secret mounts + # Defines additional mounts with secrets. Secrets must be manually created in the namespace. + extraSecretMounts: [] + # - name: secret-files + # mountPath: /etc/secrets + # subPath: "" + # secretName: alertmanager-secret-files + # readOnly: true + + ## Additional alertmanager Configmap mounts + extraConfigmapMounts: [] + # - name: template-files + # mountPath: /etc/config/templates.d + # configMap: alertmanager-template-files + # readOnly: true + + ## ConfigMap override where fullname is {{.Release.Name}}-{{.Values.alertmanager.configMapOverrideName}} + ## Defining configMapOverrideName will cause templates/alertmanager-configmap.yaml + ## to NOT generate a ConfigMap resource + ## + configMapOverrideName: "" + + ## The name of a secret in the same kubernetes namespace which contains the Alertmanager config + ## Defining configFromSecret will cause templates/alertmanager-configmap.yaml + ## to NOT generate a ConfigMap resource + ## + configFromSecret: "" + + ## The configuration file name to be loaded to alertmanager + ## Must match the key within configuration loaded from ConfigMap/Secret + ## + configFileName: alertmanager.yml + + ingress: + ## If true, alertmanager Ingress will be created + ## + enabled: false + + # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName + # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress + # ingressClassName: nginx + + ## alertmanager Ingress annotations + ## + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: 'true' + + ## alertmanager Ingress additional labels + ## + extraLabels: {} + + ## alertmanager Ingress hostnames with optional path + ## Must be provided if Ingress is enabled + ## + hosts: [] + # - alertmanager.domain.com + # - domain.com/alertmanager + + path: / + + # pathType is only for k8s >= 1.18 + pathType: Prefix + + ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. + extraPaths: [] + # - path: /* + # backend: + # serviceName: ssl-redirect + # servicePort: use-annotation + + ## alertmanager Ingress TLS configuration + ## Secrets must be manually created in the namespace + ## + tls: [] + # - secretName: prometheus-alerts-tls + # hosts: + # - alertmanager.domain.com + + ## Alertmanager Deployment Strategy type + # strategy: + # type: Recreate + + ## Node tolerations for alertmanager scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + ## Node labels for alertmanager pod assignment + ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Pod affinity + ## + affinity: {} + + ## PodDisruptionBudget settings + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + ## + podDisruptionBudget: + enabled: false + maxUnavailable: 1 + + ## Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + # schedulerName: + + persistentVolume: + ## If true, alertmanager will create/use a Persistent Volume Claim + ## If false, use emptyDir + ## + enabled: true + + ## alertmanager data Persistent Volume access modes + ## Must match those of existing PV or dynamic provisioner + ## Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + accessModes: + - ReadWriteOnce + + ## alertmanager data Persistent Volume Claim annotations + ## + annotations: {} + + ## alertmanager data Persistent Volume existing claim name + ## Requires alertmanager.persistentVolume.enabled: true + ## If defined, PVC must be created manually before volume will be bound + existingClaim: "" + + ## alertmanager data Persistent Volume mount root path + ## + mountPath: /data + + ## alertmanager data Persistent Volume size + ## + size: 2Gi + + ## alertmanager data Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + # storageClass: "-" + + ## alertmanager data Persistent Volume Binding Mode + ## If defined, volumeBindingMode: + ## If undefined (the default) or set to null, no volumeBindingMode spec is + ## set, choosing the default mode. + ## + # volumeBindingMode: "" + + ## Subdirectory of alertmanager data Persistent Volume to mount + ## Useful if the volume's root directory is not empty + ## + subPath: "" + + ## Persistent Volume Claim Selector + ## Useful if Persistent Volumes have been provisioned in advance + ## Ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#selector + ## + # selector: + # matchLabels: + # release: "stable" + # matchExpressions: + # - { key: environment, operator: In, values: [ dev ] } + + emptyDir: + ## alertmanager emptyDir volume size limit + ## + sizeLimit: "" + + ## Annotations to be added to alertmanager pods + ## + podAnnotations: {} + ## Tell prometheus to use a specific set of alertmanager pods + ## instead of all alertmanager pods found in the same namespace + ## Useful if you deploy multiple releases within the same namespace + ## + ## prometheus.io/probe: alertmanager-teamA + + ## Labels to be added to Prometheus AlertManager pods + ## + podLabels: {} + + ## Specify if a Pod Security Policy for node-exporter must be created + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + ## + podSecurityPolicy: + annotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + ## Use a StatefulSet if replicaCount needs to be greater than 1 (see below) + ## + replicaCount: 1 + + ## Annotations to be added to deployment + ## + deploymentAnnotations: {} + + statefulSet: + ## If true, use a statefulset instead of a deployment for pod management. + ## This allows to scale replicas to more than 1 pod + ## + enabled: false + + annotations: {} + labels: {} + podManagementPolicy: OrderedReady + + ## Alertmanager headless service to use for the statefulset + ## + headless: + annotations: {} + labels: {} + + ## Enabling peer mesh service end points for enabling the HA alert manager + ## Ref: https://github.com/prometheus/alertmanager/blob/master/README.md + enableMeshPeer: false + + servicePort: 80 + + ## alertmanager resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + limits: + cpu: 100m + memory: 100Mi + requests: + cpu: 50m + memory: 50Mi + + # Custom DNS configuration to be added to alertmanager pods + dnsConfig: {} + # nameservers: + # - 1.2.3.4 + # searches: + # - ns1.svc.cluster-domain.example + # - my.dns.search.suffix + # options: + # - name: ndots + # value: "2" + # - name: edns0 + + ## Security context to be added to alertmanager pods + ## + securityContext: + runAsUser: 65534 + runAsNonRoot: true + runAsGroup: 65534 + fsGroup: 65534 + + service: + annotations: {} + labels: {} + clusterIP: "" + + ## Enabling peer mesh service end points for enabling the HA alert manager + ## Ref: https://github.com/prometheus/alertmanager/blob/master/README.md + # enableMeshPeer : true + + ## List of IP addresses at which the alertmanager service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + externalIPs: [] + + loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 80 + # nodePort: 30000 + sessionAffinity: None + type: ClusterIP + + ## List of initial peers + ## Ref: https://github.com/prometheus/alertmanager/blob/main/README.md#high-availability + clusterPeers: [] + +## Monitors ConfigMap changes and POSTs to a URL +## Ref: https://github.com/jimmidyson/configmap-reload +## +configmapReload: + prometheus: + ## If false, the configmap-reload container will not be deployed + ## + enabled: true + + ## configmap-reload container name + ## + name: configmap-reload + + ## configmap-reload container image + ## + image: + repository: jimmidyson/configmap-reload + tag: v0.5.0 + pullPolicy: IfNotPresent + + # containerPort: 9533 + + ## Additional configmap-reload container arguments + ## + extraArgs: {} + ## Additional configmap-reload volume directories + ## + extraVolumeDirs: [] + + + ## Additional configmap-reload mounts + ## + extraConfigmapMounts: [] + # - name: prometheus-alerts + # mountPath: /etc/alerts.d + # subPath: "" + # configMap: prometheus-alerts + # readOnly: true + + + ## configmap-reload resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + limits: + cpu: 100m + memory: 100Mi + requests: + cpu: 50m + memory: 50Mi + alertmanager: + ## If false, the configmap-reload container will not be deployed + ## + enabled: true + + ## configmap-reload container name + ## + name: configmap-reload + + ## configmap-reload container image + ## + image: + repository: jimmidyson/configmap-reload + tag: v0.5.0 + pullPolicy: IfNotPresent + + # containerPort: 9533 + + ## Additional configmap-reload container arguments + ## + extraArgs: {} + ## Additional configmap-reload volume directories + ## + extraVolumeDirs: [] + + + ## Additional configmap-reload mounts + ## + extraConfigmapMounts: [] + # - name: prometheus-alerts + # mountPath: /etc/alerts.d + # subPath: "" + # configMap: prometheus-alerts + # readOnly: true + + + ## configmap-reload resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + limits: + cpu: 100m + memory: 100Mi + requests: + cpu: 50m + memory: 50Mi + +kubeStateMetrics: + ## If false, kube-state-metrics sub-chart will not be installed + ## + enabled: true + +## kube-state-metrics sub-chart configurable values +## Please see https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-state-metrics +## +# kube-state-metrics: + +nodeExporter: + ## If false, node-exporter will not be installed + ## + enabled: true + + ## If true, node-exporter pods share the host network namespace + ## + hostNetwork: true + + ## If true, node-exporter pods share the host PID namespace + ## + hostPID: true + + ## If true, node-exporter pods mounts host / at /host/root + ## + hostRootfs: true + + ## node-exporter container name + ## + name: node-exporter + + ## node-exporter container image + ## + image: + repository: quay.io/prometheus/node-exporter + tag: v1.3.0 + pullPolicy: IfNotPresent + + ## Specify if a Pod Security Policy for node-exporter must be created + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + ## + podSecurityPolicy: + annotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + ## node-exporter priorityClassName + ## + priorityClassName: "" + + ## Custom Update Strategy + ## + updateStrategy: + type: RollingUpdate + + ## Additional node-exporter container arguments + ## + extraArgs: {} + + ## Additional InitContainers to initialize the pod + ## + extraInitContainers: [] + + ## Additional node-exporter hostPath mounts + ## + extraHostPathMounts: [] + # - name: textfile-dir + # mountPath: /srv/txt_collector + # hostPath: /var/lib/node-exporter + # readOnly: true + # mountPropagation: HostToContainer + + extraConfigmapMounts: [] + # - name: certs-configmap + # mountPath: /prometheus + # configMap: certs-configmap + # readOnly: true + + ## Node tolerations for node-exporter scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + ## Node labels for node-exporter pod assignment + ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Annotations to be added to node-exporter pods + ## + podAnnotations: {} + + ## Labels to be added to node-exporter pods + ## + pod: + labels: {} + + ## PodDisruptionBudget settings + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + ## + podDisruptionBudget: + enabled: false + maxUnavailable: 1 + + ## node-exporter resource limits & requests + ## Ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + limits: + cpu: 500m + memory: 100Mi + requests: + cpu: 200m + memory: 50Mi + container: + securityContext: + allowPrivilegeEscalation: false + # Custom DNS configuration to be added to node-exporter pods + dnsConfig: {} + # nameservers: + # - 1.2.3.4 + # searches: + # - ns1.svc.cluster-domain.example + # - my.dns.search.suffix + # options: + # - name: ndots + # value: "2" + # - name: edns0 + + ## Security context to be added to node-exporter pods + ## + securityContext: + fsGroup: 65534 + runAsGroup: 65534 + runAsNonRoot: true + runAsUser: 65534 + + service: + annotations: + prometheus.io/scrape: "true" + labels: {} + + # Exposed as a headless service: + # https://kubernetes.io/docs/concepts/services-networking/service/#headless-services + clusterIP: "" + + ## List of IP addresses at which the node-exporter service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + externalIPs: [] + + hostPort: 9100 + loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 9100 + type: ClusterIP + +server: + ## Prometheus server container name + ## + enabled: true + + ## Use a ClusterRole (and ClusterRoleBinding) + ## - If set to false - we define a RoleBinding in the defined namespaces ONLY + ## + ## NB: because we need a Role with nonResourceURL's ("/metrics") - you must get someone with Cluster-admin privileges to define this role for you, before running with this setting enabled. + ## This makes prometheus work - for users who do not have ClusterAdmin privs, but wants prometheus to operate on their own namespaces, instead of clusterwide. + ## + ## You MUST also set namespaces to the ones you have access to and want monitored by Prometheus. + ## + # useExistingClusterRoleName: nameofclusterrole + + ## namespaces to monitor (instead of monitoring all - clusterwide). Needed if you want to run without Cluster-admin privileges. + # namespaces: + # - yournamespace + + name: server + + # sidecarContainers - add more containers to prometheus server + # Key/Value where Key is the sidecar `- name: ` + # Example: + # sidecarContainers: + # webserver: + # image: nginx + sidecarContainers: {} + + # sidecarTemplateValues - context to be used in template for sidecarContainers + # Example: + # sidecarTemplateValues: *your-custom-globals + # sidecarContainers: + # webserver: |- + # {{ include "webserver-container-template" . }} + # Template for `webserver-container-template` might looks like this: + # image: "{{ .Values.server.sidecarTemplateValues.repository }}:{{ .Values.server.sidecarTemplateValues.tag }}" + # ... + # + sidecarTemplateValues: {} + + ## Prometheus server container image + ## + image: + repository: quay.io/prometheus/prometheus + tag: v2.34.0 + pullPolicy: IfNotPresent + + ## prometheus server priorityClassName + ## + priorityClassName: "" + + ## EnableServiceLinks indicates whether information about services should be injected + ## into pod's environment variables, matching the syntax of Docker links. + ## WARNING: the field is unsupported and will be skipped in K8s prior to v1.13.0. + ## + enableServiceLinks: true + + ## The URL prefix at which the container can be accessed. Useful in the case the '-web.external-url' includes a slug + ## so that the various internal URLs are still able to access as they are in the default case. + ## (Optional) + prefixURL: "" + + ## External URL which can access prometheus + ## Maybe same with Ingress host name + baseURL: "" + + ## Additional server container environment variables + ## + ## You specify this manually like you would a raw deployment manifest. + ## This means you can bind in environment variables from secrets. + ## + ## e.g. static environment variable: + ## - name: DEMO_GREETING + ## value: "Hello from the environment" + ## + ## e.g. secret environment variable: + ## - name: USERNAME + ## valueFrom: + ## secretKeyRef: + ## name: mysecret + ## key: username + env: [] + + # List of flags to override default parameters, e.g: + # - --enable-feature=agent + # - --storage.agent.retention.max-time=30m + defaultFlagsOverride: [] + + extraFlags: + - web.enable-lifecycle + ## web.enable-admin-api flag controls access to the administrative HTTP API which includes functionality such as + ## deleting time series. This is disabled by default. + # - web.enable-admin-api + ## + ## storage.tsdb.no-lockfile flag controls BD locking + # - storage.tsdb.no-lockfile + ## + ## storage.tsdb.wal-compression flag enables compression of the write-ahead log (WAL) + # - storage.tsdb.wal-compression + + ## Path to a configuration file on prometheus server container FS + configPath: /etc/config/prometheus.yml + + ### The data directory used by prometheus to set --storage.tsdb.path + ### When empty server.persistentVolume.mountPath is used instead + storagePath: "" + + global: + ## How frequently to scrape targets by default + ## + scrape_interval: 1m + ## How long until a scrape request times out + ## + scrape_timeout: 10s + ## How frequently to evaluate rules + ## + evaluation_interval: 1m + ## https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write + ## + remoteWrite: [] + ## https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_read + ## + remoteRead: [] + + ## Custom HTTP headers for Liveness/Readiness/Startup Probe + ## + ## Useful for providing HTTP Basic Auth to healthchecks + probeHeaders: [] + + ## Additional Prometheus server container arguments + ## + extraArgs: {} + + ## Additional InitContainers to initialize the pod + ## + extraInitContainers: [] + + ## Additional Prometheus server Volume mounts + ## + extraVolumeMounts: [] + + ## Additional Prometheus server Volumes + ## + extraVolumes: [] + + ## Additional Prometheus server hostPath mounts + ## + extraHostPathMounts: [] + # - name: certs-dir + # mountPath: /etc/kubernetes/certs + # subPath: "" + # hostPath: /etc/kubernetes/certs + # readOnly: true + + extraConfigmapMounts: [] + # - name: certs-configmap + # mountPath: /prometheus + # subPath: "" + # configMap: certs-configmap + # readOnly: true + + ## Additional Prometheus server Secret mounts + # Defines additional mounts with secrets. Secrets must be manually created in the namespace. + extraSecretMounts: [] + # - name: secret-files + # mountPath: /etc/secrets + # subPath: "" + # secretName: prom-secret-files + # readOnly: true + + ## ConfigMap override where fullname is {{.Release.Name}}-{{.Values.server.configMapOverrideName}} + ## Defining configMapOverrideName will cause templates/server-configmap.yaml + ## to NOT generate a ConfigMap resource + ## + configMapOverrideName: "" + + ingress: + ## If true, Prometheus server Ingress will be created + ## + enabled: false + + # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName + # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress + # ingressClassName: nginx + + ## Prometheus server Ingress annotations + ## + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: 'true' + + ## Prometheus server Ingress additional labels + ## + extraLabels: {} + + ## Prometheus server Ingress hostnames with optional path + ## Must be provided if Ingress is enabled + ## + hosts: [] + # - prometheus.domain.com + # - domain.com/prometheus + + path: / + + # pathType is only for k8s >= 1.18 + pathType: Prefix + + ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. + extraPaths: [] + # - path: /* + # backend: + # serviceName: ssl-redirect + # servicePort: use-annotation + + ## Prometheus server Ingress TLS configuration + ## Secrets must be manually created in the namespace + ## + tls: [] + # - secretName: prometheus-server-tls + # hosts: + # - prometheus.domain.com + + ## Server Deployment Strategy type + strategy: + type: RollingUpdate + + ## hostAliases allows adding entries to /etc/hosts inside the containers + hostAliases: [] + # - ip: "127.0.0.1" + # hostnames: + # - "example.com" + + ## Node tolerations for server scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + ## Node labels for Prometheus server pod assignment + ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Pod affinity + ## + affinity: {} + + ## PodDisruptionBudget settings + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + ## + podDisruptionBudget: + enabled: false + maxUnavailable: 1 + + ## Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + # schedulerName: + + persistentVolume: + ## If true, Prometheus server will create/use a Persistent Volume Claim + ## If false, use emptyDir + ## + enabled: true + + ## Prometheus server data Persistent Volume access modes + ## Must match those of existing PV or dynamic provisioner + ## Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + accessModes: + - ReadWriteOnce + + ## Prometheus server data Persistent Volume annotations + ## + annotations: {} + + ## Prometheus server data Persistent Volume existing claim name + ## Requires server.persistentVolume.enabled: true + ## If defined, PVC must be created manually before volume will be bound + existingClaim: "" + + ## Prometheus server data Persistent Volume mount root path + ## + mountPath: /data + + ## Prometheus server data Persistent Volume size + ## + size: 8Gi + + ## Prometheus server data Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + # storageClass: "-" + + ## Prometheus server data Persistent Volume Binding Mode + ## If defined, volumeBindingMode: + ## If undefined (the default) or set to null, no volumeBindingMode spec is + ## set, choosing the default mode. + ## + # volumeBindingMode: "" + + ## Subdirectory of Prometheus server data Persistent Volume to mount + ## Useful if the volume's root directory is not empty + ## + subPath: "" + + ## Persistent Volume Claim Selector + ## Useful if Persistent Volumes have been provisioned in advance + ## Ref: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#selector + ## + # selector: + # matchLabels: + # release: "stable" + # matchExpressions: + # - { key: environment, operator: In, values: [ dev ] } + + emptyDir: + ## Prometheus server emptyDir volume size limit + ## + sizeLimit: "" + + ## Annotations to be added to Prometheus server pods + ## + podAnnotations: {} + # iam.amazonaws.com/role: prometheus + + ## Labels to be added to Prometheus server pods + ## + podLabels: {} + + ## Prometheus AlertManager configuration + ## + alertmanagers: [] + + ## Specify if a Pod Security Policy for node-exporter must be created + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + ## + podSecurityPolicy: + annotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + ## Use a StatefulSet if replicaCount needs to be greater than 1 (see below) + ## + replicaCount: 1 + + ## Annotations to be added to deployment + ## + deploymentAnnotations: {} + + statefulSet: + ## If true, use a statefulset instead of a deployment for pod management. + ## This allows to scale replicas to more than 1 pod + ## + enabled: false + + annotations: {} + labels: {} + podManagementPolicy: OrderedReady + + ## Alertmanager headless service to use for the statefulset + ## + headless: + annotations: {} + labels: {} + servicePort: 80 + ## Enable gRPC port on service to allow auto discovery with thanos-querier + gRPC: + enabled: false + servicePort: 10901 + # nodePort: 10901 + + ## Prometheus server readiness and liveness probe initial delay and timeout + ## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ + ## + tcpSocketProbeEnabled: false + probeScheme: HTTP + readinessProbeInitialDelay: 30 + readinessProbePeriodSeconds: 5 + readinessProbeTimeout: 4 + readinessProbeFailureThreshold: 3 + readinessProbeSuccessThreshold: 1 + livenessProbeInitialDelay: 30 + livenessProbePeriodSeconds: 15 + livenessProbeTimeout: 10 + livenessProbeFailureThreshold: 3 + livenessProbeSuccessThreshold: 1 + startupProbe: + enabled: false + periodSeconds: 5 + failureThreshold: 30 + timeoutSeconds: 10 + + ## Prometheus server resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + limits: + cpu: 1000m + memory: 512Mi + requests: + cpu: 500m + memory: 512Mi + + # Required for use in managed kubernetes clusters (such as AWS EKS) with custom CNI (such as calico), + # because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working + ## + hostNetwork: false + + # When hostNetwork is enabled, you probably want to set this to ClusterFirstWithHostNet + dnsPolicy: ClusterFirst + + # Use hostPort + # hostPort: 9090 + + ## Vertical Pod Autoscaler config + ## Ref: https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler + verticalAutoscaler: + ## If true a VPA object will be created for the controller (either StatefulSet or Deployemnt, based on above configs) + enabled: false + # updateMode: "Auto" + # containerPolicies: + # - containerName: 'prometheus-server' + + # Custom DNS configuration to be added to prometheus server pods + dnsConfig: {} + # nameservers: + # - 1.2.3.4 + # searches: + # - ns1.svc.cluster-domain.example + # - my.dns.search.suffix + # options: + # - name: ndots + # value: "2" + # - name: edns0 + ## Security context to be added to server pods + ## + securityContext: + runAsUser: 65534 + runAsNonRoot: true + runAsGroup: 65534 + fsGroup: 65534 + + service: + ## If false, no Service will be created for the Prometheus server + ## + enabled: true + + annotations: {} + labels: {} + clusterIP: "" + + ## List of IP addresses at which the Prometheus server service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + externalIPs: [] + + loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 80 + sessionAffinity: None + type: ClusterIP + + ## Enable gRPC port on service to allow auto discovery with thanos-querier + gRPC: + enabled: false + servicePort: 10901 + # nodePort: 10901 + + ## If using a statefulSet (statefulSet.enabled=true), configure the + ## service to connect to a specific replica to have a consistent view + ## of the data. + statefulsetReplica: + enabled: false + replica: 0 + + ## Prometheus server pod termination grace period + ## + terminationGracePeriodSeconds: 300 + + ## Prometheus data retention period (default if not specified is 15 days) + ## + retention: "15d" + + ## Array of extra Kubernetes manifests, if you want to deploy + extraObjects: [] + +pushgateway: + ## If false, pushgateway will not be installed + ## + enabled: true + + ## Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + # schedulerName: + + ## pushgateway container name + ## + name: pushgateway + + ## pushgateway container image + ## + image: + repository: prom/pushgateway + tag: v1.4.2 + pullPolicy: IfNotPresent + + ## pushgateway priorityClassName + ## + priorityClassName: "" + + ## Additional pushgateway container arguments + ## + ## for example: persistence.file: /data/pushgateway.data + extraArgs: {} + + ## Additional InitContainers to initialize the pod + ## + extraInitContainers: [] + + ingress: + ## If true, pushgateway Ingress will be created + ## + enabled: false + + # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName + # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress + # ingressClassName: nginx + + ## pushgateway Ingress annotations + ## + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: 'true' + + ## pushgateway Ingress hostnames with optional path + ## Must be provided if Ingress is enabled + ## + hosts: [] + # - pushgateway.domain.com + # - domain.com/pushgateway + + path: / + + # pathType is only for k8s >= 1.18 + pathType: Prefix + + ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. + extraPaths: [] + # - path: /* + # backend: + # serviceName: ssl-redirect + # servicePort: use-annotation + + ## pushgateway Ingress TLS configuration + ## Secrets must be manually created in the namespace + ## + tls: [] + # - secretName: prometheus-alerts-tls + # hosts: + # - pushgateway.domain.com + + ## Node tolerations for pushgateway scheduling to nodes with taints + ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + ## + tolerations: [] + # - key: "key" + # operator: "Equal|Exists" + # value: "value" + # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" + + ## Node labels for pushgateway pod assignment + ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Annotations to be added to pushgateway pods + ## + podAnnotations: {} + + ## Labels to be added to pushgateway pods + ## + podLabels: {} + + ## Specify if a Pod Security Policy for node-exporter must be created + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ + ## + podSecurityPolicy: + annotations: {} + ## Specify pod annotations + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp + ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl + ## + # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*' + # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + + replicaCount: 1 + + ## Annotations to be added to deployment + ## + deploymentAnnotations: {} + + ## PodDisruptionBudget settings + ## ref: https://kubernetes.io/docs/concepts/workloads/pods/disruptions/ + ## + podDisruptionBudget: + enabled: false + maxUnavailable: 1 + + ## pushgateway resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + limits: + cpu: 100m + memory: 100Mi + requests: + cpu: 50m + memory: 50Mi + + ## Vertical Pod Autoscaler config + ## Ref: https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler + verticalAutoscaler: + ## If true a VPA object will be created for the controller + enabled: false + # updateMode: "Auto" + # containerPolicies: + # - containerName: 'prometheus-pushgateway' + + # Custom DNS configuration to be added to push-gateway pods + dnsConfig: {} + # nameservers: + # - 1.2.3.4 + # searches: + # - ns1.svc.cluster-domain.example + # - my.dns.search.suffix + # options: + # - name: ndots + # value: "2" + # - name: edns0 + + ## Security context to be added to push-gateway pods + ## + securityContext: + runAsUser: 65534 + runAsNonRoot: true + + service: + annotations: + prometheus.io/probe: pushgateway + labels: {} + clusterIP: "" + + ## List of IP addresses at which the pushgateway service is available + ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips + ## + externalIPs: [] + + loadBalancerIP: "" + loadBalancerSourceRanges: [] + servicePort: 9091 + type: ClusterIP + + ## pushgateway Deployment Strategy type + # strategy: + # type: Recreate + + persistentVolume: + ## If true, pushgateway will create/use a Persistent Volume Claim + ## + enabled: false + + ## pushgateway data Persistent Volume access modes + ## Must match those of existing PV or dynamic provisioner + ## Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ + ## + accessModes: + - ReadWriteOnce + + ## pushgateway data Persistent Volume Claim annotations + ## + annotations: {} + + ## pushgateway data Persistent Volume existing claim name + ## Requires pushgateway.persistentVolume.enabled: true + ## If defined, PVC must be created manually before volume will be bound + existingClaim: "" + + ## pushgateway data Persistent Volume mount root path + ## + mountPath: /data + + ## pushgateway data Persistent Volume size + ## + size: 2Gi + + ## pushgateway data Persistent Volume Storage Class + ## If defined, storageClassName: + ## If set to "-", storageClassName: "", which disables dynamic provisioning + ## If undefined (the default) or set to null, no storageClassName spec is + ## set, choosing the default provisioner. (gp2 on AWS, standard on + ## GKE, AWS & OpenStack) + ## + # storageClass: "-" + + ## pushgateway data Persistent Volume Binding Mode + ## If defined, volumeBindingMode: + ## If undefined (the default) or set to null, no volumeBindingMode spec is + ## set, choosing the default mode. + ## + # volumeBindingMode: "" + + ## Subdirectory of pushgateway data Persistent Volume to mount + ## Useful if the volume's root directory is not empty + ## + subPath: "" + + +## alertmanager ConfigMap entries +## +alertmanagerFiles: + alertmanager.yml: + global: {} + # slack_api_url: '' + + receivers: + - name: default-receiver + # slack_configs: + # - channel: '@you' + # send_resolved: true + + route: + group_wait: 10s + group_interval: 5m + receiver: default-receiver + repeat_interval: 3h + +## Prometheus server ConfigMap entries for rule files (allow prometheus labels interpolation) +ruleFiles: {} + +## Prometheus server ConfigMap entries +## +serverFiles: + + ## Alerts configuration + ## Ref: https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/ + alerting_rules.yml: {} + # groups: + # - name: Instances + # rules: + # - alert: InstanceDown + # expr: up == 0 + # for: 5m + # labels: + # severity: page + # annotations: + # description: '{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes.' + # summary: 'Instance {{ $labels.instance }} down' + ## DEPRECATED DEFAULT VALUE, unless explicitly naming your files, please use alerting_rules.yml + alerts: {} + + ## Records configuration + ## Ref: https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/ + recording_rules.yml: {} + ## DEPRECATED DEFAULT VALUE, unless explicitly naming your files, please use recording_rules.yml + rules: {} + + prometheus.yml: + rule_files: + - /etc/config/recording_rules.yml + - /etc/config/alerting_rules.yml + ## Below two files are DEPRECATED will be removed from this default values file + - /etc/config/rules + - /etc/config/alerts + + scrape_configs: + - job_name: prometheus + static_configs: + - targets: + - localhost:9090 + + # A scrape configuration for running Prometheus on a Kubernetes cluster. + # This uses separate scrape configs for cluster components (i.e. API server, node) + # and services to allow each to use different authentication configs. + # + # Kubernetes labels will be added as Prometheus labels on metrics via the + # `labelmap` relabeling action. + + # Scrape config for API servers. + # + # Kubernetes exposes API servers as endpoints to the default/kubernetes + # service so this uses `endpoints` role and uses relabelling to only keep + # the endpoints associated with the default/kubernetes service using the + # default named port `https`. This works for single API server deployments as + # well as HA API server deployments. + - job_name: 'kubernetes-apiservers' + + kubernetes_sd_configs: + - role: endpoints + + # Default to scraping over https. If required, just disable this or change to + # `http`. + scheme: https + + # This TLS & bearer token file config is used to connect to the actual scrape + # endpoints for cluster components. This is separate to discovery auth + # configuration because discovery & scraping are two separate concerns in + # Prometheus. The discovery auth config is automatic if Prometheus runs inside + # the cluster. Otherwise, more config options have to be provided within the + # . + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + # If your node certificates are self-signed or use a different CA to the + # master CA, then disable certificate verification below. Note that + # certificate verification is an integral part of a secure infrastructure + # so this should only be disabled in a controlled environment. You can + # disable certificate verification by uncommenting the line below. + # + insecure_skip_verify: true + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + # Keep only the default/kubernetes service endpoints for the https port. This + # will add targets for each API server which Kubernetes adds an endpoint to + # the default/kubernetes service. + relabel_configs: + - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] + action: keep + regex: default;kubernetes;https + + - job_name: 'kubernetes-nodes' + + # Default to scraping over https. If required, just disable this or change to + # `http`. + scheme: https + + # This TLS & bearer token file config is used to connect to the actual scrape + # endpoints for cluster components. This is separate to discovery auth + # configuration because discovery & scraping are two separate concerns in + # Prometheus. The discovery auth config is automatic if Prometheus runs inside + # the cluster. Otherwise, more config options have to be provided within the + # . + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + # If your node certificates are self-signed or use a different CA to the + # master CA, then disable certificate verification below. Note that + # certificate verification is an integral part of a secure infrastructure + # so this should only be disabled in a controlled environment. You can + # disable certificate verification by uncommenting the line below. + # + insecure_skip_verify: true + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + kubernetes_sd_configs: + - role: node + + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/$1/proxy/metrics + + + - job_name: 'kubernetes-nodes-cadvisor' + + # Default to scraping over https. If required, just disable this or change to + # `http`. + scheme: https + + # This TLS & bearer token file config is used to connect to the actual scrape + # endpoints for cluster components. This is separate to discovery auth + # configuration because discovery & scraping are two separate concerns in + # Prometheus. The discovery auth config is automatic if Prometheus runs inside + # the cluster. Otherwise, more config options have to be provided within the + # . + tls_config: + ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + # If your node certificates are self-signed or use a different CA to the + # master CA, then disable certificate verification below. Note that + # certificate verification is an integral part of a secure infrastructure + # so this should only be disabled in a controlled environment. You can + # disable certificate verification by uncommenting the line below. + # + insecure_skip_verify: true + bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token + + kubernetes_sd_configs: + - role: node + + # This configuration will work only on kubelet 1.7.3+ + # As the scrape endpoints for cAdvisor have changed + # if you are using older version you need to change the replacement to + # replacement: /api/v1/nodes/$1:4194/proxy/metrics + # more info here https://github.com/coreos/prometheus-operator/issues/633 + relabel_configs: + - action: labelmap + regex: __meta_kubernetes_node_label_(.+) + - target_label: __address__ + replacement: kubernetes.default.svc:443 + - source_labels: [__meta_kubernetes_node_name] + regex: (.+) + target_label: __metrics_path__ + replacement: /api/v1/nodes/$1/proxy/metrics/cadvisor + + # Scrape config for service endpoints. + # + # The relabeling allows the actual service scrape endpoint to be configured + # via the following annotations: + # + # * `prometheus.io/scrape`: Only scrape services that have a value of + # `true`, except if `prometheus.io/scrape-slow` is set to `true` as well. + # * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need + # to set this to `https` & most likely set the `tls_config` of the scrape config. + # * `prometheus.io/path`: If the metrics path is not `/metrics` override this. + # * `prometheus.io/port`: If the metrics are exposed on a different port to the + # service then set this appropriately. + # * `prometheus.io/param_`: If the metrics endpoint uses parameters + # then you can set any parameter + - job_name: 'kubernetes-service-endpoints' + honor_labels: true + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape_slow] + action: drop + regex: true + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] + action: replace + target_label: __scheme__ + regex: (https?) + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + target_label: __address__ + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + - action: labelmap + regex: __meta_kubernetes_service_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: service + - source_labels: [__meta_kubernetes_pod_node_name] + action: replace + target_label: node + + # Scrape config for slow service endpoints; same as above, but with a larger + # timeout and a larger interval + # + # The relabeling allows the actual service scrape endpoint to be configured + # via the following annotations: + # + # * `prometheus.io/scrape-slow`: Only scrape services that have a value of `true` + # * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need + # to set this to `https` & most likely set the `tls_config` of the scrape config. + # * `prometheus.io/path`: If the metrics path is not `/metrics` override this. + # * `prometheus.io/port`: If the metrics are exposed on a different port to the + # service then set this appropriately. + # * `prometheus.io/param_`: If the metrics endpoint uses parameters + # then you can set any parameter + - job_name: 'kubernetes-service-endpoints-slow' + honor_labels: true + + scrape_interval: 5m + scrape_timeout: 30s + + kubernetes_sd_configs: + - role: endpoints + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape_slow] + action: keep + regex: true + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] + action: replace + target_label: __scheme__ + regex: (https?) + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] + action: replace + target_label: __address__ + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + - action: labelmap + regex: __meta_kubernetes_service_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_service_name] + action: replace + target_label: service + - source_labels: [__meta_kubernetes_pod_node_name] + action: replace + target_label: node + + - job_name: 'prometheus-pushgateway' + honor_labels: true + + kubernetes_sd_configs: + - role: service + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] + action: keep + regex: pushgateway + + # Example scrape config for probing services via the Blackbox Exporter. + # + # The relabeling allows the actual service scrape endpoint to be configured + # via the following annotations: + # + # * `prometheus.io/probe`: Only probe services that have a value of `true` + - job_name: 'kubernetes-services' + honor_labels: true + + metrics_path: /probe + params: + module: [http_2xx] + + kubernetes_sd_configs: + - role: service + + relabel_configs: + - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] + action: keep + regex: true + - source_labels: [__address__] + target_label: __param_target + - target_label: __address__ + replacement: blackbox + - source_labels: [__param_target] + target_label: instance + - action: labelmap + regex: __meta_kubernetes_service_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + target_label: namespace + - source_labels: [__meta_kubernetes_service_name] + target_label: service + + # Example scrape config for pods + # + # The relabeling allows the actual pod scrape endpoint to be configured via the + # following annotations: + # + # * `prometheus.io/scrape`: Only scrape pods that have a value of `true`, + # except if `prometheus.io/scrape-slow` is set to `true` as well. + # * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need + # to set this to `https` & most likely set the `tls_config` of the scrape config. + # * `prometheus.io/path`: If the metrics path is not `/metrics` override this. + # * `prometheus.io/port`: Scrape the pod on the indicated port instead of the default of `9102`. + - job_name: 'kubernetes-pods' + honor_labels: true + + kubernetes_sd_configs: + - role: pod + + relabel_configs: + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] + action: keep + regex: true + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape_slow] + action: drop + regex: true + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme] + action: replace + regex: (https?) + target_label: __scheme__ + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] + action: replace + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: pod + - source_labels: [__meta_kubernetes_pod_phase] + regex: Pending|Succeeded|Failed|Completed + action: drop + + # Example Scrape config for pods which should be scraped slower. An useful example + # would be stackriver-exporter which queries an API on every scrape of the pod + # + # The relabeling allows the actual pod scrape endpoint to be configured via the + # following annotations: + # + # * `prometheus.io/scrape-slow`: Only scrape pods that have a value of `true` + # * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need + # to set this to `https` & most likely set the `tls_config` of the scrape config. + # * `prometheus.io/path`: If the metrics path is not `/metrics` override this. + # * `prometheus.io/port`: Scrape the pod on the indicated port instead of the default of `9102`. + - job_name: 'kubernetes-pods-slow' + honor_labels: true + + scrape_interval: 5m + scrape_timeout: 30s + + kubernetes_sd_configs: + - role: pod + + relabel_configs: + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape_slow] + action: keep + regex: true + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme] + action: replace + regex: (https?) + target_label: __scheme__ + - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] + action: replace + target_label: __metrics_path__ + regex: (.+) + - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] + action: replace + regex: ([^:]+)(?::\d+)?;(\d+) + replacement: $1:$2 + target_label: __address__ + - action: labelmap + regex: __meta_kubernetes_pod_annotation_prometheus_io_param_(.+) + replacement: __param_$1 + - action: labelmap + regex: __meta_kubernetes_pod_label_(.+) + - source_labels: [__meta_kubernetes_namespace] + action: replace + target_label: namespace + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: pod + - source_labels: [__meta_kubernetes_pod_phase] + regex: Pending|Succeeded|Failed|Completed + action: drop + +# adds additional scrape configs to prometheus.yml +# must be a string so you have to add a | after extraScrapeConfigs: +# example adds prometheus-blackbox-exporter scrape config +extraScrapeConfigs: + # - job_name: 'prometheus-blackbox-exporter' + # metrics_path: /probe + # params: + # module: [http_2xx] + # static_configs: + # - targets: + # - https://example.com + # relabel_configs: + # - source_labels: [__address__] + # target_label: __param_target + # - source_labels: [__param_target] + # target_label: instance + # - target_label: __address__ + # replacement: prometheus-blackbox-exporter:9115 + +# Adds option to add alert_relabel_configs to avoid duplicate alerts in alertmanager +# useful in H/A prometheus with different external labels but the same alerts +alertRelabelConfigs: + # alert_relabel_configs: + # - source_labels: [dc] + # regex: (.+)\d+ + # target_label: dc + +networkPolicy: + ## Enable creation of NetworkPolicy resources. + ## + enabled: false + +# Force namespace of namespaced resources +forceNamespace: null diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/templates/_helpers.tpl b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/templates/_helpers.tpl new file mode 100644 index 000000000..dc2bb70f8 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/templates/_helpers.tpl @@ -0,0 +1,40 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "monitoring.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 "monitoring.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 "monitoring.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Override the naming defined by the prometheus chart. +Added as a fix for https://github.com/grafana/loki/issues/1169 +*/}} +{{- define "prometheus.fullname" -}} +{{- printf "%s-%s" .Release.Name "prometheus-server" | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/templates/datasources.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/templates/datasources.yaml new file mode 100644 index 000000000..49234cfca --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/monitoring/templates/datasources.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "monitoring.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "monitoring.name" . }} + chart: {{ template "monitoring.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + app.kubernetes.io/instance: {{ template "monitoring.name" . }} + {{- include "k8s-triliovault-operator.labels" . | nindent 4 }} + grafana_datasource: "1" +data: + monitoring-datasource.yaml: |- + apiVersion: 1 + datasources: +{{- if .Values.prometheus.enabled }} + - name: Prometheus + type: prometheus + access: proxy + isDefault: true + url: http://{{ include "prometheus.fullname" .}}:{{ .Values.prometheus.server.service.servicePort }}{{ .Values.prometheus.server.prefixURL }} + version: 1 +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/Chart.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/Chart.yaml new file mode 100644 index 000000000..12fa0fc95 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/Chart.yaml @@ -0,0 +1,16 @@ +apiVersion: v2 +appVersion: 0.1.0 +dependencies: +- condition: grafana.enabled + name: grafana + repository: https://grafana.github.io/helm-charts + version: ^6.29.2 +description: Visualization Stack designed to manage the K8s-TrilioVault Application's + Visualization. +icon: https://www.trilio.io/wp-content/uploads/2021/01/Trilio-2020-logo-RGB-gray-green.png +kubeVersion: '>=1.19.0-0' +maintainers: +- email: support@trilio.io + name: Trilio +name: visualization +version: 0.1.0 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/Chart.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/Chart.yaml new file mode 100644 index 000000000..5a3ffe454 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +appVersion: 8.5.0 +description: The leading tool for querying and visualizing time series and metrics. +home: https://grafana.net +icon: https://raw.githubusercontent.com/grafana/grafana/master/public/img/logo_transparent_400x.png +kubeVersion: ^1.8.0-0 +maintainers: +- email: support@trilio.io + name: Trilio +name: grafana +sources: +- https://github.com/grafana/grafana +type: application +version: 6.29.2 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backup-detail.json b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backup-detail.json new file mode 100644 index 000000000..2c735b766 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backup-detail.json @@ -0,0 +1,956 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + }, + { + "name": "DS_LOKI", + "label": "Loki", + "description": "", + "type": "datasource", + "pluginId": "loki", + "pluginName": "Loki" + } + ], + "__elements": [], + "__requires": [ + { + "type": "panel", + "id": "gauge", + "name": "Gauge", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.5.0" + }, + { + "type": "panel", + "id": "logs", + "name": "Logs", + "version": "" + }, + { + "type": "datasource", + "id": "loki", + "name": "Loki", + "version": "1.0.0" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + }, + { + "type": "panel", + "id": "table-old", + "name": "Table (old)", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:20", + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 12601, + "graphTooltip": 0, + "id": null, + "iteration": 1655279666650, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 2, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 31, + "options": { + "content": "

Backup Detail

", + "mode": "html" + }, + "pluginVersion": "8.5.0", + "transparent": true, + "type": "text" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "rgb(255, 255, 255)", + "value": 1 + }, + { + "color": "dark-green", + "value": 100 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 7, + "x": 0, + "y": 2 + }, + "id": 45, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_backup_status_percentage{backup=~\"$Backup\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "transparent": true, + "type": "gauge" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 4, + "x": 8, + "y": 2 + }, + "id": 50, + "links": [], + "maxDataPoints": 100, + "options": { + "content": "", + "mode": "markdown" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_backup_info{backup=~\"$Backup\",namespace=~\"$Namespace\",cluster=~\"$Cluster\"}", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "transparent": true, + "type": "text" + }, + { + "columns": [], + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fontSize": "100%", + "gridPos": { + "h": 14, + "w": 12, + "x": 12, + "y": 2 + }, + "id": 42, + "links": [], + "showHeader": true, + "sort": { + "col": 18, + "desc": true + }, + "styles": [ + { + "$$hashKey": "object:10447", + "alias": "Object Type", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "link": true, + "linkTooltip": "Show Metadata Details", + "linkUrl": "/d/0aiPMQMGk/metadata-detail?var-Backup=${Backup}&var-ObjectType=${__cell}&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}", + "mappingType": 1, + "pattern": "objecttype", + "type": "string" + }, + { + "$$hashKey": "object:1072", + "alias": "Source", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "applicationtype", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:1249", + "alias": "Count", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:10448", + "alias": "", + "align": "right", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "avg(trilio_backup_metadata_info{backup=~\"$Backup\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (objecttype, applicationtype)", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Metadata Info", + "transform": "table", + "type": "table-old" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "0": { + "text": "InProgress" + }, + "1": { + "text": "Available" + }, + "-1": { + "text": "Failed" + }, + "-2": { + "text": "UnKnown" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "dark-red", + "value": -1 + }, + { + "color": "blue", + "value": 0 + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 5, + "x": 7, + "y": 3 + }, + "id": 46, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "mean" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "", + "values": false + }, + "textMode": "value" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_backup_info{backup=~\"$Backup\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 6 + }, + "id": 47, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^backup$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_backup_info{ backup=~\"$Backup\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Name", + "type": "stat" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 6, + "y": 6 + }, + "id": 36, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^backupplan$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_backup_info{ backup=~\"$Backup\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Backup Plan", + "type": "stat" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "align": "left", + "displayMode": "auto", + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "First" + }, + "properties": [ + { + "id": "displayName", + "value": "Value" + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 49, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_backup_info{ backup=~\"$Backup\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Details", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "Time", + "applicationtype", + "backup_type", + "completion_ts", + "hook", + "size", + "start_ts", + "target", + "resource_namespace" + ] + } + } + }, + { + "id": "reduce", + "options": { + "reducers": [ + "first" + ] + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "description": "Backup Logs", + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 52, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "expr": "{transaction_type=\"Backup\",transaction_resource_name=~\"$Backup\",transaction_id=~\"$transaction_id\",service_type=~\"$service_type\",service_id=~\"$service_id\"}", + "refId": "A" + } + ], + "title": "Backup Logs", + "type": "logs" + } + ], + "refresh": "10s", + "schemaVersion": 36, + "style": "dark", + "tags": [ + "logging" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 2, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": false, + "text": "Loki", + "value": "Loki" + }, + "description": "loki datasource", + "hide": 2, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_LOKI", + "options": [], + "query": "loki", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "Cluster", + "options": [], + "query": { + "query": "trilio_system_info", + "refId": "Prometheus-Cluster-Variable-Query" + }, + "refresh": 1, + "regex": "/.*cluster=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info{cluster=~\"$Cluster\"}", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "Scope", + "options": [], + "query": { + "query": "trilio_system_info{cluster=~\"$Cluster\"}", + "refId": "Prometheus-Scope-Variable-Query" + }, + "refresh": 1, + "regex": "/.*scope=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "hide": 0, + "includeAll": false, + "label": "Install Namespace", + "multi": false, + "name": "Install_Namespace", + "options": [], + "query": { + "query": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "refId": "Prometheus-Install_Namespace-Variable-Query" + }, + "refresh": 2, + "regex": "/.*install_namespace=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_backup_info{cluster=~\"$Cluster\",install_namespace=~\"$Install_Namespace\"}", + "hide": 0, + "includeAll": false, + "label": "Backup", + "multi": false, + "name": "Backup", + "options": [], + "query": { + "query": "trilio_backup_info{cluster=~\"$Cluster\",install_namespace=~\"$Install_Namespace\"}", + "refId": "Prometheus-Backup-Variable-Query" + }, + "refresh": 2, + "regex": "/.*backup=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=~\"Backup\",transaction_resource_name=~\"$Backup\"},transaction_resource_namespace)", + "description": "Resource Namespace", + "hide": 0, + "includeAll": false, + "label": "Resource Namespace", + "multi": false, + "name": "Resource_Namespace", + "options": [], + "query": "label_values({transaction_type=~\"Backup\",transaction_resource_name=~\"$Backup\"},transaction_resource_namespace)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=~\"Backup\",transaction_resource_name=~\"$Backup\",transaction_resource_namespace=~\"$Resource_Namespace\"},transaction_id)", + "description": "Transaction ID", + "hide": 0, + "includeAll": false, + "label": "Transaction ID", + "multi": false, + "name": "transaction_id", + "options": [], + "query": "label_values({transaction_type=~\"Backup\",transaction_resource_name=~\"$Backup\",transaction_resource_namespace=~\"$Resource_Namespace\"},transaction_id)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=~\"Backup\",transaction_resource_name=~\"$Backup\",transaction_id=~\"$transaction_id\"}, service_type)", + "description": "Service Type", + "hide": 0, + "includeAll": false, + "label": "Service Type", + "multi": false, + "name": "service_type", + "options": [], + "query": "label_values({transaction_type=~\"Backup\",transaction_resource_name=~\"$Backup\",transaction_id=~\"$transaction_id\"}, service_type)", + "refresh": 2, + "regex": "/(Unquiesce|Quiesce|MetaSnapshot|DataSnapshot|DataUpload|Snapshot|MetadataUpload|Retention|Upload)$/", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=~\"Backup\",transaction_resource_name=~\"$Backup\",transaction_id=~\"$transaction_id\",service_type=~\"$service_type\"}, service_id)", + "description": "Service ID", + "hide": 0, + "includeAll": false, + "label": "Service ID", + "multi": false, + "name": "service_id", + "options": [], + "query": "label_values({transaction_type=~\"Backup\",transaction_resource_name=~\"$Backup\",transaction_id=~\"$transaction_id\",service_type=~\"$service_type\"}, service_id)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Backup Detail", + "uid": "J4pftrfZk", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backup-overview.json b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backup-overview.json new file mode 100644 index 000000000..7c017c628 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backup-overview.json @@ -0,0 +1,762 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.2.1" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table-old", + "name": "Table (old)", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "7.1.0" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:14091", + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": 12600, + "graphTooltip": 0, + "id": null, + "iteration": 1617300317993, + "links": [], + "panels": [ + { + "content": "

Backups Overview

", + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 4, + "mode": "html", + "options": { + "content": "

Backups Overview

", + "mode": "html" + }, + "pluginVersion": "7.1.0", + "timeFrom": null, + "timeShift": null, + "title": "", + "transparent": true, + "type": "text" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(115, 181, 181)", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 2, + "y": 2 + }, + "id": 31, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^All$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_backup_info{install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) ", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "All", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "All", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 6, + "y": 2 + }, + "id": 34, + "links": [], + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^Available$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_backup_info{status=\"Available\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (status)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Available", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [ + { + "from": "", + "id": 0, + "operator": "", + "text": "", + "to": "", + "type": 1 + } + ], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 10, + "y": 2 + }, + "id": 33, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^Failed$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_backup_info{status=\"Failed\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (status)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Failed", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 14, + "y": 2 + }, + "id": 32, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^InProgress$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_backup_info{status=\"InProgress\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (status)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "InProgress", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(129, 135, 135)", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 18, + "y": 2 + }, + "id": 37, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^UnKnown$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_backup_info{status=\"UnKnown\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (status)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "UnKnown", + "transparent": true, + "type": "stat" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fontSize": "100%", + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 29, + "pageSize": null, + "showHeader": true, + "sort": { + "col": 6, + "desc": true + }, + "styles": [ + { + "$$hashKey": "object:14951", + "alias": "Backup", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "Backup Detail", + "linkUrl": "/d/J4pftrfZk/backup-detail?refresh=5s&var-Backup=${__cell}&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}", + "mappingType": 1, + "pattern": "backup", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:15011", + "alias": "Backup Plan", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "backupplan", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:15022", + "alias": "Completion", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss.SSS", + "decimals": 2, + "mappingType": 1, + "pattern": "completion_ts", + "thresholds": [], + "type": "date", + "unit": "short" + }, + { + "$$hashKey": "object:15033", + "alias": "Target", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": true, + "linkTooltip": "Target Detail", + "linkUrl": "/d/OddeflXdk/target-detail?refresh=5s&var-Target=${__cell}&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}", + "mappingType": 1, + "pattern": "target", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:15093", + "alias": "Size", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": null, + "mappingType": 1, + "pattern": "size", + "thresholds": [], + "type": "number", + "unit": "decbytes" + }, + { + "$$hashKey": "object:15104", + "alias": "Percentage", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": null, + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "percent" + }, + { + "$$hashKey": "object:11270", + "alias": "Status", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "status", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:299", + "alias": "Backup Type", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "backup_type", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:18392", + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "trilio_backup_status_percentage{status=~\"$Status\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "", + "transform": "table", + "type": "table-old" + } + ], + "refresh": "5s", + "schemaVersion": 26, + "style": "dark", + "tags": [ + "logging" + ], + "templating": { + "list": [ + { + "hide": 2, + "label": "datasource", + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_system_info", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "Cluster", + "options": [], + "query": "trilio_system_info", + "refresh": 1, + "regex": "/.*cluster=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_system_info{cluster=~\"$Cluster\"}", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "Scope", + "options": [], + "query": "trilio_system_info{cluster=~\"$Cluster\"}", + "refresh": 1, + "regex": "/.*scope=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "hide": 0, + "includeAll": false, + "label": "Install Namespace", + "multi": false, + "name": "Install_Namespace", + "options": [], + "query": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "refresh": 1, + "regex": "/.*install_namespace=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_backup_info", + "hide": 0, + "includeAll": true, + "label": "Status", + "multi": false, + "name": "Status", + "options": [], + "query": "trilio_backup_info", + "refresh": 1, + "regex": "/.*status=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Backup Overview", + "uid": "J4pftrdZk", + "version": 4 +} \ No newline at end of file diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backupplan-detail.json b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backupplan-detail.json new file mode 100644 index 000000000..58e3a25c7 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backupplan-detail.json @@ -0,0 +1,965 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + }, + { + "name": "DS_LOKI", + "label": "Loki", + "description": "", + "type": "datasource", + "pluginId": "loki", + "pluginName": "Loki" + } + ], + "__elements": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.5.0" + }, + { + "type": "panel", + "id": "logs", + "name": "Logs", + "version": "" + }, + { + "type": "datasource", + "id": "loki", + "name": "Loki", + "version": "1.0.0" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table-old", + "name": "Table (old)", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:4254", + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 12605, + "graphTooltip": 0, + "id": null, + "iteration": 1655279331483, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 2, + "w": 23, + "x": 0, + "y": 0 + }, + "id": 4, + "options": { + "content": "

Backup Plan Detail

", + "mode": "html" + }, + "pluginVersion": "8.5.0", + "transparent": true, + "type": "text" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "0": { + "text": "InProgress" + }, + "1": { + "text": "Available" + }, + "-1": { + "text": "Failed" + }, + "-2": { + "text": "UnKnown" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "dark-red", + "value": -1 + }, + { + "color": "blue", + "value": 0 + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 0, + "y": 2 + }, + "id": 16, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "mean" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_backupplan_info{backupplan=~\"$BackupPlan\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Status", + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 5, + "y": 2 + }, + "id": 9, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^applicationtype$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_backupplan_info{ backupplan=~\"$BackupPlan\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Application Type", + "type": "stat" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "False" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 9, + "y": 2 + }, + "id": 10, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^protected$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_backupplan_info{ backupplan=~\"$BackupPlan\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Protected", + "type": "stat" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "0" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 13, + "y": 2 + }, + "id": 13, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^backup_count$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_backupplan_info{ backupplan=~\"$BackupPlan\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Num of Backups", + "type": "stat" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 17, + "y": 2 + }, + "id": 14, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^target$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_backupplan_info{ backupplan=~\"$BackupPlan\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Target", + "type": "stat" + }, + { + "columns": [], + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fontSize": "100%", + "gridPos": { + "h": 12, + "w": 12, + "x": 0, + "y": 5 + }, + "id": 12, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "$$hashKey": "object:14951", + "alias": "Backup", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "Backup Detail", + "linkUrl": "/d/J4pftrfZk/backup-detail?refresh=5s&var-Restore=${__cell}&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}", + "mappingType": 1, + "pattern": "backup", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:15022", + "alias": "Completion", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss.SSS", + "decimals": 2, + "mappingType": 1, + "pattern": "completion_ts", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [ + { + "$$hashKey": "object:735", + "text": "N/A", + "value": "" + } + ] + }, + { + "$$hashKey": "object:15033", + "alias": "Type", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "applicationtype", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:15093", + "alias": "Size", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "mappingType": 1, + "pattern": "size", + "thresholds": [], + "type": "number", + "unit": "decbytes" + }, + { + "$$hashKey": "object:15104", + "alias": "Status", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "status", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:948", + "alias": "Backup Type", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "backup_type", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:18392", + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_backup_info{backupplan=~\"$BackupPlan\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Backups", + "transform": "table", + "type": "table-old" + }, + { + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "description": "BackupPlan Logs", + "gridPos": { + "h": 12, + "w": 12, + "x": 12, + "y": 5 + }, + "id": 18, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "expr": "{transaction_type=\"BackupPlan\",transaction_resource_name=~\"$BackupPlan\",transaction_id=~\"$transaction_id\",service_type=~\"$service_type\"}", + "refId": "A" + } + ], + "title": "BackupPlan Logs", + "type": "logs" + } + ], + "refresh": "10s", + "schemaVersion": 36, + "style": "dark", + "tags": [ + "logging" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 2, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": false, + "text": "Loki", + "value": "Loki" + }, + "hide": 2, + "includeAll": false, + "label": "loki", + "multi": false, + "name": "DS_LOKI", + "options": [], + "query": "loki", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "Cluster", + "options": [], + "query": { + "query": "trilio_system_info", + "refId": "Prometheus-Cluster-Variable-Query" + }, + "refresh": 1, + "regex": "/.*cluster=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info{cluster=~\"$Cluster\"}", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "Scope", + "options": [], + "query": { + "query": "trilio_system_info{cluster=~\"$Cluster\"}", + "refId": "Prometheus-Scope-Variable-Query" + }, + "refresh": 1, + "regex": "/.*scope=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "hide": 0, + "includeAll": false, + "label": "Install Namespace", + "multi": false, + "name": "Install_Namespace", + "options": [], + "query": { + "query": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "refId": "Prometheus-Install_Namespace-Variable-Query" + }, + "refresh": 2, + "regex": "/.*install_namespace=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_backupplan_info{cluster=~\"$Cluster\"}", + "hide": 0, + "includeAll": false, + "label": "BackupPlan", + "multi": false, + "name": "BackupPlan", + "options": [], + "query": { + "query": "trilio_backupplan_info{cluster=~\"$Cluster\"}", + "refId": "Prometheus-BackupPlan-Variable-Query" + }, + "refresh": 2, + "regex": "/.*backupplan=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "definition": "label_values({transaction_type=\"BackupPlan\", transaction_resource_name=~\"$BackupPlan\"},transaction_resource_namespace)", + "description": "Resource Namespace", + "hide": 0, + "includeAll": false, + "label": "Resource Namespace", + "multi": false, + "name": "Resource_Namespace", + "options": [], + "query": { + "query": "label_values({transaction_type=\"BackupPlan\", transaction_resource_name=~\"$BackupPlan\"},transaction_resource_namespace)", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query", + "datasource": "${DS_PROMETHEUS}" + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=\"BackupPlan\", transaction_resource_name=~\"$BackupPlan\",transaction_resource_namespace=~\"$Resource_Namespace\"},transaction_id)", + "description": "Transaction ID", + "hide": 0, + "includeAll": false, + "label": "Transaction ID", + "multi": false, + "name": "transaction_id", + "options": [], + "query": "label_values({transaction_type=\"BackupPlan\", transaction_resource_name=~\"$BackupPlan\",transaction_resource_namespace=~\"$Resource_Namespace\"},transaction_id)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=\"BackupPlan\",transaction_resource_name=~\"$BackupPlan\",transaction_id=~\"$transaction_id\"}, service_type)", + "description": "Service Type", + "hide": 0, + "includeAll": false, + "label": "Service Type", + "multi": false, + "name": "service_type", + "options": [], + "query": "label_values({transaction_type=\"BackupPlan\",transaction_resource_name=~\"$BackupPlan\",transaction_id=~\"$transaction_id\"}, service_type)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=\"BackupPlan\",transaction_resource_name=~\"$BackupPlan\",transaction_id=~\"$transaction_id\",service_type=~\"$service_type\"}, service_id)", + "description": "Service ID", + "hide": 0, + "includeAll": false, + "label": "Service ID", + "multi": false, + "name": "service_id", + "options": [], + "query": "label_values({transaction_type=\"BackupPlan\",transaction_resource_name=~\"$BackupPlan\",transaction_id=~\"$transaction_id\",service_type=~\"$service_type\"}, service_id)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "BackupPlan Detail", + "uid": "J4pdtrbZk", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backupplan-overview.json b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backupplan-overview.json new file mode 100644 index 000000000..1b0a2c9e7 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/backupplan-overview.json @@ -0,0 +1,786 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.2.1" + }, + { + "type": "panel", + "id": "grafana-piechart-panel", + "name": "Pie Chart", + "version": "1.6.1" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table-old", + "name": "Table (old)", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "7.1.0" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:13226", + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": 12604, + "graphTooltip": 0, + "id": null, + "iteration": 1617300362017, + "links": [], + "panels": [ + { + "content": "

Backup Plan Overview

", + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 23, + "x": 0, + "y": 0 + }, + "id": 4, + "mode": "html", + "options": { + "content": "

Backup Plan Overview

", + "mode": "html" + }, + "pluginVersion": "7.1.0", + "timeFrom": null, + "timeShift": null, + "title": "", + "transparent": true, + "type": "text" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(46, 122, 122)", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 2, + "y": 2 + }, + "id": 34, + "links": [], + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^Available$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_backupplan_info{install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (status)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "All", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(105, 191, 145)", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 6, + "y": 2 + }, + "id": 35, + "links": [], + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "Helm", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_backupplan_info{applicationtype=\"Helm\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (applicationtype)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{applicationtype}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Helm", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(105, 191, 145)", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 10, + "y": 2 + }, + "id": 36, + "links": [], + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^Operator$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_backupplan_info{applicationtype=\"Operator\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (applicationtype)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{applicationtype}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Operator", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(105, 191, 145)", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 14, + "y": 2 + }, + "id": 37, + "links": [], + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^Custom$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_backupplan_info{applicationtype=\"Custom\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (applicationtype)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{applicationtype}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Custom", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(105, 191, 145)", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 18, + "y": 2 + }, + "id": 40, + "links": [], + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^Namespace$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_backupplan_info{applicationtype=\"Namespace\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (applicationtype)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{applicationtype}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Namespace", + "transparent": true, + "type": "stat" + }, + { + "aliasColors": {}, + "breakPoint": "50%", + "cacheTimeout": null, + "combine": { + "label": "Others", + "threshold": 0 + }, + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fontSize": "80%", + "format": "short", + "gridPos": { + "h": 8, + "w": 7, + "x": 0, + "y": 5 + }, + "id": 39, + "interval": null, + "legend": { + "header": "Protected", + "percentage": false, + "show": true, + "values": true + }, + "legendType": "Right side", + "links": [], + "maxDataPoints": 1, + "nullPointMode": "connected", + "pieType": "pie", + "strokeWidth": 1, + "targets": [ + { + "expr": "count(trilio_backupplan_info{applicationtype=~\"$ApplicationType\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (protected)", + "instant": true, + "interval": "", + "legendFormat": "{{protected}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Protected Backup Plan", + "transparent": true, + "type": "grafana-piechart-panel", + "valueName": "current" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 17, + "x": 7, + "y": 5 + }, + "id": 32, + "pageSize": null, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "$$hashKey": "object:13729", + "alias": "Backup Plan", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "Backup Plan Detail", + "linkUrl": "/d/J4pdtrbZk/backupplan-detail?refresh=5s&var-Application=${__cell}&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}", + "mappingType": 1, + "pattern": "backupplan", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:13730", + "alias": "Type", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "applicationtype", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:13731", + "alias": "Num of Backups", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss.SSS", + "decimals": null, + "mappingType": 1, + "pattern": "backup_count", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:13733", + "alias": "Protected", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "protected", + "thresholds": [], + "type": "number", + "unit": "decbytes" + }, + { + "$$hashKey": "object:13734", + "alias": "Last Protected", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "lastprotected", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [ + { + "$$hashKey": "object:20007", + "text": "N/A", + "value": "" + } + ] + }, + { + "$$hashKey": "object:17066", + "alias": "Target", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "Target Detail", + "linkUrl": "/d/OddeflXdk/target-detail?refresh=5s&var-Target=${__cell}&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}", + "mappingType": 1, + "pattern": "target", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:13735", + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "trilio_backupplan_info{applicationtype=~\"$ApplicationType\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "", + "transform": "table", + "type": "table-old" + } + ], + "refresh": "5s", + "schemaVersion": 26, + "style": "dark", + "tags": [ + "logging" + ], + "templating": { + "list": [ + { + "hide": 2, + "label": "datasource", + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_system_info", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "Cluster", + "options": [], + "query": "trilio_system_info", + "refresh": 1, + "regex": "/.*cluster=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_system_info{cluster=~\"$Cluster\"}", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "Scope", + "options": [], + "query": "trilio_system_info{cluster=~\"$Cluster\"}", + "refresh": 1, + "regex": "/.*scope=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "hide": 0, + "includeAll": false, + "label": "Install Namespace", + "multi": false, + "name": "Install_Namespace", + "options": [], + "query": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "refresh": 1, + "regex": "/.*install_namespace=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_backupplan_info", + "hide": 0, + "includeAll": true, + "label": "Application Type", + "multi": false, + "name": "ApplicationType", + "options": [], + "query": "trilio_backupplan_info", + "refresh": 1, + "regex": "/.*applicationtype=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "BackupPlan Overview", + "uid": "J4pdtraZk", + "version": 3 +} \ No newline at end of file diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/metadata-detail.json b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/metadata-detail.json new file mode 100644 index 000000000..db0d84bbd --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/metadata-detail.json @@ -0,0 +1,889 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.2.1" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table-old", + "name": "Table (old)", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "7.1.0" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:20", + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": 12607, + "graphTooltip": 0, + "id": null, + "iteration": 1617300281944, + "links": [], + "panels": [ + { + "content": "

Backup Metatdata

", + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 58, + "mode": "html", + "options": { + "content": "

Backup Metatdata

", + "mode": "html" + }, + "pluginVersion": "7.1.0", + "timeFrom": null, + "timeShift": null, + "title": "", + "transparent": true, + "type": "text" + }, + { + "content": "

Restore Metatdata

", + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 59, + "mode": "html", + "options": { + "content": "

Restore Metatdata

", + "mode": "html" + }, + "pluginVersion": "7.1.0", + "timeFrom": null, + "timeShift": null, + "title": "", + "transparent": true, + "type": "text" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(191, 194, 191)", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 2, + "y": 2 + }, + "id": 53, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(avg(trilio_backup_metadata_info{backup=~\"$Backup\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (objecttype))", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Component Type", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(191, 194, 191)", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 6, + "y": 2 + }, + "id": 54, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(avg(trilio_backup_metadata_info{backup=~\"$Backup\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (objectname))", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Components", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(191, 194, 191)", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 14, + "y": 2 + }, + "id": 55, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(avg(trilio_restore_metadata_info{restore=~\"$Restore\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (objecttype))", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Component Type", + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(191, 194, 191)", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 18, + "y": 2 + }, + "id": 56, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(avg(trilio_restore_metadata_info{restore=~\"$Restore\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (objectname))", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Total Components", + "type": "stat" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fontSize": "100%", + "gridPos": { + "h": 15, + "w": 12, + "x": 0, + "y": 5 + }, + "id": 42, + "links": [], + "pageSize": null, + "showHeader": true, + "sort": { + "col": 18, + "desc": true + }, + "styles": [ + { + "$$hashKey": "object:10447", + "alias": "Object Type", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "link": false, + "linkTooltip": "Show Metadata Details", + "linkUrl": "/d/0aiPMQMGk/metadata-detail?refresh=5s&var-Backup=${Backup}&var-ObjectType=${__cell}", + "mappingType": 1, + "pattern": "objecttype", + "type": "string" + }, + { + "$$hashKey": "object:1072", + "alias": "Source", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "applicationtype", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:1249", + "alias": "API Version", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": null, + "mappingType": 1, + "pattern": "apiversion", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:3063", + "alias": "Object Name", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "objectname", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:3158", + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:10448", + "alias": "", + "align": "right", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "avg(trilio_backup_metadata_info{backup=~\"$Backup\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (objectname,objecttype, apiversion)", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Metadata Info", + "transform": "table", + "type": "table-old" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fontSize": "100%", + "gridPos": { + "h": 15, + "w": 12, + "x": 12, + "y": 5 + }, + "id": 60, + "links": [], + "pageSize": null, + "showHeader": true, + "sort": { + "col": 18, + "desc": true + }, + "styles": [ + { + "$$hashKey": "object:10447", + "alias": "Object Type", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "link": false, + "linkTooltip": "Show Metadata Details", + "linkUrl": "/d/0aiPMQMGk/metadata-detail?refresh=5s&var-Backup=${Backup}&var-ObjectType=${__cell}", + "mappingType": 1, + "pattern": "objecttype", + "type": "string" + }, + { + "$$hashKey": "object:1072", + "alias": "Source", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "applicationtype", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:1249", + "alias": "API Version", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": null, + "mappingType": 1, + "pattern": "apiversion", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:3063", + "alias": "Object Name", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "objectname", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:3158", + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:10448", + "alias": "", + "align": "right", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "avg(trilio_restore_metadata_info{restore=~\"$Restore\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (objectname,objecttype, apiversion)", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Metadata Info", + "transform": "table", + "type": "table-old" + }, + { + "cacheTimeout": null, + "content": "", + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "mappings": [ + { + "from": "", + "id": 0, + "operator": "", + "text": "Available", + "to": "", + "type": 1, + "value": "1" + }, + { + "from": "", + "id": 1, + "operator": "", + "text": "InProgress", + "to": "", + "type": 1, + "value": "0" + }, + { + "from": "", + "id": 2, + "operator": "", + "text": "Failed", + "to": "", + "type": 1, + "value": "-1" + }, + { + "from": "", + "id": 3, + "operator": "", + "text": "UnKnown", + "to": "", + "type": 1, + "value": "-2" + } + ], + "nullValueMode": "connected", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "dark-red", + "value": -1 + }, + { + "color": "blue", + "value": 0 + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 1, + "w": 4, + "x": 8, + "y": 20 + }, + "id": 50, + "interval": null, + "links": [], + "maxDataPoints": 100, + "mode": "markdown", + "options": { + "content": "", + "mode": "markdown" + }, + "pluginVersion": "7.1.0", + "targets": [ + { + "expr": "trilio_backup_info{backup=~\"$Backup\",namespace=~\"$Namespace\",cluster=~\"$Cluster\"}", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "", + "transparent": true, + "type": "text" + } + ], + "refresh": "5s", + "schemaVersion": 26, + "style": "dark", + "tags": [ + "logging" + ], + "templating": { + "list": [ + { + "hide": 2, + "label": "datasource", + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_system_info", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "Cluster", + "options": [], + "query": "trilio_system_info", + "refresh": 1, + "regex": "/.*cluster=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_system_info{cluster=~\"$Cluster\"}", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "Scope", + "options": [], + "query": "trilio_system_info{cluster=~\"$Cluster\"}", + "refresh": 1, + "regex": "/.*scope=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "hide": 0, + "includeAll": false, + "label": "Install Namespace", + "multi": false, + "name": "Install_Namespace", + "options": [], + "query": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "refresh": 1, + "regex": "/.*install_namespace=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_backup_info{cluster=~\"$Cluster\",install_namespace=~\"$Install_Namespace\"}", + "hide": 0, + "includeAll": false, + "label": "Backup", + "multi": false, + "name": "Backup", + "options": [], + "query": "trilio_backup_info{cluster=~\"$Cluster\",install_namespace=~\"$Install_Namespace\"}", + "refresh": 1, + "regex": "/.*backup=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_restore_info{cluster=~\"$Cluster\",install_namespace=~\"$Install_Namespace\"}", + "hide": 0, + "includeAll": false, + "label": "Restore", + "multi": false, + "name": "Restore", + "options": [], + "query": "trilio_restore_info{cluster=~\"$Cluster\",install_namespace=~\"$Install_Namespace\"}", + "refresh": 1, + "regex": "/.*restore=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Metadata Detail", + "uid": "0aiPMQMGk", + "version": 4 +} \ No newline at end of file diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/overview.json b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/overview.json new file mode 100644 index 000000000..3f281bb53 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/overview.json @@ -0,0 +1,1093 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.5.0" + }, + { + "type": "panel", + "id": "piechart", + "name": "Pie chart", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table-old", + "name": "Table (old)", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:4047", + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 12599, + "graphTooltip": 0, + "id": null, + "iteration": 1655297057620, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 6, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 45, + "options": { + "content": "

", + "mode": "html" + }, + "pluginVersion": "8.5.0", + "transparent": true, + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "mappings": [ + { + "options": { + "0": { + "color": "red", + "index": 1, + "text": "Not Ready" + }, + "1": { + "color": "green", + "index": 0, + "text": "Ready" + } + }, + "type": "value" + } + ] + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 12, + "y": 0 + }, + "id": 47, + "options": { + "legend": { + "displayMode": "list", + "placement": "bottom" + }, + "pieType": "donut", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": false, + "expr": "trilio_component_status", + "instant": true, + "interval": "", + "legendFormat": "{{deployment}}-{{status}}", + "refId": "A" + } + ], + "transparent": true, + "type": "piechart" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 18, + "y": 0 + }, + "id": 42, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^tvk_version$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "expr": "trilio_system_info{ install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A", + "datasource": "${DS_PROMETHEUS}" + } + ], + "title": "TVK Version", + "type": "stat" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 21, + "y": 0 + }, + "id": 43, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^scope$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "expr": "trilio_system_info{ install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A", + "datasource": "${DS_PROMETHEUS}" + } + ], + "title": "TVK Scope", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Available" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#37872D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Failed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "InProgress" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FADE2A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "UnKnown" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "rgb(43, 36, 36)", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 6 + }, + "id": 34, + "links": [ + { + "title": "Show Backup Overview", + "url": "/d/J4pftrdZk/backup-overview?refresh=5s&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}" + } + ], + "maxDataPoints": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "values": [ + "value" + ] + }, + "pieType": "donut", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "count(trilio_backup_info{ install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (status)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "title": "Backup Summary", + "type": "piechart" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Completed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#37872D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Failed" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#37872D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value #C" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#E0B400", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 6 + }, + "id": 35, + "links": [ + { + "title": "Show Restore Overview", + "url": "/d/J4pdtrdZk/restore-overview?refresh=5s&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}" + } + ], + "maxDataPoints": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "values": [ + "value" + ] + }, + "pieType": "donut", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "count(trilio_restore_info{ install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (status) ", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "title": "Restore Summary", + "type": "piechart" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Available" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#37872D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Helm" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#37872D", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 6 + }, + "id": 36, + "links": [ + { + "title": "Show Backup Plan Overview", + "url": "/d/J4pdtraZk/backupplan-overview?refresh=5s&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}" + } + ], + "maxDataPoints": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "values": [ + "value" + ] + }, + "pieType": "donut", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "expr": "count(trilio_backupplan_info{install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (application)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{applicationtype}}", + "refId": "A" + } + ], + "title": "Backup Plan Summary ", + "type": "piechart" + }, + { + "columns": [], + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 13 + }, + "id": 32, + "pageSize": 5, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "$$hashKey": "object:7265", + "alias": "Component", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "deployment", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:7421", + "alias": "Health", + "align": "auto", + "colorMode": "cell", + "colors": [ + "#C4162A", + "#C4162A", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "link": false, + "mappingType": 2, + "pattern": "Value", + "rangeMaps": [ + { + "$$hashKey": "object:7471", + "from": "1", + "text": "Healthy", + "to": "999" + }, + { + "$$hashKey": "object:7529", + "from": "-1", + "text": "Unhealthy", + "to": "0" + } + ], + "thresholds": [ + "0", + "1" + ], + "type": "string", + "unit": "none", + "valueMaps": [ + { + "$$hashKey": "object:7297", + "text": "Unhealthy", + "value": "0" + } + ] + }, + { + "$$hashKey": "object:7052", + "alias": "Status", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "status", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:6723", + "alias": "", + "align": "right", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "trilio_component_status{install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A", + "datasource": "${DS_PROMETHEUS}" + } + ], + "title": "TVK Health", + "transform": "table", + "type": "table-old" + }, + { + "columns": [], + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 13 + }, + "id": 40, + "links": [ + { + "title": "Show Target Details", + "url": "/d/OddeflXdk/target-detail?refresh=5s&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}" + } + ], + "pageSize": 5, + "showHeader": true, + "sort": { + "col": 2, + "desc": false + }, + "styles": [ + { + "$$hashKey": "object:7052", + "alias": "Total Size", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "mappingType": 1, + "pattern": "size", + "thresholds": [], + "type": "number", + "unit": "decbytes" + }, + { + "$$hashKey": "object:548", + "alias": "Total Targets", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:855", + "alias": "Health", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "status", + "sanitize": false, + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:877", + "alias": "Vendor Type", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "vendorType", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:6723", + "alias": "", + "align": "right", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": false, + "expr": "count(trilio_target_info{install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (vendorType,status)", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Target Summary", + "transform": "table", + "type": "table-old" + } + ], + "refresh": "", + "schemaVersion": 36, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 2, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "Cluster", + "options": [], + "query": { + "query": "trilio_system_info", + "refId": "Prometheus-Cluster-Variable-Query" + }, + "refresh": 1, + "regex": "/.*cluster=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info{cluster=~\"$Cluster\"}", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "Scope", + "options": [], + "query": { + "query": "trilio_system_info{cluster=~\"$Cluster\"}", + "refId": "Prometheus-Scope-Variable-Query" + }, + "refresh": 1, + "regex": "/.*scope=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "hide": 0, + "includeAll": false, + "label": "Install Namespace", + "multi": false, + "name": "Install_Namespace", + "options": [], + "query": { + "query": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "refId": "Prometheus-Install_Namespace-Variable-Query" + }, + "refresh": 1, + "regex": "/.*install_namespace=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Overview", + "uid": "HSL7spxsk", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/restore-detail.json b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/restore-detail.json new file mode 100644 index 000000000..95a8afc1c --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/restore-detail.json @@ -0,0 +1,933 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + }, + { + "name": "DS_LOKI", + "label": "Loki", + "description": "", + "type": "datasource", + "pluginId": "loki", + "pluginName": "Loki" + } + ], + "__elements": [], + "__requires": [ + { + "type": "panel", + "id": "gauge", + "name": "Gauge", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.5.0" + }, + { + "type": "panel", + "id": "logs", + "name": "Logs", + "version": "" + }, + { + "type": "datasource", + "id": "loki", + "name": "Loki", + "version": "1.0.0" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + }, + { + "type": "panel", + "id": "table-old", + "name": "Table (old)", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:1512", + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 12603, + "graphTooltip": 0, + "id": null, + "iteration": 1655280394740, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 2, + "w": 23, + "x": 0, + "y": 0 + }, + "id": 4, + "options": { + "content": "

Restore Detail

", + "mode": "html" + }, + "pluginVersion": "8.5.0", + "transparent": true, + "type": "text" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "dark-red", + "value": null + }, + { + "color": "rgb(255, 255, 255)", + "value": 1 + }, + { + "color": "dark-green", + "value": 100 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 7, + "x": 0, + "y": 2 + }, + "id": 13, + "options": { + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": false + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_restore_status_percentage{restore=~\"$Restore\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "transparent": true, + "type": "gauge" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 4, + "x": 7, + "y": 2 + }, + "id": 17, + "options": { + "content": "", + "mode": "markdown" + }, + "pluginVersion": "8.5.0", + "transparent": true, + "type": "text" + }, + { + "columns": [], + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 2 + }, + "id": 11, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "$$hashKey": "object:2545", + "alias": "Object Type", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "link": true, + "linkTooltip": "${__cell}", + "linkUrl": "/d/0aiPMQMGk/metadata-detail?var-Restore=${Restore}&var-ObjectType=${__cell}&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}", + "pattern": "objecttype", + "type": "string" + }, + { + "$$hashKey": "object:1086", + "alias": "Source", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "applicationtype", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:1112", + "alias": "Count", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:2546", + "alias": "", + "align": "right", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "avg(trilio_restore_metadata_info{restore=~\"$Restore\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (objecttype, applicationtype)", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Metadata Info", + "transform": "table", + "type": "table-old" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "0": { + "text": "InProgress" + }, + "1": { + "text": "Completed" + }, + "-1": { + "text": "Failed" + }, + "-2": { + "text": "UnKnown" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "dark-red", + "value": -1 + }, + { + "color": "blue", + "value": 0 + }, + { + "color": "green", + "value": 1 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 5, + "x": 7, + "y": 3 + }, + "id": 15, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "mean" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "", + "values": false + }, + "textMode": "value" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_restore_info{restore=~\"$Restore\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "time_series", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "transparent": true, + "type": "stat" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 6 + }, + "id": 6, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^restore$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_restore_info{ restore=~\"$Restore\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Restore", + "type": "stat" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 6, + "y": 6 + }, + "id": 20, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^backup$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_restore_info{ restore=~\"$Restore\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Backup", + "type": "stat" + }, + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "align": "left", + "displayMode": "auto", + "filterable": false, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "First" + }, + "properties": [ + { + "id": "displayName", + "value": "Value" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 19, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": "${DS_PROMETHEUS}", + "expr": "trilio_restore_info{ restore=~\"$Restore\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Details", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "Time", + "completion_ts", + "size", + "start_ts", + "target", + "resource_namespace" + ] + } + } + }, + { + "id": "reduce", + "options": { + "reducers": [ + "first" + ] + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 22, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "expr": "{transaction_type=\"Restore\",transaction_resource_name=~\"$Restore\",transaction_id=~\"$transaction_id\",service_type=~\"$service_type\"}", + "refId": "A" + } + ], + "title": "Restore Logs", + "type": "logs" + } + ], + "refresh": "10s", + "schemaVersion": 36, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 2, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": false, + "text": "Loki", + "value": "Loki" + }, + "hide": 2, + "includeAll": false, + "label": "loki", + "multi": false, + "name": "DS_LOKI", + "options": [], + "query": "loki", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "Cluster", + "options": [], + "query": { + "query": "trilio_system_info", + "refId": "Prometheus-Cluster-Variable-Query" + }, + "refresh": 1, + "regex": "/.*cluster=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info{cluster=~\"$Cluster\"}", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "Scope", + "options": [], + "query": { + "query": "trilio_system_info{cluster=~\"$Cluster\"}", + "refId": "Prometheus-Scope-Variable-Query" + }, + "refresh": 1, + "regex": "/.*scope=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "hide": 0, + "includeAll": false, + "label": "Install Namespace", + "multi": false, + "name": "Install_Namespace", + "options": [], + "query": { + "query": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "refId": "Prometheus-Install_Namespace-Variable-Query" + }, + "refresh": 2, + "regex": "/.*install_namespace=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_restore_info{cluster=~\"$Cluster\"}", + "hide": 0, + "includeAll": false, + "label": "Restore", + "multi": false, + "name": "Restore", + "options": [], + "query": { + "query": "trilio_restore_info{cluster=~\"$Cluster\"}", + "refId": "Prometheus-Restore-Variable-Query" + }, + "refresh": 2, + "regex": "/.*restore=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=~\"Restore\",transaction_resource_name=~\"$Restore\"},transaction_resource_namespace)", + "description": "Resource Namespace", + "hide": 0, + "includeAll": false, + "label": "Resource Namespace", + "multi": false, + "name": "Resource_Namespace", + "options": [], + "query": "label_values({transaction_type=~\"Restore\",transaction_resource_name=~\"$Restore\"},transaction_resource_namespace)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=\"Restore\",transaction_resource_name=~\"$Restore\",transaction_resource_namespace=~\"$Resource_Namespace\"},transaction_id)", + "description": "Transaction ID", + "hide": 0, + "includeAll": false, + "label": "Transaction ID", + "multi": false, + "name": "transaction_id", + "options": [], + "query": "label_values({transaction_type=\"Restore\",transaction_resource_name=~\"$Restore\",transaction_resource_namespace=~\"$Resource_Namespace\"},transaction_id)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=\"Restore\",transaction_resource_name=~\"$Restore\",transaction_id=~\"$transaction_id\"}, service_type)", + "description": "Service Type", + "hide": 0, + "includeAll": false, + "label": "Service Type", + "multi": false, + "name": "service_type", + "options": [], + "query": "label_values({transaction_type=\"Restore\",transaction_resource_name=~\"$Restore\",transaction_id=~\"$transaction_id\"}, service_type)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=\"Restore\",transaction_resource_name=~\"$Restore\",transaction_id=~\"$transaction_id\",service_type=~\"$service_type\"}, service_id)", + "description": "Service ID", + "hide": 0, + "includeAll": false, + "label": "Service ID", + "multi": false, + "name": "service_id", + "options": [], + "query": "label_values({transaction_type=\"Restore\",transaction_resource_name=~\"$Restore\",transaction_id=~\"$transaction_id\",service_type=~\"$service_type\"}, service_id)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Restore Detail", + "uid": "J4pdtrsZk", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/restore-overview.json b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/restore-overview.json new file mode 100644 index 000000000..2dc018091 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/restore-overview.json @@ -0,0 +1,762 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.2.1" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table-old", + "name": "Table (old)", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "7.1.0" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:48276", + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "limit": 100, + "name": "Annotations & Alerts", + "showIn": 0, + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": 12602, + "graphTooltip": 0, + "id": null, + "iteration": 1617300338186, + "links": [], + "panels": [ + { + "content": "

Restores Overview

", + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "gridPos": { + "h": 2, + "w": 23, + "x": 1, + "y": 0 + }, + "id": 4, + "mode": "html", + "options": { + "content": "

Restores Overview

", + "mode": "html" + }, + "pluginVersion": "7.1.0", + "timeFrom": null, + "timeShift": null, + "title": "", + "transparent": true, + "type": "text" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(115, 181, 181)", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 2, + "y": 2 + }, + "id": 35, + "links": [], + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_restore_info{install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) ", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "All", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "All", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 6, + "y": 2 + }, + "id": 36, + "links": [], + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^Completed$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_restore_info{status=\"Completed\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (status)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Completed", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 10, + "y": 2 + }, + "id": 39, + "links": [], + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^InProgress$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_restore_info{status=\"InProgress\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (status)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "InProgress", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 14, + "y": 2 + }, + "id": 38, + "links": [], + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "/^Failed$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_restore_info{status=\"Failed\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (status)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Failed", + "transparent": true, + "type": "stat" + }, + { + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fieldConfig": { + "defaults": { + "custom": {}, + "links": [], + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgb(79, 145, 145)", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 18, + "y": 2 + }, + "id": 37, + "links": [], + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "7.2.1", + "targets": [ + { + "expr": "count(trilio_restore_info{status=\"UnKnown\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (status)", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "UnKnown", + "transformations": [], + "transparent": true, + "type": "stat" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fontSize": "100%", + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 29, + "pageSize": null, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "$$hashKey": "object:48688", + "alias": "Restore", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "Show Restore Detail", + "linkUrl": "/d/J4pdtrsZk/restore-detail?refresh=5s&var-Restore=${__cell}&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}", + "mappingType": 1, + "pattern": "restore", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:48689", + "alias": "Restore Plan", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "backupplan", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:48690", + "alias": "Completion", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss.SSS", + "decimals": 2, + "mappingType": 1, + "pattern": "completion_ts", + "thresholds": [], + "type": "date", + "unit": "short" + }, + { + "$$hashKey": "object:48691", + "alias": "Percentage", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": null, + "mappingType": 1, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "percent" + }, + { + "$$hashKey": "object:48692", + "alias": "Backup", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": true, + "linkTooltip": "Show Backup Detail", + "linkUrl": "/d/J4pftrfZk/backup-detail?refresh=5s&var-Backup=${__cell}&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}", + "mappingType": 1, + "pattern": "backup", + "thresholds": [], + "type": "string", + "unit": "decbytes", + "valueMaps": [ + { + "$$hashKey": "object:700", + "text": "N/A", + "value": "" + } + ] + }, + { + "$$hashKey": "object:48693", + "alias": "Target", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": true, + "linkTooltip": "Show Target Detail", + "linkUrl": "/d/OddeflXdk/target-detail?refresh=5s&var-Target=${__cell}&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}", + "mappingType": 1, + "pattern": "target", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:1222", + "alias": "Size", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": null, + "mappingType": 1, + "pattern": "size", + "thresholds": [], + "type": "number", + "unit": "decbytes" + }, + { + "$$hashKey": "object:5064", + "alias": "Status", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "status", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:48694", + "alias": "", + "align": "auto", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "trilio_restore_status_percentage{status=~\"$Status\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "", + "transform": "table", + "type": "table-old" + } + ], + "refresh": "5s", + "schemaVersion": 26, + "style": "dark", + "tags": [ + "logging" + ], + "templating": { + "list": [ + { + "hide": 2, + "label": "datasource", + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_system_info", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "Cluster", + "options": [], + "query": "trilio_system_info", + "refresh": 1, + "regex": "/.*cluster=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_system_info{cluster=~\"$Cluster\"}", + "hide": 2, + "includeAll": false, + "label": null, + "multi": false, + "name": "Scope", + "options": [], + "query": "trilio_system_info{cluster=~\"$Cluster\"}", + "refresh": 1, + "regex": "/.*scope=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "hide": 0, + "includeAll": false, + "label": "Install Namespace", + "multi": false, + "name": "Install_Namespace", + "options": [], + "query": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "refresh": 1, + "regex": "/.*install_namespace=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "trilio_restore_info", + "hide": 0, + "includeAll": true, + "label": "status", + "multi": false, + "name": "Status", + "options": [], + "query": "trilio_restore_info", + "refresh": 1, + "regex": "/.*status=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Restore Overview", + "uid": "J4pdtrdZk", + "version": 5 +} \ No newline at end of file diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/target-detail.json b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/target-detail.json new file mode 100644 index 000000000..bb321da4a --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/dashboards/target-detail.json @@ -0,0 +1,1164 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + }, + { + "name": "DS_LOKI", + "label": "Loki", + "description": "", + "type": "datasource", + "pluginId": "loki", + "pluginName": "Loki" + } + ], + "__elements": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.5.0" + }, + { + "type": "panel", + "id": "logs", + "name": "Logs", + "version": "" + }, + { + "type": "datasource", + "id": "loki", + "name": "Loki", + "version": "1.0.0" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table-old", + "name": "Table (old)", + "version": "" + }, + { + "type": "panel", + "id": "text", + "name": "Text", + "version": "" + } + ], + "annotations": { + "list": [ + { + "$$hashKey": "object:63480", + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 12606, + "graphTooltip": 0, + "id": null, + "iteration": 1655275350842, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 2, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 4, + "options": { + "content": "

Targets

", + "mode": "html" + }, + "pluginVersion": "8.5.0", + "transparent": true, + "type": "text" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "0": { + "text": "Unavailable" + }, + "1": { + "text": "Available" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#d44a3a", + "value": null + }, + { + "color": "dark-red", + "value": 0 + }, + { + "color": "#299c46", + "value": 1 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 0, + "y": 2 + }, + "id": 8, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "mean" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": false, + "expr": "avg(trilio_target_info{target=~\"$Target\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"})", + "format": "time_series", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Health", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#c7d0d9", + "value": null + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 4, + "y": 2 + }, + "id": 38, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "fieldOptions": { + "calcs": [ + "mean" + ] + }, + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": false, + "expr": "sum(trilio_backup_storage{target=~\"$Target\",status=~\"Available\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"})", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Total Capacity", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "text": "N/A" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 7, + "y": 2 + }, + "id": 39, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^threshold_capacity$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": false, + "expr": "trilio_target_info{ target=~\"$Target\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Threshold Capacity", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "false": { + "text": "False" + }, + "true": { + "text": "True" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 10, + "y": 2 + }, + "id": 35, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^browsing$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": false, + "expr": "trilio_target_info{ target=~\"$Target\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Browsing", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 13, + "y": 2 + }, + "id": 40, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^vendor$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": false, + "expr": "trilio_target_info{ target=~\"$Target\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Vendor ", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 16, + "y": 2 + }, + "id": 36, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^vendorType$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": false, + "expr": "trilio_target_info{ target=~\"$Target\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Vendor Type", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "dateTimeAsIso" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 5, + "x": 19, + "y": 2 + }, + "id": 37, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "first" + ], + "fields": "/^creation_ts$/", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.5.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": false, + "expr": "trilio_target_info{ target=~\"$Target\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "", + "refId": "A" + } + ], + "title": "Creattion Timestamp", + "type": "stat" + }, + { + "columns": [], + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fontSize": "100%", + "gridPos": { + "h": 18, + "w": 12, + "x": 0, + "y": 5 + }, + "id": 32, + "showHeader": true, + "sort": { + "col": 16, + "desc": true + }, + "styles": [ + { + "$$hashKey": "object:14951", + "alias": "Backup", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTargetBlank": true, + "linkTooltip": "Show Backup Detail", + "linkUrl": "/d/J4pftrfZk/backup-detail?refresh=5s&var-Backup=${__cell}&var-Cluster=${Cluster}&var-Install_Namespace=${Install_Namespace}", + "mappingType": 1, + "pattern": "backup", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:15011", + "alias": "Backup Plan", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "backupplan", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:15022", + "alias": "Completion ", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss.SSS", + "decimals": 2, + "mappingType": 1, + "pattern": "completion_ts", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [ + { + "$$hashKey": "object:2043", + "text": "N/A", + "value": "" + } + ] + }, + { + "$$hashKey": "object:15093", + "alias": "Size", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "mappingType": 1, + "pattern": "size", + "thresholds": [], + "type": "number", + "unit": "decbytes" + }, + { + "$$hashKey": "object:15104", + "alias": "Average Data Transfer", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "-", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:67733", + "alias": "Target", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "target", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:69096", + "alias": "Status", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "status", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "$$hashKey": "object:1081", + "alias": "Backup Type", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "backup_type", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "$$hashKey": "object:18392", + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": false, + "expr": "topk(10,trilio_backup_info{target=~\"$Target\",install_namespace=~\"$Install_Namespace\",cluster=~\"$Cluster\"}) by (size)", + "format": "table", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{backup}} {{status}}", + "refId": "A" + } + ], + "title": "Backups", + "transform": "table", + "type": "table-old" + }, + { + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "gridPos": { + "h": 18, + "w": 12, + "x": 12, + "y": 5 + }, + "id": 42, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": false + }, + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "expr": "{transaction_type=\"Target\",transaction_resource_name=~\"$Target\",transaction_id=~\"$transaction_id\",service_type=~\"$service_type\"}", + "refId": "A" + } + ], + "title": "Target Logs ", + "type": "logs" + } + ], + "refresh": "10s", + "schemaVersion": 36, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "Prometheus" + }, + "description": "prometheus datasource", + "hide": 2, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": false, + "text": "Loki", + "value": "Loki" + }, + "description": "loki datasource", + "hide": 2, + "includeAll": false, + "label": "loki datasource", + "multi": false, + "name": "DS_LOKI", + "options": [], + "query": "loki", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "Cluster", + "options": [], + "query": { + "query": "trilio_system_info", + "refId": "Prometheus-Cluster-Variable-Query" + }, + "refresh": 1, + "regex": "/.*cluster=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info{cluster=~\"$Cluster\"}", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "Scope", + "options": [], + "query": { + "query": "trilio_system_info{cluster=~\"$Cluster\"}", + "refId": "Prometheus-Scope-Variable-Query" + }, + "refresh": 1, + "regex": "/.*scope=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "hide": 0, + "includeAll": false, + "label": "Install Namespace", + "multi": false, + "name": "Install_Namespace", + "options": [], + "query": { + "query": "trilio_system_info{scope=~\"$Scope\",cluster=~\"$Cluster\"}", + "refId": "Prometheus-Install_Namespace-Variable-Query" + }, + "refresh": 2, + "regex": "/.*install_namespace=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allValue": ".*", + "current": {}, + "datasource": { + "uid": "${DS_PROMETHEUS}" + }, + "definition": "trilio_target_info{cluster=~\"$Cluster\"}", + "hide": 0, + "includeAll": false, + "label": "Target", + "multi": false, + "name": "Target", + "options": [], + "query": { + "query": "trilio_target_info{cluster=~\"$Cluster\"}", + "refId": "StandardVariableQuery" + }, + "refresh": 2, + "regex": "/.*target=\"([^\"]*).*/", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=\"Target\",transaction_resource_name=~\"$Target\"},transaction_resource_namespace)", + "description": "Resource Namespace", + "hide": 0, + "includeAll": false, + "label": "Resource Namespace", + "multi": false, + "name": "Resource_Namespace", + "options": [], + "query": "label_values({transaction_type=\"Target\",transaction_resource_name=~\"$Target\"},transaction_resource_namespace)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_resource_name=~\"$Target\",transaction_type=\"Target\",transaction_resource_namespace=~\"$Resource_Namespace\"},transaction_id)", + "description": "Transaction ID", + "hide": 0, + "includeAll": false, + "label": "Transaction ID", + "multi": false, + "name": "transaction_id", + "options": [], + "query": "label_values({transaction_resource_name=~\"$Target\",transaction_type=\"Target\",transaction_resource_namespace=~\"$Resource_Namespace\"},transaction_id)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=\"Target\",transaction_id=~\"$transaction_id\"}, service_type)", + "description": "Service Type", + "hide": 0, + "includeAll": false, + "label": "Service Type", + "multi": false, + "name": "service_type", + "options": [], + "query": "label_values({transaction_type=\"Target\",transaction_id=~\"$transaction_id\"}, service_type)", + "refresh": 2, + "regex": "/(Validation|TargetBrowsing|ControlPlane)$/", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "loki", + "uid": "${DS_LOKI}" + }, + "definition": "label_values({transaction_type=\"Target\",transaction_id=~\"$transaction_id\",service_type=~\"$service_type\"}, service_id)", + "description": "Service ID", + "hide": 0, + "includeAll": false, + "label": "Service ID", + "multi": false, + "name": "service_id", + "options": [], + "query": "label_values({transaction_type=\"Target\",transaction_id=~\"$transaction_id\",service_type=~\"$service_type\"}, service_id)", + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Target Detail", + "uid": "OddeflXdk", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/NOTES.txt b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/NOTES.txt new file mode 100644 index 000000000..1fc8436d9 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/NOTES.txt @@ -0,0 +1,54 @@ +1. Get your '{{ .Values.adminUser }}' user password by running: + + kubectl get secret --namespace {{ template "grafana.namespace" . }} {{ template "grafana.fullname" . }} -o jsonpath="{.data.admin-password}" | base64 --decode ; echo + +2. The Grafana server can be accessed via port {{ .Values.service.port }} on the following DNS name from within your cluster: + + {{ template "grafana.fullname" . }}.{{ template "grafana.namespace" . }}.svc.cluster.local +{{ if .Values.ingress.enabled }} + If you bind grafana to 80, please update values in values.yaml and reinstall: + ``` + securityContext: + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + + command: + - "setcap" + - "'cap_net_bind_service=+ep'" + - "/usr/sbin/grafana-server &&" + - "sh" + - "/run.sh" + ``` + Details refer to https://grafana.com/docs/installation/configuration/#http-port. + Or grafana would always crash. + + From outside the cluster, the server URL(s) are: +{{- range .Values.ingress.hosts }} + http://{{ . }} +{{- end }} +{{ else }} + Get the Grafana URL to visit by running these commands in the same shell: +{{ if contains "NodePort" .Values.service.type -}} + export NODE_PORT=$(kubectl get --namespace {{ template "grafana.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "grafana.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ template "grafana.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{ else if contains "LoadBalancer" .Values.service.type -}} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc --namespace {{ template "grafana.namespace" . }} -w {{ template "grafana.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ template "grafana.namespace" . }} {{ template "grafana.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + http://$SERVICE_IP:{{ .Values.service.port -}} +{{ else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ template "grafana.namespace" . }} -l "app.kubernetes.io/name={{ template "grafana.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ template "grafana.namespace" . }} port-forward $POD_NAME 3000 +{{- end }} +{{- end }} + +3. Login with the password from step 1 and the username: {{ .Values.adminUser }} + +{{- if not .Values.persistence.enabled }} +################################################################################# +###### WARNING: Persistence is disabled!!! You will lose your data when ##### +###### the Grafana pod is terminated. ##### +################################################################################# +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/_helpers.tpl b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/_helpers.tpl new file mode 100644 index 000000000..e3a1fff46 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/_helpers.tpl @@ -0,0 +1,165 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "grafana.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 "grafana.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 "grafana.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the service account +*/}} +{{- define "grafana.serviceAccountName" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (include "grafana.fullname" .) .Values.serviceAccount.name }} +{{- else -}} + {{ default "default" .Values.serviceAccount.name }} +{{- end -}} +{{- end -}} + +{{- define "grafana.serviceAccountNameTest" -}} +{{- if .Values.serviceAccount.create -}} + {{ default (print (include "grafana.fullname" .) "-test") .Values.serviceAccount.nameTest }} +{{- else -}} + {{ default "default" .Values.serviceAccount.nameTest }} +{{- end -}} +{{- end -}} + +{{/* +Allow the release namespace to be overridden for multi-namespace deployments in combined charts +*/}} +{{- define "grafana.namespace" -}} + {{- if .Values.namespaceOverride -}} + {{- .Values.namespaceOverride -}} + {{- else -}} + {{- .Release.Namespace -}} + {{- end -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "grafana.labels" -}} +helm.sh/chart: {{ include "grafana.chart" . }} +{{ include "grafana.selectorLabels" . }} +{{- if or .Chart.AppVersion .Values.image.tag }} +app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.extraLabels }} +{{ toYaml .Values.extraLabels }} +{{- end }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "grafana.selectorLabels" -}} +app.kubernetes.io/name: {{ include "grafana.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: k8s-triliovault-operator +app.kubernetes.io/part-of: k8s-triliovault-operator +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "grafana.imageRenderer.labels" -}} +helm.sh/chart: {{ include "grafana.chart" . }} +{{ include "grafana.imageRenderer.selectorLabels" . }} +{{- if or .Chart.AppVersion .Values.image.tag }} +app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Selector labels ImageRenderer +*/}} +{{- define "grafana.imageRenderer.selectorLabels" -}} +app.kubernetes.io/name: {{ include "grafana.name" . }}-image-renderer +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Looks if there's an existing secret and reuse its password. If not it generates +new password and use it. +*/}} +{{- define "grafana.password" -}} +{{- $secret := (lookup "v1" "Secret" (include "grafana.namespace" .) (include "grafana.fullname" .) ) -}} + {{- if $secret -}} + {{- index $secret "data" "admin-password" -}} + {{- else -}} + {{- (randAlphaNum 40) | b64enc | quote -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for rbac. +*/}} +{{- define "grafana.rbac.apiVersion" -}} + {{- if .Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1" }} + {{- print "rbac.authorization.k8s.io/v1" -}} + {{- else -}} + {{- print "rbac.authorization.k8s.io/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "grafana.ingress.apiVersion" -}} + {{- if and (.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" .Capabilities.KubeVersion.Version) -}} + {{- print "networking.k8s.io/v1" -}} + {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} + {{- print "networking.k8s.io/v1beta1" -}} + {{- else -}} + {{- print "extensions/v1beta1" -}} + {{- end -}} +{{- end -}} + +{{/* +Return if ingress is stable. +*/}} +{{- define "grafana.ingress.isStable" -}} + {{- eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +Return if ingress supports ingressClassName. +*/}} +{{- define "grafana.ingress.supportsIngressClassName" -}} + {{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) -}} +{{- end -}} + +{{/* +Return if ingress supports pathType. +*/}} +{{- define "grafana.ingress.supportsPathType" -}} + {{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/_pod.tpl b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/_pod.tpl new file mode 100644 index 000000000..230642c65 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/_pod.tpl @@ -0,0 +1,748 @@ + +{{- define "grafana.pod" -}} +{{- if .Values.schedulerName }} +schedulerName: "{{ .Values.schedulerName }}" +{{- end }} +serviceAccountName: {{ template "grafana.serviceAccountName" . }} +automountServiceAccountToken: {{ .Values.serviceAccount.autoMount }} +{{- if .Values.securityContext }} +securityContext: +{{ toYaml .Values.securityContext | indent 2 }} +{{- end }} +{{- if .Values.hostAliases }} +hostAliases: +{{ toYaml .Values.hostAliases | indent 2 }} +{{- end }} +{{- if .Values.priorityClassName }} +priorityClassName: {{ .Values.priorityClassName }} +{{- end }} +{{- if ( or .Values.persistence.enabled .Values.dashboards .Values.sidecar.notifiers.enabled .Values.extraInitContainers (and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources)) }} +initContainers: +{{- end }} +{{- if ( and .Values.persistence.enabled .Values.initChownData.enabled ) }} + - name: init-chown-data + {{- if .Values.initChownData.image.sha }} + image: "{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}@sha256:{{ .Values.initChownData.image.sha }}" + {{- else }} + image: "{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.initChownData.image.pullPolicy }} + securityContext: + runAsNonRoot: false + runAsUser: 0 + command: ["chown", "-R", "{{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }}", "/var/lib/grafana"] + resources: +{{ toYaml .Values.initChownData.resources | indent 6 }} + volumeMounts: + - name: storage + mountPath: "/var/lib/grafana" +{{- if .Values.persistence.subPath }} + subPath: {{ tpl .Values.persistence.subPath . }} +{{- end }} +{{- end }} +{{- if .Values.dashboards }} + - name: download-dashboards + {{- if .Values.downloadDashboardsImage.sha }} + image: "{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}@sha256:{{ .Values.downloadDashboardsImage.sha }}" + {{- else }} + image: "{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.downloadDashboardsImage.pullPolicy }} + command: ["/bin/sh"] + args: [ "-c", "mkdir -p /var/lib/grafana/dashboards/default && /bin/sh -x /etc/grafana/download_dashboards.sh" ] + resources: +{{ toYaml .Values.downloadDashboards.resources | indent 6 }} + env: +{{- range $key, $value := .Values.downloadDashboards.env }} + - name: "{{ $key }}" + value: "{{ $value }}" +{{- end }} +{{- if .Values.downloadDashboards.envFromSecret }} + envFrom: + - secretRef: + name: {{ tpl .Values.downloadDashboards.envFromSecret . }} +{{- end }} + volumeMounts: + - name: config + mountPath: "/etc/grafana/download_dashboards.sh" + subPath: download_dashboards.sh + - name: storage + mountPath: "/var/lib/grafana" +{{- if .Values.persistence.subPath }} + subPath: {{ tpl .Values.persistence.subPath . }} +{{- end }} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + {{- end }} +{{- end }} +{{- if and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources }} + - name: {{ template "grafana.name" . }}-init-sc-datasources + {{- if .Values.sidecar.image.sha }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + - name: METHOD + value: "LIST" + - name: LABEL + value: "{{ .Values.sidecar.datasources.label }}" + {{- if .Values.sidecar.datasources.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.datasources.labelValue }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/datasources" + - name: RESOURCE + value: {{ quote .Values.sidecar.datasources.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + {{- if .Values.sidecar.datasources.searchNamespace }} + - name: NAMESPACE + value: "{{ .Values.sidecar.datasources.searchNamespace | join "," }}" + {{- end }} + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + resources: +{{ toYaml .Values.sidecar.resources | indent 6 }} +{{- if .Values.sidecar.securityContext }} + securityContext: +{{- toYaml .Values.sidecar.securityContext | nindent 6 }} +{{- end }} + volumeMounts: + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" +{{- end }} +{{- if .Values.sidecar.notifiers.enabled }} + - name: {{ template "grafana.name" . }}-sc-notifiers + {{- if .Values.sidecar.image.sha }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + - name: METHOD + value: LIST + - name: LABEL + value: "{{ .Values.sidecar.notifiers.label }}" + - name: FOLDER + value: "/etc/grafana/provisioning/notifiers" + - name: RESOURCE + value: {{ quote .Values.sidecar.notifiers.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + {{- if .Values.sidecar.notifiers.searchNamespace }} + - name: NAMESPACE + value: "{{ .Values.sidecar.notifiers.searchNamespace | join "," }}" + {{- end }} + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} +{{- if .Values.sidecar.livenessProbe }} + livenessProbe: +{{ toYaml .Values.livenessProbe | indent 6 }} +{{- end }} +{{- if .Values.sidecar.readinessProbe }} + readinessProbe: +{{ toYaml .Values.readinessProbe | indent 6 }} +{{- end }} + resources: +{{ toYaml .Values.sidecar.resources | indent 6 }} +{{- if .Values.sidecar.securityContext }} + securityContext: +{{- toYaml .Values.sidecar.securityContext | nindent 6 }} +{{- end }} + volumeMounts: + - name: sc-notifiers-volume + mountPath: "/etc/grafana/provisioning/notifiers" +{{- end}} +{{- if .Values.extraInitContainers }} +{{ tpl (toYaml .Values.extraInitContainers) . | indent 2 }} +{{- end }} +{{- if .Values.image.pullSecrets }} +imagePullSecrets: +{{- $root := . }} +{{- range .Values.image.pullSecrets }} + - name: {{ tpl . $root }} +{{- end}} +{{- end }} +{{- if not .Values.enableKubeBackwardCompatibility }} +enableServiceLinks: {{ .Values.enableServiceLinks }} +{{- end }} +containers: +{{- if .Values.sidecar.dashboards.enabled }} + - name: {{ template "grafana.name" . }}-sc-dashboard + {{- if .Values.sidecar.image.sha }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + - name: METHOD + value: {{ .Values.sidecar.dashboards.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.dashboards.label }}" + {{- if .Values.sidecar.dashboards.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.dashboards.labelValue }} + {{- end }} + - name: FOLDER + value: "{{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }}" + - name: RESOURCE + value: {{ quote .Values.sidecar.dashboards.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + {{- if .Values.sidecar.dashboards.searchNamespace }} + - name: NAMESPACE + value: "{{ .Values.sidecar.dashboards.searchNamespace | join "," }}" + {{- end }} + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- if .Values.sidecar.dashboards.folderAnnotation }} + - name: FOLDER_ANNOTATION + value: "{{ .Values.sidecar.dashboards.folderAnnotation }}" + {{- end }} + {{- if .Values.sidecar.dashboards.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.dashboards.script }}" + {{- end }} + {{- if .Values.sidecar.dashboards.watchServerTimeout }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.dashboards.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.dashboards.watchClientTimeout }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.dashboards.watchClientTimeout }}" + {{- end }} +{{- if .Values.sidecar.livenessProbe }} + livenessProbe: +{{ toYaml .Values.livenessProbe | indent 6 }} +{{- end }} +{{- if .Values.sidecar.readinessProbe }} + readinessProbe: +{{ toYaml .Values.readinessProbe | indent 6 }} +{{- end }} + resources: +{{ toYaml .Values.sidecar.resources | indent 6 }} +{{- if .Values.sidecar.securityContext }} + securityContext: +{{- toYaml .Values.sidecar.securityContext | nindent 6 }} +{{- end }} + volumeMounts: + - name: sc-dashboard-volume + mountPath: {{ .Values.sidecar.dashboards.folder | quote }} + {{- if .Values.sidecar.dashboards.extraMounts }} + {{- toYaml .Values.sidecar.dashboards.extraMounts | trim | nindent 6}} + {{- end }} +{{- end}} +{{- if .Values.sidecar.datasources.enabled }} + - name: {{ template "grafana.name" . }}-sc-datasources + {{- if .Values.sidecar.image.sha }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + - name: METHOD + value: {{ .Values.sidecar.datasources.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.datasources.label }}" + {{- if .Values.sidecar.datasources.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.datasources.labelValue }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/datasources" + - name: RESOURCE + value: {{ quote .Values.sidecar.datasources.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + {{- if .Values.sidecar.datasources.searchNamespace }} + - name: NAMESPACE + value: "{{ .Values.sidecar.datasources.searchNamespace | join "," }}" + {{- end }} + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_USERNAME + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if not .Values.sidecar.datasources.skipReload }} + - name: REQ_URL + value: {{ .Values.sidecar.datasources.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} +{{- if .Values.sidecar.livenessProbe }} + livenessProbe: +{{ toYaml .Values.livenessProbe | indent 6 }} +{{- end }} +{{- if .Values.sidecar.readinessProbe }} + readinessProbe: +{{ toYaml .Values.readinessProbe | indent 6 }} +{{- end }} + resources: +{{ toYaml .Values.sidecar.resources | indent 6 }} +{{- if .Values.sidecar.securityContext }} + securityContext: +{{- toYaml .Values.sidecar.securityContext | nindent 6 }} +{{- end }} + volumeMounts: + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" +{{- end}} +{{- if .Values.sidecar.plugins.enabled }} + - name: {{ template "grafana.name" . }}-sc-plugins + {{- if .Values.sidecar.image.sha }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + - name: METHOD + value: {{ .Values.sidecar.plugins.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.plugins.label }}" + {{- if .Values.sidecar.plugins.labelValue }} + - name: LABEL_VALUE + value: {{ quote .Values.sidecar.plugins.labelValue }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/plugins" + - name: RESOURCE + value: {{ quote .Values.sidecar.plugins.resource }} + {{- if .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ .Values.sidecar.enableUniqueFilenames }}" + {{- end }} + {{- if .Values.sidecar.plugins.searchNamespace }} + - name: NAMESPACE + value: "{{ .Values.sidecar.plugins.searchNamespace | join "," }}" + {{- end }} + {{- if .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ .Values.sidecar.skipTlsVerify }}" + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_USERNAME + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: REQ_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if not .Values.sidecar.plugins.skipReload }} + - name: REQ_URL + value: {{ .Values.sidecar.plugins.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} +{{- if .Values.sidecar.livenessProbe }} + livenessProbe: +{{ toYaml .Values.livenessProbe | indent 6 }} +{{- end }} +{{- if .Values.sidecar.readinessProbe }} + readinessProbe: +{{ toYaml .Values.readinessProbe | indent 6 }} +{{- end }} + resources: +{{ toYaml .Values.sidecar.resources | indent 6 }} +{{- if .Values.sidecar.securityContext }} + securityContext: +{{- toYaml .Values.sidecar.securityContext | nindent 6 }} +{{- end }} + volumeMounts: + - name: sc-plugins-volume + mountPath: "/etc/grafana/provisioning/plugins" +{{- end}} + - name: {{ .Chart.Name }} + {{- if .Values.image.sha }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}@sha256:{{ .Values.image.sha }}" + {{- else }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if .Values.command }} + command: + {{- range .Values.command }} + - {{ . }} + {{- end }} + {{- end}} +{{- if .Values.containerSecurityContext }} + securityContext: +{{- toYaml .Values.containerSecurityContext | nindent 6 }} +{{- end }} + volumeMounts: + - name: config + mountPath: "/etc/grafana/grafana.ini" + subPath: grafana.ini + {{- if .Values.ldap.enabled }} + - name: ldap + mountPath: "/etc/grafana/ldap.toml" + subPath: ldap.toml + {{- end }} + {{- $root := . }} + {{- range .Values.extraConfigmapMounts }} + - name: {{ tpl .name $root }} + mountPath: {{ tpl .mountPath $root }} + subPath: {{ (tpl .subPath $root) | default "" }} + readOnly: {{ .readOnly }} + {{- end }} + - name: storage + mountPath: "/var/lib/grafana" +{{- if .Values.persistence.subPath }} + subPath: {{ tpl .Values.persistence.subPath . }} +{{- end }} +{{- if .Values.dashboards }} +{{- range $provider, $dashboards := .Values.dashboards }} +{{- range $key, $value := $dashboards }} +{{- if (or (hasKey $value "json") (hasKey $value "file")) }} + - name: dashboards-{{ $provider }} + mountPath: "/var/lib/grafana/dashboards/{{ $provider }}/{{ $key }}.json" + subPath: "{{ $key }}.json" +{{- end }} +{{- end }} +{{- end }} +{{- end -}} +{{- if .Values.dashboardsConfigMaps }} +{{- range (keys .Values.dashboardsConfigMaps | sortAlpha) }} + - name: dashboards-{{ . }} + mountPath: "/var/lib/grafana/dashboards/{{ . }}" +{{- end }} +{{- end }} +{{- if .Values.datasources }} +{{- range (keys .Values.datasources | sortAlpha) }} + - name: config + mountPath: "/etc/grafana/provisioning/datasources/{{ . }}" + subPath: {{ . | quote }} +{{- end }} +{{- end }} +{{- if .Values.notifiers }} +{{- range (keys .Values.notifiers | sortAlpha) }} + - name: config + mountPath: "/etc/grafana/provisioning/notifiers/{{ . }}" + subPath: {{ . | quote }} +{{- end }} +{{- end }} +{{- if .Values.dashboardProviders }} +{{- range (keys .Values.dashboardProviders | sortAlpha) }} + - name: config + mountPath: "/etc/grafana/provisioning/dashboards/{{ . }}" + subPath: {{ . | quote }} +{{- end }} +{{- end }} +{{- if .Values.sidecar.dashboards.enabled }} + - name: sc-dashboard-volume + mountPath: {{ .Values.sidecar.dashboards.folder | quote }} +{{ if .Values.sidecar.dashboards.SCProvider }} + - name: sc-dashboard-provider + mountPath: "/etc/grafana/provisioning/dashboards/sc-dashboardproviders.yaml" + subPath: provider.yaml +{{- end}} +{{- end}} +{{- if .Values.sidecar.datasources.enabled }} + - name: sc-datasources-volume + mountPath: "/etc/grafana/provisioning/datasources" +{{- end}} +{{- if .Values.sidecar.plugins.enabled }} + - name: sc-plugins-volume + mountPath: "/etc/grafana/provisioning/plugins" +{{- end}} +{{- if .Values.sidecar.notifiers.enabled }} + - name: sc-notifiers-volume + mountPath: "/etc/grafana/provisioning/notifiers" +{{- end}} + {{- range .Values.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + subPath: {{ .subPath | default "" }} + {{- end }} + {{- range .Values.extraVolumeMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath | default "" }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.extraEmptyDirMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + {{- end }} + ports: + - name: {{ .Values.service.portName }} + containerPort: {{ .Values.service.port }} + protocol: TCP + - name: {{ .Values.podPortName }} + containerPort: 3000 + protocol: TCP + env: + {{- if and (not .Values.env.GF_SECURITY_ADMIN_USER) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: GF_SECURITY_ADMIN_USER + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.userKey | default "admin-user" }} + {{- end }} + {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + - name: GF_SECURITY_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} + key: {{ .Values.admin.passwordKey | default "admin-password" }} + {{- end }} + {{- if .Values.plugins }} + - name: GF_INSTALL_PLUGINS + valueFrom: + configMapKeyRef: + name: {{ template "grafana.fullname" . }} + key: plugins + {{- end }} + {{- if .Values.smtp.existingSecret }} + - name: GF_SMTP_USER + valueFrom: + secretKeyRef: + name: {{ .Values.smtp.existingSecret }} + key: {{ .Values.smtp.userKey | default "user" }} + - name: GF_SMTP_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.smtp.existingSecret }} + key: {{ .Values.smtp.passwordKey | default "password" }} + {{- end }} + {{- if .Values.imageRenderer.enabled }} + - name: GF_RENDERING_SERVER_URL + value: http://{{ template "grafana.fullname" . }}-image-renderer.{{ template "grafana.namespace" . }}:{{ .Values.imageRenderer.service.port }}/render + - name: GF_RENDERING_CALLBACK_URL + value: {{ .Values.imageRenderer.grafanaProtocol }}://{{ template "grafana.fullname" . }}.{{ template "grafana.namespace" . }}:{{ .Values.service.port }}/{{ .Values.imageRenderer.grafanaSubPath }} + {{- end }} + - name: GF_PATHS_DATA + value: {{ (get .Values "grafana.ini").paths.data }} + - name: GF_PATHS_LOGS + value: {{ (get .Values "grafana.ini").paths.logs }} + - name: GF_PATHS_PLUGINS + value: {{ (get .Values "grafana.ini").paths.plugins }} + - name: GF_PATHS_PROVISIONING + value: {{ (get .Values "grafana.ini").paths.provisioning }} + {{- range $key, $value := .Values.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: +{{ tpl (toYaml $value) $ | indent 10 }} + {{- end }} +{{- range $key, $value := .Values.env }} + - name: "{{ tpl $key $ }}" + value: "{{ tpl (print $value) $ }}" +{{- end }} + {{- if or .Values.envFromSecret (or .Values.envRenderSecret .Values.envFromSecrets) .Values.envFromConfigMaps }} + envFrom: + {{- if .Values.envFromSecret }} + - secretRef: + name: {{ tpl .Values.envFromSecret . }} + {{- end }} + {{- if .Values.envRenderSecret }} + - secretRef: + name: {{ template "grafana.fullname" . }}-env + {{- end }} + {{- range .Values.envFromSecrets }} + - secretRef: + name: {{ tpl .name $ }} + optional: {{ .optional | default false }} + {{- end }} + {{- range .Values.envFromConfigMaps }} + - configMapRef: + name: {{ tpl .name $ }} + optional: {{ .optional | default false }} + {{- end }} + {{- end }} + livenessProbe: +{{ toYaml .Values.livenessProbe | indent 6 }} + readinessProbe: +{{ toYaml .Values.readinessProbe | indent 6 }} +{{- if .Values.lifecycleHooks }} + lifecycle: {{ tpl (.Values.lifecycleHooks | toYaml) . | nindent 6 }} +{{- end }} + resources: +{{ toYaml .Values.resources | indent 6 }} +{{- with .Values.extraContainers }} +{{ tpl . $ | indent 2 }} +{{- end }} +{{- with .Values.nodeSelector }} +nodeSelector: +{{ toYaml . | indent 2 }} +{{- end }} +{{- $root := . }} +{{- with .Values.affinity }} +affinity: +{{ tpl (toYaml .) $root | indent 2 }} +{{- end }} +{{- with .Values.tolerations }} +tolerations: +{{ toYaml . | indent 2 }} +{{- end }} +volumes: + - name: config + configMap: + name: {{ template "grafana.fullname" . }} +{{- $root := . }} +{{- range .Values.extraConfigmapMounts }} + - name: {{ tpl .name $root }} + configMap: + name: {{ tpl .configMap $root }} +{{- end }} + {{- if .Values.dashboards }} + {{- range (keys .Values.dashboards | sortAlpha) }} + - name: dashboards-{{ . }} + configMap: + name: {{ template "grafana.fullname" $ }}-dashboards-{{ . }} + {{- end }} + {{- end }} + {{- if .Values.dashboardsConfigMaps }} + {{ $root := . }} + {{- range $provider, $name := .Values.dashboardsConfigMaps }} + - name: dashboards-{{ $provider }} + configMap: + name: {{ tpl $name $root }} + {{- end }} + {{- end }} + {{- if .Values.ldap.enabled }} + - name: ldap + secret: + {{- if .Values.ldap.existingSecret }} + secretName: {{ .Values.ldap.existingSecret }} + {{- else }} + secretName: {{ template "grafana.fullname" . }} + {{- end }} + items: + - key: ldap-toml + path: ldap.toml + {{- end }} +{{- if and .Values.persistence.enabled (eq .Values.persistence.type "pvc") }} + - name: storage + persistentVolumeClaim: + claimName: {{ tpl (.Values.persistence.existingClaim | default (include "grafana.fullname" .)) . }} +{{- else if and .Values.persistence.enabled (eq .Values.persistence.type "statefulset") }} +# nothing +{{- else }} + - name: storage +{{- if .Values.persistence.inMemory.enabled }} + emptyDir: + medium: Memory +{{- if .Values.persistence.inMemory.sizeLimit }} + sizeLimit: {{ .Values.persistence.inMemory.sizeLimit }} +{{- end -}} +{{- else }} + emptyDir: {} +{{- end -}} +{{- end -}} +{{- if .Values.sidecar.dashboards.enabled }} + - name: sc-dashboard-volume +{{- if .Values.sidecar.dashboards.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.dashboards.sizeLimit }} +{{- else }} + emptyDir: {} +{{- end -}} +{{- if .Values.sidecar.dashboards.SCProvider }} + - name: sc-dashboard-provider + configMap: + name: {{ template "grafana.fullname" . }}-config-dashboards +{{- end }} +{{- end }} +{{- if .Values.sidecar.datasources.enabled }} + - name: sc-datasources-volume +{{- if .Values.sidecar.datasources.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.datasources.sizeLimit }} +{{- else }} + emptyDir: {} +{{- end -}} +{{- end -}} +{{- if .Values.sidecar.plugins.enabled }} + - name: sc-plugins-volume +{{- if .Values.sidecar.plugins.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.plugins.sizeLimit }} +{{- else }} + emptyDir: {} +{{- end -}} +{{- end -}} +{{- if .Values.sidecar.notifiers.enabled }} + - name: sc-notifiers-volume +{{- if .Values.sidecar.notifiers.sizeLimit }} + emptyDir: + sizeLimit: {{ .Values.sidecar.notifiers.sizeLimit }} +{{- else }} + emptyDir: {} +{{- end -}} +{{- end -}} +{{- range .Values.extraSecretMounts }} +{{- if .secretName }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + defaultMode: {{ .defaultMode }} +{{- else if .projected }} + - name: {{ .name }} + projected: {{- toYaml .projected | nindent 6 }} +{{- else if .csi }} + - name: {{ .name }} + csi: {{- toYaml .csi | nindent 6 }} +{{- end }} +{{- end }} +{{- range .Values.extraVolumeMounts }} + - name: {{ .name }} + {{- if .existingClaim }} + persistentVolumeClaim: + claimName: {{ .existingClaim }} + {{- else if .hostPath }} + hostPath: + path: {{ .hostPath }} + {{- else }} + emptyDir: {} + {{- end }} +{{- end }} +{{- range .Values.extraEmptyDirMounts }} + - name: {{ .name }} + emptyDir: {} +{{- end -}} +{{- if .Values.extraContainerVolumes }} +{{ toYaml .Values.extraContainerVolumes | indent 2 }} +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/clusterrole.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/clusterrole.yaml new file mode 100644 index 000000000..f09e06563 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/clusterrole.yaml @@ -0,0 +1,25 @@ +{{- if and .Values.rbac.create (not .Values.rbac.namespaced) (not .Values.rbac.useExistingRole) }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + name: {{ template "grafana.fullname" . }}-clusterrole +{{- if or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled .Values.rbac.extraClusterRoleRules) }} +rules: +{{- if or .Values.sidecar.dashboards.enabled .Values.sidecar.datasources.enabled }} +- apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] +{{- end}} +{{- with .Values.rbac.extraClusterRoleRules }} +{{ toYaml . | indent 0 }} +{{- end}} +{{- else }} +rules: [] +{{- end}} +{{- end}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/clusterrolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/clusterrolebinding.yaml new file mode 100644 index 000000000..4accbfac0 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/clusterrolebinding.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.rbac.create (not .Values.rbac.namespaced) }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "grafana.fullname" . }}-clusterrolebinding + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +subjects: + - kind: ServiceAccount + name: {{ template "grafana.serviceAccountName" . }} + namespace: {{ template "grafana.namespace" . }} +roleRef: + kind: ClusterRole +{{- if (not .Values.rbac.useExistingRole) }} + name: {{ template "grafana.fullname" . }}-clusterrole +{{- else }} + name: {{ .Values.rbac.useExistingRole }} +{{- end }} + apiGroup: rbac.authorization.k8s.io +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/configmap-dashboard-provider.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/configmap-dashboard-provider.yaml new file mode 100644 index 000000000..65d73858e --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/configmap-dashboard-provider.yaml @@ -0,0 +1,29 @@ +{{- if .Values.sidecar.dashboards.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} + name: {{ template "grafana.fullname" . }}-config-dashboards + namespace: {{ template "grafana.namespace" . }} +data: + provider.yaml: |- + apiVersion: 1 + providers: + - name: '{{ .Values.sidecar.dashboards.provider.name }}' + orgId: {{ .Values.sidecar.dashboards.provider.orgid }} + {{- if not .Values.sidecar.dashboards.provider.foldersFromFilesStructure }} + folder: '{{ .Values.sidecar.dashboards.provider.folder }}' + {{- end}} + type: {{ .Values.sidecar.dashboards.provider.type }} + disableDeletion: {{ .Values.sidecar.dashboards.provider.disableDelete }} + allowUiUpdates: {{ .Values.sidecar.dashboards.provider.allowUiUpdates }} + updateIntervalSeconds: {{ .Values.sidecar.dashboards.provider.updateIntervalSeconds | default 30 }} + options: + foldersFromFilesStructure: {{ .Values.sidecar.dashboards.provider.foldersFromFilesStructure }} + path: {{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }} +{{- end}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/configmap.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/configmap.yaml new file mode 100644 index 000000000..401e2aaa6 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/configmap.yaml @@ -0,0 +1,88 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +data: +{{- if .Values.plugins }} + plugins: {{ join "," .Values.plugins }} +{{- end }} + grafana.ini: | +{{- range $key, $value := index .Values "grafana.ini" }} + [{{ $key }}] + {{- range $elem, $elemVal := $value }} + {{- if kindIs "invalid" $elemVal }} + {{ $elem }} = + {{- else if kindIs "string" $elemVal }} + {{ $elem }} = {{ tpl $elemVal $ }} + {{- else }} + {{ $elem }} = {{ $elemVal }} + {{- end }} + {{- end }} +{{- end }} + +{{- if .Values.datasources }} +{{ $root := . }} + {{- range $key, $value := .Values.datasources }} + {{ $key }}: | +{{ tpl (toYaml $value | indent 4) $root }} + {{- end -}} +{{- end -}} + +{{- if .Values.notifiers }} + {{- range $key, $value := .Values.notifiers }} + {{ $key }}: | +{{ toYaml $value | indent 4 }} + {{- end -}} +{{- end -}} + +{{- if .Values.dashboardProviders }} + {{- range $key, $value := .Values.dashboardProviders }} + {{ $key }}: | +{{ toYaml $value | indent 4 }} + {{- end -}} +{{- end -}} + +{{- if .Values.dashboards }} + download_dashboards.sh: | + #!/usr/bin/env sh + set -euf + {{- if .Values.dashboardProviders }} + {{- range $key, $value := .Values.dashboardProviders }} + {{- range $value.providers }} + mkdir -p {{ .options.path }} + {{- end }} + {{- end }} + {{- end }} + {{ $dashboardProviders := .Values.dashboardProviders }} + {{- range $provider, $dashboards := .Values.dashboards }} + {{- range $key, $value := $dashboards }} + {{- if (or (hasKey $value "gnetId") (hasKey $value "url")) }} + curl -skf \ + --connect-timeout 60 \ + --max-time 60 \ + {{- if not $value.b64content }} + -H "Accept: application/json" \ + {{- if $value.token }} + -H "Authorization: token {{ $value.token }}" \ + {{- end }} + -H "Content-Type: application/json;charset=UTF-8" \ + {{ end }} + {{- $dpPath := "" -}} + {{- range $kd := (index $dashboardProviders "dashboardproviders.yaml").providers -}} + {{- if eq $kd.name $provider -}} + {{- $dpPath = $kd.options.path -}} + {{- end -}} + {{- end -}} + {{- if $value.url -}}"{{ $value.url }}"{{- else -}}"https://grafana.com/api/dashboards/{{ $value.gnetId }}/revisions/{{- if $value.revision -}}{{ $value.revision }}{{- else -}}1{{- end -}}/download"{{- end -}}{{ if $value.datasource }} | sed '/-- .* --/! s/"datasource":.*,/"datasource": "{{ $value.datasource }}",/g'{{ end }}{{- if $value.b64content -}} | base64 -d {{- end -}} \ + > "{{- if $dpPath -}}{{ $dpPath }}{{- else -}}/var/lib/grafana/dashboards/{{ $provider }}{{- end -}}/{{ $key }}.json" + {{- end }} + {{- end -}} + {{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/dashboards-json-configmap.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/dashboards-json-configmap.yaml new file mode 100644 index 000000000..24212b736 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/dashboards-json-configmap.yaml @@ -0,0 +1,36 @@ +{{- if .Values.dashboards }} +{{ $files := .Files }} +{{- range $provider, $dashboards := .Values.dashboards }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "grafana.fullname" $ }}-dashboards-{{ $provider }} + namespace: {{ template "grafana.namespace" $ }} + labels: + {{- include "grafana.labels" $ | nindent 4 }} + dashboard-provider: {{ $provider }} + grafana_dashboard: tvm +{{- if $dashboards }} +data: +{{- $dashboardFound := false }} +{{- range $key, $value := $dashboards }} +{{- if (or (hasKey $value "json") (hasKey $value "file")) }} +{{- $dashboardFound = true }} +{{ print $key | indent 2 }}.json: +{{- if hasKey $value "json" }} + |- +{{ $value.json | indent 6 }} +{{- end }} +{{- if hasKey $value "file" }} +{{ toYaml ( $files.Get $value.file ) | indent 4}} +{{- end }} +{{- end }} +{{- end }} +{{- if not $dashboardFound }} + {} +{{- end }} +{{- end }} +--- +{{- end }} + +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/deployment.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/deployment.yaml new file mode 100644 index 000000000..8dbe5e107 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/deployment.yaml @@ -0,0 +1,50 @@ +{{ if (or (not .Values.persistence.enabled) (eq .Values.persistence.type "pvc")) }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.labels }} +{{ toYaml .Values.labels | indent 4 }} +{{- end }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + {{- if and (not .Values.autoscaling.enabled) (.Values.replicas) }} + replicas: {{ .Values.replicas }} + {{- end }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} +{{- with .Values.deploymentStrategy }} + strategy: +{{ toYaml . | trim | indent 4 }} +{{- end }} + template: + metadata: + labels: + {{- include "grafana.selectorLabels" . | nindent 8 }} +{{- with .Values.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/dashboards-json-config: {{ include (print $.Template.BasePath "/dashboards-json-configmap.yaml") . | sha256sum }} + checksum/sc-dashboard-provider-config: {{ include (print $.Template.BasePath "/configmap-dashboard-provider.yaml") . | sha256sum }} +{{- if and (or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret))) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} +{{- end }} +{{- if .Values.envRenderSecret }} + checksum/secret-env: {{ include (print $.Template.BasePath "/secret-env.yaml") . | sha256sum }} +{{- end }} +{{- with .Values.podAnnotations }} +{{ toYaml . | indent 8 }} +{{- end }} + spec: + {{- include "grafana.pod" . | nindent 6 }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/extra-manifests.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/extra-manifests.yaml new file mode 100644 index 000000000..a9bb3b6ba --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/extra-manifests.yaml @@ -0,0 +1,4 @@ +{{ range .Values.extraObjects }} +--- +{{ tpl (toYaml .) $ }} +{{ end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/headless-service.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/headless-service.yaml new file mode 100644 index 000000000..1df42e967 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/headless-service.yaml @@ -0,0 +1,22 @@ +{{- if or .Values.headlessService (and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "statefulset"))}} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "grafana.fullname" . }}-headless + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + clusterIP: None + selector: + {{- include "grafana.selectorLabels" . | nindent 4 }} + type: ClusterIP + ports: + - protocol: TCP + port: 3000 + targetPort: 3000 +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/hpa.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/hpa.yaml new file mode 100644 index 000000000..9c186d74a --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/hpa.yaml @@ -0,0 +1,20 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ template "grafana.fullname" . }} + labels: + app.kubernetes.io/name: {{ template "grafana.name" . }} + helm.sh/chart: {{ template "grafana.chart" . }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ template "grafana.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: +{{ toYaml .Values.autoscaling.metrics | indent 4 }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/image-renderer-deployment.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/image-renderer-deployment.yaml new file mode 100644 index 000000000..1a9d4c58b --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/image-renderer-deployment.yaml @@ -0,0 +1,121 @@ +{{ if .Values.imageRenderer.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "grafana.fullname" . }}-image-renderer + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.imageRenderer.labels" . | nindent 4 }} +{{- if .Values.imageRenderer.labels }} +{{ toYaml .Values.imageRenderer.labels | indent 4 }} +{{- end }} +{{- with .Values.imageRenderer.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + replicas: {{ .Values.imageRenderer.replicas }} + revisionHistoryLimit: {{ .Values.imageRenderer.revisionHistoryLimit }} + selector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} +{{- with .Values.imageRenderer.deploymentStrategy }} + strategy: +{{ toYaml . | trim | indent 4 }} +{{- end }} + template: + metadata: + labels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 8 }} +{{- with .Values.imageRenderer.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} +{{- with .Values.imageRenderer.podAnnotations }} +{{ toYaml . | indent 8 }} +{{- end }} + spec: + + {{- if .Values.imageRenderer.schedulerName }} + schedulerName: "{{ .Values.imageRenderer.schedulerName }}" + {{- end }} + {{- if .Values.imageRenderer.serviceAccountName }} + serviceAccountName: "{{ .Values.imageRenderer.serviceAccountName }}" + {{- end }} + {{- if .Values.imageRenderer.securityContext }} + securityContext: + {{- toYaml .Values.imageRenderer.securityContext | nindent 8 }} + {{- end }} + {{- if .Values.imageRenderer.hostAliases }} + hostAliases: + {{- toYaml .Values.imageRenderer.hostAliases | nindent 8 }} + {{- end }} + {{- if .Values.imageRenderer.priorityClassName }} + priorityClassName: {{ .Values.imageRenderer.priorityClassName }} + {{- end }} + {{- if .Values.imageRenderer.image.pullSecrets }} + imagePullSecrets: + {{- $root := . }} + {{- range .Values.imageRenderer.image.pullSecrets }} + - name: {{ tpl . $root }} + {{- end}} + {{- end }} + containers: + - name: {{ .Chart.Name }}-image-renderer + {{- if .Values.imageRenderer.image.sha }} + image: "{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}@sha256:{{ .Values.imageRenderer.image.sha }}" + {{- else }} + image: "{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.imageRenderer.image.pullPolicy }} + {{- if .Values.imageRenderer.command }} + command: + {{- range .Values.imageRenderer.command }} + - {{ . }} + {{- end }} + {{- end}} + ports: + - name: {{ .Values.imageRenderer.service.portName }} + containerPort: {{ .Values.imageRenderer.service.port }} + protocol: TCP + livenessProbe: + httpGet: + path: / + port: {{ .Values.imageRenderer.service.portName }} + env: + - name: HTTP_PORT + value: {{ .Values.imageRenderer.service.port | quote }} + {{- range $key, $value := .Values.imageRenderer.env }} + - name: {{ $key | quote }} + value: {{ $value | quote }} + {{- end }} + securityContext: + capabilities: + drop: ['all'] + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + volumeMounts: + - mountPath: /tmp + name: image-renderer-tmpfs + {{- with .Values.imageRenderer.resources }} + resources: +{{ toYaml . | indent 12 }} + {{- end }} + {{- with .Values.imageRenderer.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- $root := . }} + {{- with .Values.imageRenderer.affinity }} + affinity: +{{ tpl (toYaml .) $root | indent 8 }} + {{- end }} + {{- with .Values.imageRenderer.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} + volumes: + - name: image-renderer-tmpfs + emptyDir: {} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/image-renderer-network-policy.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/image-renderer-network-policy.yaml new file mode 100644 index 000000000..f8ca73aab --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/image-renderer-network-policy.yaml @@ -0,0 +1,76 @@ +{{- if and (.Values.imageRenderer.enabled) (.Values.imageRenderer.networkPolicy.limitIngress) }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "grafana.fullname" . }}-image-renderer-ingress + namespace: {{ template "grafana.namespace" . }} + annotations: + comment: Limit image-renderer ingress traffic from grafana +spec: + podSelector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} + {{- if .Values.imageRenderer.podLabels }} + {{ toYaml .Values.imageRenderer.podLabels | nindent 6 }} + {{- end }} + + policyTypes: + - Ingress + ingress: + - ports: + - port: {{ .Values.imageRenderer.service.port }} + protocol: TCP + from: + - namespaceSelector: + matchLabels: + name: {{ template "grafana.namespace" . }} + podSelector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 14 }} + {{- if .Values.podLabels }} + {{ toYaml .Values.podLabels | nindent 14 }} + {{- end }} +{{ end }} + +{{- if and (.Values.imageRenderer.enabled) (.Values.imageRenderer.networkPolicy.limitEgress) }} +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "grafana.fullname" . }}-image-renderer-egress + namespace: {{ template "grafana.namespace" . }} + annotations: + comment: Limit image-renderer egress traffic to grafana +spec: + podSelector: + matchLabels: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} + {{- if .Values.imageRenderer.podLabels }} + {{ toYaml .Values.imageRenderer.podLabels | nindent 6 }} + {{- end }} + + policyTypes: + - Egress + egress: + # allow dns resolution + - ports: + - port: 53 + protocol: UDP + - port: 53 + protocol: TCP + # talk only to grafana + - ports: + - port: {{ .Values.service.port }} + protocol: TCP + to: + - namespaceSelector: + matchLabels: + name: {{ template "grafana.namespace" . }} + podSelector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 14 }} + {{- if .Values.podLabels }} + {{ toYaml .Values.podLabels | nindent 14 }} + {{- end }} +{{ end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/image-renderer-service.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/image-renderer-service.yaml new file mode 100644 index 000000000..f29586c3a --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/image-renderer-service.yaml @@ -0,0 +1,30 @@ +{{ if .Values.imageRenderer.enabled }} +{{ if .Values.imageRenderer.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "grafana.fullname" . }}-image-renderer + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.imageRenderer.labels" . | nindent 4 }} +{{- if .Values.imageRenderer.service.labels }} +{{ toYaml .Values.imageRenderer.service.labels | indent 4 }} +{{- end }} +{{- with .Values.imageRenderer.service.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + type: ClusterIP + {{- if .Values.imageRenderer.service.clusterIP }} + clusterIP: {{ .Values.imageRenderer.service.clusterIP }} + {{end}} + ports: + - name: {{ .Values.imageRenderer.service.portName }} + port: {{ .Values.imageRenderer.service.port }} + protocol: TCP + targetPort: {{ .Values.imageRenderer.service.targetPort }} + selector: + {{- include "grafana.imageRenderer.selectorLabels" . | nindent 4 }} +{{ end }} +{{ end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/ingress.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/ingress.yaml new file mode 100644 index 000000000..7699cecaa --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/ingress.yaml @@ -0,0 +1,78 @@ +{{- if .Values.ingress.enabled -}} +{{- $ingressApiIsStable := eq (include "grafana.ingress.isStable" .) "true" -}} +{{- $ingressSupportsIngressClassName := eq (include "grafana.ingress.supportsIngressClassName" .) "true" -}} +{{- $ingressSupportsPathType := eq (include "grafana.ingress.supportsPathType" .) "true" -}} +{{- $fullName := include "grafana.fullname" . -}} +{{- $servicePort := .Values.service.port -}} +{{- $ingressPath := .Values.ingress.path -}} +{{- $ingressPathType := .Values.ingress.pathType -}} +{{- $extraPaths := .Values.ingress.extraPaths -}} +apiVersion: {{ include "grafana.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ $fullName }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.ingress.labels }} +{{ toYaml .Values.ingress.labels | indent 4 }} +{{- end }} + {{- if .Values.ingress.annotations }} + annotations: + {{- range $key, $value := .Values.ingress.annotations }} + {{ $key }}: {{ tpl $value $ | quote }} + {{- end }} + {{- end }} +spec: + {{- if and $ingressSupportsIngressClassName .Values.ingress.ingressClassName }} + ingressClassName: {{ .Values.ingress.ingressClassName }} + {{- end -}} +{{- if .Values.ingress.tls }} + tls: +{{ tpl (toYaml .Values.ingress.tls) $ | indent 4 }} +{{- end }} + rules: + {{- if .Values.ingress.hosts }} + {{- range .Values.ingress.hosts }} + - host: {{ tpl . $}} + http: + paths: +{{- if $extraPaths }} +{{ toYaml $extraPaths | indent 10 }} +{{- end }} + - path: {{ $ingressPath }} + {{- if $ingressSupportsPathType }} + pathType: {{ $ingressPathType }} + {{- end }} + backend: + {{- if $ingressApiIsStable }} + service: + name: {{ $fullName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end }} + {{- else }} + - http: + paths: + - backend: + {{- if $ingressApiIsStable }} + service: + name: {{ $fullName }} + port: + number: {{ $servicePort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- if $ingressPath }} + path: {{ $ingressPath }} + {{- end }} + {{- if $ingressSupportsPathType }} + pathType: {{ $ingressPathType }} + {{- end }} + {{- end -}} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/networkpolicy.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/networkpolicy.yaml new file mode 100644 index 000000000..fc243828e --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/networkpolicy.yaml @@ -0,0 +1,37 @@ +{{- if .Values.networkPolicy.enabled }} +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.labels }} +{{ toYaml .Values.labels | indent 4 }} +{{- end }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + podSelector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} + ingress: + - ports: + - port: {{ .Values.service.targetPort }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ template "grafana.fullname" . }}-client: "true" + {{- if .Values.networkPolicy.explicitNamespacesSelector }} + namespaceSelector: + {{ toYaml .Values.networkPolicy.explicitNamespacesSelector | indent 12 }} + {{- end }} + - podSelector: + matchLabels: + {{- include "grafana.labels" . | nindent 14 }} + role: read + {{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/poddisruptionbudget.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/poddisruptionbudget.yaml new file mode 100644 index 000000000..61813a436 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/poddisruptionbudget.yaml @@ -0,0 +1,22 @@ +{{- if .Values.podDisruptionBudget }} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.labels }} +{{ toYaml .Values.labels | indent 4 }} +{{- end }} +spec: +{{- if .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} +{{- end }} +{{- if .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} +{{- end }} + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/podsecuritypolicy.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/podsecuritypolicy.yaml new file mode 100644 index 000000000..7de6c021d --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/podsecuritypolicy.yaml @@ -0,0 +1,49 @@ +{{- if .Values.rbac.pspEnabled }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "grafana.fullname" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + annotations: + seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default' + seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' + {{- if .Values.rbac.pspUseAppArmor }} + apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' + apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' + {{- end }} +spec: + privileged: false + allowPrivilegeEscalation: false + requiredDropCapabilities: + # Default set from Docker, with DAC_OVERRIDE and CHOWN + - ALL + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'csi' + - 'secret' + - 'downwardAPI' + - 'persistentVolumeClaim' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + # Forbid adding the root group. + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/pvc.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/pvc.yaml new file mode 100644 index 000000000..8d93f5c23 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/pvc.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "pvc")}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.persistence.annotations }} + annotations: +{{ toYaml . | indent 4 }} + {{- end }} + {{- with .Values.persistence.finalizers }} + finalizers: +{{ toYaml . | indent 4 }} + {{- end }} +spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.storageClassName }} + storageClassName: {{ .Values.persistence.storageClassName }} + {{- end -}} + {{- with .Values.persistence.selectorLabels }} + selector: + matchLabels: +{{ toYaml . | indent 6 }} + {{- end }} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/role.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/role.yaml new file mode 100644 index 000000000..6a1890fb9 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/role.yaml @@ -0,0 +1,32 @@ +{{- if and .Values.rbac.create (not .Values.rbac.useExistingRole) -}} +apiVersion: {{ template "grafana.rbac.apiVersion" . }} +kind: Role +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +{{- if or .Values.rbac.pspEnabled (and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled (or .Values.sidecar.datasources.enabled .Values.rbac.extraRoleRules))) }} +rules: +{{- if .Values.rbac.pspEnabled }} +- apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ template "grafana.fullname" . }}] +{{- end }} +{{- if and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled .Values.sidecar.datasources.enabled) }} +- apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] +{{- end }} +{{- with .Values.rbac.extraRoleRules }} +{{ toYaml . | indent 0 }} +{{- end}} +{{- else }} +rules: [] +{{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/rolebinding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/rolebinding.yaml new file mode 100644 index 000000000..e0107255e --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/rolebinding.yaml @@ -0,0 +1,25 @@ +{{- if .Values.rbac.create -}} +apiVersion: {{ template "grafana.rbac.apiVersion" . }} +kind: RoleBinding +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role +{{- if (not .Values.rbac.useExistingRole) }} + name: {{ template "grafana.fullname" . }} +{{- else }} + name: {{ .Values.rbac.useExistingRole }} +{{- end }} +subjects: +- kind: ServiceAccount + name: {{ template "grafana.serviceAccountName" . }} + namespace: {{ template "grafana.namespace" . }} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/secret-env.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/secret-env.yaml new file mode 100644 index 000000000..5c09313e6 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/secret-env.yaml @@ -0,0 +1,14 @@ +{{- if .Values.envRenderSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "grafana.fullname" . }}-env + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +type: Opaque +data: +{{- range $key, $val := .Values.envRenderSecret }} + {{ $key }}: {{ $val | b64enc | quote }} +{{- end -}} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/secret.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/secret.yaml new file mode 100644 index 000000000..c8aa750ac --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/secret.yaml @@ -0,0 +1,26 @@ +{{- if or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret)) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +type: Opaque +data: + {{- if and (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) }} + admin-user: {{ .Values.adminUser | b64enc | quote }} + {{- if .Values.adminPassword }} + admin-password: {{ .Values.adminPassword | b64enc | quote }} + {{- else }} + admin-password: {{ template "grafana.password" . }} + {{- end }} + {{- end }} + {{- if not .Values.ldap.existingSecret }} + ldap-toml: {{ tpl .Values.ldap.config $ | b64enc | quote }} + {{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/service.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/service.yaml new file mode 100644 index 000000000..ba84ef970 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/service.yaml @@ -0,0 +1,51 @@ +{{ if .Values.service.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- if .Values.service.labels }} +{{ toYaml .Values.service.labels | indent 4 }} +{{- end }} +{{- with .Values.service.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }} + type: ClusterIP + {{- if .Values.service.clusterIP }} + clusterIP: {{ .Values.service.clusterIP }} + {{end}} +{{- else if eq .Values.service.type "LoadBalancer" }} + type: {{ .Values.service.type }} + {{- if .Values.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if .Values.service.loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{ toYaml .Values.service.loadBalancerSourceRanges | indent 4 }} + {{- end -}} +{{- else }} + type: {{ .Values.service.type }} +{{- end }} +{{- if .Values.service.externalIPs }} + externalIPs: +{{ toYaml .Values.service.externalIPs | indent 4 }} +{{- end }} + ports: + - name: {{ .Values.service.portName }} + port: {{ .Values.service.port }} + protocol: TCP + targetPort: {{ .Values.service.targetPort }} +{{ if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} + nodePort: {{.Values.service.nodePort}} +{{ end }} + {{- if .Values.extraExposePorts }} + {{- tpl (toYaml .Values.extraExposePorts) . | indent 4 }} + {{- end }} + selector: + {{- include "grafana.selectorLabels" . | nindent 4 }} +{{ end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/serviceaccount.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/serviceaccount.yaml new file mode 100644 index 000000000..4ccee15ed --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- $root := . }} +{{- with .Values.serviceAccount.annotations }} + annotations: +{{ tpl (toYaml . | indent 4) $root }} +{{- end }} + name: {{ template "grafana.serviceAccountName" . }} + namespace: {{ template "grafana.namespace" . }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/servicemonitor.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/servicemonitor.yaml new file mode 100644 index 000000000..a18c6d336 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/servicemonitor.yaml @@ -0,0 +1,44 @@ +{{- if .Values.serviceMonitor.enabled }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "grafana.fullname" . }} + {{- if .Values.serviceMonitor.namespace }} + namespace: {{ .Values.serviceMonitor.namespace }} + {{- else }} + namespace: {{ template "grafana.namespace" . }} + {{- end }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- if .Values.serviceMonitor.labels }} + {{- toYaml .Values.serviceMonitor.labels | nindent 4 }} + {{- end }} +spec: + endpoints: + - port: {{ .Values.service.portName }} + {{- with .Values.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + honorLabels: true + path: {{ .Values.serviceMonitor.path }} + scheme: {{ .Values.serviceMonitor.scheme }} + {{- if .Values.serviceMonitor.tlsConfig }} + tlsConfig: + {{- toYaml .Values.serviceMonitor.tlsConfig | nindent 6 }} + {{- end }} + {{- if .Values.serviceMonitor.relabelings }} + relabelings: + {{- toYaml .Values.serviceMonitor.relabelings | nindent 4 }} + {{- end }} + jobLabel: "{{ .Release.Name }}" + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 8 }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/statefulset.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/statefulset.yaml new file mode 100644 index 000000000..ad3dd0696 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/templates/statefulset.yaml @@ -0,0 +1,52 @@ +{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "statefulset")}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ template "grafana.fullname" . }} + namespace: {{ template "grafana.namespace" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +{{- with .Values.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + {{- include "grafana.selectorLabels" . | nindent 6 }} + serviceName: {{ template "grafana.fullname" . }}-headless + template: + metadata: + labels: + {{- include "grafana.selectorLabels" . | nindent 8 }} +{{- with .Values.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/dashboards-json-config: {{ include (print $.Template.BasePath "/dashboards-json-configmap.yaml") . | sha256sum }} + checksum/sc-dashboard-provider-config: {{ include (print $.Template.BasePath "/configmap-dashboard-provider.yaml") . | sha256sum }} + {{- if and (or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret))) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} +{{- end }} +{{- with .Values.podAnnotations }} +{{ toYaml . | indent 8 }} +{{- end }} + spec: + {{- include "grafana.pod" . | nindent 6 }} + volumeClaimTemplates: + - metadata: + name: storage + spec: + accessModes: {{ .Values.persistence.accessModes }} + storageClassName: {{ .Values.persistence.storageClassName }} + resources: + requests: + storage: {{ .Values.persistence.size }} + {{- with .Values.persistence.selectorLabels }} + selector: + matchLabels: +{{ toYaml . | indent 10 }} + {{- end }} +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/values.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/values.yaml new file mode 100644 index 000000000..8e6bbe9ae --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/charts/observability/charts/visualization/charts/grafana/values.yaml @@ -0,0 +1,919 @@ +rbac: + create: true + ## Use an existing ClusterRole/Role (depending on rbac.namespaced false/true) + # useExistingRole: name-of-some-(cluster)role + pspEnabled: false + pspUseAppArmor: false + namespaced: false + extraRoleRules: [] + # - apiGroups: [] + # resources: [] + # verbs: [] + extraClusterRoleRules: [] + # - apiGroups: [] + # resources: [] + # verbs: [] +serviceAccount: + create: true + name: + nameTest: +## Service account annotations. Can be templated. +# annotations: +# eks.amazonaws.com/role-arn: arn:aws:iam::123456789000:role/iam-role-name-here + autoMount: true + +replicas: 1 + +## Create a headless service for the deployment +headlessService: false + +## Create HorizontalPodAutoscaler object for deployment type +# +autoscaling: + enabled: false +# minReplicas: 1 +# maxReplicas: 10 +# metrics: +# - type: Resource +# resource: +# name: cpu +# targetAverageUtilization: 60 +# - type: Resource +# resource: +# name: memory +# targetAverageUtilization: 60 + +## See `kubectl explain poddisruptionbudget.spec` for more +## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ +podDisruptionBudget: {} +# minAvailable: 1 +# maxUnavailable: 1 + +## See `kubectl explain deployment.spec.strategy` for more +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy +deploymentStrategy: + type: RollingUpdate + +readinessProbe: + httpGet: + path: /api/health + port: 3000 + +livenessProbe: + httpGet: + path: /api/health + port: 3000 + initialDelaySeconds: 60 + timeoutSeconds: 30 + failureThreshold: 10 + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: "default-scheduler" + +image: + repository: grafana/grafana + tag: 8.5.0 + sha: "" + pullPolicy: IfNotPresent + + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Can be templated. + ## + # pullSecrets: + # - myRegistrKeySecretName + +testFramework: + enabled: true + image: "bats/bats" + tag: "v1.4.1" + imagePullPolicy: IfNotPresent + securityContext: {} + +securityContext: + runAsUser: 472 + runAsGroup: 472 + fsGroup: 472 + +containerSecurityContext: + {} + +# Extra configmaps to mount in grafana pods +# Values are templated. +extraConfigmapMounts: [] + # - name: certs-configmap + # mountPath: /etc/grafana/ssl/ + # subPath: certificates.crt # (optional) + # configMap: certs-configmap + # readOnly: true + + +extraEmptyDirMounts: [] + # - name: provisioning-notifiers + # mountPath: /etc/grafana/provisioning/notifiers + + +# Apply extra labels to common labels. +extraLabels: {} + +## Assign a PriorityClassName to pods if set +# priorityClassName: + +downloadDashboardsImage: + repository: curlimages/curl + tag: 7.73.0 + sha: "" + pullPolicy: IfNotPresent + +downloadDashboards: + env: {} + envFromSecret: "" + resources: {} + +## Pod Annotations +# podAnnotations: {} + +## Pod Labels +# podLabels: {} + +podPortName: grafana + +## Deployment annotations +annotations: + ignore-check.kube-linter.io/privileged-ports : "This deployment needs to run on privileged ports 80" + ignore-check.kube-linter.io/read-secret-from-env-var : "This deployment needs to read secret from env variable for grafana admin user and password" + +## Expose the grafana service to be accessed from outside the cluster (LoadBalancer service). +## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it. +## ref: http://kubernetes.io/docs/user-guide/services/ +## +service: + enabled: true + type: ClusterIP + port: 80 + targetPort: 3000 + # targetPort: 4181 To be used with a proxy extraContainer + annotations: {} + labels: {} + portName: service + +serviceMonitor: + ## If true, a ServiceMonitor CRD is created for a prometheus operator + ## https://github.com/coreos/prometheus-operator + ## + enabled: false + path: /metrics + # namespace: monitoring (defaults to use the namespace this chart is deployed to) + labels: {} + interval: 1m + scheme: http + tlsConfig: {} + scrapeTimeout: 30s + relabelings: [] + +extraExposePorts: [] + # - name: keycloak + # port: 8080 + # targetPort: 8080 + # type: ClusterIP + +# overrides pod.spec.hostAliases in the grafana deployment's pods +hostAliases: [] + # - ip: "1.2.3.4" + # hostnames: + # - "my.host.com" + +ingress: + enabled: false + # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName + # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress + # ingressClassName: nginx + # Values can be templated + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + path: / + + # pathType is only for k8s >= 1.1= + pathType: Prefix + + hosts: + - chart-example.local + ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. + extraPaths: [] + # - path: /* + # backend: + # serviceName: ssl-redirect + # servicePort: use-annotation + ## Or for k8s > 1.19 + # - path: /* + # pathType: Prefix + # backend: + # service: + # name: ssl-redirect + # port: + # name: use-annotation + + + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + limits: + cpu: 1000m + memory: 500Mi + requests: + cpu: 200m + memory: 256Mi + +## Node labels for pod assignment +## ref: https://kubernetes.io/docs/user-guide/node-selection/ +# +nodeSelector: {} + +## Tolerations for pod assignment +## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ +## +tolerations: [] + +## Affinity for pod assignment (evaluated as template) +## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity +## +affinity: {} + +## Additional init containers (evaluated as template) +## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ +## +extraInitContainers: [] + +## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod +extraContainers: "" +# extraContainers: | +# - name: proxy +# image: quay.io/gambol99/keycloak-proxy:latest +# args: +# - -provider=github +# - -client-id= +# - -client-secret= +# - -github-org= +# - -email-domain=* +# - -cookie-secret= +# - -http-address=http://0.0.0.0:4181 +# - -upstream-url=http://127.0.0.1:3000 +# ports: +# - name: proxy-web +# containerPort: 4181 + +## Volumes that can be used in init containers that will not be mounted to deployment pods +extraContainerVolumes: [] +# - name: volume-from-secret +# secret: +# secretName: secret-to-mount +# - name: empty-dir-volume +# emptyDir: {} + +## Enable persistence using Persistent Volume Claims +## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ +## +persistence: + type: pvc + enabled: false + # storageClassName: default + accessModes: + - ReadWriteOnce + size: 10Gi + # annotations: {} + finalizers: + - kubernetes.io/pvc-protection + # selectorLabels: {} + ## Sub-directory of the PV to mount. Can be templated. + # subPath: "" + ## Name of an existing PVC. Can be templated. + # existingClaim: + + ## If persistence is not enabled, this allows to mount the + ## local storage in-memory to improve performance + ## + inMemory: + enabled: false + ## The maximum usage on memory medium EmptyDir would be + ## the minimum value between the SizeLimit specified + ## here and the sum of memory limits of all containers in a pod + ## + # sizeLimit: 300Mi + +initChownData: + ## If false, data ownership will not be reset at startup + ## This allows the prometheus-server to be run with an arbitrary user + ## + enabled: true + + ## initChownData container image + ## + image: + repository: busybox + tag: "1.31.1" + sha: "" + pullPolicy: IfNotPresent + + ## initChownData resource requests and limits + ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ + ## + resources: + limits: + cpu: 200m + memory: 2568Mi + requests: + cpu: 100m + memory: 128Mi + + +# Administrator credentials when not using an existing secret (see below) +adminUser: admin +adminPassword: Trilio@321 + +# Use an existing secret for the admin user. +admin: + ## Name of the secret. Can be templated. + existingSecret: "" + userKey: admin-user + passwordKey: admin-password + +## Define command to be executed at startup by grafana container +## Needed if using `vault-env` to manage secrets (ref: https://banzaicloud.com/blog/inject-secrets-into-pods-vault/) +## Default is "run.sh" as defined in grafana's Dockerfile +# command: +# - "sh" +# - "/run.sh" + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: + +## Extra environment variables that will be pass onto deployment pods +## +## to provide grafana with access to CloudWatch on AWS EKS: +## 1. create an iam role of type "Web identity" with provider oidc.eks.* (note the provider for later) +## 2. edit the "Trust relationships" of the role, add a line inside the StringEquals clause using the +## same oidc eks provider as noted before (same as the existing line) +## also, replace NAMESPACE and prometheus-operator-grafana with the service account namespace and name +## +## "oidc.eks.us-east-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:sub": "system:serviceaccount:NAMESPACE:prometheus-operator-grafana", +## +## 3. attach a policy to the role, you can use a built in policy called CloudWatchReadOnlyAccess +## 4. use the following env: (replace 123456789000 and iam-role-name-here with your aws account number and role name) +## +## env: +## AWS_ROLE_ARN: arn:aws:iam::123456789000:role/iam-role-name-here +## AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token +## AWS_REGION: us-east-1 +## +## 5. uncomment the EKS section in extraSecretMounts: below +## 6. uncomment the annotation section in the serviceAccount: above +## make sure to replace arn:aws:iam::123456789000:role/iam-role-name-here with your role arn + +env: {} + +## "valueFrom" environment variable references that will be added to deployment pods. Name is templated. +## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core +## Renders in container spec as: +## env: +## ... +## - name: +## valueFrom: +## +envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key + +## The name of a secret in the same kubernetes namespace which contain values to be added to the environment +## This can be useful for auth tokens, etc. Value is templated. +envFromSecret: "" + +## Sensible environment variables that will be rendered as new secret object +## This can be useful for auth tokens, etc +envRenderSecret: {} + +## The names of secrets in the same kubernetes namespace which contain values to be added to the environment +## Each entry should contain a name key, and can optionally specify whether the secret must be defined with an optional key. +## Name is templated. +envFromSecrets: [] +## - name: secret-name +## optional: true + +## The names of conifgmaps in the same kubernetes namespace which contain values to be added to the environment +## Each entry should contain a name key, and can optionally specify whether the configmap must be defined with an optional key. +## Name is templated. +## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#configmapenvsource-v1-core +envFromConfigMaps: [] +## - name: configmap-name +## optional: true + +# Inject Kubernetes services as environment variables. +# See https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/#environment-variables +enableServiceLinks: true + +## Additional grafana server secret mounts +# Defines additional mounts with secrets. Secrets must be manually created in the namespace. +extraSecretMounts: [] + # - name: secret-files + # mountPath: /etc/secrets + # secretName: grafana-secret-files + # readOnly: true + # subPath: "" + # + # for AWS EKS (cloudwatch) use the following (see also instruction in env: above) + # - name: aws-iam-token + # mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount + # readOnly: true + # projected: + # defaultMode: 420 + # sources: + # - serviceAccountToken: + # audience: sts.amazonaws.com + # expirationSeconds: 86400 + # path: token + # + # for CSI e.g. Azure Key Vault use the following + # - name: secrets-store-inline + # mountPath: /run/secrets + # readOnly: true + # csi: + # driver: secrets-store.csi.k8s.io + # readOnly: true + # volumeAttributes: + # secretProviderClass: "akv-grafana-spc" + # nodePublishSecretRef: # Only required when using service principal mode + # name: grafana-akv-creds # Only required when using service principal mode + +## Additional grafana server volume mounts +# Defines additional volume mounts. +extraVolumeMounts: [] + # - name: extra-volume-0 + # mountPath: /mnt/volume0 + # readOnly: true + # existingClaim: volume-claim + # - name: extra-volume-1 + # mountPath: /mnt/volume1 + # readOnly: true + # hostPath: /usr/shared/ + +## Container Lifecycle Hooks. Execute a specific bash command or make an HTTP request +lifecycleHooks: {} + # postStart: + # exec: + # command: [] + +## Pass the plugins you want installed as a list. +## +plugins: + - grafana-piechart-panel + # - digrich-bubblechart-panel + # - grafana-clock-panel + +## Configure grafana datasources +## ref: http://docs.grafana.org/administration/provisioning/#datasources +## +datasources: {} +# datasources.yaml: +# apiVersion: 1 +# datasources: +# - name: Prometheus +# type: prometheus +# url: http://prometheus-prometheus-server +# access: proxy +# isDefault: true +# - name: CloudWatch +# type: cloudwatch +# access: proxy +# uid: cloudwatch +# editable: false +# jsonData: +# authType: default +# defaultRegion: us-east-1 + +## Configure notifiers +## ref: http://docs.grafana.org/administration/provisioning/#alert-notification-channels +## +notifiers: {} +# notifiers.yaml: +# notifiers: +# - name: email-notifier +# type: email +# uid: email1 +# # either: +# org_id: 1 +# # or +# org_name: Main Org. +# is_default: true +# settings: +# addresses: an_email_address@example.com +# delete_notifiers: + +## Configure grafana dashboard providers +## ref: http://docs.grafana.org/administration/provisioning/#dashboards +## +## `path` must be /var/lib/grafana/dashboards/ +## +dashboardProviders: {} +# dashboardproviders.yaml: +# apiVersion: 1 +# providers: +# - name: 'default' +# orgId: 1 +# folder: '' +# type: file +# disableDeletion: false +# editable: true +# options: +# path: /var/lib/grafana/dashboards/default + +## Configure grafana dashboard to import +## NOTE: To use dashboards you must also enable/configure dashboardProviders +## ref: https://grafana.com/dashboards +## +## dashboards per provider, use provider name as key. +## +dashboards: + default: + backup-detail: + file: dashboards/backup-detail.json + backup-overview: + file: dashboards/backup-overview.json + backupplan-detail: + file: dashboards/backupplan-detail.json + backupplan-overview: + file: dashboards/backupplan-overview.json + metadata-detail: + file: dashboards/metadata-detail.json + overview: + file: dashboards/overview.json + restore-detail: + file: dashboards/restore-detail.json + restore-overview: + file: dashboards/restore-overview.json + target-detail: + file: dashboards/target-detail.json + # default: + # some-dashboard: + # json: | + # $RAW_JSON + # custom-dashboard: + # file: dashboards/custom-dashboard.json + # prometheus-stats: + # gnetId: 2 + # revision: 2 + # datasource: Prometheus + # local-dashboard: + # url: https://example.com/repository/test.json + # token: '' + # local-dashboard-base64: + # url: https://example.com/repository/test-b64.json + # token: '' + # b64content: true + +## Reference to external ConfigMap per provider. Use provider name as key and ConfigMap name as value. +## A provider dashboards must be defined either by external ConfigMaps or in values.yaml, not in both. +## ConfigMap data example: +## +## data: +## example-dashboard.json: | +## RAW_JSON +## +dashboardsConfigMaps: {} +# default: "" + +## Grafana's primary configuration +## NOTE: values in map will be converted to ini format +## ref: http://docs.grafana.org/installation/configuration/ +## +grafana.ini: + dashboards: + default_home_dashboard_path: /var/lib/grafana/dashboards/default/overview.json + paths: + data: /var/lib/grafana/ + logs: /var/log/grafana + plugins: /var/lib/grafana/plugins + provisioning: /etc/grafana/provisioning + analytics: + check_for_updates: false + log: + mode: console + grafana_net: + url: https://grafana.net +## grafana Authentication can be enabled with the following values on grafana.ini + # server: + # The full public facing url you use in browser, used for redirects and emails + # root_url: + # https://grafana.com/docs/grafana/latest/auth/github/#enable-github-in-grafana + # auth.github: + # enabled: false + # allow_sign_up: false + # scopes: user:email,read:org + # auth_url: https://github.com/login/oauth/authorize + # token_url: https://github.com/login/oauth/access_token + # api_url: https://api.github.com/user + # team_ids: + # allowed_organizations: + # client_id: + # client_secret: +## LDAP Authentication can be enabled with the following values on grafana.ini +## NOTE: Grafana will fail to start if the value for ldap.toml is invalid + # auth.ldap: + # enabled: true + # allow_sign_up: true + # config_file: /etc/grafana/ldap.toml + +## Grafana's LDAP configuration +## Templated by the template in _helpers.tpl +## NOTE: To enable the grafana.ini must be configured with auth.ldap.enabled +## ref: http://docs.grafana.org/installation/configuration/#auth-ldap +## ref: http://docs.grafana.org/installation/ldap/#configuration +ldap: + enabled: false + # `existingSecret` is a reference to an existing secret containing the ldap configuration + # for Grafana in a key `ldap-toml`. + existingSecret: "" + # `config` is the content of `ldap.toml` that will be stored in the created secret + config: "" + # config: |- + # verbose_logging = true + + # [[servers]] + # host = "my-ldap-server" + # port = 636 + # use_ssl = true + # start_tls = false + # ssl_skip_verify = false + # bind_dn = "uid=%s,ou=users,dc=myorg,dc=com" + +## Grafana's SMTP configuration +## NOTE: To enable, grafana.ini must be configured with smtp.enabled +## ref: http://docs.grafana.org/installation/configuration/#smtp +smtp: + # `existingSecret` is a reference to an existing secret containing the smtp configuration + # for Grafana. + existingSecret: "" + userKey: "user" + passwordKey: "password" + +## Sidecars that collect the configmaps with specified label and stores the included files them into the respective folders +## Requires at least Grafana 5 to work and can't be used together with parameters dashboardProviders, datasources and dashboards +sidecar: + image: + repository: quay.io/kiwigrid/k8s-sidecar + tag: 1.15.6 + sha: "" + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 200m + memory: 200Mi + requests: + cpu: 100m + memory: 100Mi + securityContext: {} + # skipTlsVerify Set to true to skip tls verification for kube api calls + # skipTlsVerify: true + enableUniqueFilenames: false + readinessProbe: {} + livenessProbe: {} + dashboards: + enabled: true + SCProvider: true + # label that the configmaps with dashboards are marked with + label: grafana_dashboard + # value of label that the configmaps with dashboards are set to + labelValue: null + # folder in the pod that should hold the collected dashboards (unless `defaultFolderName` is set) + folder: /tmp/dashboards + # The default folder name, it will create a subfolder under the `folder` and put dashboards in there instead + defaultFolderName: null + # Namespaces list. If specified, the sidecar will search for config-maps/secrets inside these namespaces. + # Otherwise the namespace in which the sidecar is running will be used. + # It's also possible to specify ALL to search in all namespaces. + searchNamespace: null + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # If specified, the sidecar will look for annotation with this name to create folder and put graph here. + # You can use this parameter together with `provider.foldersFromFilesStructure`to annotate configmaps and create folder structure. + folderAnnotation: null + # Absolute path to shell script to execute after a configmap got reloaded + script: null + # watchServerTimeout: request to the server, asking it to cleanly close the connection after that. + # defaults to 60sec; much higher values like 3600 seconds (1h) are feasible for non-Azure K8S + # watchServerTimeout: 3600 + # + # watchClientTimeout: is a client-side timeout, configuring your local socket. + # If you have a network outage dropping all packets with no RST/FIN, + # this is how long your client waits before realizing & dropping the connection. + # defaults to 66sec (sic!) + # watchClientTimeout: 60 + # + # provider configuration that lets grafana manage the dashboards + provider: + # name of the provider, should be unique + name: sidecarProvider + # orgid as configured in grafana + orgid: 1 + # folder in which the dashboards should be imported in grafana + folder: '' + # type of the provider + type: file + # disableDelete to activate a import-only behaviour + disableDelete: false + # allow updating provisioned dashboards from the UI + allowUiUpdates: false + # allow Grafana to replicate dashboard structure from filesystem + foldersFromFilesStructure: false + # Additional dashboard sidecar volume mounts + extraMounts: [] + # Sets the size limit of the dashboard sidecar emptyDir volume + sizeLimit: {} + datasources: + enabled: true + # label that the configmaps with datasources are marked with + label: grafana_datasource + # value of label that the configmaps with datasources are set to + labelValue: null + # If specified, the sidecar will search for datasource config-maps inside this namespace. + # Otherwise the namespace in which the sidecar is running will be used. + # It's also possible to specify ALL to search in all namespaces + searchNamespace: null + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # Endpoint to send request to reload datasources + reloadURL: "http://localhost:3000/api/admin/provisioning/datasources/reload" + skipReload: false + # Deploy the datasource sidecar as an initContainer in addition to a container. + # This is needed if skipReload is true, to load any datasources defined at startup time. + initDatasources: false + # Sets the size limit of the datasource sidecar emptyDir volume + sizeLimit: {} + plugins: + enabled: false + # label that the configmaps with plugins are marked with + label: grafana_plugin + # value of label that the configmaps with plugins are set to + labelValue: null + # If specified, the sidecar will search for plugin config-maps inside this namespace. + # Otherwise the namespace in which the sidecar is running will be used. + # It's also possible to specify ALL to search in all namespaces + searchNamespace: null + # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. + watchMethod: WATCH + # search in configmap, secret or both + resource: both + # Endpoint to send request to reload plugins + reloadURL: "http://localhost:3000/api/admin/provisioning/plugins/reload" + skipReload: false + # Deploy the datasource sidecar as an initContainer in addition to a container. + # This is needed if skipReload is true, to load any plugins defined at startup time. + initPlugins: false + # Sets the size limit of the plugin sidecar emptyDir volume + sizeLimit: {} + notifiers: + enabled: false + # label that the configmaps with notifiers are marked with + label: grafana_notifier + # If specified, the sidecar will search for notifier config-maps inside this namespace. + # Otherwise the namespace in which the sidecar is running will be used. + # It's also possible to specify ALL to search in all namespaces + searchNamespace: null + # search in configmap, secret or both + resource: both + # Sets the size limit of the notifier sidecar emptyDir volume + sizeLimit: {} + +## Override the deployment namespace +## +namespaceOverride: "" + +## Number of old ReplicaSets to retain +## +revisionHistoryLimit: 10 + +## Add a seperate remote image renderer deployment/service +imageRenderer: + # Enable the image-renderer deployment & service + enabled: false + replicas: 1 + image: + # image-renderer Image repository + repository: grafana/grafana-image-renderer + # image-renderer Image tag + tag: latest + # image-renderer Image sha (optional) + sha: "" + # image-renderer ImagePullPolicy + pullPolicy: Always + # extra environment variables + env: + HTTP_HOST: "0.0.0.0" + # RENDERING_ARGS: --no-sandbox,--disable-gpu,--window-size=1280x758 + # RENDERING_MODE: clustered + # IGNORE_HTTPS_ERRORS: true + # image-renderer deployment serviceAccount + serviceAccountName: "" + # image-renderer deployment securityContext + securityContext: {} + # image-renderer deployment Host Aliases + hostAliases: [] + # image-renderer deployment priority class + priorityClassName: '' + service: + # Enable the image-renderer service + enabled: true + # image-renderer service port name + portName: 'http' + # image-renderer service port used by both service and deployment + port: 8081 + targetPort: 8081 + # If https is enabled in Grafana, this needs to be set as 'https' to correctly configure the callback used in Grafana + grafanaProtocol: http + # In case a sub_path is used this needs to be added to the image renderer callback + grafanaSubPath: "" + # name of the image-renderer port on the pod + podPortName: http + # number of image-renderer replica sets to keep + revisionHistoryLimit: 10 + networkPolicy: + # Enable a NetworkPolicy to limit inbound traffic to only the created grafana pods + limitIngress: true + # Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods + limitEgress: false + resources: + limits: + cpu: 200m + memory: 200Mi + requests: + cpu: 100m + memory: 100Mi + ## Node labels for pod assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + # + nodeSelector: {} + + ## Tolerations for pod assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + + ## Affinity for pod assignment (evaluated as template) + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## + affinity: {} + +networkPolicy: + ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. + ## + enabled: false + ## @param networkPolicy.allowExternal Don't require client label for connections + ## The Policy model to apply. When set to false, only pods with the correct + ## client label will have network access to grafana port defined. + ## When true, grafana will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + ## @param networkPolicy.explicitNamespacesSelector A Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed + ## If explicitNamespacesSelector is missing or set to {}, only client Pods that are in the networkPolicy's namespace + ## and that match other criteria, the ones that have the good label, can reach the grafana. + ## But sometimes, we want the grafana to be accessible to clients from other namespaces, in this case, we can use this + ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added. + ## + ## Example: + ## explicitNamespacesSelector: + ## matchLabels: + ## role: frontend + ## matchExpressions: + ## - {key: role, operator: In, values: [frontend]} + ## + explicitNamespacesSelector: {} + +# Enable backward compatibility of kubernetes where version below 1.13 doesn't have the enableServiceLinks option +enableKubeBackwardCompatibility: false + +# Create a dynamic manifests via values: +extraObjects: [] + # - apiVersion: "kubernetes-client.io/v1" + # kind: ExternalSecret + # metadata: + # name: grafana-secrets + # spec: + # backendType: gcpSecretsManager + # data: + # - key: grafana-admin-password + # name: adminPassword diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/crds/triliovault.trilio.io_triliovaultmanagers.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/crds/triliovault.trilio.io_triliovaultmanagers.yaml new file mode 100644 index 000000000..b1f5bed25 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/crds/triliovault.trilio.io_triliovaultmanagers.yaml @@ -0,0 +1,1216 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.7.0 + creationTimestamp: null + name: triliovaultmanagers.triliovault.trilio.io +spec: + group: triliovault.trilio.io + names: + kind: TrilioVaultManager + listKind: TrilioVaultManagerList + plural: triliovaultmanagers + shortNames: + - tvm + singular: triliovaultmanager + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.releaseVersion + name: TrilioVault-Version + type: string + - jsonPath: .spec.applicationScope + name: Scope + type: string + - jsonPath: .status.conditions.type + name: Status + type: string + - jsonPath: .spec.restoreNamespaces + name: Restore-Namespaces + type: string + name: v1 + schema: + openAPIV3Schema: + description: TrilioVaultManager is the Schema for the triliovaultmanagers + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: TrilioVaultManagerSpec defines the desired state of TrilioVaultManager + properties: + affinity: + description: The scheduling constraints on application pods. + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. This field is beta-level + and is only honored when PodAffinityNamespaceSelector + feature is enabled. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + This field is beta-level and is only honored when + PodAffinityNamespaceSelector feature is enabled. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. This field is beta-level + and is only honored when PodAffinityNamespaceSelector + feature is enabled. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied to the + union of the namespaces selected by this field and + the ones listed in the namespaces field. null selector + and null or empty namespaces list means "this pod's + namespace". An empty selector ({}) matches all namespaces. + This field is beta-level and is only honored when + PodAffinityNamespaceSelector feature is enabled. + 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 + required: + - key + - operator + type: object + type: array + 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 + namespaces: + description: namespaces specifies a static list of namespace + names that the term applies to. The term is applied + to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. null or + empty namespaces list and null namespaceSelector means + "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + applicationScope: + description: Scope for the application which will be installed in + the cluster NamespaceScope or ClusterScope + enum: + - Cluster + - Namespaced + type: string + componentConfiguration: + description: ComponentConfiguration holds all the field related to + components. + properties: + admission-webhook: + description: AdmissionWebhook holds all configuration keys related + to admission-webhook + type: object + x-kubernetes-preserve-unknown-fields: true + control-plane: + description: ControlPlane holds all configuration keys related + to control-plane + type: object + x-kubernetes-preserve-unknown-fields: true + exporter: + description: Exporter holds all configuration keys related to + exporter + type: object + x-kubernetes-preserve-unknown-fields: true + ingress-controller: + description: IngressController holds all configuration keys related + to ingress-controller + type: object + x-kubernetes-preserve-unknown-fields: true + web: + description: Web holds all configuration keys related to web + type: object + x-kubernetes-preserve-unknown-fields: true + web-backend: + description: WebBackend holds all configuration keys related to + web-backend + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + csiConfig: + description: CSIConfig is the configuration for the CSI drivers which + doesn't support snapshot functionality + properties: + exclude: + description: Exclude denotes the list of CSI drivers to be excluded + from the non-snapshot functionality category + items: + type: string + type: array + include: + description: Include denotes the list of CSI drivers to be included + in the non-snapshot functionality category + items: + type: string + type: array + type: object + dataJobLimits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Deprecated: DataJobLimits are the resource limits for + all the data processing jobs.' + type: object + dataJobResources: + description: DataJobResources is the resource limits & requests for + all the data processing jobs. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources + allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + deploymentLimits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: DeploymentLimits are the resource limits for all the + deployments. + type: object + helmValues: + description: HelmValues holds all the additional fields in the values.yaml + of TVK helm chart. + type: object + x-kubernetes-preserve-unknown-fields: true + helmVersion: + description: 'Deprecated: Helm Version' + properties: + tillerNamespace: + type: string + version: + enum: + - v3 + type: string + required: + - version + type: object + ingressConfig: + description: IngressConfig holds field related to ingress + properties: + annotations: + additionalProperties: + type: string + type: object + host: + type: string + ingressClass: + type: string + tlsSecretName: + type: string + type: object + logLevel: + description: LogLevel is a level used in TVK logging. + enum: + - Panic + - Fatal + - Error + - Warn + - Info + - Debug + - Trace + type: string + metadataJobLimits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Deprecated: MetadataJobLimits are the resource limits + for all the meta processing jobs.' + type: object + metadataJobResources: + description: MetadataJobResources is the resource limits & requests + for all the meta processing jobs. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources + allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: NodeSelector specifies a map of key-value pairs. For + the pod to be eligible to run on a node, the node must have each + of the indicated key-value pairs as labels. + type: object + resources: + description: 'Deprecated: Resources are the resource requirements + for the containers.' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute resources + allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + restoreNamespaces: + description: 'Deprecated: RestoreNamespaces are the namespace where + you want to restore your applications. Restore Namespaces depends + on your k8s RBAC' + items: + type: string + type: array + tolerations: + description: The toleration of application against the specific taints + on the nodes + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + trilioVaultAppVersion: + description: 'Deprecated: TrilioVaultAppVersion Helm Chart version' + type: string + tvkInstanceName: + description: TVKInstanceName is a TVK installation name to be displayed + on UI. + type: string + required: + - applicationScope + type: object + status: + description: TrilioVaultManagerStatus defines the observed state of TrilioVaultManager + properties: + conditions: + properties: + lastTransitionTime: + format: date-time + nullable: true + type: string + message: + minLength: 0 + type: string + reason: + enum: + - InstallSuccessful + - UpdateSuccessful + - UninstallSuccessful + - InstallError + - UpdateError + - ReconcileError + - UninstallError + type: string + status: + enum: + - "True" + - "False" + - Unknown + type: string + type: + enum: + - Initialized + - Deployed + - Updated + - ReleaseFailed + - Irreconcilable + type: string + type: object + deployedRelease: + properties: + manifest: + type: string + name: + type: string + type: object + helmRevision: + type: integer + releaseVersion: + type: string + required: + - conditions + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/questions.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/questions.yaml new file mode 100644 index 000000000..ce9c928b3 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/questions.yaml @@ -0,0 +1,120 @@ +questions: +- variable: installTVK.enabled + default: true + description: "TriloVault Manager is an instance of TrilioVault for Kubernetes. Selecting this checkbox automatically creates a TrilioVault Manager instance" + required: true + type: boolean + label: "Install TrilioVault Manager Automatically" + group: "TrilioVault Manager Install Configuration" + +- variable: installTVK.tvkInstanceName + show_if: "installTVK.enabled=true" + default: "triliovault-manager" + description: "TrilioVault Manager Instance Name. This will be used to manage the Kubernetes cluster in TVK Management Console and backups performed by the TrilioVault for Kubernetes" + required: true + type: string + label: "TrilioVault Manager Instance Name" + group: "TrilioVault Manager Install Configuration" + +- variable: installTVK.applicationScope + default: Cluster + description: "TrilioVault Manager installation scope: Cluster or Namespaced" + required: true + type: enum + label: "TrilioVault Manager Installation Scope" + group: "TrilioVault Manager Install Configuration" + options: + - "Cluster" + - "Namespaced" + +- variable: installTVK.ingressConfig.host + default: "rancher.k8s-tvk.com" + description: "Hostname URL to access the TVK Management Console - For example: rancher.k8s-tvk.com" + required: true + type: hostname + label: "TVK Management Console Hostname URL" + group: "Ingress Configuration" + +- variable: installTVK.ingressConfig.tlsSecretName + default: "" + description: "TLS Secret containing an appropriate certificate to access the TVK Management Console over HTTPS protocol. Secret should of type kubernetes.io/tls" + required: false + type: secret + label: "TLS Secret of type kubernetes.io/tls (Optional)" + group: "Ingress Configuration" + +- variable: installTVK.ComponentConfiguration.ingressController.enabled + default: true + description: "Select if Trilio provided Ingress Controller (nginx) should be leveraged or if an existing Ingress Controller within the cluster should be used" + required: true + type: boolean + label: "Use Trilio Provided Ingress Controller" + group: "Ingress Configuration" + +- variable: installTVK.ComponentConfiguration.ingressController.service.type + show_if: "installTVK.ComponentConfiguration.ingressController.enabled=true" + default: "NodePort" + description: "Ingress Controller Service Type to access the TVK Management Console" + required: true + type: enum + label: "Ingress Controller Service Type" + group: "Ingress Configuration" + options: + - "NodePort" + - "LoadBalancer" + +- variable: installTVK.ingressConfig.ingressClass + show_if: "installTVK.ComponentConfiguration.ingressController.enabled=false" + default: "" + description: "Name of an existing Ingress Class to use to access the TVK Management Console. Ingress class must exist on the Kubernetes cluster" + required: true + type: string + label: "Ingress Class Name" + group: "Ingress Configuration" + +- variable: installTVK.ingressConfig.annotations + show_if: "installTVK.ComponentConfiguration.ingressController.enabled=false" + default: "" + description: "Annotations to add for the TrilioVault Manager ingress resource - For example: {'foo':'bar'}" + required: false + type: string + label: "Annotations for Ingress Resource (Optional)" + group: "Ingress Configuration" + +- variable: proxySettings.PROXY_ENABLED + default: false + description: "Select this checkbox to deploy the TrilioVault Manager via a proxy server" + required: false + type: boolean + label: "Proxy Settings (Optional)" + group: "Proxy Settings" + show_subquestion_if: true + subquestions: + - variable: proxySettings.NO_PROXY + default: "" + description: "Provide the user defined IPs/hosts and subnets to exempt from proxy. User can provide comma separated values. For example: 'localhost,127.0.0.1,10.239.112.0/20,10.240.0.0/14'" + required: false + type: string + label: "No Proxy (Optional)" + group: "Proxy Settings" + - variable: proxySettings.HTTP_PROXY + default: "" + description: "Provide HTTP proxy information. For example: http://:@:" + required: true + type: string + label: "HTTP Proxy" + group: "Proxy Settings" + - variable: proxySettings.HTTPS_PROXY + default: "" + description: "Provide HTTPS proxy information. For example: https://:@:" + required: true + type: string + label: "HTTPS Proxy" + group: "Proxy Settings" + - variable: proxySettings.CA_BUNDLE_CONFIGMAP + default: "" + description: "Provide a CA Certificate bundle configmap present on the Kubernetes cluster to communicate with the proxy server" + required: false + type: string + label: "CA Certificate Bundle Configmap Name (Optional)" + group: "Proxy Settings" diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/NOTES.txt b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/NOTES.txt new file mode 100644 index 000000000..12b2a8c9c --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/NOTES.txt @@ -0,0 +1,59 @@ +TrilioVault Operator is a helm based operator which install/upgrade/delete the helm Chart of the TrilioVault For Kubernetes. +This operator watches over the entire helm application of TrilioVault for Kubernetes and has self-healing capabilities. + +To verify that TrilioVault Operator has started, run: + + kubectl --namespace={{ .Release.Namespace }} wait --for=condition=ready pod -l "release={{ .Release.Name }}" + +{{ if .Values.installTVK.enabled }} +In one click install, a cluster scope TVM custom resource triliovault-manager is created, you can check its +configuration by running following command: + + kubectl --namespace {{ .Release.Namespace }} get triliovaultmanagers.triliovault.trilio.io triliovault-manager -o yaml + +{{- else }} + +Once the Triliovault operator is in running state, you can create the TrilioVault for Kubernetes(TVK) with the +following custom resource: + + apiVersion: triliovault.trilio.io/v1 + kind: TrilioVaultManager + metadata: + labels: + app: triliovault + name: triliovault-manager + namespace: {{ .Release.Namespace }} + spec: + trilioVaultAppVersion: latest + applicationScope: Cluster + ingressConfig: + host: "" + componentConfiguration: + ingress-controller: + enabled: true + service: + type: LoadBalancer + +Once the above CR has been created, you have to wait for the TVK pods to come up. +{{- end }} + +To check all the TVK pods come into running state, run: + + kubectl --namespace {{ .Release.Namespace }} wait --for=condition=ready pod -l "release=triliovault-manager-{{ .Release.Namespace }}" + +Once all the pods are in running state, you can access the TVK UI from your browser using following steps: + +{{- if .Values.installTVK.enabled }} +{{- if eq .Values.installTVK.ComponentConfiguration.ingressController.service.type "LoadBalancer" }} + 1. Find the external IP of the service `k8s-triliovault-ingress-nginx-controller` + 2. Hit the URL in browser: https:// +{{- else }} + 1. Find the NodePort from the service `k8s-triliovault-ingress-nginx-controller` + 2. Hit the URL in browser with NodePort: https://:/ +{{- end }} +{{- end }} + +For more details on how to access the TVK UI, follow this guide: https://docs.trilio.io/kubernetes/management-console-ui/accessing-the-ui + +You can start backup and restore of your application using TVK. For more details on how to do that, please follow our +getting started guide: https://docs.trilio.io/kubernetes/getting-started-3/getting-started-with-management-console diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/TVMCustomResource.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/TVMCustomResource.yaml new file mode 100644 index 000000000..b7d0bbdd5 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/TVMCustomResource.yaml @@ -0,0 +1,53 @@ +{{- if .Values.installTVK.enabled }} +{{- if not (lookup "triliovault.trilio.io/v1" "TrilioVaultManager" "" "").items }} + {{template "k8s-triliovault-operator.tlsSecretValidation" .}} +apiVersion: triliovault.trilio.io/v1 +kind: TrilioVaultManager +metadata: + name: "triliovault-manager" + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook": pre-install +spec: + {{- if eq .Chart.Version "0.1.0" }} + trilioVaultAppVersion: latest + {{- else}} + trilioVaultAppVersion: {{ .Chart.AppVersion }} + {{- end }} + applicationScope: {{ .Values.installTVK.applicationScope }} + {{- if .Values.installTVK.tvkInstanceName }} + tvkInstanceName: {{ .Values.installTVK.tvkInstanceName }} + {{- end }} + {{- if or .Values.imagePullSecret .Values.priorityClassName }} + helmValues: + {{- if .Values.imagePullSecret }} + imagePullSecret: {{ .Values.imagePullSecret }} + {{- end }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- end }} + # User can configure the ingress hosts, annotations and TLS secret through the ingressConfig section + ingressConfig: + {{- if and (gt (len .Values.installTVK.ingressConfig.annotations) 0) (not .Values.installTVK.ComponentConfiguration.ingressController.enabled) }} + annotations: + {{- range $key, $value := .Values.installTVK.ingressConfig.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end -}} + {{- end }} + host: {{ .Values.installTVK.ingressConfig.host | quote }} + {{- if not .Values.installTVK.ComponentConfiguration.ingressController.enabled }} + ingressClass: {{ .Values.installTVK.ingressConfig.ingressClass | quote }} + {{- end }} + {{- if .Values.installTVK.ingressConfig.tlsSecretName }} + tlsSecretName: {{ .Values.installTVK.ingressConfig.tlsSecretName | quote }} + {{- end }} + # TVK components configuration, currently supports control-plane, web, exporter, web-backend, ingress-controller, admission-webhook. + # User can configure resources for all componentes and can configure service type and host for the ingress-controller + componentConfiguration: + ingress-controller: + enabled: {{ .Values.installTVK.ComponentConfiguration.ingressController.enabled }} + service: + type: {{ .Values.installTVK.ComponentConfiguration.ingressController.service.type }} +{{- end -}} +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/_helpers.tpl b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/_helpers.tpl new file mode 100644 index 000000000..bb97d8c0c --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/_helpers.tpl @@ -0,0 +1,85 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "k8s-triliovault-operator.name" -}} +{{- default .Release.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "k8s-triliovault-operator.appName" -}} +{{- printf "%s" .Chart.Name -}} +{{- end -}} + + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "k8s-triliovault-operator.fullname" -}} +{{- printf "%s" .Chart.Name -}} +{{- end -}} + +{{/* +Return the proper TrilioVault Operator image name +*/}} +{{- define "k8s-triliovault-operator.image" -}} +{{- $registryName := .Values.image.registry -}} +{{- $repositoryName := .Values.image.repository -}} +{{- $tag := .Values.image.tag | toString -}} +{{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} +{{- end -}} + +{{/* +Validation of the secret of CA bundle if provided +*/}} +{{- define "k8s-triliovault-operator.caBundleValidation" -}} +{{- if .Values.proxySettings.CA_BUNDLE_CONFIGMAP }} +{{- if not (lookup "v1" "ConfigMap" .Release.Namespace .Values.proxySettings.CA_BUNDLE_CONFIGMAP) }} + {{ fail "Proxy CA bundle proxy is not present in the release namespace" }} +{{- else }} + {{- $caMap := (lookup "v1" "ConfigMap" .Release.Namespace .Values.proxySettings.CA_BUNDLE_CONFIGMAP).data }} + {{- if not (get $caMap "ca-bundle.crt") }} + {{ fail "Proxy CA certificate file key should be ca-bundle.crt" }} + {{- end }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* +Validation for the ingress tlsSecret, should exists if provided +*/}} + +{{- define "k8s-triliovault-operator.tlsSecretValidation" }} +{{- if .Values.installTVK.ingressConfig.tlsSecretName -}} +{{- if not (lookup "v1" "Secret" .Release.Namespace .Values.installTVK.ingressConfig.tlsSecretName ) -}} + {{ fail "Ingress tls secret is not present in the release namespace" }} +{{- end -}} +{{- end -}} +{{- end -}} + + +{{- define "k8s-triliovault-operator.preFlightValidation" }} +{{- if not .Values.preflight.storageClass }} + {{ fail "Provide the name of storage class as you have enabled the preflight" }} +{{- else }} + {{- if not (lookup "storage.k8s.io/v1" "StorageClass" "" .Values.preflight.storageClass) }} + {{ fail "Storage class provided is not present in the cluster" }} + {{- end }} +{{- end }} +{{- end }} + +{{- define "k8s-triliovault-operator.priorityClassValidator" }} +{{- if .Values.priorityClassName -}} +{{- if not (lookup "scheduling.k8s.io/v1" "PriorityClass" "" .Values.priorityClassName) }} + {{ fail "Priority class provided is not present in the cluster" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create unified labels for k8s-triliovault-operator components +*/}} +{{- define "k8s-triliovault-operator.labels" -}} +app.kubernetes.io/part-of: k8s-triliovault-operator +app.kubernetes.io/managed-by: k8s-triliovault-operator +app.kubernetes.io/name: k8s-triliovault-operator +{{- end -}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/clusterrole.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/clusterrole.yaml new file mode 100644 index 000000000..a6208e049 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/clusterrole.yaml @@ -0,0 +1,133 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{template "k8s-triliovault-operator.name" .}}-{{.Release.Namespace}}-manager-role + labels: + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{template "k8s-triliovault-operator.appName" .}}-manager-role + app.kubernetes.io/managed-by: {{ .Release.Service }} +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - get + - list + - watch + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - create + - update + - delete + - patch + - apiGroups: + - "" + resources: + - serviceaccounts + - services + - services/finalizers + - secrets + - events + - pods + - endpoints + - configmaps + verbs: + - create + - update + - delete + - patch + - apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + - mutatingwebhookconfigurations + verbs: + - create + - update + - delete + - patch + - apiGroups: + - apps + resources: + - deployments + verbs: + - create + - update + - delete + - patch + - apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + - clusterrolebindings + - roles + - rolebindings + verbs: + - create + - update + - delete + - patch + - bind + - escalate + - apiGroups: + - triliovault.trilio.io + resources: + - '*' + verbs: + - '*' + - apiGroups: + - "" + resources: + - namespaces + verbs: + - update + - apiGroups: + - batch + resources: + - cronjobs + verbs: + - delete + - apiGroups: + - batch + resources: + - jobs + verbs: + - create + - delete + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - update + - patch + - delete + - apiGroups: + - networking.k8s.io + resources: + - ingresses + - ingressclasses + verbs: + - create + - patch + - update + - delete + - apiGroups: + - networking.k8s.io + resources: + - ingresses/status + verbs: + - update + - apiGroups: + - networking.k8s.io + resources: + - ingressclasses + verbs: + - delete diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/clusterrole_binding.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/clusterrole_binding.yaml new file mode 100644 index 000000000..49d5655f6 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/clusterrole_binding.yaml @@ -0,0 +1,17 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "k8s-triliovault-operator.name" . }}-{{ .Release.Namespace }}-manager-rolebinding + labels: + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }}-manager-rolebinding + app.kubernetes.io/managed-by: {{ .Release.Service }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "k8s-triliovault-operator.name" . }}-{{ .Release.Namespace }}-manager-role +subjects: +- kind: ServiceAccount + name: {{ template "k8s-triliovault-operator.fullname" . }}-service-account + namespace: {{ .Release.Namespace }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/deployment.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/deployment.yaml new file mode 100644 index 000000000..6627305f3 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/deployment.yaml @@ -0,0 +1,200 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "k8s-triliovault-operator.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "k8s-triliovault-operator.fullname" . }} + release: "{{ .Release.Name }}" + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + selector: + matchLabels: + app: {{ template "k8s-triliovault-operator.fullname" . }} + release: "{{ .Release.Name }}" + replicas: {{ .Values.replicaCount }} + template: + metadata: + {{- if .Values.proxySettings.PROXY_ENABLED }} + annotations: + checksum/config: {{ include (print $.Template.BasePath "/proxyConfig.yaml") . | sha256sum }} + {{- end }} + labels: + app: {{ template "k8s-triliovault-operator.fullname" . }} + release: "{{ .Release.Name }}" + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + spec: + hostNetwork: {{ .Values.podSpec.hostNetwork }} + hostIPC: {{ .Values.podSpec.hostIPC }} + hostPID: {{ .Values.podSpec.hostPID }} + {{- if .Values.priorityClassName }} + {{ template "k8s-triliovault-operator.priorityClassValidator" .}} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + {{- if .Values.securityContext }} + securityContext: + {{- toYaml .Values.podSpec.securityContext | nindent 8 }} + {{- end }} + containers: + - name: k8s-triliovault-operator + image: {{ .Values.registry }}/{{ index .Values "k8s-triliovault-operator" "repository" }}:{{ .Values.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.proxySettings.PROXY_ENABLED }} + envFrom: + - secretRef: + name: {{ template "k8s-triliovault-operator.fullname" . }}-proxy + {{- end }} + env: + {{- if .Values.proxySettings.PROXY_ENABLED }} + - name: PROXY_SETTINGS_SECRET + value: {{ template "k8s-triliovault-operator.fullname" . }}-proxy + {{- if .Values.proxySettings.CA_BUNDLE_CONFIGMAP }} + - name: PROXY_CA_CONFIGMAP + value: {{ .Values.proxySettings.CA_BUNDLE_CONFIGMAP }} + {{- end }} + {{- end }} + - name: INSTALL_NAMESPACE + value: {{ .Release.Namespace }} + - name: REGISTRY + value: {{ .Values.registry }} + - name: ADMISSION_MUTATION_CONFIG + value: {{ template "k8s-triliovault-operator.name" . }}-mutating-webhook-configuration + - name: ADMISSION_VALIDATION_CONFIG + value: {{ template "k8s-triliovault-operator.name" . }}-validating-webhook-configuration + - name: NAMESPACE_VALIDATION_CONFIG + value: {{ template "k8s-triliovault-operator.name" . }}-ns-validating-webhook-configuration + - name: RELEASE_VERSION + value: {{ .Chart.AppVersion }} + livenessProbe: + httpGet: + path: /healthz + port: 8081 + scheme: HTTP + initialDelaySeconds: 60 + periodSeconds: 30 + timeoutSeconds: 2 + successThreshold: 1 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 1 + successThreshold: 1 + failureThreshold: 3 + volumeMounts: + {{- if and .Values.proxySettings.PROXY_ENABLED .Values.proxySettings.CA_BUNDLE_CONFIGMAP }} + - name: proxy-ca-cert + mountPath: /proxy-certs + readOnly: true + {{- end }} + {{- if .Values.tls.enable }} + - name: helm-tls-certs + mountPath: /root/.helm + readOnly: true + {{- if .Values.tls.verify }} + - name: helm-tls-ca + mountPath: /root/.helm/ca.crt + readOnly: true + {{- end }} + {{- end }} + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: webhook-certs + readOnly: true + {{- if .Values.securityContext }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + {{- end }} + resources: + limits: + cpu: 200m + memory: 512Mi + requests: + cpu: 10m + memory: 10Mi + initContainers: + - name: webhook-init + image: {{ .Values.registry }}/{{ index .Values "operator-webhook-init" "repository" }}:{{ .Values.tag }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if .Values.securityContext }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + {{- end }} + {{- if .Values.proxySettings.PROXY_ENABLED }} + envFrom: + - secretRef: + name: {{ template "k8s-triliovault-operator.fullname" . }}-proxy + {{- end }} + env: + {{- if .Values.proxySettings.PROXY_ENABLED }} + - name: PROXY_SETTINGS_SECRET + value: {{ template "k8s-triliovault-operator.fullname" . }}-proxy + {{- if .Values.proxySettings.CA_BUNDLE_CONFIGMAP }} + - name: PROXY_CA_CONFIGMAP + value: {{ .Values.proxySettings.CA_BUNDLE_CONFIGMAP }} + {{- end }} + {{- end }} + - name: RELEASE_VERSION + value: {{ .Chart.AppVersion }} + - name: ADMISSION_MUTATION_CONFIG + value: {{ template "k8s-triliovault-operator.name" . }}-mutating-webhook-configuration + - name: ADMISSION_VALIDATION_CONFIG + value: {{ template "k8s-triliovault-operator.name" . }}-validating-webhook-configuration + - name: NAMESPACE_VALIDATION_CONFIG + value: {{ template "k8s-triliovault-operator.name" . }}-ns-validating-webhook-configuration + - name: WEBHOOK_SERVICE + value: {{ template "k8s-triliovault-operator.fullname" . }}-webhook-service + - name: WEBHOOK_NAMESPACE + value: {{ .Release.Namespace }} + - name: SECRET_NAME + value: {{ template "k8s-triliovault-operator.fullname" . }}-webhook-certs + {{- if and .Values.proxySettings.PROXY_ENABLED .Values.proxySettings.CA_BUNDLE_CONFIGMAP }} + volumeMounts: + - name: proxy-ca-cert + mountPath: /proxy-certs + readOnly: true + {{- end }} + serviceAccountName: {{ template "k8s-triliovault-operator.fullname" . }}-service-account + {{- if .Values.nodeSelector }} + nodeSelector: {{- .Values.nodeSelector | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.affinity }} + affinity: + {{- toYaml .Values.affinity | nindent 8 }} + {{- end }} + volumes: + {{- if and .Values.proxySettings.PROXY_ENABLED .Values.proxySettings.CA_BUNDLE_CONFIGMAP }} + - name: proxy-ca-cert + configMap: + name: {{ .Values.proxySettings.CA_BUNDLE_CONFIGMAP }} + {{- end }} + {{- if .Values.tls.enable }} + - name: helm-tls-certs + secret: + secretName: {{ .Values.tls.secretName }} + defaultMode: 0400 + {{- if .Values.tls.verify }} + - name: helm-tls-ca + configMap: + name: {{ template "k8s-triliovault-operator.fullname" . }}-helm-tls-ca-config + defaultMode: 0600 + {{- end }} + {{- end }} + - name: webhook-certs + secret: + defaultMode: 420 + secretName: {{ template "k8s-triliovault-operator.fullname" . }}-webhook-certs diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/mutating-webhook.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/mutating-webhook.yaml new file mode 100644 index 000000000..692feec4e --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/mutating-webhook.yaml @@ -0,0 +1,31 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: {{ template "k8s-triliovault-operator.name" . }}-mutating-webhook-configuration + labels: + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }}-mutating-webhook-configuration + app.kubernetes.io/managed-by: {{ .Release.Service }} +webhooks: +- clientConfig: + caBundle: Cg== + service: + name: {{ template "k8s-triliovault-operator.fullname" . }}-webhook-service + namespace: {{ .Release.Namespace }} + path: /mutate-triliovault-trilio-io-v1-triliovaultmanager + failurePolicy: Fail + name: v1-tvm-mutation.trilio.io + rules: + - apiGroups: + - triliovault.trilio.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - triliovaultmanagers + sideEffects: None + admissionReviewVersions: + - v1 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/ns-validating-webhook.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/ns-validating-webhook.yaml new file mode 100644 index 000000000..f0e0618e2 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/ns-validating-webhook.yaml @@ -0,0 +1,37 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ template "k8s-triliovault-operator.name" . }}-ns-validating-webhook-configuration + labels: + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }}-ns-validating-webhook-configuration + app.kubernetes.io/managed-by: {{ .Release.Service }} +webhooks: +- clientConfig: + caBundle: Cg== + service: + name: {{ template "k8s-triliovault-operator.fullname" . }}-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-core-v1-namespace + failurePolicy: Fail + name: v1-tvm-ns-validation.trilio.io + namespaceSelector: + matchExpressions: + - key: trilio-operator-label + operator: In + values: + - {{ .Release.Namespace }} + rules: + - apiGroups: + - "" + apiVersions: + - v1 + operations: + - DELETE + resources: + - namespaces + scope: '*' + sideEffects: None + admissionReviewVersions: + - v1 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/preflight_job_preinstall_hook.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/preflight_job_preinstall_hook.yaml new file mode 100644 index 000000000..d041f3d92 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/preflight_job_preinstall_hook.yaml @@ -0,0 +1,191 @@ +{{- if .Values.preflight.enabled -}} +{{- template "k8s-triliovault-operator.preFlightValidation" . }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{template "k8s-triliovault-operator.name" .}}-{{.Release.Namespace}}-preflight-role + labels: + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{template "k8s-triliovault-operator.appName" .}}-preflight-role + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + "helm.sh/hook": "pre-install" + "helm.sh/hook-delete-policy": hook-failed, hook-succeeded + "helm.sh/hook-weight": "1" +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - get + - list + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - create + - update + - delete + - patch + - apiGroups: + - "" + resources: + - serviceaccounts + - pods + - persistentvolumeclaims + - pods/exec + verbs: + - create + - update + - delete + - patch + - apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + - clusterrolebindings + verbs: + - create + - update + - delete + - patch + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - apiGroups: + - batch + resources: + - jobs + verbs: + - create + - delete + - apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshots + - volumesnapshotclasses + verbs: + - get + - list + - create + - update + - delete + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "k8s-triliovault-operator.name" . }}-preflight-service-account + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }}-preflight-service-account + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + "helm.sh/hook": "pre-install" + "helm.sh/hook-delete-policy": hook-failed, hook-succeeded + "helm.sh/hook-weight": "2" + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "k8s-triliovault-operator.name" . }}-{{ .Release.Namespace }}-preflight-rolebinding + labels: + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }}-preflight-rolebinding + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + "helm.sh/hook": "pre-install" + "helm.sh/hook-delete-policy": hook-failed, hook-succeeded + "helm.sh/hook-weight": "3" +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "k8s-triliovault-operator.name" . }}-{{ .Release.Namespace }}-preflight-role +subjects: + - kind: ServiceAccount + name: {{ template "k8s-triliovault-operator.name" . }}-preflight-service-account + namespace: {{ .Release.Namespace }} + +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "k8s-triliovault-operator.name" . }}-preflight-job-preinstall-hook-{{ randAlphaNum 4 | lower }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "k8s-triliovault-operator.fullname" . }} + release: "{{ .Release.Name }}" + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }}-preflight-job-preinstall-hook + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + "helm.sh/hook": "pre-install" + "helm.sh/hook-delete-policy": hook-succeeded + "helm.sh/hook-weight": "4" +spec: + backoffLimit: 0 + ttlSecondsAfterFinished: 3600 + template: + spec: + containers: + - name: preflight + image: {{ index .Values "registry" }}/{{ index .Values "preflight" "repository" }}:{{ index .Values "preflight" "imageTag" }} + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + command: + - /bin/sh + - -c + - >- + /opt/tvk-plugins/preflight run --in-cluster + --log-level={{ .Values.preflight.logLevel }} + --namespace={{ .Release.Namespace }} + {{- if .Values.preflight.cleanupOnFailure }} + --cleanup-on-failure + {{- end }} + {{- if .Values.preflight.imagePullSecret }} + --image-pull-secret={{ .Values.preflight.imagePullSecret }} + {{- end }} + {{- if .Values.preflight.limits }} + --limits={{ .Values.preflight.limits }} + {{- end }} + {{- if .Values.preflight.localRegistry }} + --local-registry={{ .Values.preflight.localRegistry }} + {{- end }} + {{- if .Values.preflight.nodeSelector }} + --node-selector={{ .Values.preflight.nodeSelector }} + {{- end }} + {{- if .Values.preflight.pvcStorageRequest }} + --pvc-storage-request={{ .Values.preflight.pvcStorageRequest }} + {{- end }} + {{- if .Values.preflight.requests }} + --requests={{ .Values.preflight.requests }} + {{- end }} + {{- if .Values.preflight.storageClass }} + --storage-class={{ .Values.preflight.storageClass }} + {{- end }} + {{- if .Values.preflight.volumeSnapshotClass }} + --volume-snapshot-class={{ .Values.preflight.volumeSnapshotClass }} + {{- end }} + restartPolicy: Never + terminationGracePeriodSeconds: 0 + serviceAccountName: {{ template "k8s-triliovault-operator.name" . }}-preflight-service-account +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/proxyConfig.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/proxyConfig.yaml new file mode 100644 index 000000000..99725af36 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/proxyConfig.yaml @@ -0,0 +1,21 @@ +{{- if .Values.proxySettings.PROXY_ENABLED }} + {{ template "k8s-triliovault-operator.caBundleValidation" . }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "k8s-triliovault-operator.fullname" . }}-proxy + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }}-proxy + app.kubernetes.io/managed-by: {{ .Release.Service }} +data: + {{- range $key, $val := .Values.proxySettings }} + {{ $val = $val| toString | b64enc }} + {{- if $val -}} + {{ $key }}: {{ $val }} + {{- end -}} + {{- end }} +type: Opaque +{{- end }} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/secret.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/secret.yaml new file mode 100644 index 000000000..782140c5a --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/secret.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "k8s-triliovault-operator.fullname" . }}-webhook-certs + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }}-webhook-certs + app.kubernetes.io/managed-by: {{ .Release.Service }} +type: Opaque diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/serviceAccount.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/serviceAccount.yaml new file mode 100644 index 000000000..a108d3266 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/serviceAccount.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "k8s-triliovault-operator.fullname" . }}-service-account + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }}-service-account + app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.imagePullSecret }} +imagePullSecrets: +- name: {{ .Values.imagePullSecret }} +{{- end}} diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/validating-webhook.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/validating-webhook.yaml new file mode 100644 index 000000000..c66b6a429 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/validating-webhook.yaml @@ -0,0 +1,31 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ template "k8s-triliovault-operator.name" . }}-validating-webhook-configuration + labels: + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }}-validating-webhook-configuration + app.kubernetes.io/managed-by: {{ .Release.Service }} +webhooks: +- clientConfig: + caBundle: Cg== + service: + name: {{ template "k8s-triliovault-operator.fullname" . }}-webhook-service + namespace: {{ .Release.Namespace }} + path: /validate-triliovault-trilio-io-v1-triliovaultmanager + failurePolicy: Fail + name: v1-tvm-validation.trilio.io + rules: + - apiGroups: + - triliovault.trilio.io + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - triliovaultmanagers + sideEffects: None + admissionReviewVersions: + - v1 diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/webhook-service.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/webhook-service.yaml new file mode 100644 index 000000000..bed6993c7 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/templates/webhook-service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "k8s-triliovault-operator.fullname" . }}-webhook-service + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "k8s-triliovault-operator.fullname" . }} + release: "{{ .Release.Name }}" + app.kubernetes.io/part-of: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/name: {{ template "k8s-triliovault-operator.appName" . }} + app.kubernetes.io/instance: {{ template "k8s-triliovault-operator.appName" . }}-webhook-service + app.kubernetes.io/managed-by: {{ .Release.Service }} +spec: + ports: + - port: 443 + targetPort: 9443 + selector: + app: {{ template "k8s-triliovault-operator.fullname" . }} + release: "{{ .Release.Name }}" diff --git a/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/values.yaml b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/values.yaml new file mode 100644 index 000000000..8de258c19 --- /dev/null +++ b/charts/k8s-triliovault-operator/k8s-triliovault-operator/2.9.300/values.yaml @@ -0,0 +1,123 @@ +## TrilioVault Operator +registry: "eu.gcr.io/amazing-chalice-243510" + +operator-webhook-init: + repository: operator-webhook-init + +k8s-triliovault-operator: + repository: k8s-triliovault-operator + +tag: "2.9.3" + +# create image pull secrets and specify the name here. +imagePullSecret: "" + +priorityClassName: "" + +preflight: + enabled: false + repository: preflight + imageTag: "latest" + logLevel: "INFO" + cleanupOnFailure: false + imagePullSecret: "" + limits: "" + localRegistry: "" + nodeSelector: "" + pvcStorageRequest: "" + requests: "" + storageClass: "" + volumeSnapshotClass: "" + +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/arch + operator: In + values: + - amd64 + +image: + pullPolicy: Always +tls: + secretName: "helm-client-certs" + verify: false + enable: false + keyFile: "tls.key" + certFile: "tls.crt" + caContent: "" + hostname: "" + +nameOverride: "" + +replicaCount: 1 + +proxySettings: + PROXY_ENABLED: false + NO_PROXY: "" + HTTP_PROXY: "" + HTTPS_PROXY: "" + CA_BUNDLE_CONFIGMAP: "" + +podSpec: + hostIPC: false + hostNetwork: false + hostPID: false + securityContext: + runAsNonRoot: true + runAsUser: 1001 + +securityContext: + allowPrivilegeEscalation: false + privileged: false + readOnlyRootFilesystem: false + runAsNonRoot: true + runAsUser: 1001 + capabilities: + drop: + - ALL + +installTVK: + enabled: false + applicationScope: Cluster + tvkInstanceName: "" + ingressConfig: + host: "" + tlsSecretName: "" + annotations: {} + ingressClass: "" + ComponentConfiguration: + ingressController: + enabled: true + service: + type: LoadBalancer + +observability: + enabled: false + logging: + loki: + enabled: true + promtail: + enabled: true + monitoring: + prometheus: + enabled: true + server: + enabled: true + persistentVolume: + enabled: true + kubeStateMetrics: + enabled: false + nodeExporter: + enabled: false + pushgateway: + enabled: false + alertmanager: + enabled: false + visualization: + grafana: + enabled: true + service: + type: LoadBalancer diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/Chart.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/Chart.yaml new file mode 100644 index 000000000..a8575d70d --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/Chart.yaml @@ -0,0 +1,34 @@ +annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Portworx Essentials + catalog.cattle.io/release-name: portworx-essentials +apiVersion: v1 +appVersion: "2.9" +description: A Helm chart for installing Portworx Essentials on Kubernetes. +home: https://portworx.com/ +icon: https://raw.githubusercontent.com/portworx/helm/master/doc/media/k8s-porx.png +keywords: +- Storage +- ICP +- persistent disk +- pvc +- cloud native storage +- persistent storage +- portworx +- amd64 +- portworx essentials +- free +kubeVersion: '>=1.16.0-0' +maintainers: +- email: hadesai@purestorage.com + name: harsh-px +- email: onaumov@purestorage.com + name: trierra +- email: tasharma@purestorage.com + name: sharma-tapas +- email: dahuang@purestorage.com + name: dahuang-purestorage +name: portworx-essentials +sources: +- https://github.com/portworx/charts-rancher/tree/master/stable +version: 2.9.100 diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/README.md b/charts/portworx-essentials/portworx-essentials/2.9.100/README.md new file mode 100644 index 000000000..a90a09b2b --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/README.md @@ -0,0 +1,57 @@ +# Portworx Essentials +[Portworx Essentials](https://docs.portworx.com/concepts/portworx-essentials/) is a free Portworx license with limited functionality that allows you to run small production or proof-of-concept workloads. Essentials limits capacity and advanced features, but otherwise functions the same way as the fully-featured PX-Enterprise version of Portworx. + +The Portworx Essentials license requires that your clusters be connected to the internet and send usage data to PX-Central. Portworx Essentials clusters connect with PX-Central once per hour to renew license leases. Lease periods last for 24 hours, ensuring that any temporary interruptions to your connectivity do not impact your cluster. + +## **Pre-requisites** + +The minimum supported size for a Portworx cluster is three nodes. Each node must meet the following hardware, software, and network requirements: + +### Hardware & Software + +|Resource|Requirements| +|--------|------------| +|CPU|4 cores| +|RAM|4GB| +|Disk (/var)| 2GB free| +|Backing drive|8GB (minimum required) 128 GB (minimum recommended)| +|Storage drives| Minimum: 1 node with a storage drive. Storage drives must be unmounted block storage: raw disks, drive partitions, LVM, or cloud block storage. | +|Ethernet NIC card| 10 GB (recommended)| +|Linux kernel| Version 3.10 or greater.| +|Docker| Version 1.13.1 or greater.| +|Disable swap| Please disable swap on all nodes that will run the Portworx software. Ensure that the swap device is not automatically mounted on server reboot.| + +### Network +Open needed ports : TCP ports 9001-9022 and UDP port 9002 on all Portworx nodes. Also open the KVDB port. (As an example, etcd typically runs on port 2379). If you intend to use Portworx with sharedV4 volumes, you may need to open your NFS ports. + +Please read [this link](https://docs.portworx.com/concepts/portworx-essentials/) before installing to understand the pre-requisites. + +## **Limitations** +* The portworx helm chart can only be deployed in the kube-system namespace. Hence use "kube-system" in the "Target namespace" during configuration. + +## **Uninstalling the Chart** + +#### You can uninstall Portworx using one of the following methods: + +#### **1. Delete all the Kubernetes components associated with the chart and the release.** + +> **Note** > The Portworx configuration files under `/etc/pwx/` directory are preserved, and will not be deleted. + +To perform this operation simply delete the application from the Apps page + +#### **2. Wipe your Portworx installation** +> **Note** > The commands in this section are disruptive and will lead to data loss. Please use caution.. + +See more details [here](https://docs.portworx.com/portworx-install-with-kubernetes/install-px-helm/#uninstall) + +## **Documentation** +* [Portworx docs site](https://docs.portworx.com/install-with-other/rancher/rancher-2.x/#step-1-install-rancher) +* [Portworx interactive tutorials](https://docs.portworx.com/scheduler/kubernetes/px-k8s-interactive.html) + +## **Installing the Chart using the CLI** + +See the installation details [here](https://docs.portworx.com/portworx-install-with-kubernetes/install-px-helm/) + +## **Installing Portworx on AWS** + +See the installation details [here](https://docs.portworx.com/cloud-references/auto-disk-provisioning/aws) diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/app-readme.md b/charts/portworx-essentials/portworx-essentials/2.9.100/app-readme.md new file mode 100644 index 000000000..b1e84db9a --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/app-readme.md @@ -0,0 +1,26 @@ +# Portworx Essentials + +[Portworx Essentials](https://portworx.com/) is a free Portworx license with limited functionality that allows you to run small production or proof-of-concept workloads. Essentials limits capacity and advanced features, but otherwise functions the same way as the fully-featured PX-Enterprise version of Portworx such as + + * Run containerized stateful applications that are highly-available (HA) across multiple nodes, cloud instances, regions, data centers or even clouds + * Migrate workflows between multiple clusters running across same or hybrid clouds + * Run hyperconverged workloads where the data resides on the same host as the applications + * Have programmatic control on your storage resources + +---- +## Full Features + * Free forever + * 5 nodes + * 500 volumes + * Cloud Drive provisioning + * Failures across nodes/racks/AZ + +---- +## Limited features + * Application consistent Snapshots (5 per volume) + * Cloud Snapshots (1 per volume per day) + * BYOK Encryption (cluster key only) + * Single user cluster management UI (single user, single cluster) + +For more information [Click Here](https://portworx.com/products/features/) +The Portworx Essentials license requires that your clusters be connected to the internet and send usage data to PX-Central. Portworx Essentials clusters connect with PX-Central once per hour to renew license leases. Lease periods last for 24 hours, ensuring that any temporary interruptions to your connectivity do not impact your cluster. \ No newline at end of file diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/ci/test-values.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/ci/test-values.yaml new file mode 100644 index 000000000..879bf6910 --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/ci/test-values.yaml @@ -0,0 +1 @@ +etcdType: Built-in \ No newline at end of file diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/questions.yml b/charts/portworx-essentials/portworx-essentials/2.9.100/questions.yml new file mode 100644 index 000000000..2bff61e47 --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/questions.yml @@ -0,0 +1,841 @@ +categories: +- storage +namespace: kube-system +labels: + io.rancher.certified: partner +questions: + +################################### Essentials options ################################ +- variable: essentialID + type: string + required: true + default: "none" + label: "Essentials Entitlement ID" + description: "Get your free essentials entitlement ID from https://central.portworx.com/profile" + group: "license parameters" + + +################################### Storage options ################################ +- variable: environment + description: "Select your environment" + label: "Environment" + type: enum + default: "OnPrem" + required: true + group: "Storage Parameters" + options: + - "OnPrem" + - "Cloud" + +- variable: provider + show_if: "environment=Cloud" + description: "Select cloud platform" + label: "Cloud provider" + type: enum + required: true + group: "Storage Parameters" + options: + - "AWS" + - "Google cloud/GKE" + +- variable: onpremStorage + show_if: "environment=OnPrem" + type: enum + default: "Automatically scan disks" + label: "Select type of OnPrem storage" + group: "Storage Parameters" + required: true + options: + - "Automatically scan disks" + - "Manually specify disks" + +- variable: deviceConfig + show_if: "environment=Cloud" + description: "If you plan to use EC2 instance storage or plan to manage EBS volumes your own way, select 'Consume unused' or 'Use Existing disks'." + label: "Select a type of disk" + type: enum + default: "Create Using a Spec" + required: true + group: "Storage Parameters" + options: + - "Create Using a Spec" + - "Consume Unused" + - "Use Existing Disks" + - +- variable: journalDevice + description: "This allows PX to create it’s own journal partition on the best drive to absorb PX metadata writes. Journal writes are small with frequent syncs and hence a separate journal partition will enable better performance. Use value 'auto' if you want Portworx to create it's own journal partition." + type: string + label: "Journal Device" + group: "Storage Parameters" + +############ Consume unused ############## +- variable: usedrivesAndPartitions + show_if: "deviceConfig=Consume Unused||onpremStorage=Automatically scan disks" + label: "Use unmounted drives and partitions" + descrition: "Use unmounted disks even if they have a partition or filesystem on it. PX will never use a drive or partition that is mounted." + type: boolean + default: false + group: "Storage Parameters" + + +############ Use Exising Disks ############## +- variable: existingDisk1 + show_if: "deviceConfig=Use Existing Disks||onpremStorage=Manually specify disks" + label: "Drive/Device1" + description: "Enter the block/device name; eg: /dev/sda" + type: string + required: true + group: "Storage Parameters" + +- variable: addExistingDisk2 + show_if: "deviceConfig=Use Existing Disks||onpremStorage=Manually specify disks" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: existingDisk2 + show_if: "addExistingDisk2=true" + label: "Drive/Device2" + description: "Enter the block/device name; eg: /dev/sda" + type: string + required: true + group: "Storage Parameters" + +- variable: addExistingDisk3 + show_if: "addExistingDisk2=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: existingDisk3 + show_if: "addExistingDisk3=true" + label: "Drive/Device3" + description: "Enter the block/device name; eg: /dev/sda" + type: string + required: true + group: "Storage Parameters" + +- variable: addExistingDisk4 + show_if: "addExistingDisk3=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: existingDisk4 + show_if: "addExistingDisk4=true" + label: "Drive/Device4" + description: "Enter the block/device name; eg: /dev/sda" + type: string + required: true + group: "Storage Parameters" + +- variable: addExistingDisk5 + show_if: "addExistingDisk4=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: existingDisk5 + show_if: "addExistingDisk5=true" + label: "Drive/Device5" + description: "Enter the block/device name; eg: /dev/sda" + type: string + required: true + group: "Storage Parameters" + +##################################################### Cloud ################################ + +##################################################### AWS ################################ + +### Section 1 AWS +- variable: drive_1.aws.type + show_if: "provider=AWS&&deviceConfig=Create Using a Spec" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + default: "GP2" + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_1.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_1.aws.size + show_if: "provider=AWS&&deviceConfig=Create Using a Spec" + description: "Volume size" + label: "Size" + type: int + default: 150 + required: true + group: "Storage Parameters" + +### Section 2 AWS +- variable: addEBSDrive_2 + show_if: "provider=AWS&&deviceConfig=Create Using a Spec" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_2.aws.type + show_if: "addEBSDrive_2=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_2.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_2.aws.size + show_if: "addEBSDrive_2=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + + ### Section 3 AWS +- variable: addEBSDrive_3 + show_if: "addEBSDrive_2=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_3.aws.type + show_if: "addEBSDrive_3=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_3.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_3.aws.size + show_if: "addEBSDrive_3=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +### Section 4 AWS +- variable: addEBSDrive_4 + show_if: "addEBSDrive_3=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_4.aws.type + show_if: "addEBSDrive_4=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_4.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_4.aws.size + show_if: "addEBSDrive_4=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +### Section 5 AWS +- variable: addEBSDrive_5 + show_if: "addEBSDrive_4=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_5.aws.type + show_if: "addEBSDrive_5=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_5.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_5.aws.size + show_if: "addEBSDrive_5=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +### Section 6 AWS +- variable: addEBSDrive_6 + show_if: "addEBSDrive_5=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_6.aws.type + show_if: "addEBSDrive_6=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_6.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_6.aws.size + show_if: "addEBSDrive_6=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +### Section 7 AWS +- variable: addEBSDrive_7 + show_if: "addEBSDrive_6=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_7.aws.type + show_if: "addEBSDrive_7=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_7.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_7.aws.size + show_if: "addEBSDrive_7=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +### Section 8 AWS +- variable: addEBSDrive_8 + show_if: "addEBSDrive_7=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_8.aws.type + show_if: "addEBSDrive_8=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_8.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_8.aws.size + show_if: "addEBSDrive_8=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +### Section 9 AWS +- variable: addEBSDrive_9 + show_if: "addEBSDrive_8=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_9.aws.type + show_if: "addEBSDrive_9=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_9.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_9.aws.size + show_if: "addEBSDrive_9=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +### Section 10 AWS +- variable: addEBSDrive_10 + show_if: "addEBSDrive_9=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_10.aws.type + show_if: "addEBSDrive_10=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_10.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_10.aws.size + show_if: "addEBSDrive_10=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +##################################################### GOOGLE CLOUD ################################ + +#### Section 1 GC +- variable: drive_1.gc.type + show_if: "provider=Google cloud/GKE&&deviceConfig=Create Using a Spec" + description: "Select volume type" + label: "Volume" + type: enum + default: "standard" + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_1.gc.size + show_if: "provider=Google cloud/GKE&&deviceConfig=Create Using a Spec" + description: "Volume size" + label: "Size" + type: int + default: 150 + required: true + group: "Storage Parameters" + +#### Section 2 GC +- variable: addGCDrive_2 + show_if: "provider=Google cloud/GKE&&deviceConfig=Create Using a Spec" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_2.gc.type + show_if: "addGCDrive_2=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_2.gc.size + show_if: "addGCDrive_2=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 3 GC +- variable: addGCDrive_3 + show_if: "addGCDrive_2=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_3.gc.type + show_if: "addGCDrive_3=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_3.gc.size + show_if: "addGCDrive_3=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 4 GC +- variable: addGCDrive_4 + show_if: "addGCDrive_3=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_4.gc.type + show_if: "addGCDrive_4=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_4.gc.size + show_if: "addGCDrive_4=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 5 GC +- variable: addGCDrive_5 + show_if: "addGCDrive_4=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_5.gc.type + show_if: "addGCDrive_5=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_5.gc.size + show_if: "addGCDrive_5=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 6 GC +- variable: addGCDrive_6 + show_if: "addGCDrive_5=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_6.gc.type + show_if: "addGCDrive_6=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_6.gc.size + show_if: "addGCDrive_6=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 7 GC +- variable: addGCDrive_7 + show_if: "addGCDrive_6=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_7.gc.type + show_if: "addGCDrive_6=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_7.gc.size + show_if: "addGCDrive_7=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 8 GC +- variable: addGCDrive_8 + show_if: "addGCDrive_7=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_8.gc.type + show_if: "addGCDrive_8=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_8.gc.size + show_if: "addGCDrive_8=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 9 GC +- variable: addGCDrive_9 + show_if: "addGCDrive_8=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_9.gc.type + show_if: "addGCDrive_9=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_9.gc.size + show_if: "addGCDrive_9=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 10 GC +- variable: addGCDrive_10 + show_if: "addGCDrive_9=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_10.gc.type + show_if: "addGCDrive_10=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_10.gc.size + show_if: "addGCDrive_10=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +- variable: maxStorageNodes + show_if: "environment=Cloud&&deviceConfig=Create Using a Spec" + description: "Max storage nodes per availability zone" + label: "Max storage nodes (Optional)" + type: int + group: "Storage Parameters" + +################################### Network options ################################ +- variable: dataInterface + description: "Specify your data network interface (example: `eth1`). If set to `auto`, Portworx will automatically select the first routable interface." + type: string + label: "Data Network Interface" + default: auto + group: "Network Parameters" +- variable: managementInterface + description: "Specify your management network interface (example: `eth1`). If set to `auto`, Portworx will automatically select the first routable interface." + type: string + default: auto + label: "Management Network Interface" + group: "Network Parameters" + +################################### Platform options ################################ +- variable: platformOptions + type: enum + label: "Platform" + group: "Platform Parameters" + options: + - "AKS" + - "EKS" + - "GKE" + +################################### Registry settings options ################################ +- variable: customRegistry + label: "Use a custom container registry?" + type: boolean + default: false + group: "Container Registry Parameters" + +- variable: registrySecret + show_if: "customRegistry=true" + description: "Specify a custom Kubernetes secret that will be used to authenticate with a container registry. Must be defined in kube-system namespace. (example: regcred)" + type: string + label: "Registry Kubernetes Secret" + group: "Container Registry Parameters" +- variable: customRegistryURL + show_if: "customRegistry=true" + description: "Specify a custom container registry server (including repository) that will be used instead of index.docker.io to download Docker images. (example: dockerhub.acme.net:5443 or myregistry.com/myrepository/)" + label: "Custom Registry URL" + type: string + group: "Container Registry Parameters" + + + +################################## Optional features ############################ +# TODO: Once we have a stable CSI release, we will default this to enabled +#- variable: csi +# description: "Select if you want to enable CSI (Container Storage Interface). CSI is still in ALPHA." +# type: boolean +# label: "Enable CSI" +# default: false +# required: false +# group: "Advanced parameters" + +- variable: storkVersion + default: "2.7.0" + label: "Stork version" + type: string + group: "Advanced parameters" + +- variable: envVars + label: "Environment variables" + description: "Enter your environment variables separated by semicolons (example: MYENV1=val1;MYENV2=val2). These environment variables will be exported to Portworx." + type: string + group: "Advanced parameters" + +- variable: imageVersion + default: "2.9.1.4" + type: string + label: Portworx version to be deployed. + group: "Advanced parameters" + +- variable: clusterName + type: string + label: Portworx cluster name + default: mycluster + group: "Advanced parameters" diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/NOTES.txt b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/NOTES.txt new file mode 100644 index 000000000..ea0bb6326 --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/NOTES.txt @@ -0,0 +1,13 @@ +Your Release is named {{ .Release.Name | quote }} + +Portworx Pods should be running on each node in your cluster. + +Portworx would create a unified pool of the disks attached to your Kubernetes nodes. No further action should be required and you are ready to consume Portworx Volumes as part of your application data requirements. + +For further information on usage of the Portworx, refer to following doc pages. + +- For dynamically provisioning volumes: https://docs.portworx.com/scheduler/kubernetes/dynamic-provisioning.html +- For preprovisioned volumes: https://docs.portworx.com/scheduler/kubernetes/preprovisioned-volumes.html +- To use Stork (Storage Orchestration Runtime for Kubernetes) for hyperconvergence and snapshots: https://docs.portworx.com/scheduler/kubernetes/stork.html +- For stateful application solutions using Portworx: https://docs.portworx.com/scheduler/kubernetes/k8s-px-app-samples.html +- For interactive tutorials on using Portworx on Kubernetes: https://docs.portworx.com/scheduler/kubernetes/px-k8s-interactive.html diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/_helpers.tpl b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/_helpers.tpl new file mode 100644 index 000000000..4367d05ea --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/_helpers.tpl @@ -0,0 +1,443 @@ +{{/* Gets the correct API Version based on the version of the cluster +*/}} + +{{- define "rbac.apiVersion" -}} +{{- if semverCompare ">= 1.8-0" .Capabilities.KubeVersion.GitVersion -}} +"rbac.authorization.k8s.io/v1" +{{- else -}} +"rbac.authorization.k8s.io/v1beta1" +{{- end -}} +{{- end -}} + + +{{- define "px.labels" -}} +chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" +heritage: {{ .Release.Service | quote }} +release: {{ .Release.Name | quote }} +{{- end -}} + +{{- define "driveOpts" }} +{{ $v := .Values.installOptions.drives | split "," }} +{{$v._0}} +{{- end -}} + +{{- define "px.kubernetesVersion" -}} +{{$version := .Capabilities.KubeVersion.GitVersion | regexFind "^v\\d+\\.\\d+\\.\\d+"}}{{$version}} +{{- end -}} + + +{{- define "px.getImage" -}} +{{- if (.Values.customRegistryURL) -}} + {{- if (eq "/" (.Values.customRegistryURL | regexFind "/")) -}} + {{- if .Values.openshiftInstall -}} + {{ cat (trim .Values.customRegistryURL) "/px-monitor" | replace " " ""}} + {{- else -}} + {{ cat (trim .Values.customRegistryURL) "/oci-monitor" | replace " " ""}} + {{- end -}} + {{- else -}} + {{- if .Values.openshiftInstall -}} + {{cat (trim .Values.customRegistryURL) "/portworx/px-monitor" | replace " " ""}} + {{- else -}} + {{cat (trim .Values.customRegistryURL) "/portworx/oci-monitor" | replace " " ""}} + {{- end -}} + {{- end -}} +{{- else -}} + {{- if .Values.openshiftInstall -}} + {{ "registry.connect.redhat.com/portworx/px-monitor" }} + {{- else -}} + {{ "portworx/oci-monitor" }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{- define "px.getStorkImage" -}} +{{- if (.Values.customRegistryURL) -}} + {{- if (eq "/" (.Values.customRegistryURL | regexFind "/")) -}} + {{ cat (trim .Values.customRegistryURL) "/stork" | replace " " ""}} + {{- else -}} + {{cat (trim .Values.customRegistryURL) "/openstorage/stork" | replace " " ""}} + {{- end -}} +{{- else -}} + {{ "openstorage/stork" }} +{{- end -}} +{{- end -}} + +{{- define "px.getk8sImages" -}} +{{- $version := .Capabilities.KubeVersion.GitVersion -}} +{{- if (.Values.customRegistryURL) -}} + {{- if (eq "/" (.Values.customRegistryURL | regexFind "/")) -}} + {{ trim .Values.customRegistryURL }} + {{- else -}} + {{- if or (or (and (semverCompare ">= 1.16.14-0" $version ) (semverCompare "<=1.17.0-0" $version)) (and (semverCompare ">= 1.17.10-0" $version) (semverCompare "<=1.18.0-0" $version ))) (semverCompare ">=1.18.7-0" $version) -}} + {{cat (trim .Values.customRegistryURL) "/k8s.gcr.io" | replace " " ""}} + {{- else -}} + {{cat (trim .Values.customRegistryURL) "/gcr.io/google_containers" | replace " " ""}} + {{- end -}} + {{- end -}} +{{- else -}} + {{- if or (or (and (semverCompare ">= 1.16.14-0" $version ) (semverCompare "<=1.17.0-0" $version)) (and (semverCompare ">= 1.17.10-0" $version) (semverCompare "<=1.18.0-0" $version ))) (semverCompare ">=1.18.7-0" $version) -}} + {{ "k8s.gcr.io" }} + {{- else -}} + {{ "gcr.io/google_containers" }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{- define "px.getcsiImages" -}} +{{- if (.Values.customRegistryURL) -}} + {{- if (eq "/" (.Values.customRegistryURL | regexFind "/")) -}} + {{ trim .Values.customRegistryURL }} + {{- else -}} + {{cat (trim .Values.customRegistryURL) "/quay.io/k8scsi" | replace " " ""}} + {{- end -}} +{{- else -}} + {{ "quay.io/k8scsi" }} +{{- end -}} +{{- end -}} + + +{{- define "px.getCSIProvisionerImage" -}} +{{- if semverCompare "<1.17.0-0" .Capabilities.KubeVersion.GitVersion -}} + {{ "docker.io/openstorage/csi-provisioner:v1.6.1-1" }} +{{- else if semverCompare "< 1.20.0-0" .Capabilities.KubeVersion.GitVersion -}} + {{ "docker.io/openstorage/csi-provisioner:v2.2.2-1" }} +{{- else -}} + {{ "docker.io/openstorage/csi-provisioner:v3.0.0-1" }} +{{- end -}} +{{- end -}} + +{{- define "px.getCSISnapshotterImage" -}} +{{- if semverCompare "<1.17.0-0" .Capabilities.KubeVersion.GitVersion -}} + {{ "docker.io/openstorage/csi-snapshotter:v1.2.2-1" }} +{{- else if semverCompare "< 1.20.0-0" .Capabilities.KubeVersion.GitVersion -}} + {{ "k8s.gcr.io/sig-storage/csi-snapshotter:v3.0.3" }} +{{- else -}} + {{ "k8s.gcr.io/sig-storage/csi-snapshotter:v4.2.1" }} +{{- end -}} +{{- end -}} + +{{- define "px.getCSISnapshotControllerImage" -}} +{{- if semverCompare "< 1.20.0-0" .Capabilities.KubeVersion.GitVersion -}} + {{ "k8s.gcr.io/sig-storage/snapshot-controller:v3.0.3" }} +{{- else -}} + {{ "k8s.gcr.io/sig-storage/snapshot-controller:v4.2.1" }} +{{- end -}} +{{- end -}} + +{{- define "px.getPauseImage" -}} +{{- if (.Values.customRegistryURL) -}} + {{- if (eq "/" (.Values.customRegistryURL | regexFind "/")) -}} + {{ trim .Values.customRegistryURL }} + {{- else -}} + {{cat (trim .Values.customRegistryURL) "/k8s.gcr.io" | replace " " ""}} + {{- end -}} +{{- else -}} + {{ "k8s.gcr.io" }} +{{- end -}} +{{- end -}} + +{{- define "px.registryConfigType" -}} +{{- if semverCompare ">=1.9-0" .Capabilities.KubeVersion.GitVersion -}} +".dockerconfigjson" +{{- else -}} +".dockercfg" +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use for hooks +*/}} +{{- define "px.hookServiceAccount" -}} +{{- if .Values.serviceAccount.hook.create -}} + {{- printf "%s-hook" .Chart.Name | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{ default "default" .Values.serviceAccount.hook.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the cluster role to use for hooks +*/}} +{{- define "px.hookClusterRole" -}} +{{- if .Values.serviceAccount.hook.create -}} + {{- printf "%s-hook" .Chart.Name | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{ default "default" .Values.serviceAccount.hook.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the cluster role binding to use for hooks +*/}} +{{- define "px.hookClusterRoleBinding" -}} +{{- if .Values.serviceAccount.hook.create -}} + {{- printf "%s-hook" .Chart.Name | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{ default "default" .Values.serviceAccount.hook.name }} +{{- end -}} +{{- end -}} + +{{/* + String concatenation for drives in AWS section +*/}} +{{- define "px.storage" -}} +{{- $awsType1 := .Values.drive_1.aws.type -}} +{{- $awsType2 := .Values.drive_2.aws.type -}} +{{- $awsType3 := .Values.drive_3.aws.type -}} +{{- $awsType4 := .Values.drive_4.aws.type -}} +{{- $awsType5 := .Values.drive_5.aws.type -}} +{{- $awsType6 := .Values.drive_6.aws.type -}} +{{- $awsType7 := .Values.drive_7.aws.type -}} +{{- $awsType8 := .Values.drive_8.aws.type -}} +{{- $awsType9 := .Values.drive_9.aws.type -}} +{{- $awsType10 := .Values.drive_10.aws.type -}} + +{{- $awsSize1 := .Values.drive_1.aws.size -}} +{{- $awsSize2 := .Values.drive_2.aws.size -}} +{{- $awsSize3 := .Values.drive_3.aws.size -}} +{{- $awsSize4 := .Values.drive_4.aws.size -}} +{{- $awsSize5 := .Values.drive_5.aws.size -}} +{{- $awsSize6 := .Values.drive_6.aws.size -}} +{{- $awsSize7 := .Values.drive_7.aws.size -}} +{{- $awsSize8 := .Values.drive_8.aws.size -}} +{{- $awsSize9 := .Values.drive_9.aws.size -}} +{{- $awsSize10 := .Values.drive_10.aws.size -}} + +{{- $awsIops1 := .Values.drive_1.aws.iops -}} +{{- $awsIops2 := .Values.drive_2.aws.iops -}} +{{- $awsIops3 := .Values.drive_3.aws.iops -}} +{{- $awsIops4 := .Values.drive_4.aws.iops -}} +{{- $awsIops5 := .Values.drive_5.aws.iops -}} +{{- $awsIops6 := .Values.drive_6.aws.iops -}} +{{- $awsIops7 := .Values.drive_7.aws.iops -}} +{{- $awsIops8 := .Values.drive_8.aws.iops -}} +{{- $awsIops9 := .Values.drive_9.aws.iops -}} +{{- $awsIops10 := .Values.drive_10.aws.iops -}} + +{{- $gcType1 := .Values.drive_1.gc.type -}} +{{- $gcType2 := .Values.drive_2.gc.type -}} +{{- $gcType3 := .Values.drive_3.gc.type -}} +{{- $gcType4 := .Values.drive_4.gc.type -}} +{{- $gcType5 := .Values.drive_5.gc.type -}} +{{- $gcType6 := .Values.drive_6.gc.type -}} +{{- $gcType7 := .Values.drive_7.gc.type -}} +{{- $gcType8 := .Values.drive_8.gc.type -}} +{{- $gcType9 := .Values.drive_9.gc.type -}} +{{- $gcType10 := .Values.drive_10.gc.type -}} + +{{- $gcSize1 := .Values.drive_1.gc.size -}} +{{- $gcSize2 := .Values.drive_2.gc.size -}} +{{- $gcSize3 := .Values.drive_3.gc.size -}} +{{- $gcSize4 := .Values.drive_4.gc.size -}} +{{- $gcSize5 := .Values.drive_5.gc.size -}} +{{- $gcSize6 := .Values.drive_6.gc.size -}} +{{- $gcSize7 := .Values.drive_7.gc.size -}} +{{- $gcSize8 := .Values.drive_8.gc.size -}} +{{- $gcSize9 := .Values.drive_9.gc.size -}} +{{- $gcSize10 := .Values.drive_10.gc.size -}} + +{{- $usefileSystemDrive := .Values.usefileSystemDrive | default false }} +{{- $usedrivesAndPartitions := .Values.usedrivesAndPartitions | default false }} +{{- $deployEnvironmentIKS := .Capabilities.KubeVersion.GitVersion | regexMatch "IKS" }} + +{{- if eq "OnPrem" .Values.environment -}} + {{- if eq "Manually specify disks" .Values.onpremStorage }} + {{- if ne "none" .Values.existingDisk1 }} + "-s", "{{- .Values.existingDisk1 }}", + {{- end }} + {{- if ne "none" .Values.existingDisk2 -}} + "-s", "{{- .Values.existingDisk2 }}", + {{- end }} + {{- if ne "none" .Values.existingDisk3 -}} + "-s", "{{- .Values.existingDisk3 }}", + {{- end }} + {{- if ne "none" .Values.existingDisk4 -}} + "-s", "{{- .Values.existingDisk4 }}", + {{- end }} + {{- if ne "none" .Values.existingDisk5 }} + "-s", "{{- .Values.existingDisk5 }}", + {{- end }} + {{- else if eq "Automatically scan disks" .Values.onpremStorage -}} + {{- if or $usedrivesAndPartitions $deployEnvironmentIKS }} + "-f", + {{- end }} + {{- if eq $usedrivesAndPartitions true }} + "-A", + {{- else }} + "-a", + {{- end -}} + {{- end -}} + +{{- else if eq "Cloud" .Values.environment -}} + {{- if eq "Consume Unused" .Values.deviceConfig -}} + {{- if or $usedrivesAndPartitions $deployEnvironmentIKS }} + "-f", + {{- end }} + {{- if eq $usedrivesAndPartitions true }} + "-A", + {{- else }} + "-a", + {{- end -}} + {{- end }} +{{/*------------------- ----------------- Google cloud/GKE -------------- --------------- */}} + {{- if eq "Google cloud/GKE" .Values.provider -}} + {{- if eq "Use Existing Disks" .Values.deviceConfig -}} + {{- if .Values.existingDisk1 -}} + "-s", "{{- .Values.existingDisk1 -}}", + {{- end -}} + {{- if ne "none" .Values.existingDisk2 -}} + "-s", "{{- .Values.existingDisk2 -}}", + {{- end -}} + {{- if ne "none" .Values.existingDisk3 -}} + "-s", "{{- .Values.existingDisk3 -}}", + {{- end -}} + {{- if ne "none" .Values.existingDisk4 -}} + "-s", "{{- .Values.existingDisk4 -}}", + {{- end -}} + {{- if ne "none" .Values.existingDisk5 -}} + "-s", "{{- .Values.existingDisk5 -}}", + {{- end -}} + {{- else if eq "Create Using a Spec" .Values.deviceConfig -}} + {{- if $gcType1 }} + "-s", "type=pd-{{$gcType1 | lower}},size={{$gcSize1}}", + {{- end }} + {{/*------------------- DRIVE 2 --------------- */}} + {{- if $gcType2 -}} + "-s", "type=pd-{{$gcType2 | lower}},size={{$gcSize2}}", + {{- end }} + {{/*------------------- DRIVE 3 --------------- */}} + {{- if $gcType3 -}} + "-s", "type=pd-{{$gcType3 | lower}},size={{$gcSize3}}", + {{- end }} + {{/*------------------- DRIVE 4 --------------- */}} + {{- if $gcType4 -}} + "-s", "type=pd-{{$gcType4 | lower}},size={{$gcSize4}}", + {{- end }} + {{/*------------------- DRIVE 5 --------------- */}} + {{- if $gcType5 -}} + "-s", "type=pd-{{$gcType5 | lower}},size={{$gcSize5}}", + {{- end }} + {{/*------------------- DRIVE 6 --------------- */}} + {{- if $gcType6 -}} + "-s", "type=pd-{{$gcType6 | lower}},size={{$gcSize6}}", + {{- end }} + {{/*------------------- DRIVE 7 --------------- */}} + {{- if $gcType7 -}} + "-s", "type=pd-{{$gcType7 | lower}},size={{$gcSize7}}", + {{- end }} + {{/*------------------- DRIVE 8 --------------- */}} + {{- if $gcType8 -}} + "-s", "type=pd-{{$gcType8 | lower}},size={{$gcSize8}}", + {{- end }} + {{/*------------------- DRIVE 9 --------------- */}} + {{- if $gcType9 -}} + "-s", "type=pd-{{$gcType9 | lower}},size={{$gcSize9}}", + {{- end }} + {{/*------------------- DRIVE 10 --------------- */}} + {{- if $gcType10 -}} + "-s", "type=pd-{{$gcType1 | lower}},size={{$gcSize10}}", + {{- end }} + {{- end -}} +{{/*------------------- ----------------- AWS -------------- --------------- */}} + {{- else if eq "AWS" .Values.provider -}} + {{- if eq "Use Existing Disks" .Values.deviceConfig -}} + {{- if ne "none" .Values.existingDisk1 -}} + "-s", "{{ .Values.existingDisk1 }}", + {{- end -}} + {{- if ne "none" .Values.existingDisk2 -}} + "-s", "{{ .Values.existingDisk2 }}", + {{- end -}} + {{- if ne "none" .Values.existingDisk3 -}} + "-s", "{{ .Values.existingDisk3 }}", + {{- end -}} + {{- if ne "none" .Values.existingDisk4 -}} + "-s", "{{ .Values.existingDisk4 }}", + {{- end -}} + {{- if ne "none" .Values.existingDisk5 -}} + "-s", "{{ .Values.existingDisk5 }}", + {{- end -}} + {{- else if eq "Create Using a Spec" .Values.deviceConfig -}} + {{- if ne "none" $awsType1 }} + {{- if eq "GP2" $awsType1 -}} + "-s", "type={{$awsType1 | lower}},size={{$awsSize1}}", + {{- else if eq "IO1" $awsType1 -}} + "-s", "type={{$awsType1 | lower}},size={{$awsSize1}},iops={{$awsIops1}}", + {{- end }} + {{- end }} + {{/*------------------- DRIVE 2 --------------- */}} + {{- if ne "none" $awsType2 -}} + {{- if eq "GP2" $awsType2 -}} + "-s", "type={{$awsType2 | lower}},size={{$awsSize2}}", + {{- else if eq "IO1" $awsType2 -}} + "-s", "type={{$awsType2 | lower}},size={{$awsSize2}},iops={{$awsIops2}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 3 --------------- */}} + {{- if ne "none" $awsType3 }} + {{- if eq "GP2" $awsType3 -}} + "-s", "type={{$awsType3 | lower}},size={{$awsSize3}}", + {{- else if eq "IO1" $awsType3 -}} + "-s", "type={{$awsType3 | lower}},size={{$awsSize3}},iops={{$awsIops3}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 4 --------------- */}} + {{- if ne "none" $awsType4 }} + {{- if eq "GP2" $awsType4 -}} + "-s", "type={{$awsType4 | lower}},size={{$awsSize4}}", + {{- else if eq "IO1" $awsType4 -}} + "-s", "type={{$awsType4 | lower}},size={{$awsSize4}},iops={{$awsIops4}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 5 --------------- */}} + {{- if ne "none" $awsType5 }} + {{- if eq "GP2" $awsType5 -}} + "-s", "type={{$awsType5 | lower}},size={{$awsSize5}}", + {{- else if eq "IO1" $awsType5 -}} + "-s", "type={{$awsType5 | lower}},size={{$awsSize5}},iops={{$awsIops5}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 6 --------------- */}} + {{- if ne "none" $awsType6 }} + {{- if eq "GP2" $awsType6 -}} + "-s", "type={{$awsType6 | lower}},size={{$awsSize6}}", + {{- else if eq "IO1" $awsType6 -}} + "-s", "type={{$awsType6 | lower}},size={{$awsSize6}},iops={{$awsIops6}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 7 --------------- */}} + {{- if ne "none" $awsType7 }} + {{- if eq "GP2" $awsType7 -}} + "-s", "type={{$awsType7 | lower}},size={{$awsSize7}}", + {{- else if eq "IO1" $awsType7 -}} + "-s", "type={{$awsType7 | lower}},size={{$awsSize7}},iops={{$awsIops7}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 8 --------------- */}} + {{- if ne "none" $awsType8 }} + {{- if eq "GP2" $awsType8 -}} + "-s", "type={{$awsType8 | lower}},size={{$awsSize8}}", + {{- else if eq "IO1" $awsType8 -}} + "-s", "type={{$awsType8 | lower}},size={{$awsSize8}},iops={{$awsIops8}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 9 --------------- */}} + {{- if ne "none" $awsType9 }} + {{- if eq "GP2" $awsType9 -}} + "-s", "type={{$awsType9 | lower}},size={{$awsSize9}}", + {{- else if eq "IO1" $awsType9 -}} + "-s", "type={{$awsType9 | lower}},size={{$awsSize9}},iops={{$awsIops9}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 10 --------------- */}} + {{- if ne "none" $awsType10 }} + {{- if eq "GP2" $awsType10 -}} + "-s", "type={{$awsType10 | lower}},size={{$awsSize10}}", + {{- else if eq "IO1" $awsType10 -}} + "-s", "type={{$awsType10 | lower}},size={{$awsSize10}},iops={{$awsIops10}}", + {{- end -}} + {{- end }} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end }} + diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/hooks/post-delete/px-postdelete-unlabelnode.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/hooks/post-delete/px-postdelete-unlabelnode.yaml new file mode 100644 index 000000000..8c8efda02 --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/hooks/post-delete/px-postdelete-unlabelnode.yaml @@ -0,0 +1,40 @@ +{{- $customRegistryURL := .Values.customRegistryURL | default "none" }} +{{- $registrySecret := .Values.registrySecret | default "none" }} + +apiVersion: batch/v1 +kind: Job +metadata: + namespace: kube-system + name: px-hook-postdelete-unlabelnode + labels: + heritage: {{.Release.Service | quote }} + release: {{.Release.Name | quote }} + chart: "{{.Chart.Name}}-{{.Chart.Version}}" + app.kubernetes.io/managed-by: {{.Release.Service | quote }} + app.kubernetes.io/instance: {{.Release.Name | quote }} + annotations: + "helm.sh/hook": post-delete + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation +spec: +{{ if semverCompare ">= 1.8-0" .Capabilities.KubeVersion.GitVersion }} + backoffLimit: 0 +{{ else }} + activeDeadlineSeconds: 30 +{{ end }} + template: + spec: + {{- if not (eq $registrySecret "none") }} + imagePullSecrets: + - name: {{ $registrySecret }} + {{- end }} + restartPolicy: Never + serviceAccountName: {{ template "px.hookServiceAccount" . }} + containers: + - name: post-delete-job + {{- if eq $customRegistryURL "none" }} + image: "lachlanevenson/k8s-kubectl:{{ template "px.kubernetesVersion" . }}" + {{- else}} + image: "{{ $customRegistryURL }}/lachlanevenson/k8s-kubectl:{{ template "px.kubernetesVersion" . }}" + {{- end}} + args: ['label','nodes','--all','px/enabled-'] diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/hooks/pre-delete/px-predelete-nodelabel.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/hooks/pre-delete/px-predelete-nodelabel.yaml new file mode 100644 index 000000000..1942bade7 --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/hooks/pre-delete/px-predelete-nodelabel.yaml @@ -0,0 +1,40 @@ +{{- $customRegistryURL := .Values.customRegistryURL | default "none" }} +{{- $registrySecret := .Values.registrySecret | default "none" }} + +apiVersion: batch/v1 +kind: Job +metadata: + namespace: kube-system + name: px-hook-predelete-nodelabel + labels: + heritage: {{.Release.Service | quote }} + release: {{.Release.Name | quote }} + chart: "{{.Chart.Name}}-{{.Chart.Version}}" + app.kubernetes.io/managed-by: {{.Release.Service | quote }} + app.kubernetes.io/instance: {{.Release.Name | quote }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation +spec: +{{ if semverCompare ">= 1.8-0" .Capabilities.KubeVersion.GitVersion }} + backoffLimit: 0 +{{ else }} + activeDeadlineSeconds: 30 +{{ end }} + template: + spec: + {{- if not (eq $registrySecret "none") }} + imagePullSecrets: + - name: {{ $registrySecret }} + {{- end }} + serviceAccountName: {{ template "px.hookServiceAccount" . }} + restartPolicy: Never + containers: + - name: pre-delete-job + {{- if eq $customRegistryURL "none" }} + image: "lachlanevenson/k8s-kubectl:{{ template "px.kubernetesVersion" . }}" + {{- else}} + image: "{{ $customRegistryURL }}/lachlanevenson/k8s-kubectl:{{ template "px.kubernetesVersion" . }}" + {{- end}} + args: ['label','nodes','--all','px/enabled=remove','--overwrite'] diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-controller.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-controller.yaml new file mode 100644 index 000000000..15301f579 --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-controller.yaml @@ -0,0 +1,128 @@ +{{- if or (and (.Values.openshiftInstall) (eq .Values.openshiftInstall true)) (and (.Values.AKSorEKSInstall) (eq .Values.AKSorEKSInstall true)) ((.Capabilities.KubeVersion.GitVersion | regexMatch "gke")) }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: portworx-pvc-controller-account + namespace: kube-system +--- +kind: ClusterRole +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: portworx-pvc-controller-role +rules: +- apiGroups: [""] + resources: ["persistentvolumes"] + verbs: ["create","delete","get","list","update","watch"] +- apiGroups: [""] + resources: ["persistentvolumes/status"] + verbs: ["update"] +- apiGroups: [""] + resources: ["persistentvolumeclaims"] + verbs: ["get", "list", "update", "watch"] +- apiGroups: [""] + resources: ["persistentvolumeclaims/status"] + verbs: ["update"] +- apiGroups: [""] + resources: ["pods"] + verbs: ["create", "delete", "get", "list", "watch"] +- apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["endpoints", "services"] + verbs: ["create", "delete", "get", "update"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["events"] + verbs: ["watch"] +- apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch", "update"] +- apiGroups: [""] + resources: ["serviceaccounts"] + verbs: ["get", "create"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "create", "update"] +--- +kind: ClusterRoleBinding +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: portworx-pvc-controller-role-binding +subjects: +- kind: ServiceAccount + name: portworx-pvc-controller-account + namespace: kube-system +roleRef: + kind: ClusterRole + name: portworx-pvc-controller-role + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" + labels: + tier: control-plane + name: portworx-pvc-controller + namespace: kube-system +spec: + replicas: 3 + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" + labels: + name: portworx-pvc-controller + tier: control-plane + spec: + {{- if not (empty .Values.registrySecret) }} + imagePullSecrets: + - name: {{ .Values.registrySecret }} + {{- end }} + containers: + - command: + - kube-controller-manager + - --leader-elect=true + - --address=0.0.0.0 + - --controllers=persistentvolume-binder,persistentvolume-expander + - --use-service-account-credentials=true + - --leader-elect-resource-lock=configmaps + image: "{{ template "px.getk8sImages" . }}/kube-controller-manager-amd64:{{ template "px.kubernetesVersion" . }}" + livenessProbe: + failureThreshold: 8 + httpGet: + host: 127.0.0.1 + path: /healthz + port: 10252 + scheme: HTTP + initialDelaySeconds: 15 + timeoutSeconds: 15 + name: portworx-pvc-controller-manager + resources: + requests: + cpu: 200m + hostNetwork: true + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: "name" + operator: In + values: + - portworx-pvc-controller + topologyKey: "kubernetes.io/hostname" + serviceAccountName: portworx-pvc-controller-account +{{- end }} diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-crd.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-crd.yaml new file mode 100644 index 000000000..2811a0f8b --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-crd.yaml @@ -0,0 +1,1146 @@ +{{- if or (and (.Values.csi) (eq .Values.csi true)) (not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty))}} +{{- if (semverCompare ">= 1.17.0-0" .Capabilities.KubeVersion.GitVersion) }} +{{- if (semverCompare ">= 1.20.0-0" .Capabilities.KubeVersion.GitVersion) }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/419" + creationTimestamp: null + name: volumesnapshotclasses.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotClass + listKind: VolumeSnapshotClassList + plural: volumesnapshotclasses + 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 + 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: true + storage: false + subresources: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/419" + creationTimestamp: null + name: volumesnapshotcontents.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotContent + listKind: VolumeSnapshotContentList + plural: volumesnapshotcontents + 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 + - 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 + 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 + oneOf: + - required: ["snapshotHandle"] + - required: ["volumeHandle"] + 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: 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 + - 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: true + storage: false + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/419" + creationTimestamp: null + name: volumesnapshots.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshot + listKind: VolumeSnapshotList + plural: volumesnapshots + 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 + 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 + oneOf: + - required: ["persistentVolumeClaimName"] + - required: ["volumeSnapshotContentName"] + 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 occurrs 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: 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 occurrs 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: true + storage: false + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +{{- else }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/139" + creationTimestamp: null + name: volumesnapshotclasses.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotClass + listKind: VolumeSnapshotClassList + plural: volumesnapshotclasses + 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: v1beta1 + 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: true + storage: true + subresources: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/139" + creationTimestamp: null + name: volumesnapshotcontents.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotContent + listKind: VolumeSnapshotContentList + plural: volumesnapshotcontents + singular: volumesnapshotcontent + scope: Cluster + versions: + - additionalPrinterColumns: + - description: Indicates if a 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 + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + 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. In dynamic snapshot creation + case, this field will be filled in with the "DeletionPolicy" field + defined in the VolumeSnapshotClass the VolumeSnapshot refers to. + 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 from where a snapshot will be created. + 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. 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 to which this snapshot + belongs. + 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 with the "creation_time" + value returned from CSI "CreateSnapshotRequest" 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 latest observed error during snapshot creation, + if any. + 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 with the "ready_to_use" value returned from CSI + "CreateSnapshotRequest" 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 with the "size_bytes" value returned from CSI "CreateSnapshotRequest" + 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: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/139" + creationTimestamp: null + name: volumesnapshots.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshot + listKind: VolumeSnapshotList + plural: volumesnapshots + singular: volumesnapshot + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Indicates if a snapshot is ready to be used to restore a volume. + jsonPath: .status.readyToUse + name: ReadyToUse + type: boolean + - description: Name of the source PVC from where a dynamically taken snapshot + will be created. + jsonPath: .spec.source.persistentVolumeClaimName + name: SourcePVC + type: string + - description: Name of the VolumeSnapshotContent which represents a pre-provisioned + snapshot. + jsonPath: .spec.source.volumeSnapshotContentName + name: SourceSnapshotContent + type: string + - description: Represents the complete size of the 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: The name of the VolumeSnapshotContent to which this VolumeSnapshot + is bound. + jsonPath: .status.boundVolumeSnapshotContentName + name: SnapshotContent + type: string + - description: Timestamp when the point-in-time snapshot is taken by the underlying + storage system. + jsonPath: .status.creationTime + name: CreationTime + type: date + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + 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 in the same namespace as the VolumeSnapshot + object where the snapshot should be dynamically taken from. + This field is immutable. + type: string + volumeSnapshotContentName: + description: volumeSnapshotContentName specifies the name of a + pre-existing VolumeSnapshotContent object. This field is immutable. + type: string + type: object + volumeSnapshotClassName: + description: 'volumeSnapshotClassName is the name of the VolumeSnapshotClass + requested by the VolumeSnapshot. If not specified, the default snapshot + class will be used if one exists. If not specified, and there is + no default snapshot class, dynamic snapshot creation will fail. + Empty string is not allowed for this field. TODO(xiangqian): a webhook + validation on empty string. More info: https://kubernetes.io/docs/concepts/storage/volume-snapshot-classes' + type: string + required: + - source + type: object + status: + description: 'status represents the current information of a snapshot. + NOTE: status can be modified by sources other than system controllers, + and must not be depended upon for accuracy. Controllers should only + use information from the VolumeSnapshotContent object after verifying + that the binding is accurate and complete.' + properties: + boundVolumeSnapshotContentName: + description: 'boundVolumeSnapshotContentName represents the name of + the VolumeSnapshotContent object to which the VolumeSnapshot object + is bound. If not specified, it indicates that the VolumeSnapshot + object has not been successfully bound to a VolumeSnapshotContent + object yet. NOTE: Specified boundVolumeSnapshotContentName alone + does not mean binding is valid. Controllers MUST always verify + bidirectional binding between VolumeSnapshot and VolumeSnapshotContent + to avoid possible security issues.' + 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 with the "creation_time" + value returned from CSI "CreateSnapshotRequest" 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 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. + 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 with the "ready_to_use" value returned from CSI + "CreateSnapshotRequest" 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 complete size of the snapshot + in bytes. In dynamic snapshot creation case, this field will be + filled in with the "size_bytes" value returned from CSI "CreateSnapshotRequest" + 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: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +{{- end}} +{{- end}} +{{- end}} \ No newline at end of file diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-csi.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-csi.yaml new file mode 100644 index 000000000..b3b543483 --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-csi.yaml @@ -0,0 +1,195 @@ +{{- if or (and (.Values.csi) (eq .Values.csi true)) (not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty))}} +{{- $customRegistryURL := .Values.customRegistryURL | default "none" }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: px-csi-account + namespace: kube-system +--- +kind: ClusterRole +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: px-csi-role +rules: +- apiGroups: ["extensions"] + resources: ["podsecuritypolicies"] + resourceNames: ["privileged"] + verbs: ["use"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["*"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["persistentvolumes"] + verbs: ["get", "list", "watch", "create", "delete", "update", "patch"] +- apiGroups: [""] + resources: ["persistentvolumeclaims"] + verbs: ["get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["persistentvolumeclaims/status"] + verbs: ["update", "patch"] +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] +- apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["get", "list", "watch"] +- apiGroups: ["storage.k8s.io"] + resources: ["volumeattachments"] + verbs: ["get", "list", "watch", "update", "patch"] +- apiGroups: ["storage.k8s.io"] + resources: ["csistoragecapacities"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["apps"] + resources: ["replicasets"] + verbs: ["get"] +- apiGroups: [""] + resources: ["events"] + verbs: ["list", "watch", "create", "update", "patch"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list"] +- apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshots", "volumesnapshotcontents", "volumesnapshotclasses", "volumesnapshots/status", "volumesnapshotcontents/status"] + verbs: ["create", "get", "list", "watch", "update", "delete"] +- apiGroups: ["csi.storage.k8s.io"] + resources: ["csinodeinfos"] + verbs: ["get", "list", "watch", "update"] +- apiGroups: ["storage.k8s.io"] + resources: ["csinodes"] + verbs: ["get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] +- apiGroups: ["csi.storage.k8s.io"] + resources: ["csidrivers"] + verbs: ["create", "delete"] +- apiGroups: [""] + resources: ["endpoints"] + verbs: ["get", "watch", "list", "delete", "update", "create"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "watch", "list", "delete", "update", "create"] +- apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["*"] +--- +kind: ClusterRoleBinding +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: px-csi-role-binding +subjects: +- kind: ServiceAccount + name: px-csi-account + namespace: kube-system +roleRef: + kind: ClusterRole + name: px-csi-role + apiGroup: rbac.authorization.k8s.io +--- +kind: Service +apiVersion: v1 +metadata: + name: px-csi-service + namespace: kube-system +spec: + clusterIP: None +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: px-csi-ext + namespace: kube-system +spec: + selector: + matchLabels: + app: px-csi-driver + replicas: 1 + template: + metadata: + labels: + app: px-csi-driver + spec: + serviceAccount: px-csi-account + containers: + - name: csi-external-provisioner + imagePullPolicy: Always + image: {{ template "px.getCSIProvisionerImage" . }} + args: + - "--v=3" + - "--csi-address=$(ADDRESS)" + {{- if semverCompare "<1.17.0-0" .Capabilities.KubeVersion.GitVersion }} + - "--provisioner=pxd.portworx.com" + - "--enable-leader-election" + - "--leader-election-type={{if and (semverCompare ">=1.13.0-0" .Capabilities.KubeVersion.GitVersion) (semverCompare "<1.14.0-0" .Capabilities.KubeVersion.GitVersion) }}endpoints{{else}}leases{{end}}" + {{- else }} + - "--leader-election=true" + - "--default-fstype=ext4" + {{- end }} + env: + - name: ADDRESS + value: /csi/csi.sock + securityContext: + privileged: true + volumeMounts: + - name: socket-dir + mountPath: /csi + {{- if semverCompare ">=1.12.0-0" .Capabilities.KubeVersion.GitVersion }} + - name: csi-snapshotter + imagePullPolicy: Always + image: {{ template "px.getCSISnapshotterImage" . }} + args: + - "--v=3" + - "--csi-address=$(ADDRESS)" + - "--leader-election=true" + {{if and (semverCompare ">=1.13.0-0" .Capabilities.KubeVersion.GitVersion) (semverCompare "<1.14.0-0" .Capabilities.KubeVersion.GitVersion) }} + - "--leader-election-type=configmaps" + {{- end}} + env: + - name: ADDRESS + value: /csi/csi.sock + volumeMounts: + - name: socket-dir + mountPath: /csi + {{- end }} + {{- if semverCompare ">=1.17.0-0" .Capabilities.KubeVersion.GitVersion }} + - name: csi-snapshot-controller + imagePullPolicy: Always + image: {{ template "px.getCSISnapshotControllerImage" . }} + args: + - "--v=3" + - "--leader-election=true" + env: + - name: ADDRESS + value: /csi/csi.sock + securityContext: + privileged: true + volumeMounts: + - name: socket-dir + mountPath: /csi + {{- end }} + {{- if semverCompare ">=1.16.0-0" .Capabilities.KubeVersion.GitVersion }} + - name: csi-resizer + imagePullPolicy: Always + image: k8s.gcr.io/sig-storage/csi-resizer:v1.3.0 + args: + - "--v=3" + - "--csi-address=$(ADDRESS)" + - "--leader-election=true" + env: + - name: ADDRESS + value: /csi/csi.sock + securityContext: + privileged: true + volumeMounts: + - name: socket-dir + mountPath: /csi + {{- end }} + volumes: + - name: socket-dir + hostPath: + path: /var/lib/kubelet/plugins/pxd.portworx.com + type: DirectoryOrCreate +{{- end }} \ No newline at end of file diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-ds.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-ds.yaml new file mode 100644 index 000000000..8c8209ea2 --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-ds.yaml @@ -0,0 +1,477 @@ +{{/* Setting defaults if they are omitted. */}} +{{- $deployEnvironmentIKS := .Capabilities.KubeVersion.GitVersion | regexMatch "IKS" }} +{{- $usefileSystemDrive := .Values.usefileSystemDrive | default false }} +{{- $usedrivesAndPartitions := .Values.usedrivesAndPartitions | default false }} +{{- $secretType := .Values.secretType | default "k8s" }} +{{- $journalDevice := .Values.journalDevice | default "none" }} +{{- $maxStorageNodes := .Values.maxStorageNodes | default "none" }} +{{- $customRegistryURL := .Values.customRegistryURL | default "none" }} +{{- $registrySecret := .Values.registrySecret | default "none" }} + +{{- $dataInterface := .Values.dataInterface | default "none" }} +{{- $managementInterface := .Values.managementInterface | default "none" }} +{{- $essentialSecretID := .Values.essentialID | default "none" }} + +{{- $envVars := .Values.envVars | default "none" }} +{{- $isCoreOS := .Values.isTargetOSCoreOS | default false }} + +{{- $pksInstall := .Values.pksInstall | default false }} +{{- $internalKVDB := .Values.etcdType | default "none" }} +{{- $csi := .Values.csi | default (not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty)) }} + +{{- $etcdCredentials := .Values.etcd.credentials | default "none:none" }} +{{- $etcdCertPath := .Values.etcd.ca | default "none" }} +{{- $etcdCA := .Values.etcd.ca | default "none" }} +{{- $etcdCert := .Values.etcd.cert | default "none" }} +{{- $etcdKey := .Values.etcd.key | default "none" }} +{{- $consulToken := .Values.consul.token | default "none" }} +{{- $misc := .Values.misc | default "" | split " " }} +{{- $etcdEndPoints := .Values.kvdb }} + +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: portworx + namespace: kube-system + labels: + name: portworx +spec: + minReadySeconds: 0 + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + selector: + matchLabels: + name: portworx + app: portworx + template: + metadata: + labels: + app: portworx + name: portworx + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: px/enabled + operator: NotIn + values: + - "false" + {{- if and (.Values.openshiftInstall) (eq .Values.openshiftInstall true)}} + - key: openshift-infra + operator: DoesNotExist + {{- else if or (not .Values.deployOnMaster) (eq .Values.deployOnMaster false)}} + - key: node-role.kubernetes.io/master + operator: DoesNotExist + {{- end }} + hostNetwork: true + hostPID: true + {{- if not (eq $registrySecret "none") }} + imagePullSecrets: + - name: {{ $registrySecret }} + {{- end }} + containers: + # {{ template "px.getImage"}} + - name: portworx + image: {{ template "px.getImage" . }}:{{ required "A valid Image tag is required in the SemVer format" .Values.imageVersion }} + terminationMessagePath: "/tmp/px-termination-log" + imagePullPolicy: Always + args: + [ + {{ include "px.storage" . | indent 0 }} + {{- with .Values -}} + {{- if eq "Built-in" $internalKVDB }} + "-b", + {{- end -}} + + {{- if ne $journalDevice "none" }} + "-j", "{{ $journalDevice }}", + {{- end -}} + + {{- if $etcdEndPoints -}} + "-k", "{{ regexReplaceAllLiteral "(;)" .kvdb "," }}", + {{- else }} + {{- if ne "Built-in" $internalKVDB }} + {{- if eq "US region" .region }} + "-k", "etcd:http://px-etcd1.portworx.com:2379,etcd:http://px-etcd2.portworx.com:2379,etcd:http://px-etcd3.portworx.com:2379", + {{- else if eq "EU region" .region }} + "-k", "etcd:http://px-eu-etcd1.portworx.com:2379,etcd:http://px-eu-etcd2.portworx.com:2379,etcd:http://px-eu-etcd3.portworx.com:2379", + {{- else }} + "{{ required "A valid kvdb url is required." .kvdb }}" + {{- end -}} + {{- end -}} + {{- end -}} + "-c", "{{ required "Clustername cannot be empty" .clusterName }}", + + {{- if ne $secretType "none" }} + "-secret_type", "{{ $secretType }}", + {{- else }} + {{- if $deployEnvironmentIKS }} + "-secret_type", "ibm-kp", + {{- end -}} + {{- end -}} + + {{- if and (ne $dataInterface "none") (ne $dataInterface "auto")}} + "-d", "{{ $dataInterface }}", + {{- end -}} + + {{- if and (ne $managementInterface "none") (ne $managementInterface "auto") }} + "-m", "{{ $managementInterface }}", + {{- end -}} + + {{- if ne $etcdCredentials "none:none" }} + "-userpwd", "{{ $etcdCredentials }}", + {{- end -}} + + {{- if ne $etcdCA "none" }} + "-ca", "/etc/pwx/etcdcerts/{{ $etcdCA }}", + {{- end -}} + + {{- if ne $etcdCert "none" }} + "-cert", "/etc/pwx/etcdcerts/{{ $etcdCert }}", + {{- end -}} + + {{- if ne $etcdKey "none" }} + "-key", "/etc/pwx/etcdcerts/{{ $etcdKey }}", + {{- end -}} + + {{- if ne $consulToken "none" }} + "-acltoken", "{{ $consulToken }}", + {{- end -}} + + {{- if .misc }} + {{- range $index, $name := $misc }} + "{{ $name }}", + {{- end }} + {{ end -}} + + {{- if ne $essentialSecretID "none" }} + "--oem", "esse", + {{ end -}} + "-marketplace_name","rancher_catalog", + "-x", "kubernetes" + {{- end -}} + ] + env: + - name: "PX_TEMPLATE_VERSION" + value: "v2" + {{ if not (eq $envVars "none") }} + {{- $vars := $envVars | split ";" }} + {{- range $key, $val := $vars }} + {{- $envVariable := $val | split "=" }} + - name: {{ $envVariable._0 | trim | quote }} + value: {{ $envVariable._1 | trim | quote }} + {{ end }} + {{- end }} + + {{- if not (eq $registrySecret "none") }} + - name: REGISTRY_CONFIG + valueFrom: + secretKeyRef: + {{- if (semverCompare ">=1.9-0" .Capabilities.KubeVersion.GitVersion) or (.Values.openshiftInstall and semverCompare ">=1.8-0" .Capabilities.KubeVersion.GitVersion) }} + key: ".dockerconfigjson" + {{- else }} + key: ".dockercfg" + {{- end }} + name: "{{ $registrySecret }}" + {{- end }} + + {{- if eq $pksInstall true }} + - name: "PRE-EXEC" + value: "if [ ! -x /bin/systemctl ]; then apt-get update; apt-get install -y systemd; fi" + {{- end }} + + {{- if eq $csi true }} + - name: CSI_ENDPOINT + value: unix:///var/lib/kubelet/plugins/pxd.portworx.com/csi.sock + {{- end }} + + livenessProbe: + periodSeconds: 30 + initialDelaySeconds: 840 # allow image pull in slow networks + httpGet: + host: 127.0.0.1 + path: /status + port: 9001 + readinessProbe: + periodSeconds: 10 + httpGet: + host: 127.0.0.1 + {{- if eq (.Values.deploymentType | upper | lower) "oci" }} + path: /health + port: 9015 + {{- else }} + path: /v1/cluster/nodehealth + port: 9001 + {{- end}} + securityContext: + privileged: true + volumeMounts: + {{- if not (eq $etcdCertPath "none") }} + - mountPath: /etc/pwx/etcdcerts + name: etcdcerts + {{- end }} + {{- if not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty) }} + - name: containerd-k3s + mountPath: /run/containerd/containerd.sock + {{- end }} + - name: dockersock + mountPath: /var/run/docker.sock + - name: containerdsock + mountPath: /run/containerd + - name: etcpwx + mountPath: /etc/pwx + - name: cores + mountPath: /var/cores + {{- if eq (.Values.deploymentType | upper | lower) "oci" }} + - name: optpwx + mountPath: /opt/pwx + - name: sysdmount + mountPath: /etc/systemd/system + - name: journalmount1 + mountPath: /var/run/log + readOnly: true + - name: journalmount2 + mountPath: /var/log + readOnly: true + - name: dbusmount + mountPath: /var/run/dbus + - name: hostproc + mountPath: /host_proc + {{- else if eq (.Values.deploymentType | upper | lower) "docker" }} + - name: dev + mountPath: /dev + - name: optpwx + mountPath: /export_bin + - name: dockerplugins + mountPath: /run/docker/plugins + - name: hostproc + mountPath: /hostproc + {{- if semverCompare "< 1.10-0" .Capabilities.KubeVersion.GitVersion }} + - name: libosd + mountPath: /var/lib/osd:shared + {{- if (.Values.openshiftInstall) and (eq .Values.openshiftInstall true)}} + - name: kubelet + mountPath: /var/lib/origin/openshift.local.volumes:shared + {{- else }} + - name: kubelet + mountPath: /var/lib/kubelet:shared + {{- end }} + + {{- else }} + - name: libosd + mountPath: /var/lib/osd + mountPropagation: "Bidirectional" + {{- if (.Values.openshiftInstall) and (eq .Values.openshiftInstall true)}} + - name: kubelet + mountPath: /var/lib/origin/openshift.local.volumes + mountPropagation: "Bidirectional" + {{- else }} + - name: kubelet + mountPath: /var/lib/kubelet + mountPropagation: "Bidirectional" + {{- end }} + + {{- end }} + + {{- if eq $isCoreOS true}} + - name: src + mountPath: /lib/modules + {{- else }} + - name: src + mountPath: /usr/src + {{- end }} + {{- end }} + + {{- if eq $csi true }} + - name: csi-node-driver-registrar + imagePullPolicy: Always + {{- if eq $customRegistryURL "none" }} + image: "k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.1.0" + {{- else }} + image: "{{ $customRegistryURL }}/k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.1.0" + {{- end}} + args: + - "--v=5" + - "--csi-address=$(ADDRESS)" + - "--kubelet-registration-path=/var/lib/kubelet/plugins/pxd.portworx.com/csi.sock" + env: + - name: ADDRESS + value: /csi/csi.sock + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + volumeMounts: + - name: csi-driver-path + mountPath: /csi + - name: registration-dir + mountPath: /registration + {{- end }} + + restartPolicy: Always + {{- if not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty) }} + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule + {{- end }} + serviceAccountName: px-account + volumes: + {{- if ne $etcdCertPath "none" }} + - name: etcdcerts + secret: + secretName: px-etcd-certs + items: + - key: "{{ $etcdCA }}" + path: "{{ $etcdCA }}" + - key: "{{ $etcdCert }}" + path: "{{ $etcdCert }}" + - key: "{{ $etcdKey }}" + path: "{{ $etcdKey }}" + {{- end}} + {{- if not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty) }} + - name: containerd-k3s + hostPath: + path: /run/k3s/containerd/containerd.sock + {{- end }} + - name: dockersock + hostPath: + path: {{if eq $pksInstall true}}/var/vcap/sys/run/docker/docker.sock{{else}}/var/run/docker.sock{{end}} + - name: containerdsock + hostPath: + path: {{if eq $pksInstall true}}/var/vcap/sys/run/containerd{{else}}/run/containerd{{end}} + {{- if eq $csi true}} + - name: csi-driver-path + hostPath: + path: /var/lib/kubelet/plugins/pxd.portworx.com + type: DirectoryOrCreate + - name: registration-dir + hostPath: + path: /var/lib/kubelet/plugins_registry + type: DirectoryOrCreate + {{- end}} + - name: etcpwx + hostPath: + path: /etc/pwx + - name: cores + hostPath: + path: {{if eq $pksInstall true }}/var/vcap/store/cores{{else}}/var/cores{{end}} + {{- if eq (.Values.deploymentType | upper | lower) "oci" }} + - name: optpwx + hostPath: + path: {{if eq $pksInstall true }}/var/vcap/store/opt/pwx{{else}}/opt/pwx{{end}} + - name: sysdmount + hostPath: + path: /etc/systemd/system + - name: journalmount1 + hostPath: + path: /var/run/log + - name: journalmount2 + hostPath: + path: /var/log + - name: dbusmount + hostPath: + path: /var/run/dbus + - name: hostproc + hostPath: + path: /proc + {{- else if eq (.Values.deploymentType | upper | lower) "docker" }} + - name: libosd + hostPath: + path: /var/lib/osd + - name: optpwx + hostPath: + path: /opt/pwx/bin + - name: dev + hostPath: + path: /dev + {{- if (.Values.openshiftInstall) and (eq .Values.openshiftInstall true)}} + - name: kubelet + hostPath: + path: /var/lib/origin/openshift.local.volumes + {{- else }} + - name: kubelet + hostPath: + path: /var/lib/kubelet + {{- end }} + {{- if eq $isCoreOS true}} + - name: src + hostPath: + path: /lib/modules + {{- else }} + - name: src + hostPath: + path: /usr/src + {{- end }} + - name: dockerplugins + hostPath: + path: /run/docker/plugins + - name: hostproc + hostPath: + path: /proc + {{- end }} +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: portworx-api + namespace: kube-system + labels: + name: portworx-api +spec: + selector: + matchLabels: + name: portworx-api + minReadySeconds: 0 + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 100% + template: + metadata: + labels: + name: portworx-api + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: px/enabled + operator: NotIn + values: + - "false" + {{- if not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty) }} + - key: node-role.kubernetes.io/master + operator: DoesNotExist + {{- end }} + hostNetwork: true + hostPID: false + containers: + - name: portworx-api + image: "{{ template "px.getPauseImage" . }}/pause:3.1" + imagePullPolicy: Always + readinessProbe: + periodSeconds: 10 + httpGet: + host: 127.0.0.1 + path: /status + port: 9001 + restartPolicy: Always + serviceAccountName: px-account +{{- if eq $csi true }} +--- +apiVersion: storage.k8s.io/v1 +kind: CSIDriver +metadata: + name: "pxd.portworx.com" +spec: + attachRequired: false + podInfoOnMount: true + volumeLifecycleModes: + - Persistent + - Ephemeral +{{- end}} \ No newline at end of file diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-essential.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-essential.yaml new file mode 100644 index 000000000..6decc3047 --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-essential.yaml @@ -0,0 +1,19 @@ +{{- $essentialSecretID := .Values.essentialID | default "none" }} +{{- if ne $essentialSecretID "none" -}} +apiVersion: v1 +kind: Secret +metadata: + name: px-essential + namespace: kube-system + labels: + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{.Release.Service | quote }} + app.kubernetes.io/instance: {{.Release.Name | quote }} + chart: "{{.Chart.Name}}-{{.Chart.Version}}" +type: Opaque +data: + px-essen-user-id: {{ $essentialSecretID | b64enc }} + px-osb-endpoint: aHR0cHM6Ly9weGVzc2VudGlhbHMucG9ydHdvcnguY29tL29zYi9iaWxsaW5nL3YxL3JlZ2lzdGVy + px-essen-market-place: cmFuY2hlci1tYXJrZXRwbGFjZQ== +{{- end -}} \ No newline at end of file diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-rbac-config.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-rbac-config.yaml new file mode 100644 index 000000000..0cbb3b0a3 --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-rbac-config.yaml @@ -0,0 +1,56 @@ + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: px-account + namespace: kube-system +--- + +kind: ClusterRole +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: node-get-put-list-role +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["watch", "get", "update", "list"] +- apiGroups: [""] + resources: ["pods"] + verbs: ["delete", "get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["persistentvolumeclaims", "persistentvolumes"] + verbs: ["get", "list"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "update", "create"] +- apiGroups: ["extensions"] + resources: ["podsecuritypolicies"] + resourceNames: ["privileged"] + verbs: ["use"] +- apiGroups: ["portworx.io"] + resources: ["volumeplacementstrategies"] + verbs: ["get", "list"] +- apiGroups: ["stork.libopenstorage.org"] + resources: ["backuplocations"] + verbs: ["get", "list"] +- apiGroups: [""] + resources: ["events"] + verbs: ["create"] +--- + +kind: ClusterRoleBinding +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: node-role-binding +subjects: +- kind: ServiceAccount + name: px-account + namespace: kube-system +roleRef: + kind: ClusterRole + name: node-get-put-list-role + apiGroup: rbac.authorization.k8s.io diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-service.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-service.yaml new file mode 100644 index 000000000..8d3ac159d --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-service.yaml @@ -0,0 +1,54 @@ +kind: Service +apiVersion: v1 +metadata: + name: portworx-service + namespace: kube-system + labels: + name: portworx +spec: + selector: + name: portworx + type: ClusterIP + ports: + - name: px-api + protocol: TCP + port: 9001 + targetPort: 9001 + - name: px-kvdb + protocol: TCP + port: 9019 + targetPort: 9019 + - name: px-sdk + protocol: TCP + port: 9020 + targetPort: 9020 + - name: px-rest-gateway + protocol: TCP + port: 9021 + targetPort: 9021 +--- +kind: Service +apiVersion: v1 +metadata: + name: portworx-api + namespace: kube-system + labels: + name: portworx-api +spec: + selector: + name: portworx-api + type: ClusterIP + ports: + - name: px-api + protocol: TCP + port: 9001 + targetPort: 9001 + - name: px-sdk + protocol: TCP + port: 9020 + targetPort: 9020 + - name: px-rest-gateway + protocol: TCP + port: 9021 + targetPort: 9021 +--- diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-storageclasses.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-storageclasses.yaml new file mode 100644 index 000000000..b430fee8f --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-storageclasses.yaml @@ -0,0 +1,56 @@ +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: portworx-db-sc +provisioner: kubernetes.io/portworx-volume +parameters: + repl: "3" + io_profile: "db" +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: portworx-db2-sc +provisioner: kubernetes.io/portworx-volume +parameters: + repl: "3" + block_size: "512b" + io_profile: "db" +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: portworx-shared-sc +provisioner: kubernetes.io/portworx-volume +parameters: + repl: "3" + shared: "true" +--- +# +# NULL StorageClass that documents all possible +# Portworx StorageClass parameters +# +# Please refer to : https://docs.portworx.com/scheduler/kubernetes/dynamic-provisioning.html +# +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: portworx-null-sc + annotations: + params/docs: 'https://docs.portworx.com/scheduler/kubernetes/dynamic-provisioning.html' + params/fs: "Filesystem to be laid out: none|xfs|ext4 " + params/block_size: "Block size" + params/repl: "Replication factor for the volume: 1|2|3" + params/shared: "Flag to create a globally shared namespace volume which can be used by multiple pods : true|false" + params/priority_io: "IO Priority: low|medium|high" + params/io_profile: "IO Profile can be used to override the I/O algorithm Portworx uses for the volumes. Supported values are [db](/maintain/performance/tuning.html#db), [sequential](/maintain/performance/tuning.html#sequential), [random](/maintain/performance/tuning.html#random), [cms](/maintain/performance/tuning.html#cms)" + params/group: "The group a volume should belong too. Portworx will restrict replication sets of volumes of the same group on different nodes. If the force group option 'fg' is set to true, the volume group rule will be strictly enforced. By default, it's not strictly enforced." + params/fg: "This option enforces volume group policy. If a volume belonging to a group cannot find nodes for it's replication sets which don't have other volumes of same group, the volume creation will fail." + params/label: "List of comma-separated name=value pairs to apply to the Portworx volume" + params/nodes: "Comma-separated Portworx Node ID's to use for replication sets of the volume" + params/aggregation_level: "Specifies the number of replication sets the volume can be aggregated from" + params/snap_schedule: "Snapshot schedule. Following are the accepted formats: periodic=_mins_,_snaps-to-keep_ daily=_hh:mm_,_snaps-to-keep_ weekly=_weekday@hh:mm_,_snaps-to-keep_ monthly=_day@hh:mm_,_snaps-to-keep_ _snaps-to-keep_ is optional. Periodic, Daily, Weekly and Monthly keep last 5, 7, 5 and 12 snapshots by default respectively" + params/sticky: "Flag to create sticky volumes that cannot be deleted until the flag is disabled" + params/journal: "Flag to indicate if you want to use journal device for the volume's metadata. This will use the journal device that you used when installing Portworx. As of PX version 1.3, it is recommended to use a journal device to absorb PX metadata writes" +provisioner: kubernetes.io/portworx-volume +parameters: diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-stork.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-stork.yaml new file mode 100644 index 000000000..77449b394 --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/portworx-stork.yaml @@ -0,0 +1,645 @@ +{{- if and (.Values.stork) (eq .Values.stork true)}} + {{- $isCoreOS := .Values.isTargetOSCoreOS | default false }} + {{- $customRegistryURL := .Values.customRegistryURL | default "none" }} + {{- $registrySecret := .Values.registrySecret | default "none" }} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: stork-config + namespace: kube-system +data: + policy.cfg: |- + { + "kind": "Policy", + "apiVersion": "v1", +{{- if semverCompare "< 1.10-0" .Capabilities.KubeVersion.GitVersion }} + "predicates": [ +{{- if semverCompare "< 1.9-0" .Capabilities.KubeVersion.GitVersion }} + {"name": "NoVolumeNodeConflict"}, +{{- end}} + {"name": "MaxAzureDiskVolumeCount"}, + {"name": "NoVolumeZoneConflict"}, + {"name": "PodToleratesNodeTaints"}, + {"name": "CheckNodeMemoryPressure"}, + {"name": "MaxEBSVolumeCount"}, + {"name": "MaxGCEPDVolumeCount"}, + {"name": "MatchInterPodAffinity"}, + {"name": "NoDiskConflict"}, + {"name": "GeneralPredicates"}, + {"name": "CheckNodeDiskPressure"} + ], + "priorities": [ + {"name": "NodeAffinityPriority", "weight": 1}, + {"name": "TaintTolerationPriority", "weight": 1}, + {"name": "SelectorSpreadPriority", "weight": 1}, + {"name": "InterPodAffinityPriority", "weight": 1}, + {"name": "LeastRequestedPriority", "weight": 1}, + {"name": "BalancedResourceAllocation", "weight": 1}, + {"name": "NodePreferAvoidPodsPriority", "weight": 1} + ], +{{- end}} + "extenders": [ + { + "urlPrefix": "http://stork-service.kube-system:8099", + "apiVersion": "v1beta1", + "filterVerb": "filter", + "prioritizeVerb": "prioritize", + "weight": 5, + "enableHttps": false, + "nodeCacheCapable": false + } + ] + } +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: stork-account + namespace: kube-system +--- +kind: ClusterRole +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: stork-role +rules: + - apiGroups: ["*"] + resources: ["*"] + verbs: ["*"] +--- +kind: ClusterRoleBinding +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: stork-role-binding +subjects: + - kind: ServiceAccount + name: stork-account + namespace: kube-system +roleRef: + kind: ClusterRole + name: stork-role + apiGroup: rbac.authorization.k8s.io +--- +kind: Service +apiVersion: v1 +metadata: + name: stork-service + namespace: kube-system +spec: + selector: + name: stork + ports: + - name: extender + protocol: TCP + port: 8099 + targetPort: 8099 + - name: webhook + protocol: TCP + port: 443 + targetPort: 443 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: volumeplacementstrategies.portworx.io +spec: + group: portworx.io + versions: + - name: v1beta2 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + required: + - spec + properties: + spec: + type: object + description: The desired spec of the volume placement strategy + properties: + replicaAffinity: + type: array + description: Allows you to specify a rule which creates an affinity for replicas within a volume + items: + type: object + properties: + affected_replicas: + type: integer + description: The number of volume replicas affected by the replica affinity + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + matchExpressions: + description: Expression to use for the replica affinity rule + type: array + items: + type: object + properties: + key: + type: string + minLength: 1 + operator: + type: string + enum: + - In + - NotIn + - Exists + - DoesNotExist + - Lt + - Gt + description: The logical operator to use for comparing the key and values in the match expression + values: + type: array + items: + type: string + required: + - key + - operator + replicaAntiAffinity: + type: array + description: Allows you to specify a rule that creates an anti-affinity for replicas within a volume + items: + type: object + properties: + affected_replicas: + type: integer + description: The number of volume replicas affected by the replica anti affinity + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + required: + - topologyKey + volumeAffinity: + type: array + description: Allows you to colocate volumes by specifying rules that place replicas of a volume together with those of another volume for which the specified labels match + items: + type: object + properties: + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + matchExpressions: + description: Expression to use for the volume affinity rule + type: array + items: + type: object + properties: + key: + type: string + minLength: 1 + operator: + type: string + enum: + - In + - NotIn + - Exists + - DoesNotExist + - Lt + - Gt + description: The logical operator to use for comparing the key and values in the match expression + values: + type: array + items: + type: string + required: + - key + - operator + required: + - matchExpressions + volumeAntiAffinity: + type: array + description: Allows you to specify dissociation rules between 2 or more volumes that match the given labels + items: + type: object + properties: + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + matchExpressions: + description: Expression to use for the volume anti affinity rule + type: array + items: + type: object + properties: + key: + type: string + minLength: 1 + operator: + type: string + enum: + - In + - NotIn + - Exists + - DoesNotExist + - Lt + - Gt + description: The logical operator to use for comparing the key and values in the match expression + values: + type: array + items: + type: string + required: + - key + - operator + required: + - matchExpressions + - name: v1beta1 + served: false + storage: false + schema: + openAPIV3Schema: + type: object + required: + - spec + properties: + spec: + type: object + description: The desired spec of the volume placement strategy + properties: + replicaAffinity: + type: array + description: Allows you to specify a rule which creates an affinity for replicas within a volume + items: + type: object + properties: + affected_replicas: + type: integer + description: The number of volume replicas affected by the replica affinity + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + matchExpressions: + description: Expression to use for the replica affinity rule + type: array + items: + type: object + properties: + key: + type: string + minLength: 1 + operator: + type: string + enum: + - In + - NotIn + - Exists + - DoesNotExist + - Lt + - Gt + description: The logical operator to use for comparing the key and values in the match expression + values: + type: array + items: + type: string + required: + - key + - operator + replicaAntiAffinity: + type: array + description: Allows you to specify a rule that creates an anti-affinity for replicas within a volume + items: + type: object + properties: + affected_replicas: + type: integer + description: The number of volume replicas affected by the replica anti affinity + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + required: + - topologyKey + volumeAffinity: + type: array + description: Allows you to colocate volumes by specifying rules that place replicas of a volume together with those of another volume for which the specified labels match + items: + type: object + properties: + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + matchExpressions: + description: Expression to use for the volume affinity rule + type: array + items: + type: object + properties: + key: + type: string + minLength: 1 + operator: + type: string + enum: + - In + - NotIn + - Exists + - DoesNotExist + - Lt + - Gt + description: The logical operator to use for comparing the key and values in the match expression + values: + type: array + items: + type: string + required: + - key + - operator + required: + - matchExpressions + volumeAntiAffinity: + type: array + description: Allows you to specify dissociation rules between 2 or more volumes that match the given labels + items: + type: object + properties: + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + matchExpressions: + description: Expression to use for the volume anti affinity rule + type: array + items: + type: object + properties: + key: + type: string + minLength: 1 + operator: + type: string + enum: + - In + - NotIn + - Exists + - DoesNotExist + - Lt + - Gt + description: The logical operator to use for comparing the key and values in the match expression + values: + type: array + items: + type: string + required: + - key + - operator + required: + - matchExpressions + scope: Cluster + names: + plural: volumeplacementstrategies + singular: volumeplacementstrategy + kind: VolumePlacementStrategy + shortNames: + - vps + - vp +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" + labels: + tier: control-plane + name: stork + namespace: kube-system +spec: + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + replicas: 3 + selector: + matchLabels: + name: stork + tier: control-plane + template: + metadata: + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" + labels: + name: stork + tier: control-plane + spec: + {{- if not (eq $registrySecret "none") }} + imagePullSecrets: + - name: {{ $registrySecret }} + {{- end }} + containers: + - command: + - /stork + - --driver=pxd + - --verbose + - --leader-elect=true + - --webhook-controller=false + imagePullPolicy: Always + image: {{ template "px.getStorkImage" . }}:{{ required "A valid Image tag is required in the SemVer format" .Values.storkVersion }} + resources: + requests: + cpu: '0.1' + name: stork + hostPID: false + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: "name" + operator: In + values: + - stork + topologyKey: "kubernetes.io/hostname" + serviceAccountName: stork-account +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: stork-snapshot-sc +provisioner: stork-snapshot +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: stork-scheduler-account + namespace: kube-system +--- +kind: ClusterRole +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: stork-scheduler-role +rules: + - apiGroups: [""] + resources: ["endpoints"] + verbs: ["get", "update"] + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] + - apiGroups: ["", "events.k8s.io"] + resources: ["events"] + verbs: ["create", "patch", "update"] + - apiGroups: [""] + resources: ["endpoints"] + verbs: ["create"] + - apiGroups: [""] + resourceNames: ["kube-scheduler"] + resources: ["endpoints"] + verbs: ["delete", "get", "patch", "update"] + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["delete", "get", "list", "watch"] + - apiGroups: [""] + resources: ["bindings", "pods/binding"] + verbs: ["create"] + - apiGroups: [""] + resources: ["pods/status"] + verbs: ["patch", "update"] + - apiGroups: [""] + resources: ["replicationcontrollers", "services"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps", "extensions"] + resources: ["replicasets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps"] + resources: ["statefulsets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["policy"] + resources: ["poddisruptionbudgets"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["persistentvolumeclaims", "persistentvolumes"] + verbs: ["get", "list", "watch"] + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses", "csinodes", "csidrivers", "csistoragecapacities"] + verbs: ["get", "list", "watch"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["create", "update", "get", "list", "watch"] +--- +kind: ClusterRoleBinding +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: stork-scheduler-role-binding +subjects: + - kind: ServiceAccount + name: stork-scheduler-account + namespace: kube-system +roleRef: + kind: ClusterRole + name: stork-scheduler-role + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + component: scheduler + tier: control-plane + name: stork-scheduler + namespace: kube-system +spec: + replicas: 3 + selector: + matchLabels: + component: scheduler + tier: control-plane + template: + metadata: + labels: + component: scheduler + tier: control-plane + name: stork-scheduler + spec: + containers: + - command: + - /usr/local/bin/kube-scheduler + - --address=0.0.0.0 + - --leader-elect=true + - --scheduler-name=stork + - --policy-configmap=stork-config + - --policy-configmap-namespace=kube-system + - --lock-object-name=stork-scheduler + image: "{{ template "px.getk8sImages" . }}/kube-scheduler-amd64:v1.21.4" + livenessProbe: + httpGet: + path: /healthz + port: 10251 + initialDelaySeconds: 15 + name: stork-scheduler + readinessProbe: + httpGet: + path: /healthz + port: 10251 + resources: + requests: + cpu: '0.1' + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: "name" + operator: In + values: + - stork-scheduler + topologyKey: "kubernetes.io/hostname" + hostPID: false + serviceAccountName: stork-scheduler-account + {{- end }} diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/templates/serviceaccount-hook.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/serviceaccount-hook.yaml new file mode 100644 index 000000000..9f4f0defd --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/templates/serviceaccount-hook.yaml @@ -0,0 +1,42 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "px.hookServiceAccount" . }} + namespace: kube-system + annotations: + "helm.sh/hook-delete-policy": before-hook-creation + "helm.sh/hook": "post-install,pre-delete,post-delete" + labels: + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{.Release.Service | quote }} + app.kubernetes.io/instance: {{.Release.Name | quote }} + chart: "{{.Chart.Name}}-{{.Chart.Version}}" +--- +kind: ClusterRole +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + annotations: + "helm.sh/hook-delete-policy": before-hook-creation + "helm.sh/hook": "post-install,pre-delete,post-delete" + name: {{ template "px.hookClusterRole" . }} +rules: +- apiGroups: [""] + resources: ["nodes"] + verbs: ["patch", "get", "update", "list"] +--- +kind: ClusterRoleBinding +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + annotations: + "helm.sh/hook-delete-policy": before-hook-creation + "helm.sh/hook": "post-install,pre-delete,post-delete" + name: {{ template "px.hookClusterRoleBinding" . }} +subjects: +- kind: ServiceAccount + name: {{ template "px.hookServiceAccount" . }} + namespace: kube-system +roleRef: + kind: ClusterRole + name: {{ template "px.hookClusterRole" . }} + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/charts/portworx-essentials/portworx-essentials/2.9.100/values.yaml b/charts/portworx-essentials/portworx-essentials/2.9.100/values.yaml new file mode 100644 index 000000000..279a15b1f --- /dev/null +++ b/charts/portworx-essentials/portworx-essentials/2.9.100/values.yaml @@ -0,0 +1,151 @@ +# Please uncomment and specify values for these options as per your requirements. +kvdb: +ownEtcdOption: none +etcdAuth: none +etcdType: "Built-in" # KVDB type + +etcd: + credentials: none:none # Username and password for ETCD authentication in the form user:password + ca: none # Name of CA file for ETCD authentication. server.ca + cert: none # Name of certificate for ETCD authentication. Should be server.crt + key: none # Name of certificate key for ETCD authentication Should be server.key +consul: + token: none # ACL token value used for Consul authentication. (example: 398073a8-5091-4d9c-871a-bbbeb030d1f6) +region: none # US or EU regions for Portworx hosted etcds + +dataInterface: none # Name of the interface +managementInterface: none # Name of the interface +platformOptions: none # AKS, EKS or GKE platforms + +customRegistryURL: +registrySecret: + +clusterName: mycluster # This is the default. please change it to your cluster name. +secretType: k8s # Defaults to None, but can be AWS / KVDB / Vault. +envVars: none # NOTE: This is a ";" seperated list of environment variables. For eg: MYENV1=myvalue1;MYENV2=myvalue2 +stork: true # Use Stork https://docs.portworx.com/scheduler/kubernetes/stork.html for hyperconvergence. +storkVersion: 2.7.0 + +deployOnMaster: false # For POC only +csi: true # Enable CSI + +openshiftInstall: false +AKSorEKSInstall: false +serviceAccount: + hook: + create: true + name: + +deploymentType: oci # accepts "oci" or "docker" +imageType: none # +imageVersion: 2.9.1.4 # Version of the PX Image. + +result: none +environment: none +onpremStorage: none + +maxStorageNodes: none +journalDevice: none + +usefileSystemDrive: false # true/false Instructs PX to use an unmounted Drive even if it has a filesystem. +usedrivesAndPartitions: false # Use unmounted disks even if they have a partition or filesystem on it. PX will never use a drive or partition that is mounted. (useDrivesAndPartitions) + +provider: none +deviceConfig: none +essentialID: none + +drive_1: + aws: + type: none + size: none + iops: none + gc: + type: standard + size: 1000 + +drive_2: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_3: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_4: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_5: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_6: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_7: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_8: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_9: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_10: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +existingDisk1: none +existingDisk2: none +existingDisk3: none +existingDisk4: none +existingDisk5: none diff --git a/charts/portworx/portworx/2.9.101/Chart.yaml b/charts/portworx/portworx/2.9.101/Chart.yaml new file mode 100644 index 000000000..8aa101ac9 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/Chart.yaml @@ -0,0 +1,32 @@ +annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Portworx + catalog.cattle.io/release-name: portworx +apiVersion: v1 +appVersion: "2.9" +description: A Helm chart for installing Portworx on Kubernetes. +home: https://portworx.com/ +icon: https://raw.githubusercontent.com/portworx/helm/master/doc/media/k8s-porx.png +keywords: +- Storage +- ICP +- persistent disk +- pvc +- cloud native storage +- persistent storage +- portworx +- amd64 +kubeVersion: '>=1.16.0-0' +maintainers: +- email: hadesai@purestorage.com + name: harsh-px +- email: onaumov@purestorage.com + name: trierra +- email: tasharma@purestorage.com + name: sharma-tapas +- email: dahuang@purestorage.com + name: dahuang-purestorage +name: portworx +sources: +- https://github.com/portworx/charts-rancher/tree/master/stable +version: 2.9.101 diff --git a/charts/portworx/portworx/2.9.101/README.md b/charts/portworx/portworx/2.9.101/README.md new file mode 100644 index 000000000..76066d7e2 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/README.md @@ -0,0 +1,76 @@ +# Portworx + +## **Pre-requisites** + +Use this Helm chart to deploy [Portworx](https://portworx.com/) and [Stork](https://docs.portworx.com/scheduler/kubernetes/stork.html) to your Kubernetes cluster. + +Prerequisites + +Refer to the [Install Portworx on Kubernetes via Helm](https://docs.portworx.com/portworx-install-with-kubernetes/install-px-helm/#pre-requisites) page for the list of prerequisites. + +## **Limitations** +* The portworx helm chart can only be deployed in the kube-system namespace. Hence use "kube-system" in the "Target namespace" during configuration. + +## **Uninstalling the Chart** + +#### You can uninstall Portworx using one of the following methods: + +#### **1. Delete all the Kubernetes components associated with the chart and the release.** + +> **Note** > The Portworx configuration files under `/etc/pwx/` directory are preserved, and will not be deleted. + +To perform this operation simply delete the application from the Apps page + +#### **2. Wipe your Portworx installation** +> **Note** > The commands in this section are disruptive and will lead to data loss. Please use caution.. + +See more details [here](https://docs.portworx.com/portworx-install-with-kubernetes/install-px-helm/#uninstall) + +## **Documentation** +* [Portworx docs site](https://docs.portworx.com/install-with-other/rancher/rancher-2.x/#step-1-install-rancher) +* [Portworx interactive tutorials](https://docs.portworx.com/scheduler/kubernetes/px-k8s-interactive.html) + +## **Installing the Chart using the CLI** + +See the installation details [here](https://docs.portworx.com/portworx-install-with-kubernetes/install-px-helm/) + +## **Installing Portworx on AWS** + +See the installation details [here](https://docs.portworx.com/cloud-references/auto-disk-provisioning/aws) + +## ** Giving your etcd certificates to Portworx using Kubernetes Secrets.** +This is the recommended way of providing etcd certificates, as the certificates will be automatically available to the new nodes joining the cluster + +* Create Kubernetes secret +* Copy all your etcd certificates and key in a directory etcd-secrets/ to create a Kubernetes secret from it. Make sure the file names are the same as you gave above. + +``` +# ls -1 etcd-secrets/ +etcd-ca.crt +etcd.crt +etcd.key +``` + +* Use kubectl to create the secret named px-etcd-certs from the above files: +``` +# kubectl -n kube-system create secret generic px-etcd-certs --from-file=etcd-secrets/ +``` + +* Notice that the secret has 3 keys etcd-ca.crt, etcd.crt and etcd.key, corresponding to file names in the etcd-secrets folder. We will use these keys in the Portworx spec file to reference the certificates. + +``` +# kubectl -n kube-system describe secret px-etcd-certs +Name: px-etcd-certs +Namespace: kube-system +Labels: +Annotations: + +Type: Opaque + +Data +==== +etcd-ca.crt: 1679 bytes +etcd.crt: 1680 bytes +etcd.key: 414 bytes +``` +Once above secret is created, proceed to the next steps. diff --git a/charts/portworx/portworx/2.9.101/app-readme.md b/charts/portworx/portworx/2.9.101/app-readme.md new file mode 100644 index 000000000..ae8bbe96f --- /dev/null +++ b/charts/portworx/portworx/2.9.101/app-readme.md @@ -0,0 +1,8 @@ +# Portworx + +[Portworx](https://portworx.com/) is a software defined storage overlay that allows you to + + * Run containerized stateful applications that are highly-available (HA) across multiple nodes, cloud instances, regions, data centers or even clouds + * Migrate workflows between multiple clusters running across same or hybrid clouds + * Run hyperconverged workloads where the data resides on the same host as the applications + * Have programmatic control on your storage resources \ No newline at end of file diff --git a/charts/portworx/portworx/2.9.101/ci/test-values.yaml b/charts/portworx/portworx/2.9.101/ci/test-values.yaml new file mode 100644 index 000000000..879bf6910 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/ci/test-values.yaml @@ -0,0 +1 @@ +etcdType: Built-in \ No newline at end of file diff --git a/charts/portworx/portworx/2.9.101/questions.yml b/charts/portworx/portworx/2.9.101/questions.yml new file mode 100644 index 000000000..2de597bd3 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/questions.yml @@ -0,0 +1,915 @@ +categories: +- storage +namespace: kube-system +labels: + io.rancher.certified: partner +questions: + +################################### KVDB options ################################ +- variable: etcdType + label: "Select ETCD" + type: enum + required: true + group: "Key value store parameters (Required)" + options: + - "Provide your own etcd" + - "Built-in" + +# ------ "Provide your own etcd" ------ +- variable: ownEtcdOption + show_if: "etcdType=Provide your own etcd" + label: "Select one of 2 options for your ETCD cluster" + type: enum + required: true + group: "Key value store parameters (Required)" + options: + - "Your etcd details" + - "Portworx hosted (for PoCs only)" + +- variable: etcdAuth + show_if: "ownEtcdOption=Your etcd details&&etcdType=Provide your own etcd" + label: "Select an auth option for your ETCD cluster" + type: enum + default: "Disable HTTPS" + required: true + group: "Key value store parameters (Required)" + options: + - "Disable HTTPS" + - "Certificate Auth" + - "Password Auth" + +- variable: region + show_if: "ownEtcdOption=Portworx hosted (for PoCs only)" + label: "Select region" + type: enum + required: true + group: "Key value store parameters (Required)" + options: + - "US region" + - "EU region" + +# kvdb endpoint +- variable: kvdb + show_if: "ownEtcdOption=Your etcd details" + description: "Enter your etcd or Consul endpoints separated by semicolons. Use the following as an example: etcd://myetc1.company.com:2379;etcd://myetc2.company.com.2379. Note: If the `etcdAuth` key is set to 'Disable HTTPS', you must provide HTTP endpoints." + type: string + label: "Endpoint address" + required: true + group: "Key value store parameters (Required)" + +- variable: etcd.ca + show_if: "etcdAuth=Certificate Auth" + description: "Name of CA file for ETCD authentication. Example: etcd-ca.crt. Follow https://docs.portworx.com/scheduler/kubernetes/etcd-certs-using-secrets.html to create a Kubernetes secret for the etcd certs." + type: string + required: true + label: "ETCD CA file" + group: "Key value store security Parameters (Details in README)" + +- variable: etcd.cert + show_if: "etcdAuth=Certificate Auth" + description: "Name of certificate for ETCD authentication. Example: etcd.crt" + type: string + required: true + label: "ETCD cert file" + group: "Key value store security Parameters (Details in README)" + +- variable: etcd.key + show_if: "etcdAuth=Certificate Auth" + description: "Name of certificate key for ETCD authentication Example: etcd.key" + type: string + required: true + label: "ETCD cert key file" + group: "Key value store security Parameters (Details in README)" + +- variable: etcd.credentials + show_if: "etcdAuth=Password Auth" + description: "Username and password for ETCD authentication in the form user:password. Not needed if using certificates." + type: string + required: true + label: "ETCD credentials" + group: "Key value store security Parameters (Details in README)" + +################################### Storage options ################################ +- variable: environment + description: "Select your environment" + label: "Environment" + type: enum + default: "OnPrem" + required: true + group: "Storage Parameters" + options: + - "OnPrem" + - "Cloud" + +- variable: provider + show_if: "environment=Cloud" + description: "Select cloud platform" + label: "Cloud provider" + type: enum + required: true + group: "Storage Parameters" + options: + - "AWS" + - "Google cloud/GKE" + +- variable: onpremStorage + show_if: "environment=OnPrem" + type: enum + default: "Automatically scan disks" + label: "Select type of OnPrem storage" + group: "Storage Parameters" + required: true + options: + - "Automatically scan disks" + - "Manually specify disks" + +- variable: deviceConfig + show_if: "environment=Cloud" + description: "If you plan to use EC2 instance storage or plan to manage EBS volumes your own way, select 'Consume unused' or 'Use Existing disks'." + label: "Select a type of disk" + type: enum + default: "Create Using a Spec" + required: true + group: "Storage Parameters" + options: + - "Create Using a Spec" + - "Consume Unused" + - "Use Existing Disks" + - +- variable: journalDevice + description: "This allows PX to create it’s own journal partition on the best drive to absorb PX metadata writes. Journal writes are small with frequent syncs and hence a separate journal partition will enable better performance. Use value 'auto' if you want Portworx to create it's own journal partition." + type: string + label: "Journal Device" + group: "Storage Parameters" + +############ Consume unused ############## +- variable: usedrivesAndPartitions + show_if: "deviceConfig=Consume Unused||onpremStorage=Automatically scan disks" + label: "Use unmounted drives and partitions" + descrition: "Use unmounted disks even if they have a partition or filesystem on it. PX will never use a drive or partition that is mounted." + type: boolean + default: false + group: "Storage Parameters" + + +############ Use Exising Disks ############## +- variable: existingDisk1 + show_if: "deviceConfig=Use Existing Disks||onpremStorage=Manually specify disks" + label: "Drive/Device1" + description: "Enter the block/device name; eg: /dev/sda" + type: string + required: true + group: "Storage Parameters" + +- variable: addExistingDisk2 + show_if: "deviceConfig=Use Existing Disks||onpremStorage=Manually specify disks" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: existingDisk2 + show_if: "addExistingDisk2=true" + label: "Drive/Device2" + description: "Enter the block/device name; eg: /dev/sda" + type: string + required: true + group: "Storage Parameters" + +- variable: addExistingDisk3 + show_if: "addExistingDisk2=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: existingDisk3 + show_if: "addExistingDisk3=true" + label: "Drive/Device3" + description: "Enter the block/device name; eg: /dev/sda" + type: string + required: true + group: "Storage Parameters" + +- variable: addExistingDisk4 + show_if: "addExistingDisk3=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: existingDisk4 + show_if: "addExistingDisk4=true" + label: "Drive/Device4" + description: "Enter the block/device name; eg: /dev/sda" + type: string + required: true + group: "Storage Parameters" + +- variable: addExistingDisk5 + show_if: "addExistingDisk4=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: existingDisk5 + show_if: "addExistingDisk5=true" + label: "Drive/Device5" + description: "Enter the block/device name; eg: /dev/sda" + type: string + required: true + group: "Storage Parameters" + +##################################################### Cloud ################################ + +##################################################### AWS ################################ + +### Section 1 AWS +- variable: drive_1.aws.type + show_if: "provider=AWS&&deviceConfig=Create Using a Spec" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + default: "GP2" + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_1.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_1.aws.size + show_if: "provider=AWS&&deviceConfig=Create Using a Spec" + description: "Volume size" + label: "Size" + type: int + default: 150 + required: true + group: "Storage Parameters" + +### Section 2 AWS +- variable: addEBSDrive_2 + show_if: "provider=AWS&&deviceConfig=Create Using a Spec" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_2.aws.type + show_if: "addEBSDrive_2=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_2.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_2.aws.size + show_if: "addEBSDrive_2=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + + ### Section 3 AWS +- variable: addEBSDrive_3 + show_if: "addEBSDrive_2=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_3.aws.type + show_if: "addEBSDrive_3=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_3.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_3.aws.size + show_if: "addEBSDrive_3=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +### Section 4 AWS +- variable: addEBSDrive_4 + show_if: "addEBSDrive_3=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_4.aws.type + show_if: "addEBSDrive_4=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_4.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_4.aws.size + show_if: "addEBSDrive_4=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +### Section 5 AWS +- variable: addEBSDrive_5 + show_if: "addEBSDrive_4=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_5.aws.type + show_if: "addEBSDrive_5=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_5.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_5.aws.size + show_if: "addEBSDrive_5=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +### Section 6 AWS +- variable: addEBSDrive_6 + show_if: "addEBSDrive_5=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_6.aws.type + show_if: "addEBSDrive_6=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_6.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_6.aws.size + show_if: "addEBSDrive_6=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +### Section 7 AWS +- variable: addEBSDrive_7 + show_if: "addEBSDrive_6=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_7.aws.type + show_if: "addEBSDrive_7=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_7.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_7.aws.size + show_if: "addEBSDrive_7=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +### Section 8 AWS +- variable: addEBSDrive_8 + show_if: "addEBSDrive_7=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_8.aws.type + show_if: "addEBSDrive_8=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_8.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_8.aws.size + show_if: "addEBSDrive_8=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +### Section 9 AWS +- variable: addEBSDrive_9 + show_if: "addEBSDrive_8=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_9.aws.type + show_if: "addEBSDrive_9=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_9.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_9.aws.size + show_if: "addEBSDrive_9=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +### Section 10 AWS +- variable: addEBSDrive_10 + show_if: "addEBSDrive_9=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_10.aws.type + show_if: "addEBSDrive_10=true" + description: "Select the type of EBS volume" + label: "EBS volume" + type: enum + required: true + show_subquestion_if: "IO1" + group: "Storage Parameters" + options: + - "GP2" + - "IO1" + subquestions: + - variable: drive_10.aws.iops + required: true + description: "*IOPS required from EBS volume" + type: int + label: IOPS + +- variable: drive_10.aws.size + show_if: "addEBSDrive_10=true" + description: "Volume size" + label: "Size" + required: true + type: int + group: "Storage Parameters" + +##################################################### GOOGLE CLOUD ################################ + +#### Section 1 GC +- variable: drive_1.gc.type + show_if: "provider=Google cloud/GKE&&deviceConfig=Create Using a Spec" + description: "Select volume type" + label: "Volume" + type: enum + default: "standard" + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_1.gc.size + show_if: "provider=Google cloud/GKE&&deviceConfig=Create Using a Spec" + description: "Volume size" + label: "Size" + type: int + default: 150 + required: true + group: "Storage Parameters" + +#### Section 2 GC +- variable: addGCDrive_2 + show_if: "provider=Google cloud/GKE&&deviceConfig=Create Using a Spec" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_2.gc.type + show_if: "addGCDrive_2=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_2.gc.size + show_if: "addGCDrive_2=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 3 GC +- variable: addGCDrive_3 + show_if: "addGCDrive_2=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_3.gc.type + show_if: "addGCDrive_3=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_3.gc.size + show_if: "addGCDrive_3=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 4 GC +- variable: addGCDrive_4 + show_if: "addGCDrive_3=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_4.gc.type + show_if: "addGCDrive_4=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_4.gc.size + show_if: "addGCDrive_4=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 5 GC +- variable: addGCDrive_5 + show_if: "addGCDrive_4=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_5.gc.type + show_if: "addGCDrive_5=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_5.gc.size + show_if: "addGCDrive_5=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 6 GC +- variable: addGCDrive_6 + show_if: "addGCDrive_5=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_6.gc.type + show_if: "addGCDrive_6=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_6.gc.size + show_if: "addGCDrive_6=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 7 GC +- variable: addGCDrive_7 + show_if: "addGCDrive_6=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_7.gc.type + show_if: "addGCDrive_6=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_7.gc.size + show_if: "addGCDrive_7=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 8 GC +- variable: addGCDrive_8 + show_if: "addGCDrive_7=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_8.gc.type + show_if: "addGCDrive_8=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_8.gc.size + show_if: "addGCDrive_8=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 9 GC +- variable: addGCDrive_9 + show_if: "addGCDrive_8=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_9.gc.type + show_if: "addGCDrive_9=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_9.gc.size + show_if: "addGCDrive_9=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +#### Section 10 GC +- variable: addGCDrive_10 + show_if: "addGCDrive_9=true" + label: "Add another drive?" + type: boolean + default: false + group: "Storage Parameters" + +- variable: drive_10.gc.type + show_if: "addGCDrive_10=true" + description: "Select volume type" + label: "Volume" + type: enum + required: true + group: "Storage Parameters" + options: + - "standard" + - "ssd" + +- variable: drive_10.gc.size + show_if: "addGCDrive_10=true" + description: "Volume size" + label: "Size" + type: int + required: true + group: "Storage Parameters" + +- variable: maxStorageNodes + show_if: "environment=Cloud&&deviceConfig=Create Using a Spec" + description: "Max storage nodes per availability zone" + label: "Max storage nodes (Optional)" + type: int + group: "Storage Parameters" + +################################### Network options ################################ +- variable: dataInterface + description: "Specify your data network interface (example: `eth1`). If set to `auto`, Portworx will automatically select the first routable interface." + type: string + label: "Data Network Interface" + default: auto + group: "Network Parameters" +- variable: managementInterface + description: "Specify your management network interface (example: `eth1`). If set to `auto`, Portworx will automatically select the first routable interface." + type: string + default: auto + label: "Management Network Interface" + group: "Network Parameters" + +################################### Platform options ################################ +- variable: platformOptions + type: enum + label: "Platform" + group: "Platform Parameters" + options: + - "AKS" + - "EKS" + - "GKE" + +################################### Registry settings options ################################ +- variable: customRegistry + label: "Use a custom container registry?" + type: boolean + default: false + group: "Container Registry Parameters" + +- variable: registrySecret + show_if: "customRegistry=true" + description: "Specify a custom Kubernetes secret that will be used to authenticate with a container registry. Must be defined in kube-system namespace. (example: regcred)" + type: string + label: "Registry Kubernetes Secret" + group: "Container Registry Parameters" +- variable: customRegistryURL + show_if: "customRegistry=true" + description: "Specify a custom container registry server (including repository) that will be used instead of index.docker.io to download Docker images. (example: dockerhub.acme.net:5443 or myregistry.com/myrepository/)" + label: "Custom Registry URL" + type: string + group: "Container Registry Parameters" + + + +################################## Optional features ############################ +# TODO: Once we have a stable CSI release, we will default this to enabled +#- variable: csi +# description: "Select if you want to enable CSI (Container Storage Interface). CSI is still in ALPHA." +# type: boolean +# label: "Enable CSI" +# default: false +# required: false +# group: "Advanced parameters" + +- variable: storkVersion + default: "2.6.3" + label: "Stork version" + type: string + group: "Advanced parameters" + +- variable: envVars + label: "Environment variables" + description: "Enter your environment variables separated by semicolons (example: API_SERVER=http://lighthouse-new.portworx.com;MYENV1=val1;MYENV2=val2). These environment variables will be exported to Portworx." + type: string + group: "Advanced parameters" + +- variable: imageVersion + default: "2.9.1.4" + type: string + label: Portworx version to be deployed. + group: "Advanced parameters" + +- variable: clusterName + type: string + label: Portworx cluster name + default: mycluster + group: "Advanced parameters" diff --git a/charts/portworx/portworx/2.9.101/templates/NOTES.txt b/charts/portworx/portworx/2.9.101/templates/NOTES.txt new file mode 100644 index 000000000..ea0bb6326 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/NOTES.txt @@ -0,0 +1,13 @@ +Your Release is named {{ .Release.Name | quote }} + +Portworx Pods should be running on each node in your cluster. + +Portworx would create a unified pool of the disks attached to your Kubernetes nodes. No further action should be required and you are ready to consume Portworx Volumes as part of your application data requirements. + +For further information on usage of the Portworx, refer to following doc pages. + +- For dynamically provisioning volumes: https://docs.portworx.com/scheduler/kubernetes/dynamic-provisioning.html +- For preprovisioned volumes: https://docs.portworx.com/scheduler/kubernetes/preprovisioned-volumes.html +- To use Stork (Storage Orchestration Runtime for Kubernetes) for hyperconvergence and snapshots: https://docs.portworx.com/scheduler/kubernetes/stork.html +- For stateful application solutions using Portworx: https://docs.portworx.com/scheduler/kubernetes/k8s-px-app-samples.html +- For interactive tutorials on using Portworx on Kubernetes: https://docs.portworx.com/scheduler/kubernetes/px-k8s-interactive.html diff --git a/charts/portworx/portworx/2.9.101/templates/_helpers.tpl b/charts/portworx/portworx/2.9.101/templates/_helpers.tpl new file mode 100644 index 000000000..892bc3257 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/_helpers.tpl @@ -0,0 +1,443 @@ +{{/* Gets the correct API Version based on the version of the cluster +*/}} + +{{- define "rbac.apiVersion" -}} +{{- if semverCompare ">= 1.8-0" .Capabilities.KubeVersion.GitVersion -}} +"rbac.authorization.k8s.io/v1" +{{- else -}} +"rbac.authorization.k8s.io/v1beta1" +{{- end -}} +{{- end -}} + + +{{- define "px.labels" -}} +chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" +heritage: {{ .Release.Service | quote }} +release: {{ .Release.Name | quote }} +{{- end -}} + +{{- define "driveOpts" }} +{{ $v := .Values.installOptions.drives | split "," }} +{{$v._0}} +{{- end -}} + +{{- define "px.kubernetesVersion" -}} +{{$version := .Capabilities.KubeVersion.GitVersion | regexFind "^v\\d+\\.\\d+\\.\\d+"}}{{$version}} +{{- end -}} + + +{{- define "px.getImage" -}} +{{- if (.Values.customRegistryURL) -}} + {{- if (eq "/" (.Values.customRegistryURL | regexFind "/")) -}} + {{- if .Values.openshiftInstall -}} + {{ cat (trim .Values.customRegistryURL) "/px-monitor" | replace " " ""}} + {{- else -}} + {{ cat (trim .Values.customRegistryURL) "/oci-monitor" | replace " " ""}} + {{- end -}} + {{- else -}} + {{- if .Values.openshiftInstall -}} + {{cat (trim .Values.customRegistryURL) "/portworx/px-monitor" | replace " " ""}} + {{- else -}} + {{cat (trim .Values.customRegistryURL) "/portworx/oci-monitor" | replace " " ""}} + {{- end -}} + {{- end -}} +{{- else -}} + {{- if .Values.openshiftInstall -}} + {{ "registry.connect.redhat.com/portworx/px-monitor" }} + {{- else -}} + {{ "portworx/oci-monitor" }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{- define "px.getStorkImage" -}} +{{- if (.Values.customRegistryURL) -}} + {{- if (eq "/" (.Values.customRegistryURL | regexFind "/")) -}} + {{ cat (trim .Values.customRegistryURL) "/stork" | replace " " ""}} + {{- else -}} + {{cat (trim .Values.customRegistryURL) "/openstorage/stork" | replace " " ""}} + {{- end -}} +{{- else -}} + {{ "openstorage/stork" }} +{{- end -}} +{{- end -}} + +{{- define "px.getk8sImages" -}} +{{- $version := .Capabilities.KubeVersion.GitVersion -}} +{{- if (.Values.customRegistryURL) -}} + {{- if (eq "/" (.Values.customRegistryURL | regexFind "/")) -}} + {{ trim .Values.customRegistryURL }} + {{- else -}} + {{- if or (or (and (semverCompare ">= 1.16.14-0" $version ) (semverCompare "<=1.17.0-0" $version)) (and (semverCompare ">= 1.17.10" $version) (semverCompare "<=1.18.0-0" $version ))) (semverCompare ">=1.18.7-0" $version) -}} + {{cat (trim .Values.customRegistryURL) "/k8s.gcr.io" | replace " " ""}} + {{- else -}} + {{cat (trim .Values.customRegistryURL) "/gcr.io/google_containers" | replace " " ""}} + {{- end -}} + {{- end -}} +{{- else -}} + {{- if or (or (and (semverCompare ">= 1.16.14-0" $version ) (semverCompare "<=1.17.0-0" $version)) (and (semverCompare ">= 1.17.10-0" $version) (semverCompare "<=1.18.0-0" $version ))) (semverCompare ">=1.18.7-0" $version) -}} + {{ "k8s.gcr.io" }} + {{- else -}} + {{ "gcr.io/google_containers" }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{- define "px.getcsiImages" -}} +{{- if (.Values.customRegistryURL) -}} + {{- if (eq "/" (.Values.customRegistryURL | regexFind "/")) -}} + {{ trim .Values.customRegistryURL }} + {{- else -}} + {{cat (trim .Values.customRegistryURL) "/quay.io/k8scsi" | replace " " ""}} + {{- end -}} +{{- else -}} + {{ "quay.io/k8scsi" }} +{{- end -}} +{{- end -}} + + +{{- define "px.getCSIProvisionerImage" -}} +{{- if semverCompare "<1.17.0-0" .Capabilities.KubeVersion.GitVersion -}} + {{ "docker.io/openstorage/csi-provisioner:v1.6.1-1" }} +{{- else if semverCompare "< 1.20.0-0" .Capabilities.KubeVersion.GitVersion -}} + {{ "docker.io/openstorage/csi-provisioner:v2.2.2-1" }} +{{- else -}} + {{ "docker.io/openstorage/csi-provisioner:v3.0.0-1" }} +{{- end -}} +{{- end -}} + +{{- define "px.getCSISnapshotterImage" -}} +{{- if semverCompare "<1.17.0-0" .Capabilities.KubeVersion.GitVersion -}} + {{ "docker.io/openstorage/csi-snapshotter:v1.2.2-1" }} +{{- else if semverCompare "< 1.20.0-0" .Capabilities.KubeVersion.GitVersion -}} + {{ "k8s.gcr.io/sig-storage/csi-snapshotter:v3.0.3" }} +{{- else -}} + {{ "k8s.gcr.io/sig-storage/csi-snapshotter:v4.2.1" }} +{{- end -}} +{{- end -}} + +{{- define "px.getCSISnapshotControllerImage" -}} +{{- if semverCompare "< 1.20.0-0" .Capabilities.KubeVersion.GitVersion -}} + {{ "k8s.gcr.io/sig-storage/snapshot-controller:v3.0.3" }} +{{- else -}} + {{ "k8s.gcr.io/sig-storage/snapshot-controller:v4.2.1" }} +{{- end -}} +{{- end -}} + +{{- define "px.getPauseImage" -}} +{{- if (.Values.customRegistryURL) -}} + {{- if (eq "/" (.Values.customRegistryURL | regexFind "/")) -}} + {{ trim .Values.customRegistryURL }} + {{- else -}} + {{cat (trim .Values.customRegistryURL) "/k8s.gcr.io" | replace " " ""}} + {{- end -}} +{{- else -}} + {{ "k8s.gcr.io" }} +{{- end -}} +{{- end -}} + +{{- define "px.registryConfigType" -}} +{{- if semverCompare ">=1.9-0" .Capabilities.KubeVersion.GitVersion -}} +".dockerconfigjson" +{{- else -}} +".dockercfg" +{{- end -}} +{{- end -}} + +{{/* +Create the name of the service account to use for hooks +*/}} +{{- define "px.hookServiceAccount" -}} +{{- if .Values.serviceAccount.hook.create -}} + {{- printf "%s-hook" .Chart.Name | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{ default "default" .Values.serviceAccount.hook.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the cluster role to use for hooks +*/}} +{{- define "px.hookClusterRole" -}} +{{- if .Values.serviceAccount.hook.create -}} + {{- printf "%s-hook" .Chart.Name | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{ default "default" .Values.serviceAccount.hook.name }} +{{- end -}} +{{- end -}} + +{{/* +Create the name of the cluster role binding to use for hooks +*/}} +{{- define "px.hookClusterRoleBinding" -}} +{{- if .Values.serviceAccount.hook.create -}} + {{- printf "%s-hook" .Chart.Name | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{ default "default" .Values.serviceAccount.hook.name }} +{{- end -}} +{{- end -}} + +{{/* + String concatenation for drives in AWS section +*/}} +{{- define "px.storage" -}} +{{- $awsType1 := .Values.drive_1.aws.type -}} +{{- $awsType2 := .Values.drive_2.aws.type -}} +{{- $awsType3 := .Values.drive_3.aws.type -}} +{{- $awsType4 := .Values.drive_4.aws.type -}} +{{- $awsType5 := .Values.drive_5.aws.type -}} +{{- $awsType6 := .Values.drive_6.aws.type -}} +{{- $awsType7 := .Values.drive_7.aws.type -}} +{{- $awsType8 := .Values.drive_8.aws.type -}} +{{- $awsType9 := .Values.drive_9.aws.type -}} +{{- $awsType10 := .Values.drive_10.aws.type -}} + +{{- $awsSize1 := .Values.drive_1.aws.size -}} +{{- $awsSize2 := .Values.drive_2.aws.size -}} +{{- $awsSize3 := .Values.drive_3.aws.size -}} +{{- $awsSize4 := .Values.drive_4.aws.size -}} +{{- $awsSize5 := .Values.drive_5.aws.size -}} +{{- $awsSize6 := .Values.drive_6.aws.size -}} +{{- $awsSize7 := .Values.drive_7.aws.size -}} +{{- $awsSize8 := .Values.drive_8.aws.size -}} +{{- $awsSize9 := .Values.drive_9.aws.size -}} +{{- $awsSize10 := .Values.drive_10.aws.size -}} + +{{- $awsIops1 := .Values.drive_1.aws.iops -}} +{{- $awsIops2 := .Values.drive_2.aws.iops -}} +{{- $awsIops3 := .Values.drive_3.aws.iops -}} +{{- $awsIops4 := .Values.drive_4.aws.iops -}} +{{- $awsIops5 := .Values.drive_5.aws.iops -}} +{{- $awsIops6 := .Values.drive_6.aws.iops -}} +{{- $awsIops7 := .Values.drive_7.aws.iops -}} +{{- $awsIops8 := .Values.drive_8.aws.iops -}} +{{- $awsIops9 := .Values.drive_9.aws.iops -}} +{{- $awsIops10 := .Values.drive_10.aws.iops -}} + +{{- $gcType1 := .Values.drive_1.gc.type -}} +{{- $gcType2 := .Values.drive_2.gc.type -}} +{{- $gcType3 := .Values.drive_3.gc.type -}} +{{- $gcType4 := .Values.drive_4.gc.type -}} +{{- $gcType5 := .Values.drive_5.gc.type -}} +{{- $gcType6 := .Values.drive_6.gc.type -}} +{{- $gcType7 := .Values.drive_7.gc.type -}} +{{- $gcType8 := .Values.drive_8.gc.type -}} +{{- $gcType9 := .Values.drive_9.gc.type -}} +{{- $gcType10 := .Values.drive_10.gc.type -}} + +{{- $gcSize1 := .Values.drive_1.gc.size -}} +{{- $gcSize2 := .Values.drive_2.gc.size -}} +{{- $gcSize3 := .Values.drive_3.gc.size -}} +{{- $gcSize4 := .Values.drive_4.gc.size -}} +{{- $gcSize5 := .Values.drive_5.gc.size -}} +{{- $gcSize6 := .Values.drive_6.gc.size -}} +{{- $gcSize7 := .Values.drive_7.gc.size -}} +{{- $gcSize8 := .Values.drive_8.gc.size -}} +{{- $gcSize9 := .Values.drive_9.gc.size -}} +{{- $gcSize10 := .Values.drive_10.gc.size -}} + +{{- $usefileSystemDrive := .Values.usefileSystemDrive | default false }} +{{- $usedrivesAndPartitions := .Values.usedrivesAndPartitions | default false }} +{{- $deployEnvironmentIKS := .Capabilities.KubeVersion.GitVersion | regexMatch "IKS" }} + +{{- if eq "OnPrem" .Values.environment -}} + {{- if eq "Manually specify disks" .Values.onpremStorage }} + {{- if ne "none" .Values.existingDisk1 }} + "-s", "{{- .Values.existingDisk1 }}", + {{- end }} + {{- if ne "none" .Values.existingDisk2 -}} + "-s", "{{- .Values.existingDisk2 }}", + {{- end }} + {{- if ne "none" .Values.existingDisk3 -}} + "-s", "{{- .Values.existingDisk3 }}", + {{- end }} + {{- if ne "none" .Values.existingDisk4 -}} + "-s", "{{- .Values.existingDisk4 }}", + {{- end }} + {{- if ne "none" .Values.existingDisk5 }} + "-s", "{{- .Values.existingDisk5 }}", + {{- end }} + {{- else if eq "Automatically scan disks" .Values.onpremStorage -}} + {{- if or $usedrivesAndPartitions $deployEnvironmentIKS }} + "-f", + {{- end }} + {{- if eq $usedrivesAndPartitions true }} + "-A", + {{- else }} + "-a", + {{- end -}} + {{- end -}} + +{{- else if eq "Cloud" .Values.environment -}} + {{- if eq "Consume Unused" .Values.deviceConfig -}} + {{- if or $usedrivesAndPartitions $deployEnvironmentIKS }} + "-f", + {{- end }} + {{- if eq $usedrivesAndPartitions true }} + "-A", + {{- else }} + "-a", + {{- end -}} + {{- end }} +{{/*------------------- ----------------- Google cloud/GKE -------------- --------------- */}} + {{- if eq "Google cloud/GKE" .Values.provider -}} + {{- if eq "Use Existing Disks" .Values.deviceConfig -}} + {{- if .Values.existingDisk1 -}} + "-s", "{{- .Values.existingDisk1 -}}", + {{- end -}} + {{- if ne "none" .Values.existingDisk2 -}} + "-s", "{{- .Values.existingDisk2 -}}", + {{- end -}} + {{- if ne "none" .Values.existingDisk3 -}} + "-s", "{{- .Values.existingDisk3 -}}", + {{- end -}} + {{- if ne "none" .Values.existingDisk4 -}} + "-s", "{{- .Values.existingDisk4 -}}", + {{- end -}} + {{- if ne "none" .Values.existingDisk5 -}} + "-s", "{{- .Values.existingDisk5 -}}", + {{- end -}} + {{- else if eq "Create Using a Spec" .Values.deviceConfig -}} + {{- if $gcType1 }} + "-s", "type=pd-{{$gcType1 | lower}},size={{$gcSize1}}", + {{- end }} + {{/*------------------- DRIVE 2 --------------- */}} + {{- if $gcType2 -}} + "-s", "type=pd-{{$gcType2 | lower}},size={{$gcSize2}}", + {{- end }} + {{/*------------------- DRIVE 3 --------------- */}} + {{- if $gcType3 -}} + "-s", "type=pd-{{$gcType3 | lower}},size={{$gcSize3}}", + {{- end }} + {{/*------------------- DRIVE 4 --------------- */}} + {{- if $gcType4 -}} + "-s", "type=pd-{{$gcType4 | lower}},size={{$gcSize4}}", + {{- end }} + {{/*------------------- DRIVE 5 --------------- */}} + {{- if $gcType5 -}} + "-s", "type=pd-{{$gcType5 | lower}},size={{$gcSize5}}", + {{- end }} + {{/*------------------- DRIVE 6 --------------- */}} + {{- if $gcType6 -}} + "-s", "type=pd-{{$gcType6 | lower}},size={{$gcSize6}}", + {{- end }} + {{/*------------------- DRIVE 7 --------------- */}} + {{- if $gcType7 -}} + "-s", "type=pd-{{$gcType7 | lower}},size={{$gcSize7}}", + {{- end }} + {{/*------------------- DRIVE 8 --------------- */}} + {{- if $gcType8 -}} + "-s", "type=pd-{{$gcType8 | lower}},size={{$gcSize8}}", + {{- end }} + {{/*------------------- DRIVE 9 --------------- */}} + {{- if $gcType9 -}} + "-s", "type=pd-{{$gcType9 | lower}},size={{$gcSize9}}", + {{- end }} + {{/*------------------- DRIVE 10 --------------- */}} + {{- if $gcType10 -}} + "-s", "type=pd-{{$gcType1 | lower}},size={{$gcSize10}}", + {{- end }} + {{- end -}} +{{/*------------------- ----------------- AWS -------------- --------------- */}} + {{- else if eq "AWS" .Values.provider -}} + {{- if eq "Use Existing Disks" .Values.deviceConfig -}} + {{- if ne "none" .Values.existingDisk1 -}} + "-s", "{{ .Values.existingDisk1 }}", + {{- end -}} + {{- if ne "none" .Values.existingDisk2 -}} + "-s", "{{ .Values.existingDisk2 }}", + {{- end -}} + {{- if ne "none" .Values.existingDisk3 -}} + "-s", "{{ .Values.existingDisk3 }}", + {{- end -}} + {{- if ne "none" .Values.existingDisk4 -}} + "-s", "{{ .Values.existingDisk4 }}", + {{- end -}} + {{- if ne "none" .Values.existingDisk5 -}} + "-s", "{{ .Values.existingDisk5 }}", + {{- end -}} + {{- else if eq "Create Using a Spec" .Values.deviceConfig -}} + {{- if ne "none" $awsType1 }} + {{- if eq "GP2" $awsType1 -}} + "-s", "type={{$awsType1 | lower}},size={{$awsSize1}}", + {{- else if eq "IO1" $awsType1 -}} + "-s", "type={{$awsType1 | lower}},size={{$awsSize1}},iops={{$awsIops1}}", + {{- end }} + {{- end }} + {{/*------------------- DRIVE 2 --------------- */}} + {{- if ne "none" $awsType2 -}} + {{- if eq "GP2" $awsType2 -}} + "-s", "type={{$awsType2 | lower}},size={{$awsSize2}}", + {{- else if eq "IO1" $awsType2 -}} + "-s", "type={{$awsType2 | lower}},size={{$awsSize2}},iops={{$awsIops2}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 3 --------------- */}} + {{- if ne "none" $awsType3 }} + {{- if eq "GP2" $awsType3 -}} + "-s", "type={{$awsType3 | lower}},size={{$awsSize3}}", + {{- else if eq "IO1" $awsType3 -}} + "-s", "type={{$awsType3 | lower}},size={{$awsSize3}},iops={{$awsIops3}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 4 --------------- */}} + {{- if ne "none" $awsType4 }} + {{- if eq "GP2" $awsType4 -}} + "-s", "type={{$awsType4 | lower}},size={{$awsSize4}}", + {{- else if eq "IO1" $awsType4 -}} + "-s", "type={{$awsType4 | lower}},size={{$awsSize4}},iops={{$awsIops4}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 5 --------------- */}} + {{- if ne "none" $awsType5 }} + {{- if eq "GP2" $awsType5 -}} + "-s", "type={{$awsType5 | lower}},size={{$awsSize5}}", + {{- else if eq "IO1" $awsType5 -}} + "-s", "type={{$awsType5 | lower}},size={{$awsSize5}},iops={{$awsIops5}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 6 --------------- */}} + {{- if ne "none" $awsType6 }} + {{- if eq "GP2" $awsType6 -}} + "-s", "type={{$awsType6 | lower}},size={{$awsSize6}}", + {{- else if eq "IO1" $awsType6 -}} + "-s", "type={{$awsType6 | lower}},size={{$awsSize6}},iops={{$awsIops6}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 7 --------------- */}} + {{- if ne "none" $awsType7 }} + {{- if eq "GP2" $awsType7 -}} + "-s", "type={{$awsType7 | lower}},size={{$awsSize7}}", + {{- else if eq "IO1" $awsType7 -}} + "-s", "type={{$awsType7 | lower}},size={{$awsSize7}},iops={{$awsIops7}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 8 --------------- */}} + {{- if ne "none" $awsType8 }} + {{- if eq "GP2" $awsType8 -}} + "-s", "type={{$awsType8 | lower}},size={{$awsSize8}}", + {{- else if eq "IO1" $awsType8 -}} + "-s", "type={{$awsType8 | lower}},size={{$awsSize8}},iops={{$awsIops8}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 9 --------------- */}} + {{- if ne "none" $awsType9 }} + {{- if eq "GP2" $awsType9 -}} + "-s", "type={{$awsType9 | lower}},size={{$awsSize9}}", + {{- else if eq "IO1" $awsType9 -}} + "-s", "type={{$awsType9 | lower}},size={{$awsSize9}},iops={{$awsIops9}}", + {{- end -}} + {{- end }} + {{/*------------------- DRIVE 10 --------------- */}} + {{- if ne "none" $awsType10 }} + {{- if eq "GP2" $awsType10 -}} + "-s", "type={{$awsType10 | lower}},size={{$awsSize10}}", + {{- else if eq "IO1" $awsType10 -}} + "-s", "type={{$awsType10 | lower}},size={{$awsSize10}},iops={{$awsIops10}}", + {{- end -}} + {{- end }} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end }} + diff --git a/charts/portworx/portworx/2.9.101/templates/hooks/post-delete/px-postdelete-unlabelnode.yaml b/charts/portworx/portworx/2.9.101/templates/hooks/post-delete/px-postdelete-unlabelnode.yaml new file mode 100644 index 000000000..8c8efda02 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/hooks/post-delete/px-postdelete-unlabelnode.yaml @@ -0,0 +1,40 @@ +{{- $customRegistryURL := .Values.customRegistryURL | default "none" }} +{{- $registrySecret := .Values.registrySecret | default "none" }} + +apiVersion: batch/v1 +kind: Job +metadata: + namespace: kube-system + name: px-hook-postdelete-unlabelnode + labels: + heritage: {{.Release.Service | quote }} + release: {{.Release.Name | quote }} + chart: "{{.Chart.Name}}-{{.Chart.Version}}" + app.kubernetes.io/managed-by: {{.Release.Service | quote }} + app.kubernetes.io/instance: {{.Release.Name | quote }} + annotations: + "helm.sh/hook": post-delete + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation +spec: +{{ if semverCompare ">= 1.8-0" .Capabilities.KubeVersion.GitVersion }} + backoffLimit: 0 +{{ else }} + activeDeadlineSeconds: 30 +{{ end }} + template: + spec: + {{- if not (eq $registrySecret "none") }} + imagePullSecrets: + - name: {{ $registrySecret }} + {{- end }} + restartPolicy: Never + serviceAccountName: {{ template "px.hookServiceAccount" . }} + containers: + - name: post-delete-job + {{- if eq $customRegistryURL "none" }} + image: "lachlanevenson/k8s-kubectl:{{ template "px.kubernetesVersion" . }}" + {{- else}} + image: "{{ $customRegistryURL }}/lachlanevenson/k8s-kubectl:{{ template "px.kubernetesVersion" . }}" + {{- end}} + args: ['label','nodes','--all','px/enabled-'] diff --git a/charts/portworx/portworx/2.9.101/templates/hooks/pre-delete/px-predelete-nodelabel.yaml b/charts/portworx/portworx/2.9.101/templates/hooks/pre-delete/px-predelete-nodelabel.yaml new file mode 100644 index 000000000..1942bade7 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/hooks/pre-delete/px-predelete-nodelabel.yaml @@ -0,0 +1,40 @@ +{{- $customRegistryURL := .Values.customRegistryURL | default "none" }} +{{- $registrySecret := .Values.registrySecret | default "none" }} + +apiVersion: batch/v1 +kind: Job +metadata: + namespace: kube-system + name: px-hook-predelete-nodelabel + labels: + heritage: {{.Release.Service | quote }} + release: {{.Release.Name | quote }} + chart: "{{.Chart.Name}}-{{.Chart.Version}}" + app.kubernetes.io/managed-by: {{.Release.Service | quote }} + app.kubernetes.io/instance: {{.Release.Name | quote }} + annotations: + "helm.sh/hook": pre-delete + "helm.sh/hook-weight": "-5" + "helm.sh/hook-delete-policy": before-hook-creation +spec: +{{ if semverCompare ">= 1.8-0" .Capabilities.KubeVersion.GitVersion }} + backoffLimit: 0 +{{ else }} + activeDeadlineSeconds: 30 +{{ end }} + template: + spec: + {{- if not (eq $registrySecret "none") }} + imagePullSecrets: + - name: {{ $registrySecret }} + {{- end }} + serviceAccountName: {{ template "px.hookServiceAccount" . }} + restartPolicy: Never + containers: + - name: pre-delete-job + {{- if eq $customRegistryURL "none" }} + image: "lachlanevenson/k8s-kubectl:{{ template "px.kubernetesVersion" . }}" + {{- else}} + image: "{{ $customRegistryURL }}/lachlanevenson/k8s-kubectl:{{ template "px.kubernetesVersion" . }}" + {{- end}} + args: ['label','nodes','--all','px/enabled=remove','--overwrite'] diff --git a/charts/portworx/portworx/2.9.101/templates/portworx-controller.yaml b/charts/portworx/portworx/2.9.101/templates/portworx-controller.yaml new file mode 100644 index 000000000..15301f579 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/portworx-controller.yaml @@ -0,0 +1,128 @@ +{{- if or (and (.Values.openshiftInstall) (eq .Values.openshiftInstall true)) (and (.Values.AKSorEKSInstall) (eq .Values.AKSorEKSInstall true)) ((.Capabilities.KubeVersion.GitVersion | regexMatch "gke")) }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: portworx-pvc-controller-account + namespace: kube-system +--- +kind: ClusterRole +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: portworx-pvc-controller-role +rules: +- apiGroups: [""] + resources: ["persistentvolumes"] + verbs: ["create","delete","get","list","update","watch"] +- apiGroups: [""] + resources: ["persistentvolumes/status"] + verbs: ["update"] +- apiGroups: [""] + resources: ["persistentvolumeclaims"] + verbs: ["get", "list", "update", "watch"] +- apiGroups: [""] + resources: ["persistentvolumeclaims/status"] + verbs: ["update"] +- apiGroups: [""] + resources: ["pods"] + verbs: ["create", "delete", "get", "list", "watch"] +- apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["endpoints", "services"] + verbs: ["create", "delete", "get", "update"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["events"] + verbs: ["watch"] +- apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch", "update"] +- apiGroups: [""] + resources: ["serviceaccounts"] + verbs: ["get", "create"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "create", "update"] +--- +kind: ClusterRoleBinding +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: portworx-pvc-controller-role-binding +subjects: +- kind: ServiceAccount + name: portworx-pvc-controller-account + namespace: kube-system +roleRef: + kind: ClusterRole + name: portworx-pvc-controller-role + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" + labels: + tier: control-plane + name: portworx-pvc-controller + namespace: kube-system +spec: + replicas: 3 + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" + labels: + name: portworx-pvc-controller + tier: control-plane + spec: + {{- if not (empty .Values.registrySecret) }} + imagePullSecrets: + - name: {{ .Values.registrySecret }} + {{- end }} + containers: + - command: + - kube-controller-manager + - --leader-elect=true + - --address=0.0.0.0 + - --controllers=persistentvolume-binder,persistentvolume-expander + - --use-service-account-credentials=true + - --leader-elect-resource-lock=configmaps + image: "{{ template "px.getk8sImages" . }}/kube-controller-manager-amd64:{{ template "px.kubernetesVersion" . }}" + livenessProbe: + failureThreshold: 8 + httpGet: + host: 127.0.0.1 + path: /healthz + port: 10252 + scheme: HTTP + initialDelaySeconds: 15 + timeoutSeconds: 15 + name: portworx-pvc-controller-manager + resources: + requests: + cpu: 200m + hostNetwork: true + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: "name" + operator: In + values: + - portworx-pvc-controller + topologyKey: "kubernetes.io/hostname" + serviceAccountName: portworx-pvc-controller-account +{{- end }} diff --git a/charts/portworx/portworx/2.9.101/templates/portworx-crd.yaml b/charts/portworx/portworx/2.9.101/templates/portworx-crd.yaml new file mode 100644 index 000000000..2811a0f8b --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/portworx-crd.yaml @@ -0,0 +1,1146 @@ +{{- if or (and (.Values.csi) (eq .Values.csi true)) (not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty))}} +{{- if (semverCompare ">= 1.17.0-0" .Capabilities.KubeVersion.GitVersion) }} +{{- if (semverCompare ">= 1.20.0-0" .Capabilities.KubeVersion.GitVersion) }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/419" + creationTimestamp: null + name: volumesnapshotclasses.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotClass + listKind: VolumeSnapshotClassList + plural: volumesnapshotclasses + 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 + 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: true + storage: false + subresources: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/419" + creationTimestamp: null + name: volumesnapshotcontents.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotContent + listKind: VolumeSnapshotContentList + plural: volumesnapshotcontents + 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 + - 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 + 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 + oneOf: + - required: ["snapshotHandle"] + - required: ["volumeHandle"] + 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: 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 + - 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: true + storage: false + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/419" + creationTimestamp: null + name: volumesnapshots.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshot + listKind: VolumeSnapshotList + plural: volumesnapshots + 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 + 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 + oneOf: + - required: ["persistentVolumeClaimName"] + - required: ["volumeSnapshotContentName"] + 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 occurrs 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: 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 occurrs 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: true + storage: false + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +{{- else }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/139" + creationTimestamp: null + name: volumesnapshotclasses.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotClass + listKind: VolumeSnapshotClassList + plural: volumesnapshotclasses + 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: v1beta1 + 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: true + storage: true + subresources: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/139" + creationTimestamp: null + name: volumesnapshotcontents.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshotContent + listKind: VolumeSnapshotContentList + plural: volumesnapshotcontents + singular: volumesnapshotcontent + scope: Cluster + versions: + - additionalPrinterColumns: + - description: Indicates if a 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 + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + 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. In dynamic snapshot creation + case, this field will be filled in with the "DeletionPolicy" field + defined in the VolumeSnapshotClass the VolumeSnapshot refers to. + 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 from where a snapshot will be created. + 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. 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 to which this snapshot + belongs. + 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 with the "creation_time" + value returned from CSI "CreateSnapshotRequest" 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 latest observed error during snapshot creation, + if any. + 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 with the "ready_to_use" value returned from CSI + "CreateSnapshotRequest" 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 with the "size_bytes" value returned from CSI "CreateSnapshotRequest" + 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: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/139" + creationTimestamp: null + name: volumesnapshots.snapshot.storage.k8s.io +spec: + group: snapshot.storage.k8s.io + names: + kind: VolumeSnapshot + listKind: VolumeSnapshotList + plural: volumesnapshots + singular: volumesnapshot + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Indicates if a snapshot is ready to be used to restore a volume. + jsonPath: .status.readyToUse + name: ReadyToUse + type: boolean + - description: Name of the source PVC from where a dynamically taken snapshot + will be created. + jsonPath: .spec.source.persistentVolumeClaimName + name: SourcePVC + type: string + - description: Name of the VolumeSnapshotContent which represents a pre-provisioned + snapshot. + jsonPath: .spec.source.volumeSnapshotContentName + name: SourceSnapshotContent + type: string + - description: Represents the complete size of the 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: The name of the VolumeSnapshotContent to which this VolumeSnapshot + is bound. + jsonPath: .status.boundVolumeSnapshotContentName + name: SnapshotContent + type: string + - description: Timestamp when the point-in-time snapshot is taken by the underlying + storage system. + jsonPath: .status.creationTime + name: CreationTime + type: date + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + 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 in the same namespace as the VolumeSnapshot + object where the snapshot should be dynamically taken from. + This field is immutable. + type: string + volumeSnapshotContentName: + description: volumeSnapshotContentName specifies the name of a + pre-existing VolumeSnapshotContent object. This field is immutable. + type: string + type: object + volumeSnapshotClassName: + description: 'volumeSnapshotClassName is the name of the VolumeSnapshotClass + requested by the VolumeSnapshot. If not specified, the default snapshot + class will be used if one exists. If not specified, and there is + no default snapshot class, dynamic snapshot creation will fail. + Empty string is not allowed for this field. TODO(xiangqian): a webhook + validation on empty string. More info: https://kubernetes.io/docs/concepts/storage/volume-snapshot-classes' + type: string + required: + - source + type: object + status: + description: 'status represents the current information of a snapshot. + NOTE: status can be modified by sources other than system controllers, + and must not be depended upon for accuracy. Controllers should only + use information from the VolumeSnapshotContent object after verifying + that the binding is accurate and complete.' + properties: + boundVolumeSnapshotContentName: + description: 'boundVolumeSnapshotContentName represents the name of + the VolumeSnapshotContent object to which the VolumeSnapshot object + is bound. If not specified, it indicates that the VolumeSnapshot + object has not been successfully bound to a VolumeSnapshotContent + object yet. NOTE: Specified boundVolumeSnapshotContentName alone + does not mean binding is valid. Controllers MUST always verify + bidirectional binding between VolumeSnapshot and VolumeSnapshotContent + to avoid possible security issues.' + 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 with the "creation_time" + value returned from CSI "CreateSnapshotRequest" 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 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. + 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 with the "ready_to_use" value returned from CSI + "CreateSnapshotRequest" 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 complete size of the snapshot + in bytes. In dynamic snapshot creation case, this field will be + filled in with the "size_bytes" value returned from CSI "CreateSnapshotRequest" + 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: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +{{- end}} +{{- end}} +{{- end}} \ No newline at end of file diff --git a/charts/portworx/portworx/2.9.101/templates/portworx-csi.yaml b/charts/portworx/portworx/2.9.101/templates/portworx-csi.yaml new file mode 100644 index 000000000..b3b543483 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/portworx-csi.yaml @@ -0,0 +1,195 @@ +{{- if or (and (.Values.csi) (eq .Values.csi true)) (not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty))}} +{{- $customRegistryURL := .Values.customRegistryURL | default "none" }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: px-csi-account + namespace: kube-system +--- +kind: ClusterRole +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: px-csi-role +rules: +- apiGroups: ["extensions"] + resources: ["podsecuritypolicies"] + resourceNames: ["privileged"] + verbs: ["use"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["*"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["persistentvolumes"] + verbs: ["get", "list", "watch", "create", "delete", "update", "patch"] +- apiGroups: [""] + resources: ["persistentvolumeclaims"] + verbs: ["get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["persistentvolumeclaims/status"] + verbs: ["update", "patch"] +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] +- apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["get", "list", "watch"] +- apiGroups: ["storage.k8s.io"] + resources: ["volumeattachments"] + verbs: ["get", "list", "watch", "update", "patch"] +- apiGroups: ["storage.k8s.io"] + resources: ["csistoragecapacities"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +- apiGroups: ["apps"] + resources: ["replicasets"] + verbs: ["get"] +- apiGroups: [""] + resources: ["events"] + verbs: ["list", "watch", "create", "update", "patch"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list"] +- apiGroups: ["snapshot.storage.k8s.io"] + resources: ["volumesnapshots", "volumesnapshotcontents", "volumesnapshotclasses", "volumesnapshots/status", "volumesnapshotcontents/status"] + verbs: ["create", "get", "list", "watch", "update", "delete"] +- apiGroups: ["csi.storage.k8s.io"] + resources: ["csinodeinfos"] + verbs: ["get", "list", "watch", "update"] +- apiGroups: ["storage.k8s.io"] + resources: ["csinodes"] + verbs: ["get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] +- apiGroups: ["csi.storage.k8s.io"] + resources: ["csidrivers"] + verbs: ["create", "delete"] +- apiGroups: [""] + resources: ["endpoints"] + verbs: ["get", "watch", "list", "delete", "update", "create"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "watch", "list", "delete", "update", "create"] +- apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["*"] +--- +kind: ClusterRoleBinding +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: px-csi-role-binding +subjects: +- kind: ServiceAccount + name: px-csi-account + namespace: kube-system +roleRef: + kind: ClusterRole + name: px-csi-role + apiGroup: rbac.authorization.k8s.io +--- +kind: Service +apiVersion: v1 +metadata: + name: px-csi-service + namespace: kube-system +spec: + clusterIP: None +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: px-csi-ext + namespace: kube-system +spec: + selector: + matchLabels: + app: px-csi-driver + replicas: 1 + template: + metadata: + labels: + app: px-csi-driver + spec: + serviceAccount: px-csi-account + containers: + - name: csi-external-provisioner + imagePullPolicy: Always + image: {{ template "px.getCSIProvisionerImage" . }} + args: + - "--v=3" + - "--csi-address=$(ADDRESS)" + {{- if semverCompare "<1.17.0-0" .Capabilities.KubeVersion.GitVersion }} + - "--provisioner=pxd.portworx.com" + - "--enable-leader-election" + - "--leader-election-type={{if and (semverCompare ">=1.13.0-0" .Capabilities.KubeVersion.GitVersion) (semverCompare "<1.14.0-0" .Capabilities.KubeVersion.GitVersion) }}endpoints{{else}}leases{{end}}" + {{- else }} + - "--leader-election=true" + - "--default-fstype=ext4" + {{- end }} + env: + - name: ADDRESS + value: /csi/csi.sock + securityContext: + privileged: true + volumeMounts: + - name: socket-dir + mountPath: /csi + {{- if semverCompare ">=1.12.0-0" .Capabilities.KubeVersion.GitVersion }} + - name: csi-snapshotter + imagePullPolicy: Always + image: {{ template "px.getCSISnapshotterImage" . }} + args: + - "--v=3" + - "--csi-address=$(ADDRESS)" + - "--leader-election=true" + {{if and (semverCompare ">=1.13.0-0" .Capabilities.KubeVersion.GitVersion) (semverCompare "<1.14.0-0" .Capabilities.KubeVersion.GitVersion) }} + - "--leader-election-type=configmaps" + {{- end}} + env: + - name: ADDRESS + value: /csi/csi.sock + volumeMounts: + - name: socket-dir + mountPath: /csi + {{- end }} + {{- if semverCompare ">=1.17.0-0" .Capabilities.KubeVersion.GitVersion }} + - name: csi-snapshot-controller + imagePullPolicy: Always + image: {{ template "px.getCSISnapshotControllerImage" . }} + args: + - "--v=3" + - "--leader-election=true" + env: + - name: ADDRESS + value: /csi/csi.sock + securityContext: + privileged: true + volumeMounts: + - name: socket-dir + mountPath: /csi + {{- end }} + {{- if semverCompare ">=1.16.0-0" .Capabilities.KubeVersion.GitVersion }} + - name: csi-resizer + imagePullPolicy: Always + image: k8s.gcr.io/sig-storage/csi-resizer:v1.3.0 + args: + - "--v=3" + - "--csi-address=$(ADDRESS)" + - "--leader-election=true" + env: + - name: ADDRESS + value: /csi/csi.sock + securityContext: + privileged: true + volumeMounts: + - name: socket-dir + mountPath: /csi + {{- end }} + volumes: + - name: socket-dir + hostPath: + path: /var/lib/kubelet/plugins/pxd.portworx.com + type: DirectoryOrCreate +{{- end }} \ No newline at end of file diff --git a/charts/portworx/portworx/2.9.101/templates/portworx-ds.yaml b/charts/portworx/portworx/2.9.101/templates/portworx-ds.yaml new file mode 100644 index 000000000..89eb4f516 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/portworx-ds.yaml @@ -0,0 +1,472 @@ +{{/* Setting defaults if they are omitted. */}} +{{- $deployEnvironmentIKS := .Capabilities.KubeVersion.GitVersion | regexMatch "IKS" }} +{{- $usefileSystemDrive := .Values.usefileSystemDrive | default false }} +{{- $usedrivesAndPartitions := .Values.usedrivesAndPartitions | default false }} +{{- $secretType := .Values.secretType | default "k8s" }} +{{- $journalDevice := .Values.journalDevice | default "none" }} +{{- $maxStorageNodes := .Values.maxStorageNodes | default "none" }} +{{- $customRegistryURL := .Values.customRegistryURL | default "none" }} +{{- $registrySecret := .Values.registrySecret | default "none" }} + +{{- $dataInterface := .Values.dataInterface | default "none" }} +{{- $managementInterface := .Values.managementInterface | default "none" }} + +{{- $envVars := .Values.envVars | default "none" }} +{{- $isCoreOS := .Values.isTargetOSCoreOS | default false }} + +{{- $pksInstall := .Values.pksInstall | default false }} +{{- $internalKVDB := .Values.etcdType | default "none" }} +{{- $csi := .Values.csi | default (not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty)) }} + +{{- $etcdCredentials := .Values.etcd.credentials | default "none:none" }} +{{- $etcdCertPath := .Values.etcd.ca | default "none" }} +{{- $etcdCA := .Values.etcd.ca | default "none" }} +{{- $etcdCert := .Values.etcd.cert | default "none" }} +{{- $etcdKey := .Values.etcd.key | default "none" }} +{{- $consulToken := .Values.consul.token | default "none" }} +{{- $misc := .Values.misc | default "" | split " " }} +{{- $etcdEndPoints := .Values.kvdb }} + +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: portworx + namespace: kube-system + labels: + name: portworx +spec: + minReadySeconds: 0 + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 1 + selector: + matchLabels: + name: portworx + app: portworx + template: + metadata: + labels: + app: portworx + name: portworx + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: px/enabled + operator: NotIn + values: + - "false" + {{- if and (.Values.openshiftInstall) (eq .Values.openshiftInstall true)}} + - key: openshift-infra + operator: DoesNotExist + {{- else if or (not .Values.deployOnMaster) (eq .Values.deployOnMaster false)}} + - key: node-role.kubernetes.io/master + operator: DoesNotExist + {{- end }} + hostNetwork: true + hostPID: true + {{- if not (eq $registrySecret "none") }} + imagePullSecrets: + - name: {{ $registrySecret }} + {{- end }} + containers: + # {{ template "px.getImage"}} + - name: portworx + image: {{ template "px.getImage" . }}:{{ required "A valid Image tag is required in the SemVer format" .Values.imageVersion }} + terminationMessagePath: "/tmp/px-termination-log" + imagePullPolicy: Always + args: + [ + {{ include "px.storage" . | indent 0 }} + {{- with .Values -}} + {{- if eq "Built-in" $internalKVDB }} + "-b", + {{- end -}} + + {{- if ne $journalDevice "none" }} + "-j", "{{ $journalDevice }}", + {{- end -}} + + {{- if $etcdEndPoints -}} + "-k", "{{ regexReplaceAllLiteral "(;)" .kvdb "," }}", + {{- else }} + {{- if ne "Built-in" $internalKVDB }} + {{- if eq "US region" .region }} + "-k", "etcd:http://px-etcd1.portworx.com:2379,etcd:http://px-etcd2.portworx.com:2379,etcd:http://px-etcd3.portworx.com:2379", + {{- else if eq "EU region" .region }} + "-k", "etcd:http://px-eu-etcd1.portworx.com:2379,etcd:http://px-eu-etcd2.portworx.com:2379,etcd:http://px-eu-etcd3.portworx.com:2379", + {{- else }} + "{{ required "A valid kvdb url is required." .kvdb }}" + {{- end -}} + {{- end -}} + {{- end -}} + "-c", "{{ required "Clustername cannot be empty" .clusterName }}", + + {{- if ne $secretType "none" }} + "-secret_type", "{{ $secretType }}", + {{- else }} + {{- if $deployEnvironmentIKS }} + "-secret_type", "ibm-kp", + {{- end -}} + {{- end -}} + + {{- if and (ne $dataInterface "none") (ne $dataInterface "auto")}} + "-d", "{{ $dataInterface }}", + {{- end -}} + + {{- if and (ne $managementInterface "none") (ne $managementInterface "auto") }} + "-m", "{{ $managementInterface }}", + {{- end -}} + + {{- if ne $etcdCredentials "none:none" }} + "-userpwd", "{{ $etcdCredentials }}", + {{- end -}} + + {{- if ne $etcdCA "none" }} + "-ca", "/etc/pwx/etcdcerts/{{ $etcdCA }}", + {{- end -}} + + {{- if ne $etcdCert "none" }} + "-cert", "/etc/pwx/etcdcerts/{{ $etcdCert }}", + {{- end -}} + + {{- if ne $etcdKey "none" }} + "-key", "/etc/pwx/etcdcerts/{{ $etcdKey }}", + {{- end -}} + + {{- if ne $consulToken "none" }} + "-acltoken", "{{ $consulToken }}", + {{- end -}} + + {{- if .misc }} + {{- range $index, $name := $misc }} + "{{ $name }}", + {{- end }} + {{ end -}} + + "-x", "kubernetes" + {{- end -}} + ] + env: + - name: "PX_TEMPLATE_VERSION" + value: "v2" + {{ if not (eq $envVars "none") }} + {{- $vars := $envVars | split ";" }} + {{- range $key, $val := $vars }} + {{- $envVariable := $val | split "=" }} + - name: {{ $envVariable._0 | trim | quote }} + value: {{ $envVariable._1 | trim | quote }} + {{ end }} + {{- end }} + + {{- if not (eq $registrySecret "none") }} + - name: REGISTRY_CONFIG + valueFrom: + secretKeyRef: + {{- if (semverCompare ">=1.9-0" .Capabilities.KubeVersion.GitVersion) or (.Values.openshiftInstall and semverCompare ">=1.8-0" .Capabilities.KubeVersion.GitVersion) }} + key: ".dockerconfigjson" + {{- else }} + key: ".dockercfg" + {{- end }} + name: "{{ $registrySecret }}" + {{- end }} + + {{- if eq $pksInstall true }} + - name: "PRE-EXEC" + value: "if [ ! -x /bin/systemctl ]; then apt-get update; apt-get install -y systemd; fi" + {{- end }} + + {{- if eq $csi true }} + - name: CSI_ENDPOINT + value: unix:///var/lib/kubelet/plugins/pxd.portworx.com/csi.sock + {{- end }} + + livenessProbe: + periodSeconds: 30 + initialDelaySeconds: 840 # allow image pull in slow networks + httpGet: + host: 127.0.0.1 + path: /status + port: 9001 + readinessProbe: + periodSeconds: 10 + httpGet: + host: 127.0.0.1 + {{- if eq (.Values.deploymentType | upper | lower) "oci" }} + path: /health + port: 9015 + {{- else }} + path: /v1/cluster/nodehealth + port: 9001 + {{- end}} + securityContext: + privileged: true + volumeMounts: + {{- if not (eq $etcdCertPath "none") }} + - mountPath: /etc/pwx/etcdcerts + name: etcdcerts + {{- end }} + {{- if not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty) }} + - name: containerd-k3s + mountPath: /run/containerd/containerd.sock + {{- end }} + - name: dockersock + mountPath: /var/run/docker.sock + - name: containerdsock + mountPath: /run/containerd + - name: etcpwx + mountPath: /etc/pwx + - name: cores + mountPath: /var/cores + {{- if eq (.Values.deploymentType | upper | lower) "oci" }} + - name: optpwx + mountPath: /opt/pwx + - name: sysdmount + mountPath: /etc/systemd/system + - name: journalmount1 + mountPath: /var/run/log + readOnly: true + - name: journalmount2 + mountPath: /var/log + readOnly: true + - name: dbusmount + mountPath: /var/run/dbus + - name: hostproc + mountPath: /host_proc + {{- else if eq (.Values.deploymentType | upper | lower) "docker" }} + - name: dev + mountPath: /dev + - name: optpwx + mountPath: /export_bin + - name: dockerplugins + mountPath: /run/docker/plugins + - name: hostproc + mountPath: /hostproc + {{- if semverCompare "< 1.10-0" .Capabilities.KubeVersion.GitVersion }} + - name: libosd + mountPath: /var/lib/osd:shared + {{- if (.Values.openshiftInstall) and (eq .Values.openshiftInstall true)}} + - name: kubelet + mountPath: /var/lib/origin/openshift.local.volumes:shared + {{- else }} + - name: kubelet + mountPath: /var/lib/kubelet:shared + {{- end }} + + {{- else }} + - name: libosd + mountPath: /var/lib/osd + mountPropagation: "Bidirectional" + {{- if (.Values.openshiftInstall) and (eq .Values.openshiftInstall true)}} + - name: kubelet + mountPath: /var/lib/origin/openshift.local.volumes + mountPropagation: "Bidirectional" + {{- else }} + - name: kubelet + mountPath: /var/lib/kubelet + mountPropagation: "Bidirectional" + {{- end }} + + {{- end }} + + {{- if eq $isCoreOS true}} + - name: src + mountPath: /lib/modules + {{- else }} + - name: src + mountPath: /usr/src + {{- end }} + {{- end }} + + {{- if eq $csi true }} + - name: csi-node-driver-registrar + imagePullPolicy: Always + {{- if eq $customRegistryURL "none" }} + image: "k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.1.0" + {{- else }} + image: "{{ $customRegistryURL }}/k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.1.0" + {{- end}} + args: + - "--v=5" + - "--csi-address=$(ADDRESS)" + - "--kubelet-registration-path=/var/lib/kubelet/plugins/pxd.portworx.com/csi.sock" + env: + - name: ADDRESS + value: /csi/csi.sock + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + volumeMounts: + - name: csi-driver-path + mountPath: /csi + - name: registration-dir + mountPath: /registration + {{- end }} + + restartPolicy: Always + {{- if not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty) }} + tolerations: + - key: node-role.kubernetes.io/master + effect: NoSchedule + {{- end }} + serviceAccountName: px-account + volumes: + {{- if ne $etcdCertPath "none" }} + - name: etcdcerts + secret: + secretName: px-etcd-certs + items: + - key: "{{ $etcdCA }}" + path: "{{ $etcdCA }}" + - key: "{{ $etcdCert }}" + path: "{{ $etcdCert }}" + - key: "{{ $etcdKey }}" + path: "{{ $etcdKey }}" + {{- end}} + {{- if not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty) }} + - name: containerd-k3s + hostPath: + path: /run/k3s/containerd/containerd.sock + {{- end }} + - name: dockersock + hostPath: + path: {{if eq $pksInstall true}}/var/vcap/sys/run/docker/docker.sock{{else}}/var/run/docker.sock{{end}} + - name: containerdsock + hostPath: + path: {{if eq $pksInstall true}}/var/vcap/sys/run/containerd{{else}}/run/containerd{{end}} + {{- if eq $csi true}} + - name: csi-driver-path + hostPath: + path: /var/lib/kubelet/plugins/pxd.portworx.com + type: DirectoryOrCreate + - name: registration-dir + hostPath: + path: /var/lib/kubelet/plugins_registry + type: DirectoryOrCreate + {{- end}} + - name: etcpwx + hostPath: + path: /etc/pwx + - name: cores + hostPath: + path: {{if eq $pksInstall true }}/var/vcap/store/cores{{else}}/var/cores{{end}} + {{- if eq (.Values.deploymentType | upper | lower) "oci" }} + - name: optpwx + hostPath: + path: {{if eq $pksInstall true }}/var/vcap/store/opt/pwx{{else}}/opt/pwx{{end}} + - name: sysdmount + hostPath: + path: /etc/systemd/system + - name: journalmount1 + hostPath: + path: /var/run/log + - name: journalmount2 + hostPath: + path: /var/log + - name: dbusmount + hostPath: + path: /var/run/dbus + - name: hostproc + hostPath: + path: /proc + {{- else if eq (.Values.deploymentType | upper | lower) "docker" }} + - name: libosd + hostPath: + path: /var/lib/osd + - name: optpwx + hostPath: + path: /opt/pwx/bin + - name: dev + hostPath: + path: /dev + {{- if (.Values.openshiftInstall) and (eq .Values.openshiftInstall true)}} + - name: kubelet + hostPath: + path: /var/lib/origin/openshift.local.volumes + {{- else }} + - name: kubelet + hostPath: + path: /var/lib/kubelet + {{- end }} + {{- if eq $isCoreOS true}} + - name: src + hostPath: + path: /lib/modules + {{- else }} + - name: src + hostPath: + path: /usr/src + {{- end }} + - name: dockerplugins + hostPath: + path: /run/docker/plugins + - name: hostproc + hostPath: + path: /proc + {{- end }} +--- +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: portworx-api + namespace: kube-system + labels: + name: portworx-api +spec: + selector: + matchLabels: + name: portworx-api + minReadySeconds: 0 + updateStrategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 100% + template: + metadata: + labels: + name: portworx-api + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: px/enabled + operator: NotIn + values: + - "false" + {{- if not (.Capabilities.KubeVersion.GitVersion | toString | regexFind "(k3s|rke2)" | empty) }} + - key: node-role.kubernetes.io/master + operator: DoesNotExist + {{- end }} + hostNetwork: true + hostPID: false + containers: + - name: portworx-api + image: "{{ template "px.getPauseImage" . }}/pause:3.1" + imagePullPolicy: Always + readinessProbe: + periodSeconds: 10 + httpGet: + host: 127.0.0.1 + path: /status + port: 9001 + restartPolicy: Always + serviceAccountName: px-account +{{- if eq $csi true }} +--- +apiVersion: storage.k8s.io/v1 +kind: CSIDriver +metadata: + name: "pxd.portworx.com" +spec: + attachRequired: false + podInfoOnMount: true + volumeLifecycleModes: + - Persistent + - Ephemeral +{{- end}} \ No newline at end of file diff --git a/charts/portworx/portworx/2.9.101/templates/portworx-rbac-config.yaml b/charts/portworx/portworx/2.9.101/templates/portworx-rbac-config.yaml new file mode 100644 index 000000000..382e84a7c --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/portworx-rbac-config.yaml @@ -0,0 +1,68 @@ + +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: px-account + namespace: kube-system +--- + +kind: ClusterRole +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: node-get-put-list-role +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["watch", "get", "update", "list"] +- apiGroups: [""] + resources: ["pods"] + verbs: ["delete", "get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["persistentvolumeclaims", "persistentvolumes"] + verbs: ["get", "list"] +- apiGroups: ["storage.k8s.io"] + resources: ["storageclasses"] + verbs: ["get", "list"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "update", "create"] +- apiGroups: [""] + resources: ["services"] + verbs: ["get", "list", "create", "update", "delete"] +- apiGroups: [""] + resources: ["endpoints"] + verbs: ["get", "list", "create", "update", "delete"] +- apiGroups: ["extensions"] + resources: ["podsecuritypolicies"] + resourceNames: ["privileged"] + verbs: ["use"] +- apiGroups: ["portworx.io"] + resources: ["volumeplacementstrategies"] + verbs: ["get", "list"] +- apiGroups: ["stork.libopenstorage.org"] + resources: ["backuplocations"] + verbs: ["get", "list"] +- apiGroups: ["core.libopenstorage.org"] + resources: ["*"] + verbs: ["*"] +- apiGroups: [""] + resources: ["events"] + verbs: ["create"] +--- + +kind: ClusterRoleBinding +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: node-role-binding +subjects: +- kind: ServiceAccount + name: px-account + namespace: kube-system +roleRef: + kind: ClusterRole + name: node-get-put-list-role + apiGroup: rbac.authorization.k8s.io diff --git a/charts/portworx/portworx/2.9.101/templates/portworx-service.yaml b/charts/portworx/portworx/2.9.101/templates/portworx-service.yaml new file mode 100644 index 000000000..8d3ac159d --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/portworx-service.yaml @@ -0,0 +1,54 @@ +kind: Service +apiVersion: v1 +metadata: + name: portworx-service + namespace: kube-system + labels: + name: portworx +spec: + selector: + name: portworx + type: ClusterIP + ports: + - name: px-api + protocol: TCP + port: 9001 + targetPort: 9001 + - name: px-kvdb + protocol: TCP + port: 9019 + targetPort: 9019 + - name: px-sdk + protocol: TCP + port: 9020 + targetPort: 9020 + - name: px-rest-gateway + protocol: TCP + port: 9021 + targetPort: 9021 +--- +kind: Service +apiVersion: v1 +metadata: + name: portworx-api + namespace: kube-system + labels: + name: portworx-api +spec: + selector: + name: portworx-api + type: ClusterIP + ports: + - name: px-api + protocol: TCP + port: 9001 + targetPort: 9001 + - name: px-sdk + protocol: TCP + port: 9020 + targetPort: 9020 + - name: px-rest-gateway + protocol: TCP + port: 9021 + targetPort: 9021 +--- diff --git a/charts/portworx/portworx/2.9.101/templates/portworx-storageclasses.yaml b/charts/portworx/portworx/2.9.101/templates/portworx-storageclasses.yaml new file mode 100644 index 000000000..b430fee8f --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/portworx-storageclasses.yaml @@ -0,0 +1,56 @@ +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: portworx-db-sc +provisioner: kubernetes.io/portworx-volume +parameters: + repl: "3" + io_profile: "db" +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: portworx-db2-sc +provisioner: kubernetes.io/portworx-volume +parameters: + repl: "3" + block_size: "512b" + io_profile: "db" +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: portworx-shared-sc +provisioner: kubernetes.io/portworx-volume +parameters: + repl: "3" + shared: "true" +--- +# +# NULL StorageClass that documents all possible +# Portworx StorageClass parameters +# +# Please refer to : https://docs.portworx.com/scheduler/kubernetes/dynamic-provisioning.html +# +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: portworx-null-sc + annotations: + params/docs: 'https://docs.portworx.com/scheduler/kubernetes/dynamic-provisioning.html' + params/fs: "Filesystem to be laid out: none|xfs|ext4 " + params/block_size: "Block size" + params/repl: "Replication factor for the volume: 1|2|3" + params/shared: "Flag to create a globally shared namespace volume which can be used by multiple pods : true|false" + params/priority_io: "IO Priority: low|medium|high" + params/io_profile: "IO Profile can be used to override the I/O algorithm Portworx uses for the volumes. Supported values are [db](/maintain/performance/tuning.html#db), [sequential](/maintain/performance/tuning.html#sequential), [random](/maintain/performance/tuning.html#random), [cms](/maintain/performance/tuning.html#cms)" + params/group: "The group a volume should belong too. Portworx will restrict replication sets of volumes of the same group on different nodes. If the force group option 'fg' is set to true, the volume group rule will be strictly enforced. By default, it's not strictly enforced." + params/fg: "This option enforces volume group policy. If a volume belonging to a group cannot find nodes for it's replication sets which don't have other volumes of same group, the volume creation will fail." + params/label: "List of comma-separated name=value pairs to apply to the Portworx volume" + params/nodes: "Comma-separated Portworx Node ID's to use for replication sets of the volume" + params/aggregation_level: "Specifies the number of replication sets the volume can be aggregated from" + params/snap_schedule: "Snapshot schedule. Following are the accepted formats: periodic=_mins_,_snaps-to-keep_ daily=_hh:mm_,_snaps-to-keep_ weekly=_weekday@hh:mm_,_snaps-to-keep_ monthly=_day@hh:mm_,_snaps-to-keep_ _snaps-to-keep_ is optional. Periodic, Daily, Weekly and Monthly keep last 5, 7, 5 and 12 snapshots by default respectively" + params/sticky: "Flag to create sticky volumes that cannot be deleted until the flag is disabled" + params/journal: "Flag to indicate if you want to use journal device for the volume's metadata. This will use the journal device that you used when installing Portworx. As of PX version 1.3, it is recommended to use a journal device to absorb PX metadata writes" +provisioner: kubernetes.io/portworx-volume +parameters: diff --git a/charts/portworx/portworx/2.9.101/templates/portworx-stork.yaml b/charts/portworx/portworx/2.9.101/templates/portworx-stork.yaml new file mode 100644 index 000000000..77449b394 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/portworx-stork.yaml @@ -0,0 +1,645 @@ +{{- if and (.Values.stork) (eq .Values.stork true)}} + {{- $isCoreOS := .Values.isTargetOSCoreOS | default false }} + {{- $customRegistryURL := .Values.customRegistryURL | default "none" }} + {{- $registrySecret := .Values.registrySecret | default "none" }} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: stork-config + namespace: kube-system +data: + policy.cfg: |- + { + "kind": "Policy", + "apiVersion": "v1", +{{- if semverCompare "< 1.10-0" .Capabilities.KubeVersion.GitVersion }} + "predicates": [ +{{- if semverCompare "< 1.9-0" .Capabilities.KubeVersion.GitVersion }} + {"name": "NoVolumeNodeConflict"}, +{{- end}} + {"name": "MaxAzureDiskVolumeCount"}, + {"name": "NoVolumeZoneConflict"}, + {"name": "PodToleratesNodeTaints"}, + {"name": "CheckNodeMemoryPressure"}, + {"name": "MaxEBSVolumeCount"}, + {"name": "MaxGCEPDVolumeCount"}, + {"name": "MatchInterPodAffinity"}, + {"name": "NoDiskConflict"}, + {"name": "GeneralPredicates"}, + {"name": "CheckNodeDiskPressure"} + ], + "priorities": [ + {"name": "NodeAffinityPriority", "weight": 1}, + {"name": "TaintTolerationPriority", "weight": 1}, + {"name": "SelectorSpreadPriority", "weight": 1}, + {"name": "InterPodAffinityPriority", "weight": 1}, + {"name": "LeastRequestedPriority", "weight": 1}, + {"name": "BalancedResourceAllocation", "weight": 1}, + {"name": "NodePreferAvoidPodsPriority", "weight": 1} + ], +{{- end}} + "extenders": [ + { + "urlPrefix": "http://stork-service.kube-system:8099", + "apiVersion": "v1beta1", + "filterVerb": "filter", + "prioritizeVerb": "prioritize", + "weight": 5, + "enableHttps": false, + "nodeCacheCapable": false + } + ] + } +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: stork-account + namespace: kube-system +--- +kind: ClusterRole +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: stork-role +rules: + - apiGroups: ["*"] + resources: ["*"] + verbs: ["*"] +--- +kind: ClusterRoleBinding +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: stork-role-binding +subjects: + - kind: ServiceAccount + name: stork-account + namespace: kube-system +roleRef: + kind: ClusterRole + name: stork-role + apiGroup: rbac.authorization.k8s.io +--- +kind: Service +apiVersion: v1 +metadata: + name: stork-service + namespace: kube-system +spec: + selector: + name: stork + ports: + - name: extender + protocol: TCP + port: 8099 + targetPort: 8099 + - name: webhook + protocol: TCP + port: 443 + targetPort: 443 +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: volumeplacementstrategies.portworx.io +spec: + group: portworx.io + versions: + - name: v1beta2 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + required: + - spec + properties: + spec: + type: object + description: The desired spec of the volume placement strategy + properties: + replicaAffinity: + type: array + description: Allows you to specify a rule which creates an affinity for replicas within a volume + items: + type: object + properties: + affected_replicas: + type: integer + description: The number of volume replicas affected by the replica affinity + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + matchExpressions: + description: Expression to use for the replica affinity rule + type: array + items: + type: object + properties: + key: + type: string + minLength: 1 + operator: + type: string + enum: + - In + - NotIn + - Exists + - DoesNotExist + - Lt + - Gt + description: The logical operator to use for comparing the key and values in the match expression + values: + type: array + items: + type: string + required: + - key + - operator + replicaAntiAffinity: + type: array + description: Allows you to specify a rule that creates an anti-affinity for replicas within a volume + items: + type: object + properties: + affected_replicas: + type: integer + description: The number of volume replicas affected by the replica anti affinity + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + required: + - topologyKey + volumeAffinity: + type: array + description: Allows you to colocate volumes by specifying rules that place replicas of a volume together with those of another volume for which the specified labels match + items: + type: object + properties: + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + matchExpressions: + description: Expression to use for the volume affinity rule + type: array + items: + type: object + properties: + key: + type: string + minLength: 1 + operator: + type: string + enum: + - In + - NotIn + - Exists + - DoesNotExist + - Lt + - Gt + description: The logical operator to use for comparing the key and values in the match expression + values: + type: array + items: + type: string + required: + - key + - operator + required: + - matchExpressions + volumeAntiAffinity: + type: array + description: Allows you to specify dissociation rules between 2 or more volumes that match the given labels + items: + type: object + properties: + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + matchExpressions: + description: Expression to use for the volume anti affinity rule + type: array + items: + type: object + properties: + key: + type: string + minLength: 1 + operator: + type: string + enum: + - In + - NotIn + - Exists + - DoesNotExist + - Lt + - Gt + description: The logical operator to use for comparing the key and values in the match expression + values: + type: array + items: + type: string + required: + - key + - operator + required: + - matchExpressions + - name: v1beta1 + served: false + storage: false + schema: + openAPIV3Schema: + type: object + required: + - spec + properties: + spec: + type: object + description: The desired spec of the volume placement strategy + properties: + replicaAffinity: + type: array + description: Allows you to specify a rule which creates an affinity for replicas within a volume + items: + type: object + properties: + affected_replicas: + type: integer + description: The number of volume replicas affected by the replica affinity + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + matchExpressions: + description: Expression to use for the replica affinity rule + type: array + items: + type: object + properties: + key: + type: string + minLength: 1 + operator: + type: string + enum: + - In + - NotIn + - Exists + - DoesNotExist + - Lt + - Gt + description: The logical operator to use for comparing the key and values in the match expression + values: + type: array + items: + type: string + required: + - key + - operator + replicaAntiAffinity: + type: array + description: Allows you to specify a rule that creates an anti-affinity for replicas within a volume + items: + type: object + properties: + affected_replicas: + type: integer + description: The number of volume replicas affected by the replica anti affinity + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + required: + - topologyKey + volumeAffinity: + type: array + description: Allows you to colocate volumes by specifying rules that place replicas of a volume together with those of another volume for which the specified labels match + items: + type: object + properties: + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + matchExpressions: + description: Expression to use for the volume affinity rule + type: array + items: + type: object + properties: + key: + type: string + minLength: 1 + operator: + type: string + enum: + - In + - NotIn + - Exists + - DoesNotExist + - Lt + - Gt + description: The logical operator to use for comparing the key and values in the match expression + values: + type: array + items: + type: string + required: + - key + - operator + required: + - matchExpressions + volumeAntiAffinity: + type: array + description: Allows you to specify dissociation rules between 2 or more volumes that match the given labels + items: + type: object + properties: + enforcement: + type: string + enum: + - required + - preferred + description: Specifies if the given rule is required (hard) or preferred (soft) + topologyKey: + type: string + minLength: 1 + description: Key for the node label that the system uses to denote a topology domain. The key can be for any node label that is present on the Kubernetes node. + matchExpressions: + description: Expression to use for the volume anti affinity rule + type: array + items: + type: object + properties: + key: + type: string + minLength: 1 + operator: + type: string + enum: + - In + - NotIn + - Exists + - DoesNotExist + - Lt + - Gt + description: The logical operator to use for comparing the key and values in the match expression + values: + type: array + items: + type: string + required: + - key + - operator + required: + - matchExpressions + scope: Cluster + names: + plural: volumeplacementstrategies + singular: volumeplacementstrategy + kind: VolumePlacementStrategy + shortNames: + - vps + - vp +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" + labels: + tier: control-plane + name: stork + namespace: kube-system +spec: + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + replicas: 3 + selector: + matchLabels: + name: stork + tier: control-plane + template: + metadata: + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" + labels: + name: stork + tier: control-plane + spec: + {{- if not (eq $registrySecret "none") }} + imagePullSecrets: + - name: {{ $registrySecret }} + {{- end }} + containers: + - command: + - /stork + - --driver=pxd + - --verbose + - --leader-elect=true + - --webhook-controller=false + imagePullPolicy: Always + image: {{ template "px.getStorkImage" . }}:{{ required "A valid Image tag is required in the SemVer format" .Values.storkVersion }} + resources: + requests: + cpu: '0.1' + name: stork + hostPID: false + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: "name" + operator: In + values: + - stork + topologyKey: "kubernetes.io/hostname" + serviceAccountName: stork-account +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: stork-snapshot-sc +provisioner: stork-snapshot +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: stork-scheduler-account + namespace: kube-system +--- +kind: ClusterRole +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: stork-scheduler-role +rules: + - apiGroups: [""] + resources: ["endpoints"] + verbs: ["get", "update"] + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] + - apiGroups: ["", "events.k8s.io"] + resources: ["events"] + verbs: ["create", "patch", "update"] + - apiGroups: [""] + resources: ["endpoints"] + verbs: ["create"] + - apiGroups: [""] + resourceNames: ["kube-scheduler"] + resources: ["endpoints"] + verbs: ["delete", "get", "patch", "update"] + - apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["delete", "get", "list", "watch"] + - apiGroups: [""] + resources: ["bindings", "pods/binding"] + verbs: ["create"] + - apiGroups: [""] + resources: ["pods/status"] + verbs: ["patch", "update"] + - apiGroups: [""] + resources: ["replicationcontrollers", "services"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps", "extensions"] + resources: ["replicasets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps"] + resources: ["statefulsets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["policy"] + resources: ["poddisruptionbudgets"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["persistentvolumeclaims", "persistentvolumes"] + verbs: ["get", "list", "watch"] + - apiGroups: ["storage.k8s.io"] + resources: ["storageclasses", "csinodes", "csidrivers", "csistoragecapacities"] + verbs: ["get", "list", "watch"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["create", "update", "get", "list", "watch"] +--- +kind: ClusterRoleBinding +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + name: stork-scheduler-role-binding +subjects: + - kind: ServiceAccount + name: stork-scheduler-account + namespace: kube-system +roleRef: + kind: ClusterRole + name: stork-scheduler-role + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + component: scheduler + tier: control-plane + name: stork-scheduler + namespace: kube-system +spec: + replicas: 3 + selector: + matchLabels: + component: scheduler + tier: control-plane + template: + metadata: + labels: + component: scheduler + tier: control-plane + name: stork-scheduler + spec: + containers: + - command: + - /usr/local/bin/kube-scheduler + - --address=0.0.0.0 + - --leader-elect=true + - --scheduler-name=stork + - --policy-configmap=stork-config + - --policy-configmap-namespace=kube-system + - --lock-object-name=stork-scheduler + image: "{{ template "px.getk8sImages" . }}/kube-scheduler-amd64:v1.21.4" + livenessProbe: + httpGet: + path: /healthz + port: 10251 + initialDelaySeconds: 15 + name: stork-scheduler + readinessProbe: + httpGet: + path: /healthz + port: 10251 + resources: + requests: + cpu: '0.1' + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: "name" + operator: In + values: + - stork-scheduler + topologyKey: "kubernetes.io/hostname" + hostPID: false + serviceAccountName: stork-scheduler-account + {{- end }} diff --git a/charts/portworx/portworx/2.9.101/templates/serviceaccount-hook.yaml b/charts/portworx/portworx/2.9.101/templates/serviceaccount-hook.yaml new file mode 100644 index 000000000..758863039 --- /dev/null +++ b/charts/portworx/portworx/2.9.101/templates/serviceaccount-hook.yaml @@ -0,0 +1,42 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "px.hookServiceAccount" . }} + namespace: kube-system + annotations: + "helm.sh/hook-delete-policy": before-hook-creation + "helm.sh/hook": "post-install,pre-delete,post-delete" + labels: + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{.Release.Service | quote }} + app.kubernetes.io/instance: {{.Release.Name | quote }} + chart: "{{.Chart.Name}}-{{.Chart.Version}}" +--- +kind: ClusterRole +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + annotations: + "helm.sh/hook-delete-policy": before-hook-creation + "helm.sh/hook": "post-install,pre-delete,post-delete" + name: {{ template "px.hookClusterRole" . }} +rules: +- apiGroups: [""] + resources: ["nodes"] + verbs: ["patch", "get", "update", "list"] +--- +kind: ClusterRoleBinding +apiVersion: {{ template "rbac.apiVersion" . }} +metadata: + annotations: + "helm.sh/hook-delete-policy": before-hook-creation + "helm.sh/hook": "post-install,pre-delete,post-delete" + name: {{ template "px.hookClusterRoleBinding" . }} +subjects: +- kind: ServiceAccount + name: {{ template "px.hookServiceAccount" . }} + namespace: kube-system +roleRef: + kind: ClusterRole + name: {{ template "px.hookClusterRole" . }} + apiGroup: rbac.authorization.k8s.io diff --git a/charts/portworx/portworx/2.9.101/values.yaml b/charts/portworx/portworx/2.9.101/values.yaml new file mode 100644 index 000000000..705b782ac --- /dev/null +++ b/charts/portworx/portworx/2.9.101/values.yaml @@ -0,0 +1,149 @@ +# Please uncomment and specify values for these options as per your requirements. +kvdb: +ownEtcdOption: none +etcdAuth: none +etcdType: none # KVDB type + +etcd: + credentials: none:none # Username and password for ETCD authentication in the form user:password + ca: none # Name of CA file for ETCD authentication. server.ca + cert: none # Name of certificate for ETCD authentication. Should be server.crt + key: none # Name of certificate key for ETCD authentication Should be server.key +consul: + token: none # ACL token value used for Consul authentication. (example: 398073a8-5091-4d9c-871a-bbbeb030d1f6) +region: none # US or EU regions for Portworx hosted etcds + +dataInterface: none # Name of the interface +managementInterface: none # Name of the interface +platformOptions: none # AKS, EKS or GKE platforms + +customRegistryURL: +registrySecret: + +clusterName: mycluster # This is the default. please change it to your cluster name. +secretType: k8s # Defaults to None, but can be AWS / KVDB / Vault. +envVars: none # NOTE: This is a ";" seperated list of environment variables. For eg: MYENV1=myvalue1;MYENV2=myvalue2 +stork: true # Use Stork https://docs.portworx.com/scheduler/kubernetes/stork.html for hyperconvergence. +storkVersion: 2.7.0 + +deployOnMaster: false # For POC only +csi: false # Enable CSI +openshiftInstall: false +AKSorEKSInstall: false +serviceAccount: + hook: + create: true + name: + +deploymentType: oci # accepts "oci" or "docker" +imageType: none # +imageVersion: 2.9.1.4 # Version of the PX Image. + +result: none +environment: none +onpremStorage: none + +maxStorageNodes: none +journalDevice: none + +usefileSystemDrive: false # true/false Instructs PX to use an unmounted Drive even if it has a filesystem. +usedrivesAndPartitions: false # Use unmounted disks even if they have a partition or filesystem on it. PX will never use a drive or partition that is mounted. (useDrivesAndPartitions) + +provider: none +deviceConfig: none + +drive_1: + aws: + type: none + size: none + iops: none + gc: + type: standard + size: 1000 + +drive_2: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_3: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_4: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_5: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_6: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_7: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_8: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_9: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +drive_10: + aws: + type: none + size: none + iops: none + gc: + type: none + size: none + +existingDisk1: none +existingDisk2: none +existingDisk3: none +existingDisk4: none +existingDisk5: none diff --git a/index.yaml b/index.yaml index 10a4b747a..6778c9c68 100755 --- a/index.yaml +++ b/index.yaml @@ -1014,6 +1014,30 @@ entries: urls: - assets/datadog/datadog-2.4.200.tgz version: 2.4.200 + dkube-deployer: + - annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Dkube + catalog.cattle.io/release-name: dkube + apiVersion: v2 + appVersion: 3.2.0.1 + created: "2022-05-04T16:37:14.95132553+05:30" + description: A Kubernetes-based MLOps platform based on open standards Kubeflow + and MLflow + digest: a3c0c5ad1abab6fa143abced6fb9a3dc100844327b2e4a881f46c10e89900a75 + home: https://dkube.io + icon: https://www.dkube.io/img/logo_new.png + keywords: + - kubernetes + - MLOps + - Kubeflow + - AI + kubeVersion: "1.20" + name: dkube-deployer + type: application + urls: + - assets/dkube/dkube-deployer-1.0.601.tgz + version: 1.0.601 dynatrace-oneagent-operator: - annotations: catalog.cattle.io/certified: partner @@ -1088,6 +1112,29 @@ entries: - assets/dynatrace-oneagent-operator/dynatrace-oneagent-operator-0.8.000.tgz version: 0.8.000 external-secrets: + - annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: External Secrets Operator + catalog.cattle.io/release-name: external-secrets-operator + apiVersion: v2 + appVersion: v0.5.6 + created: "2022-06-07T11:52:59.318539Z" + description: External secret management for Kubernetes + digest: b0c874a4ab6eab429ab0a38238d3b0ee8175e34fbabaeb8fb755893a83c59a04 + home: https://github.com/external-secrets/external-secrets + icon: https://raw.githubusercontent.com/external-secrets/external-secrets/main/assets/eso-logo-large.png + keywords: + - kubernetes-external-secrets + - secrets + kubeVersion: '>= 1.19.0-0' + maintainers: + - email: kellinmcavoy@gmail.com + name: mcavoyk + name: external-secrets + type: application + urls: + - assets/external-secrets-operator/external-secrets-0.5.600.tgz + version: 0.5.600 - annotations: catalog.cattle.io/certified: partner catalog.cattle.io/display-name: External Secrets Operator @@ -2272,6 +2319,32 @@ entries: - assets/instana-agent/instana-agent-1.0.2900.tgz version: 1.0.2900 k8s-triliovault-operator: + - annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: TrilioVault for Kubernetes Operator + catalog.cattle.io/release-name: k8s-triliovault-operator + apiVersion: v2 + appVersion: 2.9.3 + created: "2022-06-16T07:06:47.995457657Z" + dependencies: + - condition: observability.enabled + name: observability + repository: file://./charts/observability + description: K8s-TrilioVault-Operator is an operator designed to manage the K8s-TrilioVault + Application Lifecycle. + digest: 3250777c43cd3e4e8924a17746dd92649422999320ee13b564e084048226a0a0 + home: https://github.com/trilioData/k8s-triliovault-operator + icon: https://www.trilio.io/wp-content/uploads/2021/01/Trilio-2020-logo-RGB-gray-green.png + kubeVersion: '>=1.19.0-0' + maintainers: + - email: prafull.ladha@trilio.io + name: prafull11 + name: k8s-triliovault-operator + sources: + - https://github.com/trilioData/k8s-triliovault-operator + urls: + - assets/k8s-triliovault-operator/k8s-triliovault-operator-2.9.300.tgz + version: 2.9.300 - annotations: catalog.cattle.io/certified: partner catalog.cattle.io/display-name: TrilioVault for Kubernetes Operator @@ -3888,6 +3961,42 @@ entries: - assets/portshift-operator/portshift-operator-0.1.000.tgz version: 0.1.000 portworx: + - annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Portworx + catalog.cattle.io/release-name: portworx + apiVersion: v1 + appVersion: "2.9" + created: "2022-06-16T14:25:31.633584-04:00" + description: A Helm chart for installing Portworx on Kubernetes. + digest: a44698f46c5b43abf1b69cbf0ba278db7a5f3962e20b0feedec078fef07fbc79 + home: https://portworx.com/ + icon: https://raw.githubusercontent.com/portworx/helm/master/doc/media/k8s-porx.png + keywords: + - Storage + - ICP + - persistent disk + - pvc + - cloud native storage + - persistent storage + - portworx + - amd64 + kubeVersion: '>=1.16.0-0' + maintainers: + - email: hadesai@purestorage.com + name: harsh-px + - email: onaumov@purestorage.com + name: trierra + - email: tasharma@purestorage.com + name: sharma-tapas + - email: dahuang@purestorage.com + name: dahuang-purestorage + name: portworx + sources: + - https://github.com/portworx/charts-rancher/tree/master/stable + urls: + - assets/portworx/portworx-2.9.101.tgz + version: 2.9.101 - annotations: catalog.cattle.io/certified: partner catalog.cattle.io/display-name: Portworx @@ -3996,6 +4105,45 @@ entries: urls: - assets/portworx/portworx-2.8.0.tgz version: 2.8.0 + portworx-essentials: + - annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Portworx Essentials + catalog.cattle.io/release-name: portworx-essentials + apiVersion: v1 + appVersion: "2.9" + created: "2022-06-08T18:39:47.60312875-06:00" + description: A Helm chart for installing Portworx Essentials on Kubernetes. + digest: dd8a4cac44e1c5f68f4568abcc76c6e7600a1ecb9a8ec345723f061cbfcbefc6 + home: https://portworx.com/ + icon: https://raw.githubusercontent.com/portworx/helm/master/doc/media/k8s-porx.png + keywords: + - Storage + - ICP + - persistent disk + - pvc + - cloud native storage + - persistent storage + - portworx + - amd64 + - portworx essentials + - free + kubeVersion: '>=1.16.0-0' + maintainers: + - email: hadesai@purestorage.com + name: harsh-px + - email: onaumov@purestorage.com + name: trierra + - email: tasharma@purestorage.com + name: sharma-tapas + - email: dahuang@purestorage.com + name: dahuang-purestorage + name: portworx-essentials + sources: + - https://github.com/portworx/charts-rancher/tree/master/stable + urls: + - assets/portworx-essentials/portworx-essentials-2.9.100.tgz + version: 2.9.100 sextant: - annotations: catalog.cattle.io/certified: partner