From 2cb05806c5a72d53a5c8cb2c64335549167b0dc0 Mon Sep 17 00:00:00 2001 From: Bastiaan Date: Wed, 10 Jul 2024 12:06:49 +0200 Subject: [PATCH] Update grafana to chart version 8.3.2 --- external/grafana/Chart.yaml | 21 +- external/grafana/README.md | 290 ++++- .../ci/with-image-renderer-values.yaml | 88 ++ external/grafana/templates/NOTES.txt | 33 +- external/grafana/templates/_helpers.tpl | 247 +++- external/grafana/templates/_pod.tpl | 1138 +++++++++++++---- external/grafana/templates/clusterrole.yaml | 28 +- .../grafana/templates/clusterrolebinding.yaml | 26 +- .../configmap-dashboard-provider.yaml | 30 +- external/grafana/templates/configmap.yaml | 88 +- .../templates/dashboards-json-configmap.yaml | 21 +- external/grafana/templates/deployment.yaml | 55 +- .../grafana/templates/headless-service.yaml | 18 +- external/grafana/templates/hpa.yaml | 44 +- .../templates/image-renderer-deployment.yaml | 180 ++- .../image-renderer-network-policy.yaml | 43 +- .../templates/image-renderer-service.yaml | 31 +- external/grafana/templates/ingress.yaml | 30 +- external/grafana/templates/networkpolicy.yaml | 52 +- .../templates/poddisruptionbudget.yaml | 24 +- .../grafana/templates/podsecuritypolicy.yaml | 4 +- external/grafana/templates/pvc.yaml | 24 +- external/grafana/templates/role.yaml | 42 +- external/grafana/templates/rolebinding.yaml | 28 +- external/grafana/templates/secret-env.yaml | 8 +- external/grafana/templates/secret.yaml | 22 +- external/grafana/templates/service.yaml | 80 +- .../grafana/templates/serviceaccount.yaml | 14 +- .../grafana/templates/servicemonitor.yaml | 30 +- external/grafana/templates/statefulset.yaml | 36 +- .../templates/tests/test-configmap.yaml | 11 +- .../tests/test-podsecuritypolicy.yaml | 19 +- .../grafana/templates/tests/test-role.yaml | 17 +- .../templates/tests/test-rolebinding.yaml | 17 +- .../templates/tests/test-serviceaccount.yaml | 7 +- external/grafana/templates/tests/test.yaml | 36 +- external/grafana/values.yaml | 598 ++++++++- 37 files changed, 2568 insertions(+), 912 deletions(-) diff --git a/external/grafana/Chart.yaml b/external/grafana/Chart.yaml index 2a0e0d2f..99d765d9 100644 --- a/external/grafana/Chart.yaml +++ b/external/grafana/Chart.yaml @@ -1,8 +1,18 @@ +annotations: + artifacthub.io/license: Apache-2.0 + artifacthub.io/links: | + - name: Chart Source + url: https://github.com/grafana/helm-charts + - name: Upstream Project + url: https://github.com/grafana/grafana apiVersion: v2 -appVersion: 8.5.0 +appVersion: 11.1.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 +home: https://grafana.com +icon: https://artifacthub.io/image/b4fed1a7-6c8f-4945-b99d-096efa3e4116 +keywords: +- monitoring +- metric kubeVersion: ^1.8.0-0 maintainers: - email: zanhsieh@gmail.com @@ -15,8 +25,11 @@ maintainers: name: Xtigyro - email: mail@torstenwalter.de name: torstenwalter +- email: github@jkroepke.de + name: jkroepke name: grafana sources: - https://github.com/grafana/grafana +- https://github.com/grafana/helm-charts type: application -version: 6.26.8 +version: 8.3.2 diff --git a/external/grafana/README.md b/external/grafana/README.md index 97a608a9..8c2a9872 100644 --- a/external/grafana/README.md +++ b/external/grafana/README.md @@ -46,6 +46,13 @@ You have to add --force to your helm upgrade command as the labels of the chart This version requires Helm >= 3.1.0. +### To 7.0.0 + +For consistency with other Helm charts, the `global.image.registry` parameter was renamed +to `global.imageRegistry`. If you were not previously setting `global.image.registry`, no action +is required on upgrade. If you were previously setting `global.image.registry`, you will +need to instead set `global.imageRegistry`. + ## Configuration | Parameter | Description | Default | @@ -53,28 +60,34 @@ This version requires Helm >= 3.1.0. | `replicas` | Number of nodes | `1` | | `podDisruptionBudget.minAvailable` | Pod disruption minimum available | `nil` | | `podDisruptionBudget.maxUnavailable` | Pod disruption maximum unavailable | `nil` | +| `podDisruptionBudget.apiVersion` | Pod disruption apiVersion | `nil` | | `deploymentStrategy` | Deployment strategy | `{ "type": "RollingUpdate" }` | | `livenessProbe` | Liveness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } "initialDelaySeconds": 60, "timeoutSeconds": 30, "failureThreshold": 10 }` | | `readinessProbe` | Readiness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } }`| | `securityContext` | Deployment securityContext | `{"runAsUser": 472, "runAsGroup": 472, "fsGroup": 472}` | | `priorityClassName` | Name of Priority Class to assign pods | `nil` | +| `image.registry` | Image registry | `docker.io` | | `image.repository` | Image repository | `grafana/grafana` | -| `image.tag` | Image tag (`Must be >= 5.0.0`) | `8.2.5` | -| `image.sha` | Image sha (optional) | `2acf04c016c77ca2e89af3536367ce847ee326effb933121881c7c89781051d3` | +| `image.tag` | Overrides the Grafana image tag whose default is the chart appVersion (`Must be >= 5.0.0`) | `` | +| `image.sha` | Image sha (optional) | `` | | `image.pullPolicy` | Image pull policy | `IfNotPresent` | -| `image.pullSecrets` | Image pull secrets | `{}` | +| `image.pullSecrets` | Image pull secrets (can be templated) | `[]` | | `service.enabled` | Enable grafana service | `true` | +| `service.ipFamilies` | Kubernetes service IP families | `[]` | +| `service.ipFamilyPolicy` | Kubernetes service IP family policy | `""` | | `service.type` | Kubernetes service type | `ClusterIP` | | `service.port` | Kubernetes port where service is exposed | `80` | | `service.portName` | Name of the port on the service | `service` | +| `service.appProtocol` | Adds the appProtocol field to the service | `` | | `service.targetPort` | Internal service is port | `3000` | | `service.nodePort` | Kubernetes service nodePort | `nil` | -| `service.annotations` | Service annotations | `{}` | +| `service.annotations` | Service annotations (can be templated) | `{}` | | `service.labels` | Custom labels | `{}` | | `service.clusterIP` | internal cluster service IP | `nil` | | `service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `nil` | | `service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to lb (if supported) | `[]` | | `service.externalIPs` | service external IP addresses | `[]` | +| `service.externalTrafficPolicy` | change the default externalTrafficPolicy | `nil` | | `headlessService` | Create a headless service | `false` | | `extraExposePorts` | Additional service ports for sidecar containers| `[]` | | `hostAliases` | adds rules to the pod's /etc/hosts | `[]` | @@ -84,8 +97,9 @@ This version requires Helm >= 3.1.0. | `ingress.path` | Ingress accepted path | `/` | | `ingress.pathType` | Ingress type of path | `Prefix` | | `ingress.hosts` | Ingress accepted hostnames | `["chart-example.local"]` | -| `ingress.extraPaths` | Ingress extra paths to prepend to every host configuration. Useful when configuring [custom actions with AWS ALB Ingress Controller](https://kubernetes-sigs.github.io/aws-alb-ingress-controller/guide/ingress/annotation/#actions). Requires `ingress.hosts` to have one or more host entries. | `[]` | +| `ingress.extraPaths` | Ingress extra paths to prepend to every host configuration. Useful when configuring [custom actions with AWS ALB Ingress Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.6/guide/ingress/annotations/#actions). Requires `ingress.hosts` to have one or more host entries. | `[]` | | `ingress.tls` | Ingress TLS configuration | `[]` | +| `ingress.ingressClassName` | Ingress Class Name. MAY be required for Kubernetes versions >= 1.18 | `""` | | `resources` | CPU/Memory resource requests/limits | `{}` | | `nodeSelector` | Node labels for pod assignment | `{}` | | `tolerations` | Toleration labels for pod assignment | `[]` | @@ -98,15 +112,18 @@ This version requires Helm >= 3.1.0. | `persistence.enabled` | Use persistent volume to store data | `false` | | `persistence.type` | Type of persistence (`pvc` or `statefulset`) | `pvc` | | `persistence.size` | Size of persistent volume claim | `10Gi` | -| `persistence.existingClaim` | Use an existing PVC to persist data | `nil` | +| `persistence.existingClaim` | Use an existing PVC to persist data (can be templated) | `nil` | | `persistence.storageClassName` | Type of persistent volume claim | `nil` | | `persistence.accessModes` | Persistence access modes | `[ReadWriteOnce]` | | `persistence.annotations` | PersistentVolumeClaim annotations | `{}` | | `persistence.finalizers` | PersistentVolumeClaim finalizers | `[ "kubernetes.io/pvc-protection" ]` | -| `persistence.subPath` | Mount a sub dir of the persistent volume | `nil` | +| `persistence.extraPvcLabels` | Extra labels to apply to a PVC. | `{}` | +| `persistence.subPath` | Mount a sub dir of the persistent volume (can be templated) | `nil` | | `persistence.inMemory.enabled` | If persistence is not enabled, whether to mount the local storage in-memory to improve performance | `false` | | `persistence.inMemory.sizeLimit` | SizeLimit for the in-memory local storage | `nil` | +| `persistence.disableWarning` | Hide NOTES warning, useful when persiting to a database | `false` | | `initChownData.enabled` | If false, don't reset data ownership at startup | true | +| `initChownData.image.registry` | init-chown-data container image registry | `docker.io` | | `initChownData.image.repository` | init-chown-data container image repository | `busybox` | | `initChownData.image.tag` | init-chown-data container image tag | `1.31.1` | | `initChownData.image.sha` | init-chown-data container image sha (optional)| `""` | @@ -118,19 +135,25 @@ This version requires Helm >= 3.1.0. | `envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` | | `envFromSecrets` | List of Kubernetes secrets (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `[]` | | `envFromConfigMaps` | List of Kubernetes ConfigMaps (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `[]` | -| `envRenderSecret` | Sensible environment variables passed to pods and stored as secret | `{}` | +| `envRenderSecret` | Sensible environment variables passed to pods and stored as secret. (passed through [tpl](https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-tpl-function)) | `{}` | | `enableServiceLinks` | Inject Kubernetes services as environment variables. | `true` | | `extraSecretMounts` | Additional grafana server secret mounts | `[]` | | `extraVolumeMounts` | Additional grafana server volume mounts | `[]` | -| `extraConfigmapMounts` | Additional grafana server configMap volume mounts | `[]` | +| `extraVolumes` | Additional Grafana server volumes | `[]` | +| `automountServiceAccountToken` | Mounted the service account token on the grafana pod. Mandatory, if sidecars are enabled | `true` | +| `createConfigmap` | Enable creating the grafana configmap | `true` | +| `extraConfigmapMounts` | Additional grafana server configMap volume mounts (values are templated) | `[]` | | `extraEmptyDirMounts` | Additional grafana server emptyDir volume mounts | `[]` | | `plugins` | Plugins to be loaded along with Grafana | `[]` | | `datasources` | Configure grafana datasources (passed through tpl) | `{}` | +| `alerting` | Configure grafana alerting (passed through tpl) | `{}` | | `notifiers` | Configure grafana notifiers | `{}` | | `dashboardProviders` | Configure grafana dashboard providers | `{}` | | `dashboards` | Dashboards to import | `{}` | | `dashboardsConfigMaps` | ConfigMaps reference that contains dashboards | `{}` | | `grafana.ini` | Grafana's primary configuration | `{}` | +| `global.imageRegistry` | Global image pull registry for all images. | `null` | +| `global.imagePullSecrets` | Global image pull secrets (can be templated). Allows either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style). | `[]` | | `ldap.enabled` | Enable LDAP authentication | `false` | | `ldap.existingSecret` | The name of an existing secret containing the `ldap.toml` file, this must have the key `ldap-toml`. | `""` | | `ldap.config` | Grafana's LDAP configuration | `""` | @@ -140,18 +163,30 @@ This version requires Helm >= 3.1.0. | `podLabels` | Pod labels | `{}` | | `podPortName` | Name of the grafana port on the pod | `grafana` | | `lifecycleHooks` | Lifecycle hooks for podStart and preStop [Example](https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/#define-poststart-and-prestop-handlers) | `{}` | -| `sidecar.image.repository` | Sidecar image repository | `quay.io/kiwigrid/k8s-sidecar` | -| `sidecar.image.tag` | Sidecar image tag | `1.15.6` | +| `sidecar.image.registry` | Sidecar image registry | `quay.io` | +| `sidecar.image.repository` | Sidecar image repository | `kiwigrid/k8s-sidecar` | +| `sidecar.image.tag` | Sidecar image tag | `1.26.0` | | `sidecar.image.sha` | Sidecar image sha (optional) | `""` | | `sidecar.imagePullPolicy` | Sidecar image pull policy | `IfNotPresent` | | `sidecar.resources` | Sidecar resources | `{}` | | `sidecar.securityContext` | Sidecar securityContext | `{}` | | `sidecar.enableUniqueFilenames` | Sets the kiwigrid/k8s-sidecar UNIQUE_FILENAMES environment variable. If set to `true` the sidecar will create unique filenames where duplicate data keys exist between ConfigMaps and/or Secrets within the same or multiple Namespaces. | `false` | +| `sidecar.alerts.enabled` | Enables the cluster wide search for alerts and adds/updates/deletes them in grafana |`false` | +| `sidecar.alerts.label` | Label that config maps with alerts should have to be added | `grafana_alert` | +| `sidecar.alerts.labelValue` | Label value that config maps with alerts should have to be added | `""` | +| `sidecar.alerts.searchNamespace` | Namespaces list. If specified, the sidecar will search for alerts config-maps 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. | `nil` | +| `sidecar.alerts.watchMethod` | 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. | `WATCH` | +| `sidecar.alerts.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | +| `sidecar.alerts.reloadURL` | Full url of datasource configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/alerting/reload"` | +| `sidecar.alerts.skipReload` | Enabling this omits defining the REQ_URL and REQ_METHOD environment variables | `false` | +| `sidecar.alerts.initAlerts` | Set to true to deploy the alerts sidecar as an initContainer. This is needed if skipReload is true, to load any alerts defined at startup time. | `false` | +| `sidecar.alerts.extraMounts` | Additional alerts sidecar volume mounts. | `[]` | | `sidecar.dashboards.enabled` | Enables the cluster wide search for dashboards and adds/updates/deletes them in grafana | `false` | | `sidecar.dashboards.SCProvider` | Enables creation of sidecar provider | `true` | | `sidecar.dashboards.provider.name` | Unique name of the grafana provider | `sidecarProvider` | | `sidecar.dashboards.provider.orgid` | Id of the organisation, to which the dashboards should be added | `1` | | `sidecar.dashboards.provider.folder` | Logical folder in which grafana groups dashboards | `""` | +| `sidecar.dashboards.provider.folderUid` | Allows you to specify the static UID for the logical folder above | `""` | | `sidecar.dashboards.provider.disableDelete` | Activate to avoid the deletion of imported dashboards | `false` | | `sidecar.dashboards.provider.allowUiUpdates` | Allow updating provisioned dashboards from the UI | `false` | | `sidecar.dashboards.provider.type` | Provider type | `file` | @@ -159,53 +194,66 @@ This version requires Helm >= 3.1.0. | `sidecar.dashboards.watchMethod` | 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. | `WATCH` | | `sidecar.skipTlsVerify` | Set to true to skip tls verification for kube api calls | `nil` | | `sidecar.dashboards.label` | Label that config maps with dashboards should have to be added | `grafana_dashboard` | -| `sidecar.dashboards.labelValue` | Label value that config maps with dashboards should have to be added | `nil` | +| `sidecar.dashboards.labelValue` | Label value that config maps with dashboards should have to be added | `""` | | `sidecar.dashboards.folder` | Folder in the pod that should hold the collected dashboards (unless `sidecar.dashboards.defaultFolderName` is set). This path will be mounted. | `/tmp/dashboards` | | `sidecar.dashboards.folderAnnotation` | The annotation the sidecar will look for in configmaps to override the destination folder for files | `nil` | | `sidecar.dashboards.defaultFolderName` | The default folder name, it will create a subfolder under the `sidecar.dashboards.folder` and put dashboards in there instead | `nil` | -| `sidecar.dashboards.searchNamespace` | Namespaces list. If specified, the sidecar will search for dashboards config-maps 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. | `nil` | +| `sidecar.dashboards.searchNamespace` | Namespaces list. If specified, the sidecar will search for dashboards config-maps 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. | `nil` | | `sidecar.dashboards.script` | Absolute path to shell script to execute after a configmap got reloaded. | `nil` | +| `sidecar.dashboards.reloadURL` | Full url of dashboards configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/dashboards/reload"` | +| `sidecar.dashboards.skipReload` | Enabling this omits defining the REQ_USERNAME, REQ_PASSWORD, REQ_URL and REQ_METHOD environment variables | `false` | | `sidecar.dashboards.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | | `sidecar.dashboards.extraMounts` | Additional dashboard sidecar volume mounts. | `[]` | | `sidecar.datasources.enabled` | Enables the cluster wide search for datasources and adds/updates/deletes them in grafana |`false` | | `sidecar.datasources.label` | Label that config maps with datasources should have to be added | `grafana_datasource` | -| `sidecar.datasources.labelValue` | Label value that config maps with datasources should have to be added | `nil` | -| `sidecar.datasources.searchNamespace` | Namespaces list. If specified, the sidecar will search for datasources config-maps 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. | `nil` | +| `sidecar.datasources.labelValue` | Label value that config maps with datasources should have to be added | `""` | +| `sidecar.datasources.searchNamespace` | Namespaces list. If specified, the sidecar will search for datasources config-maps 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. | `nil` | +| `sidecar.datasources.watchMethod` | 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. | `WATCH` | | `sidecar.datasources.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | | `sidecar.datasources.reloadURL` | Full url of datasource configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/datasources/reload"` | | `sidecar.datasources.skipReload` | Enabling this omits defining the REQ_URL and REQ_METHOD environment variables | `false` | +| `sidecar.datasources.initDatasources` | Set to true to 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. | `false` | | `sidecar.notifiers.enabled` | Enables the cluster wide search for notifiers and adds/updates/deletes them in grafana | `false` | | `sidecar.notifiers.label` | Label that config maps with notifiers should have to be added | `grafana_notifier` | -| `sidecar.notifiers.searchNamespace` | Namespaces list. If specified, the sidecar will search for notifiers config-maps (or 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. | `nil` | +| `sidecar.notifiers.labelValue` | Label value that config maps with notifiers should have to be added | `""` | +| `sidecar.notifiers.searchNamespace` | Namespaces list. If specified, the sidecar will search for notifiers config-maps (or 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. | `nil` | +| `sidecar.notifiers.watchMethod` | 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. | `WATCH` | | `sidecar.notifiers.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` | +| `sidecar.notifiers.reloadURL` | Full url of notifier configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/notifications/reload"` | +| `sidecar.notifiers.skipReload` | Enabling this omits defining the REQ_URL and REQ_METHOD environment variables | `false` | +| `sidecar.notifiers.initNotifiers` | Set to true to deploy the notifier sidecar as an initContainer in addition to a container. This is needed if skipReload is true, to load any notifiers defined at startup time. | `false` | | `smtp.existingSecret` | The name of an existing secret containing the SMTP credentials. | `""` | | `smtp.userKey` | The key in the existing SMTP secret containing the username. | `"user"` | | `smtp.passwordKey` | The key in the existing SMTP secret containing the password. | `"password"` | -| `admin.existingSecret` | The name of an existing secret containing the admin credentials. | `""` | +| `admin.existingSecret` | The name of an existing secret containing the admin credentials (can be templated). | `""` | | `admin.userKey` | The key in the existing admin secret containing the username. | `"admin-user"` | | `admin.passwordKey` | The key in the existing admin secret containing the password. | `"admin-password"` | -| `serviceAccount.autoMount` | Automount the service account token in the pod| `true` | +| `serviceAccount.automountServiceAccountToken` | Automount the service account token on all pods where is service account is used | `false` | | `serviceAccount.annotations` | ServiceAccount annotations | | | `serviceAccount.create` | Create service account | `true` | +| `serviceAccount.labels` | ServiceAccount labels | `{}` | | `serviceAccount.name` | Service account name to use, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `` | | `serviceAccount.nameTest` | Service account name to use for test, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `nil` | | `rbac.create` | Create and use RBAC resources | `true` | | `rbac.namespaced` | Creates Role and Rolebinding instead of the default ClusterRole and ClusteRoleBindings for the grafana instance | `false` | | `rbac.useExistingRole` | Set to a rolename to use existing role - skipping role creating - but still doing serviceaccount and rolebinding to the rolename set here. | `nil` | -| `rbac.pspEnabled` | Create PodSecurityPolicy (with `rbac.create`, grant roles permissions as well) | `true` | -| `rbac.pspUseAppArmor` | Enforce AppArmor in created PodSecurityPolicy (requires `rbac.pspEnabled`) | `true` | +| `rbac.pspEnabled` | Create PodSecurityPolicy (with `rbac.create`, grant roles permissions as well) | `false` | +| `rbac.pspUseAppArmor` | Enforce AppArmor in created PodSecurityPolicy (requires `rbac.pspEnabled`) | `false` | | `rbac.extraRoleRules` | Additional rules to add to the Role | [] | | `rbac.extraClusterRoleRules` | Additional rules to add to the ClusterRole | [] | -| `command` | Define command to be executed by grafana container at startup | `nil` | +| `command` | Define command to be executed by grafana container at startup | `nil` | +| `args` | Define additional args if command is used | `nil` | | `testFramework.enabled` | Whether to create test-related resources | `true` | -| `testFramework.image` | `test-framework` image repository. | `bats/bats` | -| `testFramework.tag` | `test-framework` image tag. | `v1.4.1` | +| `testFramework.image.registry` | `test-framework` image registry. | `docker.io` | +| `testFramework.image.repository` | `test-framework` image repository. | `bats/bats` | +| `testFramework.image.tag` | `test-framework` image tag. | `v1.4.1` | | `testFramework.imagePullPolicy` | `test-framework` image pull policy. | `IfNotPresent` | | `testFramework.securityContext` | `test-framework` securityContext | `{}` | | `downloadDashboards.env` | Environment variables to be passed to the `download-dashboards` container | `{}` | | `downloadDashboards.envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` | | `downloadDashboards.resources` | Resources of `download-dashboards` container | `{}` | -| `downloadDashboardsImage.repository` | Curl docker image repo | `curlimages/curl` | +| `downloadDashboardsImage.registry` | Curl docker image registry | `docker.io` | +| `downloadDashboardsImage.repository` | Curl docker image repository | `curlimages/curl` | | `downloadDashboardsImage.tag` | Curl docker image tag | `7.73.0` | | `downloadDashboardsImage.sha` | Curl docker image sha (optional) | `""` | | `downloadDashboardsImage.pullPolicy` | Curl docker image pull policy | `IfNotPresent` | @@ -218,41 +266,52 @@ This version requires Helm >= 3.1.0. | `serviceMonitor.tlsConfig` | TLS configuration block for the endpoint | `{}` | | `serviceMonitor.labels` | Labels for the servicemonitor passed to Prometheus Operator | `{}` | | `serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `30s` | -| `serviceMonitor.relabelings` | MetricRelabelConfigs to apply to samples before ingestion. | `[]` | +| `serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping. | `[]` | +| `serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion. | `[]` | | `revisionHistoryLimit` | Number of old ReplicaSets to retain | `10` | | `imageRenderer.enabled` | Enable the image-renderer deployment & service | `false` | +| `imageRenderer.image.registry` | image-renderer Image registry | `docker.io` | | `imageRenderer.image.repository` | image-renderer Image repository | `grafana/grafana-image-renderer` | | `imageRenderer.image.tag` | image-renderer Image tag | `latest` | | `imageRenderer.image.sha` | image-renderer Image sha (optional) | `""` | | `imageRenderer.image.pullPolicy` | image-renderer ImagePullPolicy | `Always` | | `imageRenderer.env` | extra env-vars for image-renderer | `{}` | +| `imageRenderer.envValueFrom` | Environment variables for image-renderer from alternate sources. See the API docs on [EnvVarSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#envvarsource-v1-core) for format details. Can be templated | `{}` | +| `imageRenderer.extraConfigmapMounts` | Additional image-renderer configMap volume mounts (values are templated) | `[]` | +| `imageRenderer.extraSecretMounts` | Additional image-renderer secret volume mounts | `[]` | +| `imageRenderer.extraVolumeMounts` | Additional image-renderer volume mounts | `[]` | +| `imageRenderer.extraVolumes` | Additional image-renderer volumes | `[]` | | `imageRenderer.serviceAccountName` | image-renderer deployment serviceAccountName | `""` | | `imageRenderer.securityContext` | image-renderer deployment securityContext | `{}` | +| `imageRenderer.podAnnotations` | image-renderer image-renderer pod annotation | `{}` | | `imageRenderer.hostAliases` | image-renderer deployment Host Aliases | `[]` | | `imageRenderer.priorityClassName` | image-renderer deployment priority class | `''` | | `imageRenderer.service.enabled` | Enable the image-renderer service | `true` | | `imageRenderer.service.portName` | image-renderer service port name | `http` | -| `imageRenderer.service.port` | image-renderer service port used by both service and deployment | `8081` | -| `imageRenderer.grafanaProtocol` | Protocol to use for image renderer callback url | `http` | +| `imageRenderer.service.port` | image-renderer port used by deployment | `8081` | +| `imageRenderer.service.targetPort` | image-renderer service port used by service | `8081` | +| `imageRenderer.appProtocol` | Adds the appProtocol field to the service | `` | | `imageRenderer.grafanaSubPath` | Grafana sub path to use for image renderer callback url | `''` | | `imageRenderer.podPortName` | name of the image-renderer port on the pod | `http` | | `imageRenderer.revisionHistoryLimit` | number of image-renderer replica sets to keep | `10` | -| `imageRenderer.networkPolicy.limitIngress` | Enable a NetworkPolicy to limit inbound traffic from only the created grafana pods | `true` | -| `imageRenderer.networkPolicy.limitEgress` | Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods | `false` | -| `imageRenderer.resources` | Set resource limits for image-renderer pdos | `{}` | +| `imageRenderer.networkPolicy.limitIngress` | Enable a NetworkPolicy to limit inbound traffic from only the created grafana pods | `true` | +| `imageRenderer.networkPolicy.limitEgress` | Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods | `false` | +| `imageRenderer.resources` | Set resource limits for image-renderer pods | `{}` | | `imageRenderer.nodeSelector` | Node labels for pod assignment | `{}` | | `imageRenderer.tolerations` | Toleration labels for pod assignment | `[]` | | `imageRenderer.affinity` | Affinity settings for pod assignment | `{}` | | `networkPolicy.enabled` | Enable creation of NetworkPolicy resources. | `false` | | `networkPolicy.allowExternal` | Don't require client label for connections | `true` | | `networkPolicy.explicitNamespacesSelector` | A Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed | `{}` | +| `networkPolicy.ingress` | Enable the creation of an ingress network policy | `true` | +| `networkPolicy.egress.enabled` | Enable the creation of an egress network policy | `false` | +| `networkPolicy.egress.ports` | An array of ports to allow for the egress | `[]` | | `enableKubeBackwardCompatibility` | Enable backward compatibility of kubernetes where pod's defintion version below 1.13 doesn't have the enableServiceLinks option | `false` | - - ### Example ingress with path With grafana 6.3 and above + ```yaml grafana.ini: server: @@ -266,24 +325,35 @@ ingress: path: "/grafana" ``` -### Example of extraVolumeMounts +### Example of extraVolumeMounts and extraVolumes + +Configure additional volumes with `extraVolumes` and volume mounts with `extraVolumeMounts`. -Volume can be type persistentVolumeClaim or hostPath but not both at same time. -If none existingClaim or hostPath argument is givent then type is emptyDir. +Example for `extraVolumeMounts` and corresponding `extraVolumes`: ```yaml -- extraVolumeMounts: +extraVolumeMounts: - name: plugins mountPath: /var/lib/grafana/plugins subPath: configs/grafana/plugins - existingClaim: existing-grafana-claim readOnly: false - name: dashboards mountPath: /var/lib/grafana/dashboards hostPath: /usr/shared/grafana/dashboards readOnly: false + +extraVolumes: + - name: plugins + existingClaim: existing-grafana-claim + - name: dashboards + hostPath: /usr/shared/grafana/dashboards ``` +Volumes default to `emptyDir`. Set to `persistentVolumeClaim`, +`hostPath`, `csi`, or `configMap` for other types. For a +`persistentVolumeClaim`, specify an existing claim name with +`existingClaim`. + ## Import dashboards There are a few methods to import dashboards to Grafana. Below are some examples and explanations as to how to use each method: @@ -312,6 +382,14 @@ dashboards: gnetId: 2 revision: 2 datasource: Prometheus + loki-dashboard-quick-search: + gnetId: 12019 + revision: 2 + datasource: + - name: DS_PROMETHEUS + value: Prometheus + - name: DS_LOKI + value: Loki local-dashboard: url: https://raw.githubusercontent.com/user/repository/master/dashboards/dashboard.json ``` @@ -361,9 +439,42 @@ filters out the ones with a label as defined in `sidecar.datasources.label`. The those secrets are written to a folder and accessed by grafana on startup. Using these yaml files, the data sources in grafana can be imported. +Should you aim for reloading datasources in Grafana each time the config is changed, set `sidecar.datasources.skipReload: false` and adjust `sidecar.datasources.reloadURL` to `http://..svc.cluster.local/api/admin/provisioning/datasources/reload`. + Secrets are recommended over configmaps for this usecase because datasources usually contain private data like usernames and passwords. Secrets are the more appropriate cluster resource to manage those. +Example values to add a postgres datasource as a kubernetes secret: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: grafana-datasources + labels: + grafana_datasource: 'true' # default value for: sidecar.datasources.label +stringData: + pg-db.yaml: |- + apiVersion: 1 + datasources: + - name: My pg db datasource + type: postgres + url: my-postgresql-db:5432 + user: db-readonly-user + secureJsonData: + password: 'SUperSEcretPa$$word' + jsonData: + database: my_datase + sslmode: 'disable' # disable/require/verify-ca/verify-full + maxOpenConns: 0 # Grafana v5.4+ + maxIdleConns: 2 # Grafana v5.4+ + connMaxLifetime: 14400 # Grafana v5.4+ + postgresVersion: 1000 # 903=9.3, 904=9.4, 905=9.5, 906=9.6, 1000=10 + timescaledb: false + # allow users to edit datasources from the UI. + editable: false +``` + Example values to add a datasource adapted from [Grafana](http://docs.grafana.org/administration/provisioning/#example-datasource-config-file): ```yaml @@ -455,6 +566,106 @@ delete_notifiers: # default org_id: 1 ``` +## Sidecar for alerting resources + +If the parameter `sidecar.alerts.enabled` is set, a sidecar container is deployed in the grafana +pod. This container watches all configmaps (or secrets) in the cluster (namespace defined by `sidecar.alerts.searchNamespace`) and filters out the ones with +a label as defined in `sidecar.alerts.label` (default is `grafana_alert`). The files defined in those configmaps are written +to a folder and accessed by grafana. Changes to the configmaps are monitored and the imported alerting resources are updated, however, deletions are a little more complicated (see below). + +This sidecar can be used to provision alert rules, contact points, notification policies, notification templates and mute timings as shown in [Grafana Documentation](https://grafana.com/docs/grafana/next/alerting/set-up/provision-alerting-resources/file-provisioning/). + +To fetch the alert config which will be provisioned, use the alert provisioning API ([Grafana Documentation](https://grafana.com/docs/grafana/next/developers/http_api/alerting_provisioning/)). +You can use either JSON or YAML format. + +Example config for an alert rule: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: sample-grafana-alert + labels: + grafana_alert: "1" +data: + k8s-alert.yml: |- + apiVersion: 1 + groups: + - orgId: 1 + name: k8s-alert + [...] +``` + +To delete provisioned alert rules is a two step process, you need to delete the configmap which defined the alert rule +and then create a configuration which deletes the alert rule. + +Example deletion configuration: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: delete-sample-grafana-alert + namespace: monitoring + labels: + grafana_alert: "1" +data: + delete-k8s-alert.yml: |- + apiVersion: 1 + deleteRules: + - orgId: 1 + uid: 16624780-6564-45dc-825c-8bded4ad92d3 +``` + +## Statically provision alerting resources + +If you don't need to change alerting resources (alert rules, contact points, notification policies and notification templates) regularly you could use the `alerting` config option instead of the sidecar option above. +This will grab the alerting config and apply it statically at build time for the helm file. + +There are two methods to statically provision alerting configuration in Grafana. Below are some examples and explanations as to how to use each method: + +```yaml +alerting: + team1-alert-rules.yaml: + file: alerting/team1/rules.yaml + team2-alert-rules.yaml: + file: alerting/team2/rules.yaml + team3-alert-rules.yaml: + file: alerting/team3/rules.yaml + notification-policies.yaml: + file: alerting/shared/notification-policies.yaml + notification-templates.yaml: + file: alerting/shared/notification-templates.yaml + contactpoints.yaml: + apiVersion: 1 + contactPoints: + - orgId: 1 + name: Slack channel + receivers: + - uid: default-receiver + type: slack + settings: + # Webhook URL to be filled in + url: "" + # We need to escape double curly braces for the tpl function. + text: '{{ `{{ template "default.message" . }}` }}' + title: '{{ `{{ template "default.title" . }}` }}' +``` + +The two possibilities for static alerting resource provisioning are: + +* Inlining the file contents as shown for contact points in the above example. +* Importing a file using a relative path starting from the chart root directory as shown for the alert rules in the above example. + +### Important notes on file provisioning + +* The format of the files is defined in the [Grafana documentation](https://grafana.com/docs/grafana/next/alerting/set-up/provision-alerting-resources/file-provisioning/) on file provisioning. +* The chart supports importing YAML and JSON files. +* The filename must be unique, otherwise one volume mount will overwrite the other. +* In case of inlining, double curly braces that arise from the Grafana configuration format and are not intended as templates for the chart must be escaped. +* The number of total files under `alerting:` is not limited. Each file will end up as a volume mount in the corresponding provisioning folder of the deployed Grafana instance. +* The file size for each import is limited by what the function `.Files.Get` can handle, which suffices for most cases. + ## How to serve Grafana with a path prefix (/grafana) In order to serve Grafana with a prefix (e.g., ), add the following to your values.yaml. @@ -478,7 +689,7 @@ grafana.ini: ## How to securely reference secrets in grafana.ini -This example uses Grafana uses [file providers](https://grafana.com/docs/grafana/latest/administration/configuration/#file-provider) for secret values and the `extraSecretMounts` configuration flag (Additional grafana server secret mounts) to mount the secrets. +This example uses Grafana [file providers](https://grafana.com/docs/grafana/latest/administration/configuration/#file-provider) for secret values and the `extraSecretMounts` configuration flag (Additional grafana server secret mounts) to mount the secrets. In grafana.ini: @@ -562,6 +773,9 @@ grafana.ini: unified_alerting: enabled: true ha_peers: {{ Name }}-headless:9094 + ha_listen_address: ${POD_IP}:9094 + ha_advertise_address: ${POD_IP}:9094 + alerting: enabled: false ``` diff --git a/external/grafana/ci/with-image-renderer-values.yaml b/external/grafana/ci/with-image-renderer-values.yaml index 32f30743..06c0bda1 100644 --- a/external/grafana/ci/with-image-renderer-values.yaml +++ b/external/grafana/ci/with-image-renderer-values.yaml @@ -17,3 +17,91 @@ imageRenderer: requests: cpu: 500m memory: 50Mi + extraVolumes: + - name: empty-renderer-volume + emtpyDir: {} + extraVolumeMounts: + - mountPath: /tmp/renderer + name: empty-renderer-volume + extraConfigmapMounts: + - name: renderer-config + mountPath: /usr/src/app/config.json + subPath: renderer-config.json + configMap: image-renderer-config + extraSecretMounts: + - name: renderer-certificate + mountPath: /usr/src/app/certs/ + secretName: image-renderer-certificate + readOnly: true + +extraObjects: + - apiVersion: v1 + kind: ConfigMap + metadata: + name: image-renderer-config + data: + renderer-config.json: | + { + "service": { + "host": null, + "port": 8081, + "protocol": "http", + "certFile": "", + "certKey": "", + + "metrics": { + "enabled": true, + "collectDefaultMetrics": true, + "requestDurationBuckets": [1, 5, 7, 9, 11, 13, 15, 20, 30] + }, + + "logging": { + "level": "info", + "console": { + "json": true, + "colorize": false + } + }, + + "security": { + "authToken": "-" + } + }, + "rendering": { + "chromeBin": null, + "args": ["--no-sandbox", "--disable-gpu"], + "ignoresHttpsErrors": false, + + "timezone": null, + "acceptLanguage": null, + "width": 1000, + "height": 500, + "deviceScaleFactor": 1, + "maxWidth": 3080, + "maxHeight": 3000, + "maxDeviceScaleFactor": 4, + "pageZoomLevel": 1, + "headed": false, + + "mode": "default", + "emulateNetworkConditions": false, + "clustering": { + "monitor": false, + "mode": "browser", + "maxConcurrency": 5, + "timeout": 30 + }, + + "verboseLogging": false, + "dumpio": false, + "timingMetrics": false + } + } + - apiVersion: v1 + kind: Secret + metadata: + name: image-renderer-certificate + type: Opaque + data: + # Decodes to 'PLACEHOLDER CERTIFICATE' + not-a-real-certificate: UExBQ0VIT0xERVIgQ0VSVElGSUNBVEU= diff --git a/external/grafana/templates/NOTES.txt b/external/grafana/templates/NOTES.txt index 1fc8436d..a40f666a 100644 --- a/external/grafana/templates/NOTES.txt +++ b/external/grafana/templates/NOTES.txt @@ -1,10 +1,11 @@ 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 + kubectl get secret --namespace {{ include "grafana.namespace" . }} {{ .Values.admin.existingSecret | default (include "grafana.fullname" .) }} -o jsonpath="{.data.{{ .Values.admin.passwordKey | default "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 + {{ include "grafana.fullname" . }}.{{ include "grafana.namespace" . }}.svc.cluster.local {{ if .Values.ingress.enabled }} If you bind grafana to 80, please update values in values.yaml and reinstall: ``` @@ -24,29 +25,29 @@ Or grafana would always crash. From outside the cluster, the server URL(s) are: -{{- range .Values.ingress.hosts }} + {{- range .Values.ingress.hosts }} http://{{ . }} -{{- end }} -{{ else }} + {{- 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}") + {{- if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ include "grafana.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "grafana.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ include "grafana.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}") echo http://$NODE_IP:$NODE_PORT -{{ else if contains "LoadBalancer" .Values.service.type -}} + {{- 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}') + You can watch the status of by running 'kubectl get svc --namespace {{ include "grafana.namespace" . }} -w {{ include "grafana.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ include "grafana.namespace" . }} {{ include "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 }} + {{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ include "grafana.namespace" . }} -l "app.kubernetes.io/name={{ include "grafana.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + kubectl --namespace {{ include "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 }} +{{- if and (not .Values.persistence.enabled) (not .Values.persistence.disableWarning) }} ################################################################################# ###### WARNING: Persistence is disabled!!! You will lose your data when ##### ###### the Grafana pod is terminated. ##### diff --git a/external/grafana/templates/_helpers.tpl b/external/grafana/templates/_helpers.tpl index f0c06aad..f3ebc37c 100644 --- a/external/grafana/templates/_helpers.tpl +++ b/external/grafana/templates/_helpers.tpl @@ -3,8 +3,8 @@ Expand the name of the chart. */}} {{- define "grafana.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} {{/* Create a default fully qualified app name. @@ -12,54 +12,54 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this 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 -}} +{{- 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 -}} +{{- 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 -}} +{{- 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 -}} +{{- 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 -}} +{{- if .Values.namespaceOverride }} +{{- .Values.namespaceOverride }} +{{- else }} +{{- .Release.Namespace }} +{{- end }} +{{- end }} {{/* Common labels @@ -68,13 +68,13 @@ Common 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 }} +app.kubernetes.io/version: {{ mustRegexReplaceAllLiteral "@sha.*" .Values.image.tag "" | default .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- if .Values.extraLabels }} -{{ toYaml .Values.extraLabels }} +{{- with .Values.extraLabels }} +{{ toYaml . }} +{{- end }} {{- end }} -{{- end -}} {{/* Selector labels @@ -82,7 +82,7 @@ Selector labels {{- define "grafana.selectorLabels" -}} app.kubernetes.io/name: {{ include "grafana.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} +{{- end }} {{/* Common labels @@ -91,10 +91,10 @@ Common 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 }} +app.kubernetes.io/version: {{ mustRegexReplaceAllLiteral "@sha.*" .Values.image.tag "" | default .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end -}} +{{- end }} {{/* Selector labels ImageRenderer @@ -102,62 +102,175 @@ Selector labels ImageRenderer {{- define "grafana.imageRenderer.selectorLabels" -}} app.kubernetes.io/name: {{ include "grafana.name" . }}-image-renderer app.kubernetes.io/instance: {{ .Release.Name }} -{{- end -}} +{{- 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 -}} +{{- $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 -}} +{{- 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 -}} +{{- 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 the appropriate apiVersion for Horizontal Pod Autoscaler. +*/}} +{{- define "grafana.hpa.apiVersion" -}} +{{- if .Capabilities.APIVersions.Has "autoscaling/v2" }} +{{- print "autoscaling/v2" }} +{{- else }} +{{- print "autoscaling/v2beta2" }} +{{- end }} +{{- end }} + +{{/* +Return the appropriate apiVersion for podDisruptionBudget. +*/}} +{{- define "grafana.podDisruptionBudget.apiVersion" -}} +{{- if $.Values.podDisruptionBudget.apiVersion }} +{{- print $.Values.podDisruptionBudget.apiVersion }} +{{- else if $.Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }} +{{- print "policy/v1" }} +{{- else }} +{{- print "policy/v1beta1" }} +{{- end }} +{{- end }} {{/* Return if ingress is stable. */}} {{- define "grafana.ingress.isStable" -}} - {{- eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1" -}} -{{- end -}} +{{- 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 -}} +{{- 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)) -}} +{{- 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 }} + +{{/* +Formats imagePullSecrets. Input is (dict "root" . "imagePullSecrets" .{specific imagePullSecrets}) +*/}} +{{- define "grafana.imagePullSecrets" -}} +{{- $root := .root }} +{{- range (concat .root.Values.global.imagePullSecrets .imagePullSecrets) }} +{{- if eq (typeOf .) "map[string]interface {}" }} +- {{ toYaml (dict "name" (tpl .name $root)) | trim }} +{{- else }} +- name: {{ tpl . $root }} +{{- end }} +{{- end }} +{{- end }} + + +{{/* + Checks whether or not the configSecret secret has to be created + */}} +{{- define "grafana.shouldCreateConfigSecret" -}} +{{- $secretFound := false -}} +{{- range $key, $value := .Values.datasources }} + {{- if hasKey $value "secret" }} + {{- $secretFound = true}} + {{- end }} +{{- end }} +{{- range $key, $value := .Values.notifiers }} + {{- if hasKey $value "secret" }} + {{- $secretFound = true}} + {{- end }} +{{- end }} +{{- range $key, $value := .Values.alerting }} + {{- if (or (hasKey $value "secret") (hasKey $value "secretFile")) }} + {{- $secretFound = true}} + {{- end }} +{{- end }} +{{- $secretFound}} +{{- end -}} + +{{/* + Checks whether the user is attempting to store secrets in plaintext + in the grafana.ini configmap +*/}} +{{/* grafana.assertNoLeakedSecrets checks for sensitive keys in values */}} +{{- define "grafana.assertNoLeakedSecrets" -}} + {{- $sensitiveKeysYaml := ` +sensitiveKeys: +- path: ["database", "password"] +- path: ["smtp", "password"] +- path: ["security", "secret_key"] +- path: ["security", "admin_password"] +- path: ["auth.basic", "password"] +- path: ["auth.ldap", "bind_password"] +- path: ["auth.google", "client_secret"] +- path: ["auth.github", "client_secret"] +- path: ["auth.gitlab", "client_secret"] +- path: ["auth.generic_oauth", "client_secret"] +- path: ["auth.okta", "client_secret"] +- path: ["auth.azuread", "client_secret"] +- path: ["auth.grafana_com", "client_secret"] +- path: ["auth.grafananet", "client_secret"] +- path: ["azure", "user_identity_client_secret"] +- path: ["unified_alerting", "ha_redis_password"] +- path: ["metrics", "basic_auth_password"] +- path: ["external_image_storage.s3", "secret_key"] +- path: ["external_image_storage.webdav", "password"] +- path: ["external_image_storage.azure_blob", "account_key"] +` | fromYaml -}} + {{- if $.Values.assertNoLeakedSecrets -}} + {{- $grafanaIni := index .Values "grafana.ini" -}} + {{- range $_, $secret := $sensitiveKeysYaml.sensitiveKeys -}} + {{- $currentMap := $grafanaIni -}} + {{- $shouldContinue := true -}} + {{- range $index, $elem := $secret.path -}} + {{- if and $shouldContinue (hasKey $currentMap $elem) -}} + {{- if eq (len $secret.path) (add1 $index) -}} + {{- if not (regexMatch "\\$(?:__(?:env|file|vault))?{[^}]+}" (index $currentMap $elem)) -}} + {{- fail (printf "Sensitive key '%s' should not be defined explicitly in values. Use variable expansion instead. You can disable this client-side validation by changing the value of assertNoLeakedSecrets." (join "." $secret.path)) -}} + {{- end -}} + {{- else -}} + {{- $currentMap = index $currentMap $elem -}} + {{- end -}} + {{- else -}} + {{- $shouldContinue = false -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} {{- end -}} diff --git a/external/grafana/templates/_pod.tpl b/external/grafana/templates/_pod.tpl index 5f35d276..93f8da30 100644 --- a/external/grafana/templates/_pod.tpl +++ b/external/grafana/templates/_pod.tpl @@ -1,284 +1,613 @@ - {{- define "grafana.pod" -}} -{{- if .Values.schedulerName }} -schedulerName: "{{ .Values.schedulerName }}" +{{- $sts := list "sts" "StatefulSet" "statefulset" -}} +{{- $root := . -}} +{{- with .Values.schedulerName }} +schedulerName: "{{ . }}" {{- end }} -serviceAccountName: {{ template "grafana.serviceAccountName" . }} -automountServiceAccountToken: {{ .Values.serviceAccount.autoMount }} -{{- if .Values.securityContext }} +serviceAccountName: {{ include "grafana.serviceAccountName" . }} +automountServiceAccountToken: {{ .Values.automountServiceAccountToken }} +{{- with .Values.securityContext }} securityContext: -{{ toYaml .Values.securityContext | indent 2 }} + {{- toYaml . | nindent 2 }} {{- end }} -{{- if .Values.hostAliases }} +{{- with .Values.hostAliases }} hostAliases: -{{ toYaml .Values.hostAliases | indent 2 }} + {{- toYaml . | nindent 2 }} {{- end }} -{{- if .Values.priorityClassName }} -priorityClassName: {{ .Values.priorityClassName }} +{{- if .Values.dnsPolicy }} +dnsPolicy: {{ .Values.dnsPolicy }} {{- end }} -{{- if ( or .Values.persistence.enabled .Values.dashboards .Values.sidecar.notifiers.enabled .Values.extraInitContainers (and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources)) }} +{{- with .Values.dnsConfig }} +dnsConfig: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- with .Values.priorityClassName }} +priorityClassName: {{ . }} +{{- end }} +{{- if ( or .Values.persistence.enabled .Values.dashboards .Values.extraInitContainers (and .Values.sidecar.alerts.enabled .Values.sidecar.alerts.initAlerts) (and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources) (and .Values.sidecar.notifiers.enabled .Values.sidecar.notifiers.initNotifiers)) }} initContainers: {{- end }} {{- if ( and .Values.persistence.enabled .Values.initChownData.enabled ) }} - name: init-chown-data + {{- $registry := .Values.global.imageRegistry | default .Values.initChownData.image.registry -}} {{- if .Values.initChownData.image.sha }} - image: "{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}@sha256:{{ .Values.initChownData.image.sha }}" + image: "{{ $registry }}/{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}@sha256:{{ .Values.initChownData.image.sha }}" {{- else }} - image: "{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}" + image: "{{ $registry }}/{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}" {{- end }} imagePullPolicy: {{ .Values.initChownData.image.pullPolicy }} + {{- with .Values.initChownData.securityContext }} securityContext: - runAsNonRoot: false - runAsUser: 0 - command: ["chown", "-R", "{{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }}", "/var/lib/grafana"] + {{- toYaml . | nindent 6 }} + {{- end }} + command: + - chown + - -R + - {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} + - /var/lib/grafana + {{- with .Values.initChownData.resources }} resources: -{{ toYaml .Values.initChownData.resources | indent 6 }} + {{- toYaml . | nindent 6 }} + {{- end }} volumeMounts: - name: storage mountPath: "/var/lib/grafana" -{{- if .Values.persistence.subPath }} - subPath: {{ .Values.persistence.subPath }} -{{- end }} + {{- with .Values.persistence.subPath }} + subPath: {{ tpl . $root }} + {{- end }} {{- end }} {{- if .Values.dashboards }} - name: download-dashboards + {{- $registry := .Values.global.imageRegistry | default .Values.downloadDashboardsImage.registry -}} {{- if .Values.downloadDashboardsImage.sha }} - image: "{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}@sha256:{{ .Values.downloadDashboardsImage.sha }}" + image: "{{ $registry }}/{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}@sha256:{{ .Values.downloadDashboardsImage.sha }}" {{- else }} - image: "{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}" + image: "{{ $registry }}/{{ .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" ] + {{- with .Values.downloadDashboards.resources }} resources: -{{ toYaml .Values.downloadDashboards.resources | indent 6 }} + {{- toYaml . | nindent 6 }} + {{- end }} env: -{{- range $key, $value := .Values.downloadDashboards.env }} + {{- range $key, $value := .Values.downloadDashboards.env }} - name: "{{ $key }}" value: "{{ $value }}" -{{- end }} -{{- if .Values.downloadDashboards.envFromSecret }} + {{- end }} + {{- range $key, $value := .Values.downloadDashboards.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 10 }} + {{- end }} + {{- with .Values.downloadDashboards.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.downloadDashboards.envFromSecret }} envFrom: - secretRef: - name: {{ tpl .Values.downloadDashboards.envFromSecret . }} -{{- end }} + name: {{ tpl . $root }} + {{- 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: {{ .Values.persistence.subPath }} -{{- end }} - {{- range .Values.extraSecretMounts }} + {{- with .Values.persistence.subPath }} + subPath: {{ tpl . $root }} + {{- end }} + {{- range .Values.extraSecretMounts }} - name: {{ .name }} mountPath: {{ .mountPath }} readOnly: {{ .readOnly }} + {{- end }} +{{- end }} +{{- if and .Values.sidecar.alerts.enabled .Values.sidecar.alerts.initAlerts }} + - name: {{ include "grafana.name" . }}-init-sc-alerts + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} + {{- if .Values.sidecar.image.sha }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.alerts.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.alerts.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: "LIST" + - name: LABEL + value: "{{ .Values.sidecar.alerts.label }}" + {{- with .Values.sidecar.alerts.labelValue }} + - name: LABEL_VALUE + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.alerts.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.alerts.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/alerting" + - name: RESOURCE + value: {{ quote .Values.sidecar.alerts.resource }} + {{- with .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.alerts.searchNamespace }} + - name: NAMESPACE + value: {{ . | join "," | quote }} + {{- end }} + {{- with .Values.sidecar.alerts.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: {{ quote . }} + {{- end }} + {{- with .Values.sidecar.alerts.script }} + - name: SCRIPT + value: {{ quote . }} + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-alerts-volume + mountPath: "/etc/grafana/provisioning/alerting" + {{- with .Values.sidecar.alerts.extraMounts }} + {{- toYaml . | trim | nindent 6 }} + {{- end }} {{- end }} {{- if and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources }} - - name: {{ template "grafana.name" . }}-init-sc-datasources + - name: {{ include "grafana.name" . }}-init-sc-datasources + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" {{- end }} imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} env: + {{- range $key, $value := .Values.sidecar.datasources.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- range $key, $value := .Values.sidecar.datasources.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 10 }} + {{- end }} + {{- if .Values.sidecar.datasources.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} - name: METHOD value: "LIST" - name: LABEL value: "{{ .Values.sidecar.datasources.label }}" - {{- if .Values.sidecar.datasources.labelValue }} + {{- with .Values.sidecar.datasources.labelValue }} - name: LABEL_VALUE - value: {{ quote .Values.sidecar.datasources.labelValue }} + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} {{- end }} - name: FOLDER value: "/etc/grafana/provisioning/datasources" - name: RESOURCE value: {{ quote .Values.sidecar.datasources.resource }} - {{- if .Values.sidecar.enableUniqueFilenames }} + {{- with .Values.sidecar.enableUniqueFilenames }} - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" + value: "{{ . }}" {{- end }} {{- if .Values.sidecar.datasources.searchNamespace }} - name: NAMESPACE - value: "{{ .Values.sidecar.datasources.searchNamespace | join "," }}" + value: "{{ tpl (.Values.sidecar.datasources.searchNamespace | join ",") . }}" {{- end }} - {{- if .Values.sidecar.skipTlsVerify }} + {{- with .Values.sidecar.skipTlsVerify }} - name: SKIP_TLS_VERIFY - value: "{{ .Values.sidecar.skipTlsVerify }}" + value: "{{ . }}" {{- end }} + {{- with .Values.sidecar.resources }} resources: -{{ toYaml .Values.sidecar.resources | indent 6 }} -{{- if .Values.sidecar.securityContext }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} securityContext: -{{- toYaml .Values.sidecar.securityContext | nindent 6 }} -{{- end }} + {{- toYaml . | 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 and .Values.sidecar.notifiers.enabled .Values.sidecar.notifiers.initNotifiers }} + - name: {{ include "grafana.name" . }}-init-sc-notifiers + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" {{- end }} imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} env: + {{- range $key, $value := .Values.sidecar.notifiers.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.notifiers.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} - name: METHOD value: LIST - name: LABEL value: "{{ .Values.sidecar.notifiers.label }}" + {{- with .Values.sidecar.notifiers.labelValue }} + - name: LABEL_VALUE + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} + {{- end }} - name: FOLDER value: "/etc/grafana/provisioning/notifiers" - name: RESOURCE value: {{ quote .Values.sidecar.notifiers.resource }} - {{- if .Values.sidecar.enableUniqueFilenames }} + {{- with .Values.sidecar.enableUniqueFilenames }} - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" + value: "{{ . }}" {{- end }} - {{- if .Values.sidecar.notifiers.searchNamespace }} + {{- with .Values.sidecar.notifiers.searchNamespace }} - name: NAMESPACE - value: "{{ .Values.sidecar.notifiers.searchNamespace | join "," }}" + value: "{{ tpl (. | join ",") $root }}" {{- end }} - {{- if .Values.sidecar.skipTlsVerify }} + {{- with .Values.sidecar.skipTlsVerify }} - name: SKIP_TLS_VERIFY - value: "{{ .Values.sidecar.skipTlsVerify }}" + value: "{{ . }}" {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} resources: -{{ toYaml .Values.sidecar.resources | indent 6 }} -{{- if .Values.sidecar.securityContext }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} securityContext: -{{- toYaml .Values.sidecar.securityContext | nindent 6 }} -{{- end }} + {{- toYaml . | nindent 6 }} + {{- end }} volumeMounts: - name: sc-notifiers-volume mountPath: "/etc/grafana/provisioning/notifiers" {{- end}} -{{- if .Values.extraInitContainers }} -{{ tpl (toYaml .Values.extraInitContainers) . | indent 2 }} +{{- with .Values.extraInitContainers }} + {{- tpl (toYaml .) $root | nindent 2 }} {{- end }} -{{- if .Values.image.pullSecrets }} +{{- if or .Values.image.pullSecrets .Values.global.imagePullSecrets }} imagePullSecrets: -{{- range .Values.image.pullSecrets }} - - name: {{ . }} -{{- end}} + {{- include "grafana.imagePullSecrets" (dict "root" $root "imagePullSecrets" .Values.image.pullSecrets) | nindent 2 }} {{- end }} {{- if not .Values.enableKubeBackwardCompatibility }} enableServiceLinks: {{ .Values.enableServiceLinks }} {{- end }} containers: +{{- if and .Values.sidecar.alerts.enabled (not .Values.sidecar.alerts.initAlerts) }} + - name: {{ include "grafana.name" . }}-sc-alerts + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} + {{- if .Values.sidecar.image.sha }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.alerts.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.alerts.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.alerts.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.alerts.label }}" + {{- with .Values.sidecar.alerts.labelValue }} + - name: LABEL_VALUE + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.alerts.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.alerts.logLevel }} + {{- end }} + - name: FOLDER + value: "/etc/grafana/provisioning/alerting" + - name: RESOURCE + value: {{ quote .Values.sidecar.alerts.resource }} + {{- with .Values.sidecar.enableUniqueFilenames }} + - name: UNIQUE_FILENAMES + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.alerts.searchNamespace }} + - name: NAMESPACE + value: {{ . | join "," | quote }} + {{- end }} + {{- with .Values.sidecar.alerts.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: {{ quote . }} + {{- end }} + {{- with .Values.sidecar.alerts.script }} + - name: SCRIPT + value: {{ quote . }} + {{- 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.alerts.skipReload }} + - name: REQ_URL + value: {{ .Values.sidecar.alerts.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} + {{- if .Values.sidecar.alerts.watchServerTimeout }} + {{- if ne .Values.sidecar.alerts.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.alerts.watchServerTimeout with .Values.sidecar.alerts.watchMethod %s" .Values.sidecar.alerts.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.alerts.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.alerts.watchClientTimeout }} + {{- if ne .Values.sidecar.alerts.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.alerts.watchClientTimeout with .Values.sidecar.alerts.watchMethod %s" .Values.sidecar.alerts.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.alerts.watchClientTimeout }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-alerts-volume + mountPath: "/etc/grafana/provisioning/alerting" + {{- with .Values.sidecar.alerts.extraMounts }} + {{- toYaml . | trim | nindent 6 }} + {{- end }} +{{- end}} {{- if .Values.sidecar.dashboards.enabled }} - - name: {{ template "grafana.name" . }}-sc-dashboard + - name: {{ include "grafana.name" . }}-sc-dashboard + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" {{- end }} imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} env: + {{- range $key, $value := .Values.sidecar.dashboards.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- range $key, $value := .Values.sidecar.dashboards.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 10 }} + {{- end }} + {{- if .Values.sidecar.dashboards.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} - name: METHOD value: {{ .Values.sidecar.dashboards.watchMethod }} - name: LABEL value: "{{ .Values.sidecar.dashboards.label }}" - {{- if .Values.sidecar.dashboards.labelValue }} + {{- with .Values.sidecar.dashboards.labelValue }} - name: LABEL_VALUE - value: {{ quote .Values.sidecar.dashboards.labelValue }} + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.dashboards.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.dashboards.logLevel }} {{- 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 }} + {{- with .Values.sidecar.enableUniqueFilenames }} - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" + value: "{{ . }}" {{- end }} - {{- if .Values.sidecar.dashboards.searchNamespace }} + {{- with .Values.sidecar.dashboards.searchNamespace }} - name: NAMESPACE - value: "{{ .Values.sidecar.dashboards.searchNamespace | join "," }}" + value: "{{ tpl (. | join ",") $root }}" {{- end }} - {{- if .Values.sidecar.skipTlsVerify }} + {{- with .Values.sidecar.skipTlsVerify }} - name: SKIP_TLS_VERIFY - value: "{{ .Values.sidecar.skipTlsVerify }}" + value: "{{ . }}" {{- end }} - {{- if .Values.sidecar.dashboards.folderAnnotation }} + {{- with .Values.sidecar.dashboards.folderAnnotation }} - name: FOLDER_ANNOTATION - value: "{{ .Values.sidecar.dashboards.folderAnnotation }}" + value: "{{ . }}" {{- end }} - {{- if .Values.sidecar.dashboards.script }} + {{- with .Values.sidecar.dashboards.script }} - name: SCRIPT - value: "{{ .Values.sidecar.dashboards.script }}" + value: "{{ . }}" + {{- end }} + {{- if not .Values.sidecar.dashboards.skipReload }} + {{- 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 }} + - name: REQ_URL + value: {{ .Values.sidecar.dashboards.reloadURL }} + - name: REQ_METHOD + value: POST {{- end }} {{- if .Values.sidecar.dashboards.watchServerTimeout }} + {{- if ne .Values.sidecar.dashboards.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.dashboards.watchServerTimeout with .Values.sidecar.dashboards.watchMethod %s" .Values.sidecar.dashboards.watchMethod) }} + {{- end }} - name: WATCH_SERVER_TIMEOUT value: "{{ .Values.sidecar.dashboards.watchServerTimeout }}" {{- end }} {{- if .Values.sidecar.dashboards.watchClientTimeout }} + {{- if ne .Values.sidecar.dashboards.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.dashboards.watchClientTimeout with .Values.sidecar.dashboards.watchMethod %s" .Values.sidecar.dashboards.watchMethod) }} + {{- end }} - name: WATCH_CLIENT_TIMEOUT - value: "{{ .Values.sidecar.dashboards.watchClientTimeout }}" + value: {{ .Values.sidecar.dashboards.watchClientTimeout | quote }} {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} resources: -{{ toYaml .Values.sidecar.resources | indent 6 }} -{{- if .Values.sidecar.securityContext }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} securityContext: -{{- toYaml .Values.sidecar.securityContext | nindent 6 }} -{{- end }} + {{- toYaml . | 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}} + {{- with .Values.sidecar.dashboards.extraMounts }} + {{- toYaml . | trim | nindent 6 }} {{- end }} {{- end}} -{{- if .Values.sidecar.datasources.enabled }} - - name: {{ template "grafana.name" . }}-sc-datasources +{{- if and .Values.sidecar.datasources.enabled (not .Values.sidecar.datasources.initDatasources) }} + - name: {{ include "grafana.name" . }}-sc-datasources + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" {{- end }} imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} env: + {{- range $key, $value := .Values.sidecar.datasources.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- range $key, $value := .Values.sidecar.datasources.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 10 }} + {{- end }} + {{- if .Values.sidecar.datasources.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} - name: METHOD value: {{ .Values.sidecar.datasources.watchMethod }} - name: LABEL value: "{{ .Values.sidecar.datasources.label }}" - {{- if .Values.sidecar.datasources.labelValue }} + {{- with .Values.sidecar.datasources.labelValue }} - name: LABEL_VALUE - value: {{ quote .Values.sidecar.datasources.labelValue }} + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.datasources.logLevel }} {{- end }} - name: FOLDER value: "/etc/grafana/provisioning/datasources" - name: RESOURCE value: {{ quote .Values.sidecar.datasources.resource }} - {{- if .Values.sidecar.enableUniqueFilenames }} + {{- with .Values.sidecar.enableUniqueFilenames }} - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" + value: "{{ . }}" {{- end }} - {{- if .Values.sidecar.datasources.searchNamespace }} + {{- with .Values.sidecar.datasources.searchNamespace }} - name: NAMESPACE - value: "{{ .Values.sidecar.datasources.searchNamespace | join "," }}" + value: "{{ tpl (. | join ",") $root }}" {{- end }} {{- if .Values.sidecar.skipTlsVerify }} - name: SKIP_TLS_VERIFY value: "{{ .Values.sidecar.skipTlsVerify }}" {{- end }} + {{- if .Values.sidecar.datasources.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.datasources.script }}" + {{- 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: {{ .Values.admin.existingSecret | default (include "grafana.fullname" .) }} + 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: {{ .Values.admin.existingSecret | default (include "grafana.fullname" .) }} + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} key: {{ .Values.admin.passwordKey | default "admin-password" }} {{- end }} {{- if not .Values.sidecar.datasources.skipReload }} @@ -287,25 +616,162 @@ containers: - name: REQ_METHOD value: POST {{- end }} + {{- if .Values.sidecar.datasources.watchServerTimeout }} + {{- if ne .Values.sidecar.datasources.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.datasources.watchServerTimeout with .Values.sidecar.datasources.watchMethod %s" .Values.sidecar.datasources.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.datasources.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.datasources.watchClientTimeout }} + {{- if ne .Values.sidecar.datasources.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.datasources.watchClientTimeout with .Values.sidecar.datasources.watchMethod %s" .Values.sidecar.datasources.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.datasources.watchClientTimeout }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} resources: -{{ toYaml .Values.sidecar.resources | indent 6 }} -{{- if .Values.sidecar.securityContext }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} securityContext: -{{- toYaml .Values.sidecar.securityContext | nindent 6 }} -{{- end }} + {{- toYaml . | nindent 6 }} + {{- end }} volumeMounts: - name: sc-datasources-volume mountPath: "/etc/grafana/provisioning/datasources" {{- end}} +{{- if .Values.sidecar.notifiers.enabled }} + - name: {{ include "grafana.name" . }}-sc-notifiers + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} + {{- if .Values.sidecar.image.sha }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + {{- else }} + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + {{- end }} + imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} + env: + {{- range $key, $value := .Values.sidecar.notifiers.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.notifiers.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} + - name: METHOD + value: {{ .Values.sidecar.notifiers.watchMethod }} + - name: LABEL + value: "{{ .Values.sidecar.notifiers.label }}" + {{- with .Values.sidecar.notifiers.labelValue }} + - name: LABEL_VALUE + value: {{ quote . }} + {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.notifiers.logLevel }} + {{- end }} + - 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 }} + {{- with .Values.sidecar.notifiers.searchNamespace }} + - name: NAMESPACE + value: "{{ tpl (. | join ",") $root }}" + {{- end }} + {{- with .Values.sidecar.skipTlsVerify }} + - name: SKIP_TLS_VERIFY + value: "{{ . }}" + {{- end }} + {{- if .Values.sidecar.notifiers.script }} + - name: SCRIPT + value: "{{ .Values.sidecar.notifiers.script }}" + {{- 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.notifiers.skipReload }} + - name: REQ_URL + value: {{ .Values.sidecar.notifiers.reloadURL }} + - name: REQ_METHOD + value: POST + {{- end }} + {{- if .Values.sidecar.notifiers.watchServerTimeout }} + {{- if ne .Values.sidecar.notifiers.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.notifiers.watchServerTimeout with .Values.sidecar.notifiers.watchMethod %s" .Values.sidecar.notifiers.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.notifiers.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.notifiers.watchClientTimeout }} + {{- if ne .Values.sidecar.notifiers.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.notifiers.watchClientTimeout with .Values.sidecar.notifiers.watchMethod %s" .Values.sidecar.notifiers.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.notifiers.watchClientTimeout }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} + resources: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} + securityContext: + {{- toYaml . | nindent 6 }} + {{- end }} + volumeMounts: + - name: sc-notifiers-volume + mountPath: "/etc/grafana/provisioning/notifiers" +{{- end}} {{- if .Values.sidecar.plugins.enabled }} - - name: {{ template "grafana.name" . }}-sc-plugins + - name: {{ include "grafana.name" . }}-sc-plugins + {{- $registry := .Values.global.imageRegistry | default .Values.sidecar.image.registry -}} {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" + image: "{{ $registry }}/{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" {{- end }} imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} env: + {{- range $key, $value := .Values.sidecar.plugins.env }} + - name: "{{ $key }}" + value: "{{ $value }}" + {{- end }} + {{- if .Values.sidecar.plugins.ignoreAlreadyProcessed }} + - name: IGNORE_ALREADY_PROCESSED + value: "true" + {{- end }} - name: METHOD value: {{ .Values.sidecar.plugins.watchMethod }} - name: LABEL @@ -314,34 +780,42 @@ containers: - name: LABEL_VALUE value: {{ quote .Values.sidecar.plugins.labelValue }} {{- end }} + {{- if or .Values.sidecar.logLevel .Values.sidecar.plugins.logLevel }} + - name: LOG_LEVEL + value: {{ default .Values.sidecar.logLevel .Values.sidecar.plugins.logLevel }} + {{- end }} - name: FOLDER value: "/etc/grafana/provisioning/plugins" - name: RESOURCE value: {{ quote .Values.sidecar.plugins.resource }} - {{- if .Values.sidecar.enableUniqueFilenames }} + {{- with .Values.sidecar.enableUniqueFilenames }} - name: UNIQUE_FILENAMES - value: "{{ .Values.sidecar.enableUniqueFilenames }}" + value: "{{ . }}" {{- end }} - {{- if .Values.sidecar.plugins.searchNamespace }} + {{- with .Values.sidecar.plugins.searchNamespace }} - name: NAMESPACE - value: "{{ .Values.sidecar.plugins.searchNamespace | join "," }}" + value: "{{ tpl (. | join ",") $root }}" {{- end }} - {{- if .Values.sidecar.skipTlsVerify }} + {{- with .Values.sidecar.plugins.script }} + - name: SCRIPT + value: "{{ . }}" + {{- end }} + {{- with .Values.sidecar.skipTlsVerify }} - name: SKIP_TLS_VERIFY - value: "{{ .Values.sidecar.skipTlsVerify }}" + value: "{{ . }}" {{- 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: {{ .Values.admin.existingSecret | default (include "grafana.fullname" .) }} + 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: {{ .Values.admin.existingSecret | default (include "grafana.fullname" .) }} + name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} key: {{ .Values.admin.passwordKey | default "admin-password" }} {{- end }} {{- if not .Values.sidecar.plugins.skipReload }} @@ -350,33 +824,64 @@ containers: - name: REQ_METHOD value: POST {{- end }} + {{- if .Values.sidecar.plugins.watchServerTimeout }} + {{- if ne .Values.sidecar.plugins.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.plugins.watchServerTimeout with .Values.sidecar.plugins.watchMethod %s" .Values.sidecar.plugins.watchMethod) }} + {{- end }} + - name: WATCH_SERVER_TIMEOUT + value: "{{ .Values.sidecar.plugins.watchServerTimeout }}" + {{- end }} + {{- if .Values.sidecar.plugins.watchClientTimeout }} + {{- if ne .Values.sidecar.plugins.watchMethod "WATCH" }} + {{- fail (printf "Cannot use .Values.sidecar.plugins.watchClientTimeout with .Values.sidecar.plugins.watchMethod %s" .Values.sidecar.plugins.watchMethod) }} + {{- end }} + - name: WATCH_CLIENT_TIMEOUT + value: "{{ .Values.sidecar.plugins.watchClientTimeout }}" + {{- end }} + {{- with .Values.sidecar.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.resources }} resources: -{{ toYaml .Values.sidecar.resources | indent 6 }} -{{- if .Values.sidecar.securityContext }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.sidecar.securityContext }} securityContext: -{{- toYaml .Values.sidecar.securityContext | nindent 6 }} -{{- end }} + {{- toYaml . | nindent 6 }} + {{- end }} volumeMounts: - name: sc-plugins-volume mountPath: "/etc/grafana/provisioning/plugins" {{- end}} - name: {{ .Chart.Name }} + {{- $registry := .Values.global.imageRegistry | default .Values.image.registry -}} {{- if .Values.image.sha }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}@sha256:{{ .Values.image.sha }}" + image: "{{ $registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}@sha256:{{ .Values.image.sha }}" {{- else }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + image: "{{ $registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" {{- end }} imagePullPolicy: {{ .Values.image.pullPolicy }} - {{- if .Values.command }} + {{- if .Values.command }} command: {{- range .Values.command }} - - {{ . }} + - {{ . | quote }} + {{- end }} + {{- end }} + {{- if .Values.args }} + args: + {{- range .Values.args }} + - {{ . | quote }} {{- end }} - {{- end}} -{{- if .Values.containerSecurityContext }} + {{- end }} + {{- with .Values.containerSecurityContext }} securityContext: -{{- toYaml .Values.containerSecurityContext | nindent 6 }} -{{- end }} + {{- toYaml . | nindent 6 }} + {{- end }} volumeMounts: - name: config mountPath: "/etc/grafana/grafana.ini" @@ -387,118 +892,157 @@ containers: subPath: ldap.toml {{- end }} {{- range .Values.extraConfigmapMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - subPath: {{ .subPath | default "" }} + - name: {{ tpl .name $root }} + mountPath: {{ tpl .mountPath $root }} + subPath: {{ tpl (.subPath | default "") $root }} readOnly: {{ .readOnly }} {{- end }} - name: storage mountPath: "/var/lib/grafana" -{{- if .Values.persistence.subPath }} - subPath: {{ .Values.persistence.subPath }} -{{- end }} -{{- if .Values.dashboards }} -{{- range $provider, $dashboards := .Values.dashboards }} -{{- range $key, $value := $dashboards }} -{{- if (or (hasKey $value "json") (hasKey $value "file")) }} + {{- with .Values.persistence.subPath }} + subPath: {{ tpl . $root }} + {{- end }} + {{- with .Values.dashboards }} + {{- range $provider, $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) }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.dashboardsConfigMaps }} + {{- range (keys . | sortAlpha) }} - name: dashboards-{{ . }} mountPath: "/var/lib/grafana/dashboards/{{ . }}" -{{- end }} -{{- end }} -{{- if .Values.datasources }} -{{- range (keys .Values.datasources | sortAlpha) }} + {{- end }} + {{- end }} + {{- with .Values.datasources }} + {{- $datasources := . }} + {{- range (keys . | sortAlpha) }} + {{- if (or (hasKey (index $datasources .) "secret")) }} {{/*check if current datasource should be handeled as secret */}} + - name: config-secret + mountPath: "/etc/grafana/provisioning/datasources/{{ . }}" + subPath: {{ . | quote }} + {{- else }} - name: config mountPath: "/etc/grafana/provisioning/datasources/{{ . }}" subPath: {{ . | quote }} -{{- end }} -{{- end }} -{{- if .Values.notifiers }} -{{- range (keys .Values.notifiers | sortAlpha) }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.notifiers }} + {{- $notifiers := . }} + {{- range (keys . | sortAlpha) }} + {{- if (or (hasKey (index $notifiers .) "secret")) }} {{/*check if current notifier should be handeled as secret */}} + - name: config-secret + mountPath: "/etc/grafana/provisioning/notifiers/{{ . }}" + subPath: {{ . | quote }} + {{- else }} - name: config mountPath: "/etc/grafana/provisioning/notifiers/{{ . }}" subPath: {{ . | quote }} -{{- end }} -{{- end }} -{{- if .Values.dashboardProviders }} -{{- range (keys .Values.dashboardProviders | sortAlpha) }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.alerting }} + {{- $alertingmap := .}} + {{- range (keys . | sortAlpha) }} + {{- if (or (hasKey (index $.Values.alerting .) "secret") (hasKey (index $.Values.alerting .) "secretFile")) }} {{/*check if current alerting entry should be handeled as secret */}} + - name: config-secret + mountPath: "/etc/grafana/provisioning/alerting/{{ . }}" + subPath: {{ . | quote }} + {{- else }} + - name: config + mountPath: "/etc/grafana/provisioning/alerting/{{ . }}" + subPath: {{ . | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.dashboardProviders }} + {{- range (keys . | sortAlpha) }} - name: config mountPath: "/etc/grafana/provisioning/dashboards/{{ . }}" subPath: {{ . | quote }} -{{- end }} -{{- end }} -{{- if .Values.sidecar.dashboards.enabled }} + {{- end }} + {{- end }} + {{- with .Values.sidecar.alerts.enabled }} + - name: sc-alerts-volume + mountPath: "/etc/grafana/provisioning/alerting" + {{- end}} + {{- if .Values.sidecar.dashboards.enabled }} - name: sc-dashboard-volume mountPath: {{ .Values.sidecar.dashboards.folder | quote }} -{{ if .Values.sidecar.dashboards.SCProvider }} + {{- 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 }} + {{- end}} + {{- end}} + {{- if .Values.sidecar.datasources.enabled }} - name: sc-datasources-volume mountPath: "/etc/grafana/provisioning/datasources" -{{- end}} -{{- if .Values.sidecar.plugins.enabled }} + {{- end}} + {{- if .Values.sidecar.plugins.enabled }} - name: sc-plugins-volume mountPath: "/etc/grafana/provisioning/plugins" -{{- end}} -{{- if .Values.sidecar.notifiers.enabled }} + {{- end}} + {{- if .Values.sidecar.notifiers.enabled }} - name: sc-notifiers-volume mountPath: "/etc/grafana/provisioning/notifiers" -{{- end}} - {{- range .Values.extraSecretMounts }} + {{- end}} + {{- range .Values.extraSecretMounts }} - name: {{ .name }} mountPath: {{ .mountPath }} readOnly: {{ .readOnly }} subPath: {{ .subPath | default "" }} - {{- end }} - {{- range .Values.extraVolumeMounts }} + {{- end }} + {{- range .Values.extraVolumeMounts }} - name: {{ .name }} mountPath: {{ .mountPath }} subPath: {{ .subPath | default "" }} readOnly: {{ .readOnly }} - {{- end }} - {{- range .Values.extraEmptyDirMounts }} + {{- end }} + {{- range .Values.extraEmptyDirMounts }} - name: {{ .name }} mountPath: {{ .mountPath }} - {{- end }} + {{- end }} ports: - - name: {{ .Values.service.portName }} - containerPort: {{ .Values.service.port }} - protocol: TCP - name: {{ .Values.podPortName }} - containerPort: 3000 + containerPort: {{ .Values.service.targetPort }} + protocol: TCP + - name: {{ .Values.gossipPortName }}-tcp + containerPort: 9094 protocol: TCP + - name: {{ .Values.gossipPortName }}-udp + containerPort: 9094 + protocol: UDP env: + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP {{- 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: {{ .Values.admin.existingSecret | default (include "grafana.fullname" .) }} + 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: {{ .Values.admin.existingSecret | default (include "grafana.fullname" .) }} + 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" . }} + name: {{ include "grafana.fullname" . }} key: plugins {{- end }} {{- if .Values.smtp.existingSecret }} @@ -515,9 +1059,9 @@ containers: {{- 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 + value: http://{{ include "grafana.fullname" . }}-image-renderer.{{ include "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 }} + value: {{ .Values.imageRenderer.grafanaProtocol }}://{{ include "grafana.fullname" . }}.{{ include "grafana.namespace" . }}:{{ .Values.service.port }}/{{ .Values.imageRenderer.grafanaSubPath }} {{- end }} - name: GF_PATHS_DATA value: {{ (get .Values "grafana.ini").paths.data }} @@ -527,83 +1071,109 @@ containers: value: {{ (get .Values "grafana.ini").paths.plugins }} - name: GF_PATHS_PROVISIONING value: {{ (get .Values "grafana.ini").paths.provisioning }} - {{- range $key, $value := .Values.envValueFrom }} + {{- range $key, $value := .Values.envValueFrom }} - name: {{ $key | quote }} valueFrom: -{{ tpl (toYaml $value) $ | indent 10 }} - {{- end }} -{{- range $key, $value := .Values.env }} + {{- tpl (toYaml $value) $ | nindent 10 }} + {{- end }} + {{- range $key, $value := .Values.env }} - name: "{{ tpl $key $ }}" value: "{{ tpl (print $value) $ }}" -{{- end }} + {{- end }} {{- if or .Values.envFromSecret (or .Values.envRenderSecret .Values.envFromSecrets) .Values.envFromConfigMaps }} envFrom: - {{- if .Values.envFromSecret }} + {{- if .Values.envFromSecret }} - secretRef: name: {{ tpl .Values.envFromSecret . }} - {{- end }} - {{- if .Values.envRenderSecret }} + {{- end }} + {{- if .Values.envRenderSecret }} - secretRef: - name: {{ template "grafana.fullname" . }}-env - {{- end }} - {{- range .Values.envFromSecrets }} + name: {{ include "grafana.fullname" . }}-env + {{- end }} + {{- range .Values.envFromSecrets }} - secretRef: name: {{ tpl .name $ }} optional: {{ .optional | default false }} - {{- end }} - {{- range .Values.envFromConfigMaps }} + {{- if .prefix }} + prefix: {{ tpl .prefix $ }} + {{- end }} + {{- end }} + {{- range .Values.envFromConfigMaps }} - configMapRef: name: {{ tpl .name $ }} optional: {{ .optional | default false }} + {{- if .prefix }} + prefix: {{ tpl .prefix $ }} + {{- end }} + {{- end }} {{- end }} - {{- end }} + {{- with .Values.livenessProbe }} livenessProbe: -{{ toYaml .Values.livenessProbe | indent 6 }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.readinessProbe }} readinessProbe: -{{ toYaml .Values.readinessProbe | indent 6 }} -{{- if .Values.lifecycleHooks }} - lifecycle: {{ tpl (.Values.lifecycleHooks | toYaml) . | nindent 6 }} -{{- end }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.lifecycleHooks }} + lifecycle: + {{- tpl (toYaml .) $root | nindent 6 }} + {{- end }} + {{- with .Values.resources }} resources: -{{ toYaml .Values.resources | indent 6 }} + {{- toYaml . | nindent 6 }} + {{- end }} {{- with .Values.extraContainers }} -{{ tpl . $ | indent 2 }} + {{- tpl . $ | nindent 2 }} {{- end }} {{- with .Values.nodeSelector }} nodeSelector: -{{ toYaml . | indent 2 }} + {{- toYaml . | nindent 2 }} {{- end }} {{- with .Values.affinity }} affinity: -{{ toYaml . | indent 2 }} + {{- tpl (toYaml .) $root | nindent 2 }} +{{- end }} +{{- with .Values.topologySpreadConstraints }} +topologySpreadConstraints: + {{- toYaml . | nindent 2 }} {{- end }} {{- with .Values.tolerations }} tolerations: -{{ toYaml . | indent 2 }} + {{- toYaml . | nindent 2 }} {{- end }} volumes: - name: config configMap: - name: {{ template "grafana.fullname" . }} -{{- range .Values.extraConfigmapMounts }} - - name: {{ .name }} + name: {{ include "grafana.fullname" . }} + {{- $createConfigSecret := eq (include "grafana.shouldCreateConfigSecret" .) "true" -}} + {{- if and .Values.createConfigmap $createConfigSecret }} + - name: config-secret + secret: + secretName: {{ include "grafana.fullname" . }}-config-secret + {{- end }} + {{- range .Values.extraConfigmapMounts }} + - name: {{ tpl .name $root }} configMap: - name: {{ .configMap }} -{{- end }} + name: {{ tpl .configMap $root }} + {{- with .items }} + items: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} {{- if .Values.dashboards }} - {{- range (keys .Values.dashboards | sortAlpha) }} + {{- range (keys .Values.dashboards | sortAlpha) }} - name: dashboards-{{ . }} configMap: - name: {{ template "grafana.fullname" $ }}-dashboards-{{ . }} - {{- end }} + name: {{ include "grafana.fullname" $ }}-dashboards-{{ . }} + {{- end }} {{- end }} {{- if .Values.dashboardsConfigMaps }} - {{ $root := . }} - {{- range $provider, $name := .Values.dashboardsConfigMaps }} + {{- range $provider, $name := .Values.dashboardsConfigMaps }} - name: dashboards-{{ $provider }} configMap: name: {{ tpl $name $root }} - {{- end }} + {{- end }} {{- end }} {{- if .Values.ldap.enabled }} - name: ldap @@ -611,82 +1181,126 @@ volumes: {{- if .Values.ldap.existingSecret }} secretName: {{ .Values.ldap.existingSecret }} {{- else }} - secretName: {{ template "grafana.fullname" . }} + secretName: {{ include "grafana.fullname" . }} {{- end }} items: - key: ldap-toml path: ldap.toml {{- end }} -{{- if and .Values.persistence.enabled (eq .Values.persistence.type "pvc") }} + {{- if and .Values.persistence.enabled (eq .Values.persistence.type "pvc") }} - name: storage persistentVolumeClaim: - claimName: {{ .Values.persistence.existingClaim | default (include "grafana.fullname" .) }} -{{- else if and .Values.persistence.enabled (eq .Values.persistence.type "statefulset") }} -# nothing -{{- else }} + claimName: {{ tpl (.Values.persistence.existingClaim | default (include "grafana.fullname" .)) . }} + {{- else if and .Values.persistence.enabled (has .Values.persistence.type $sts) }} + {{/* nothing */}} + {{- else }} - name: storage -{{- if .Values.persistence.inMemory.enabled }} + {{- if .Values.persistence.inMemory.enabled }} emptyDir: medium: Memory -{{- if .Values.persistence.inMemory.sizeLimit }} - sizeLimit: {{ .Values.persistence.inMemory.sizeLimit }} -{{- end -}} -{{- else }} + {{- with .Values.persistence.inMemory.sizeLimit }} + sizeLimit: {{ . }} + {{- end }} + {{- else }} emptyDir: {} -{{- end -}} -{{- end -}} -{{- if .Values.sidecar.dashboards.enabled }} + {{- end }} + {{- end }} + {{- if .Values.sidecar.alerts.enabled }} + - name: sc-alerts-volume + emptyDir: + {{- with .Values.sidecar.alerts.sizeLimit }} + sizeLimit: {{ . }} + {{- else }} + {} + {{- end }} + {{- end }} + {{- if .Values.sidecar.dashboards.enabled }} - name: sc-dashboard-volume - emptyDir: {} -{{- if .Values.sidecar.dashboards.SCProvider }} + emptyDir: + {{- with .Values.sidecar.dashboards.sizeLimit }} + sizeLimit: {{ . }} + {{- else }} + {} + {{- 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: {{ include "grafana.fullname" . }}-config-dashboards + {{- end }} + {{- end }} + {{- if .Values.sidecar.datasources.enabled }} - name: sc-datasources-volume - emptyDir: {} -{{- end -}} -{{- if .Values.sidecar.plugins.enabled }} + emptyDir: + {{- with .Values.sidecar.datasources.sizeLimit }} + sizeLimit: {{ . }} + {{- else }} + {} + {{- end }} + {{- end }} + {{- if .Values.sidecar.plugins.enabled }} - name: sc-plugins-volume - emptyDir: {} -{{- end -}} -{{- if .Values.sidecar.notifiers.enabled }} + emptyDir: + {{- with .Values.sidecar.plugins.sizeLimit }} + sizeLimit: {{ . }} + {{- else }} + {} + {{- end }} + {{- end }} + {{- if .Values.sidecar.notifiers.enabled }} - name: sc-notifiers-volume - emptyDir: {} -{{- end -}} -{{- range .Values.extraSecretMounts }} -{{- if .secretName }} + emptyDir: + {{- with .Values.sidecar.notifiers.sizeLimit }} + sizeLimit: {{ . }} + {{- else }} + {} + {{- end }} + {{- end }} + {{- range .Values.extraSecretMounts }} + {{- if .secretName }} - name: {{ .name }} secret: secretName: {{ .secretName }} defaultMode: {{ .defaultMode }} -{{- else if .projected }} + {{- with .items }} + items: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- else if .projected }} - name: {{ .name }} - projected: {{- toYaml .projected | nindent 6 }} -{{- else if .csi }} + projected: + {{- toYaml .projected | nindent 6 }} + {{- else if .csi }} - name: {{ .name }} - csi: {{- toYaml .csi | nindent 6 }} -{{- end }} -{{- end }} -{{- range .Values.extraVolumeMounts }} + csi: + {{- toYaml .csi | nindent 6 }} + {{- end }} + {{- end }} + {{- range .Values.extraVolumes }} - name: {{ .name }} {{- if .existingClaim }} persistentVolumeClaim: claimName: {{ .existingClaim }} {{- else if .hostPath }} hostPath: - path: {{ .hostPath }} + {{ toYaml .hostPath | nindent 6 }} + {{- else if .csi }} + csi: + {{- toYaml .csi | nindent 6 }} + {{- else if .configMap }} + configMap: + {{- toYaml .configMap | nindent 6 }} + {{- else if .emptyDir }} + emptyDir: + {{- toYaml .emptyDir | nindent 6 }} {{- else }} emptyDir: {} {{- end }} -{{- end }} -{{- range .Values.extraEmptyDirMounts }} + {{- end }} + {{- range .Values.extraEmptyDirMounts }} - name: {{ .name }} emptyDir: {} -{{- end -}} -{{- if .Values.extraContainerVolumes }} -{{ toYaml .Values.extraContainerVolumes | indent 2 }} -{{- end }} + {{- end }} + {{- with .Values.extraContainerVolumes }} + {{- tpl (toYaml .) $root | nindent 2 }} + {{- end }} {{- end }} diff --git a/external/grafana/templates/clusterrole.yaml b/external/grafana/templates/clusterrole.yaml index f09e0656..3af4b62b 100644 --- a/external/grafana/templates/clusterrole.yaml +++ b/external/grafana/templates/clusterrole.yaml @@ -1,24 +1,24 @@ -{{- if and .Values.rbac.create (not .Values.rbac.namespaced) (not .Values.rbac.useExistingRole) }} +{{- if and .Values.rbac.create (or (not .Values.rbac.namespaced) .Values.rbac.extraClusterRoleRules) (not .Values.rbac.useExistingClusterRole) }} kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: labels: {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} + {{- 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) }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "grafana.fullname" . }}-clusterrole +{{- if or .Values.sidecar.dashboards.enabled .Values.rbac.extraClusterRoleRules .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled .Values.sidecar.alerts.enabled }} 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}} + {{- if or .Values.sidecar.dashboards.enabled .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled .Values.sidecar.alerts.enabled }} + - apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] + {{- end}} + {{- with .Values.rbac.extraClusterRoleRules }} + {{- toYaml . | nindent 2 }} + {{- end}} {{- else }} rules: [] {{- end}} diff --git a/external/grafana/templates/clusterrolebinding.yaml b/external/grafana/templates/clusterrolebinding.yaml index 4accbfac..bda9431a 100644 --- a/external/grafana/templates/clusterrolebinding.yaml +++ b/external/grafana/templates/clusterrolebinding.yaml @@ -1,24 +1,24 @@ -{{- if and .Values.rbac.create (not .Values.rbac.namespaced) }} +{{- if and .Values.rbac.create (or (not .Values.rbac.namespaced) .Values.rbac.extraClusterRoleRules) }} kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: - name: {{ template "grafana.fullname" . }}-clusterrolebinding + name: {{ include "grafana.fullname" . }}-clusterrolebinding labels: {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} + {{- with .Values.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} subjects: - kind: ServiceAccount - name: {{ template "grafana.serviceAccountName" . }} - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.serviceAccountName" . }} + namespace: {{ include "grafana.namespace" . }} roleRef: kind: ClusterRole -{{- if (not .Values.rbac.useExistingRole) }} - name: {{ template "grafana.fullname" . }}-clusterrole -{{- else }} - name: {{ .Values.rbac.useExistingRole }} -{{- end }} + {{- if .Values.rbac.useExistingClusterRole }} + name: {{ .Values.rbac.useExistingClusterRole }} + {{- else }} + name: {{ include "grafana.fullname" . }}-clusterrole + {{- end }} apiGroup: rbac.authorization.k8s.io -{{- end -}} +{{- end }} diff --git a/external/grafana/templates/configmap-dashboard-provider.yaml b/external/grafana/templates/configmap-dashboard-provider.yaml index 65d73858..b412c4d1 100644 --- a/external/grafana/templates/configmap-dashboard-provider.yaml +++ b/external/grafana/templates/configmap-dashboard-provider.yaml @@ -1,29 +1,15 @@ -{{- if .Values.sidecar.dashboards.enabled }} +{{- if and .Values.sidecar.dashboards.enabled .Values.sidecar.dashboards.SCProvider }} apiVersion: v1 kind: ConfigMap metadata: labels: {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} + {{- with .Values.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} - name: {{ template "grafana.fullname" . }}-config-dashboards - namespace: {{ template "grafana.namespace" . }} + {{- toYaml . | nindent 4 }} + {{- end }} + name: {{ include "grafana.fullname" . }}-config-dashboards + namespace: {{ include "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}} + {{- include "grafana.configDashboardProviderData" . | nindent 2 }} +{{- end }} diff --git a/external/grafana/templates/configmap.yaml b/external/grafana/templates/configmap.yaml index 401e2aaa..0a2edf47 100644 --- a/external/grafana/templates/configmap.yaml +++ b/external/grafana/templates/configmap.yaml @@ -1,88 +1,20 @@ +{{- if .Values.createConfigmap }} apiVersion: v1 kind: ConfigMap metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} + {{- if or .Values.configMapAnnotations .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 }} + {{- with .Values.annotations }} + {{- toYaml . | nindent 4 }} {{- end }} + {{- with .Values.configMapAnnotations }} + {{- toYaml . | nindent 4 }} {{- 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 }} +data: + {{- include "grafana.configData" . | nindent 2 }} {{- end }} diff --git a/external/grafana/templates/dashboards-json-configmap.yaml b/external/grafana/templates/dashboards-json-configmap.yaml index 59e0be64..b96ce720 100644 --- a/external/grafana/templates/dashboards-json-configmap.yaml +++ b/external/grafana/templates/dashboards-json-configmap.yaml @@ -4,25 +4,28 @@ apiVersion: v1 kind: ConfigMap metadata: - name: {{ template "grafana.fullname" $ }}-dashboards-{{ $provider }} - namespace: {{ template "grafana.namespace" $ }} + name: {{ include "grafana.fullname" $ }}-dashboards-{{ $provider }} + namespace: {{ include "grafana.namespace" $ }} labels: {{- include "grafana.labels" $ | nindent 4 }} dashboard-provider: {{ $provider }} + {{- if $.Values.sidecar.dashboards.enabled }} + {{ $.Values.sidecar.dashboards.label }}: {{ $.Values.sidecar.dashboards.labelValue | quote }} + {{- end }} {{- 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" }} + {{- print $key | nindent 2 }}.json: + {{- if hasKey $value "json" }} |- -{{ $value.json | indent 6 }} -{{- end }} -{{- if hasKey $value "file" }} -{{ toYaml ( $files.Get $value.file ) | indent 4}} -{{- end }} + {{- $value.json | nindent 6 }} + {{- end }} + {{- if hasKey $value "file" }} + {{- toYaml ( $files.Get $value.file ) | nindent 4}} + {{- end }} {{- end }} {{- end }} {{- if not $dashboardFound }} diff --git a/external/grafana/templates/deployment.yaml b/external/grafana/templates/deployment.yaml index 8dbe5e10..46c016fa 100644 --- a/external/grafana/templates/deployment.yaml +++ b/external/grafana/templates/deployment.yaml @@ -1,18 +1,18 @@ -{{ if (or (not .Values.persistence.enabled) (eq .Values.persistence.type "pvc")) }} +{{- if (and (not .Values.useStatefulSet) (or (not .Values.persistence.enabled) (eq .Values.persistence.type "pvc"))) }} apiVersion: apps/v1 kind: Deployment metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.labels }} -{{ toYaml .Values.labels | indent 4 }} -{{- end }} -{{- with .Values.annotations }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: {{- if and (not .Values.autoscaling.enabled) (.Values.replicas) }} replicas: {{ .Values.replicas }} @@ -21,30 +21,33 @@ spec: selector: matchLabels: {{- include "grafana.selectorLabels" . | nindent 6 }} -{{- with .Values.deploymentStrategy }} + {{- with .Values.deploymentStrategy }} strategy: -{{ toYaml . | trim | indent 4 }} -{{- end }} + {{- toYaml . | trim | nindent 4 }} + {{- end }} template: metadata: labels: {{- include "grafana.selectorLabels" . | nindent 8 }} -{{- with .Values.podLabels }} -{{ toYaml . | indent 8 }} -{{- end }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} annotations: - checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/config: {{ include "grafana.configData" . | sha256sum }} + {{- if .Values.dashboards }} 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 }} + {{- end }} + checksum/sc-dashboard-provider-config: {{ include "grafana.configDashboardProviderData" . | 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 "grafana.secretsData" . | sha256sum }} + {{- end }} + {{- if .Values.envRenderSecret }} + checksum/secret-env: {{ tpl (toYaml .Values.envRenderSecret) . | sha256sum }} + {{- end }} + kubectl.kubernetes.io/default-container: {{ .Chart.Name }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} spec: {{- include "grafana.pod" . | nindent 6 }} {{- end }} diff --git a/external/grafana/templates/headless-service.yaml b/external/grafana/templates/headless-service.yaml index 1df42e96..3028589d 100644 --- a/external/grafana/templates/headless-service.yaml +++ b/external/grafana/templates/headless-service.yaml @@ -1,22 +1,22 @@ -{{- if or .Values.headlessService (and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "statefulset"))}} +{{- $sts := list "sts" "StatefulSet" "statefulset" -}} +{{- if or .Values.headlessService (and .Values.persistence.enabled (not .Values.persistence.existingClaim) (has .Values.persistence.type $sts)) }} apiVersion: v1 kind: Service metadata: - name: {{ template "grafana.fullname" . }}-headless - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }}-headless + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} + {{- with .Values.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: clusterIP: None selector: {{- include "grafana.selectorLabels" . | nindent 4 }} type: ClusterIP ports: - - protocol: TCP - port: 3000 - targetPort: 3000 + - name: {{ .Values.gossipPortName }}-tcp + port: 9094 {{- end }} diff --git a/external/grafana/templates/hpa.yaml b/external/grafana/templates/hpa.yaml index 9c186d74..46bbcb49 100644 --- a/external/grafana/templates/hpa.yaml +++ b/external/grafana/templates/hpa.yaml @@ -1,20 +1,52 @@ +{{- $sts := list "sts" "StatefulSet" "statefulset" -}} {{- if .Values.autoscaling.enabled }} -apiVersion: autoscaling/v2beta1 +apiVersion: {{ include "grafana.hpa.apiVersion" . }} kind: HorizontalPodAutoscaler metadata: - name: {{ template "grafana.fullname" . }} + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} labels: - app.kubernetes.io/name: {{ template "grafana.name" . }} - helm.sh/chart: {{ template "grafana.chart" . }} + app.kubernetes.io/name: {{ include "grafana.name" . }} + helm.sh/chart: {{ include "grafana.chart" . }} app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/instance: {{ .Release.Name }} spec: scaleTargetRef: apiVersion: apps/v1 + {{- if has .Values.persistence.type $sts }} + kind: StatefulSet + {{- else }} kind: Deployment - name: {{ template "grafana.fullname" . }} + {{- end }} + name: {{ include "grafana.fullname" . }} minReplicas: {{ .Values.autoscaling.minReplicas }} maxReplicas: {{ .Values.autoscaling.maxReplicas }} metrics: -{{ toYaml .Values.autoscaling.metrics | indent 4 }} + {{- if .Values.autoscaling.targetMemory }} + - type: Resource + resource: + name: memory + {{- if eq (include "grafana.hpa.apiVersion" .) "autoscaling/v2beta1" }} + targetAverageUtilization: {{ .Values.autoscaling.targetMemory }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemory }} + {{- end }} + {{- end }} + {{- if .Values.autoscaling.targetCPU }} + - type: Resource + resource: + name: cpu + {{- if eq (include "grafana.hpa.apiVersion" .) "autoscaling/v2beta1" }} + targetAverageUtilization: {{ .Values.autoscaling.targetCPU }} + {{- else }} + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPU }} + {{- end }} + {{- end }} + {{- if .Values.autoscaling.behavior }} + behavior: {{ toYaml .Values.autoscaling.behavior | nindent 4 }} + {{- end }} {{- end }} diff --git a/external/grafana/templates/image-renderer-deployment.yaml b/external/grafana/templates/image-renderer-deployment.yaml index 39769955..4828aa38 100644 --- a/external/grafana/templates/image-renderer-deployment.yaml +++ b/external/grafana/templates/image-renderer-deployment.yaml @@ -1,82 +1,86 @@ {{ if .Values.imageRenderer.enabled }} +{{- $root := . -}} apiVersion: apps/v1 kind: Deployment metadata: - name: {{ template "grafana.fullname" . }}-image-renderer - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }}-image-renderer + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.imageRenderer.labels" . | nindent 4 }} -{{- if .Values.imageRenderer.labels }} -{{ toYaml .Values.imageRenderer.labels | indent 4 }} -{{- end }} -{{- with .Values.imageRenderer.annotations }} + {{- with .Values.imageRenderer.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.imageRenderer.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: + {{- if and (not .Values.imageRenderer.autoscaling.enabled) (.Values.imageRenderer.replicas) }} replicas: {{ .Values.imageRenderer.replicas }} + {{- end }} revisionHistoryLimit: {{ .Values.imageRenderer.revisionHistoryLimit }} selector: matchLabels: {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} -{{- with .Values.imageRenderer.deploymentStrategy }} + + {{- with .Values.imageRenderer.deploymentStrategy }} strategy: -{{ toYaml . | trim | indent 4 }} -{{- end }} + {{- toYaml . | trim | nindent 4 }} + {{- end }} template: metadata: labels: {{- include "grafana.imageRenderer.selectorLabels" . | nindent 8 }} -{{- with .Values.imageRenderer.podLabels }} -{{ toYaml . | indent 8 }} -{{- end }} + {{- with .Values.imageRenderer.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} annotations: checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} -{{- with .Values.imageRenderer.podAnnotations }} -{{ toYaml . | indent 8 }} -{{- end }} + {{- with .Values.imageRenderer.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} spec: - - {{- if .Values.imageRenderer.schedulerName }} - schedulerName: "{{ .Values.imageRenderer.schedulerName }}" + {{- with .Values.imageRenderer.schedulerName }} + schedulerName: "{{ . }}" {{- end }} - {{- if .Values.imageRenderer.serviceAccountName }} - serviceAccountName: "{{ .Values.imageRenderer.serviceAccountName }}" + {{- with .Values.imageRenderer.serviceAccountName }} + serviceAccountName: "{{ . }}" {{- end }} - {{- if .Values.imageRenderer.securityContext }} + {{- with .Values.imageRenderer.securityContext }} securityContext: - {{- toYaml .Values.imageRenderer.securityContext | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} - {{- if .Values.imageRenderer.hostAliases }} + {{- with .Values.imageRenderer.hostAliases }} hostAliases: - {{- toYaml .Values.imageRenderer.hostAliases | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} - {{- if .Values.imageRenderer.priorityClassName }} - priorityClassName: {{ .Values.imageRenderer.priorityClassName }} + {{- with .Values.imageRenderer.priorityClassName }} + priorityClassName: {{ . }} {{- end }} - {{- if .Values.imageRenderer.image.pullSecrets }} + {{- with .Values.imageRenderer.image.pullSecrets }} imagePullSecrets: - {{- range .Values.imageRenderer.image.pullSecrets }} - - name: {{ . }} - {{- end}} + {{- range . }} + - name: {{ tpl . $root }} + {{- end}} {{- end }} containers: - name: {{ .Chart.Name }}-image-renderer + {{- $registry := .Values.global.imageRegistry | default .Values.imageRenderer.image.registry -}} {{- if .Values.imageRenderer.image.sha }} - image: "{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}@sha256:{{ .Values.imageRenderer.image.sha }}" + image: "{{ $registry }}/{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}@sha256:{{ .Values.imageRenderer.image.sha }}" {{- else }} - image: "{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}" + image: "{{ $registry }}/{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}" {{- end }} imagePullPolicy: {{ .Values.imageRenderer.image.pullPolicy }} - {{- if .Values.imageRenderer.command }} + {{- if .Values.imageRenderer.command }} command: - {{- range .Values.imageRenderer.command }} + {{- range .Values.imageRenderer.command }} - {{ . }} - {{- end }} - {{- end}} + {{- end }} + {{- end}} ports: - name: {{ .Values.imageRenderer.service.portName }} - containerPort: {{ .Values.imageRenderer.service.port }} + containerPort: {{ .Values.imageRenderer.service.targetPort }} protocol: TCP livenessProbe: httpGet: @@ -84,36 +88,112 @@ spec: port: {{ .Values.imageRenderer.service.portName }} env: - name: HTTP_PORT - value: {{ .Values.imageRenderer.service.port | quote }} + value: {{ .Values.imageRenderer.service.targetPort | quote }} + {{- if .Values.imageRenderer.serviceMonitor.enabled }} + - name: ENABLE_METRICS + value: "true" + {{- end }} + {{- range $key, $value := .Values.imageRenderer.envValueFrom }} + - name: {{ $key | quote }} + valueFrom: + {{- tpl (toYaml $value) $ | nindent 16 }} + {{- end }} {{- range $key, $value := .Values.imageRenderer.env }} - name: {{ $key | quote }} value: {{ $value | quote }} {{- end }} + {{- with .Values.imageRenderer.containerSecurityContext }} securityContext: - capabilities: - drop: ['all'] - allowPrivilegeEscalation: false - readOnlyRootFilesystem: true + {{- toYaml . | nindent 12 }} + {{- end }} volumeMounts: - mountPath: /tmp name: image-renderer-tmpfs - {{- with .Values.imageRenderer.resources }} + {{- range .Values.imageRenderer.extraConfigmapMounts }} + - name: {{ tpl .name $root }} + mountPath: {{ tpl .mountPath $root }} + subPath: {{ tpl (.subPath | default "") $root }} + readOnly: {{ .readOnly }} + {{- end }} + {{- range .Values.imageRenderer.extraSecretMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + readOnly: {{ .readOnly }} + subPath: {{ .subPath | default "" }} + {{- end }} + {{- range .Values.imageRenderer.extraVolumeMounts }} + - name: {{ .name }} + mountPath: {{ .mountPath }} + subPath: {{ .subPath | default "" }} + readOnly: {{ .readOnly }} + {{- end }} + {{- with .Values.imageRenderer.resources }} resources: -{{ toYaml . | indent 12 }} - {{- end }} + {{- toYaml . | nindent 12 }} + {{- end }} {{- with .Values.imageRenderer.nodeSelector }} nodeSelector: -{{ toYaml . | indent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.imageRenderer.affinity }} affinity: -{{ toYaml . | indent 8 }} + {{- tpl (toYaml .) $root | nindent 8 }} {{- end }} {{- with .Values.imageRenderer.tolerations }} tolerations: -{{ toYaml . | indent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} volumes: - name: image-renderer-tmpfs emptyDir: {} + {{- range .Values.imageRenderer.extraConfigmapMounts }} + - name: {{ tpl .name $root }} + configMap: + name: {{ tpl .configMap $root }} + {{- with .items }} + items: + {{- toYaml . | nindent 14 }} + {{- end }} + {{- end }} + {{- range .Values.imageRenderer.extraSecretMounts }} + {{- if .secretName }} + - name: {{ .name }} + secret: + secretName: {{ .secretName }} + defaultMode: {{ .defaultMode }} + {{- with .items }} + items: + {{- toYaml . | nindent 14 }} + {{- end }} + {{- else if .projected }} + - name: {{ .name }} + projected: + {{- toYaml .projected | nindent 12 }} + {{- else if .csi }} + - name: {{ .name }} + csi: + {{- toYaml .csi | nindent 12 }} + {{- end }} + {{- end }} + {{- range .Values.imageRenderer.extraVolumes }} + - name: {{ .name }} + {{- if .existingClaim }} + persistentVolumeClaim: + claimName: {{ .existingClaim }} + {{- else if .hostPath }} + hostPath: + {{ toYaml .hostPath | nindent 12 }} + {{- else if .csi }} + csi: + {{- toYaml .csi | nindent 12 }} + {{- else if .configMap }} + configMap: + {{- toYaml .configMap | nindent 12 }} + {{- else if .emptyDir }} + emptyDir: + {{- toYaml .emptyDir | nindent 12 }} + {{- else }} + emptyDir: {} + {{- end }} + {{- end }} {{- end }} diff --git a/external/grafana/templates/image-renderer-network-policy.yaml b/external/grafana/templates/image-renderer-network-policy.yaml index f8ca73aa..d1a0eb31 100644 --- a/external/grafana/templates/image-renderer-network-policy.yaml +++ b/external/grafana/templates/image-renderer-network-policy.yaml @@ -1,53 +1,56 @@ -{{- if and (.Values.imageRenderer.enabled) (.Values.imageRenderer.networkPolicy.limitIngress) }} +{{- 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" . }} + name: {{ include "grafana.fullname" . }}-image-renderer-ingress + namespace: {{ include "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 }} + {{- with .Values.imageRenderer.podLabels }} + {{- toYaml . | nindent 6 }} {{- end }} policyTypes: - Ingress ingress: - ports: - - port: {{ .Values.imageRenderer.service.port }} + - port: {{ .Values.imageRenderer.service.targetPort }} protocol: TCP from: - namespaceSelector: matchLabels: - name: {{ template "grafana.namespace" . }} + kubernetes.io/metadata.name: {{ include "grafana.namespace" . }} podSelector: matchLabels: {{- include "grafana.selectorLabels" . | nindent 14 }} - {{- if .Values.podLabels }} - {{ toYaml .Values.podLabels | nindent 14 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 14 }} {{- end }} -{{ end }} + {{- with .Values.imageRenderer.networkPolicy.extraIngressSelectors -}} + {{ toYaml . | nindent 8 }} + {{- end }} +{{- end }} -{{- if and (.Values.imageRenderer.enabled) (.Values.imageRenderer.networkPolicy.limitEgress) }} +{{- 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" . }} + name: {{ include "grafana.fullname" . }}-image-renderer-egress + namespace: {{ include "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 }} + {{- with .Values.imageRenderer.podLabels }} + {{- toYaml . | nindent 6 }} {{- end }} policyTypes: @@ -61,16 +64,16 @@ spec: protocol: TCP # talk only to grafana - ports: - - port: {{ .Values.service.port }} + - port: {{ .Values.service.targetPort }} protocol: TCP to: - namespaceSelector: matchLabels: - name: {{ template "grafana.namespace" . }} + name: {{ include "grafana.namespace" . }} podSelector: matchLabels: {{- include "grafana.selectorLabels" . | nindent 14 }} - {{- if .Values.podLabels }} - {{ toYaml .Values.podLabels | nindent 14 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 14 }} {{- end }} -{{ end }} +{{- end }} diff --git a/external/grafana/templates/image-renderer-service.yaml b/external/grafana/templates/image-renderer-service.yaml index f29586c3..f8da127c 100644 --- a/external/grafana/templates/image-renderer-service.yaml +++ b/external/grafana/templates/image-renderer-service.yaml @@ -1,30 +1,31 @@ -{{ if .Values.imageRenderer.enabled }} -{{ if .Values.imageRenderer.service.enabled }} +{{- if and .Values.imageRenderer.enabled .Values.imageRenderer.service.enabled }} apiVersion: v1 kind: Service metadata: - name: {{ template "grafana.fullname" . }}-image-renderer - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }}-image-renderer + namespace: {{ include "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 }} + {{- with .Values.imageRenderer.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.imageRenderer.service.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: type: ClusterIP - {{- if .Values.imageRenderer.service.clusterIP }} - clusterIP: {{ .Values.imageRenderer.service.clusterIP }} - {{end}} + {{- with .Values.imageRenderer.service.clusterIP }} + clusterIP: {{ . }} + {{- end }} ports: - name: {{ .Values.imageRenderer.service.portName }} port: {{ .Values.imageRenderer.service.port }} protocol: TCP targetPort: {{ .Values.imageRenderer.service.targetPort }} + {{- with .Values.imageRenderer.appProtocol }} + appProtocol: {{ . }} + {{- end }} selector: {{- include "grafana.imageRenderer.selectorLabels" . | nindent 4 }} -{{ end }} -{{ end }} +{{- end }} diff --git a/external/grafana/templates/ingress.yaml b/external/grafana/templates/ingress.yaml index 7699ceca..b2ffd810 100644 --- a/external/grafana/templates/ingress.yaml +++ b/external/grafana/templates/ingress.yaml @@ -11,15 +11,15 @@ apiVersion: {{ include "grafana.ingress.apiVersion" . }} kind: Ingress metadata: name: {{ $fullName }} - namespace: {{ template "grafana.namespace" . }} + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.ingress.labels }} -{{ toYaml .Values.ingress.labels | indent 4 }} -{{- end }} - {{- if .Values.ingress.annotations }} + {{- with .Values.ingress.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.ingress.annotations }} annotations: - {{- range $key, $value := .Values.ingress.annotations }} + {{- range $key, $value := . }} {{ $key }}: {{ tpl $value $ | quote }} {{- end }} {{- end }} @@ -27,19 +27,19 @@ spec: {{- if and $ingressSupportsIngressClassName .Values.ingress.ingressClassName }} ingressClassName: {{ .Values.ingress.ingressClassName }} {{- end -}} -{{- if .Values.ingress.tls }} + {{- with .Values.ingress.tls }} tls: -{{ tpl (toYaml .Values.ingress.tls) $ | indent 4 }} -{{- end }} + {{- tpl (toYaml .) $ | nindent 4 }} + {{- end }} rules: {{- if .Values.ingress.hosts }} {{- range .Values.ingress.hosts }} - - host: {{ tpl . $}} + - host: {{ tpl . $ | quote }} http: paths: -{{- if $extraPaths }} -{{ toYaml $extraPaths | indent 10 }} -{{- end }} + {{- with $extraPaths }} + {{- toYaml . | nindent 10 }} + {{- end }} - path: {{ $ingressPath }} {{- if $ingressSupportsPathType }} pathType: {{ $ingressPathType }} @@ -68,8 +68,8 @@ spec: serviceName: {{ $fullName }} servicePort: {{ $servicePort }} {{- end }} - {{- if $ingressPath }} - path: {{ $ingressPath }} + {{- with $ingressPath }} + path: {{ . }} {{- end }} {{- if $ingressSupportsPathType }} pathType: {{ $ingressPathType }} diff --git a/external/grafana/templates/networkpolicy.yaml b/external/grafana/templates/networkpolicy.yaml index fc243828..4cd3ed69 100644 --- a/external/grafana/templates/networkpolicy.yaml +++ b/external/grafana/templates/networkpolicy.yaml @@ -2,21 +2,44 @@ apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.labels }} -{{ toYaml .Values.labels | indent 4 }} -{{- end }} -{{- with .Values.annotations }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: + policyTypes: + {{- if .Values.networkPolicy.ingress }} + - Ingress + {{- end }} + {{- if .Values.networkPolicy.egress.enabled }} + - Egress + {{- end }} podSelector: matchLabels: - {{- include "grafana.selectorLabels" . | nindent 6 }} + {{- include "grafana.selectorLabels" . | nindent 6 }} + + {{- if .Values.networkPolicy.egress.enabled }} + egress: + {{- if not .Values.networkPolicy.egress.blockDNSResolution }} + - ports: + - port: 53 + protocol: UDP + {{- end }} + - ports: + {{ .Values.networkPolicy.egress.ports | toJson }} + {{- with .Values.networkPolicy.egress.to }} + to: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.networkPolicy.ingress }} ingress: - ports: - port: {{ .Values.service.targetPort }} @@ -24,14 +47,15 @@ spec: from: - podSelector: matchLabels: - {{ template "grafana.fullname" . }}-client: "true" - {{- if .Values.networkPolicy.explicitNamespacesSelector }} - namespaceSelector: - {{ toYaml .Values.networkPolicy.explicitNamespacesSelector | indent 12 }} - {{- end }} + {{ include "grafana.fullname" . }}-client: "true" + {{- with .Values.networkPolicy.explicitNamespacesSelector }} + - namespaceSelector: + {{- toYaml . | nindent 12 }} + {{- end }} - podSelector: matchLabels: {{- include "grafana.labels" . | nindent 14 }} role: read {{- end }} + {{- end }} {{- end }} diff --git a/external/grafana/templates/poddisruptionbudget.yaml b/external/grafana/templates/poddisruptionbudget.yaml index 61813a43..05251214 100644 --- a/external/grafana/templates/poddisruptionbudget.yaml +++ b/external/grafana/templates/poddisruptionbudget.yaml @@ -1,21 +1,21 @@ {{- if .Values.podDisruptionBudget }} -apiVersion: policy/v1beta1 +apiVersion: {{ include "grafana.podDisruptionBudget.apiVersion" . }} kind: PodDisruptionBudget metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.labels }} -{{ toYaml .Values.labels | indent 4 }} -{{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: -{{- if .Values.podDisruptionBudget.minAvailable }} - minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} -{{- end }} -{{- if .Values.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} -{{- end }} + {{- with .Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ . }} + {{- end }} + {{- with .Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ . }} + {{- end }} selector: matchLabels: {{- include "grafana.selectorLabels" . | nindent 6 }} diff --git a/external/grafana/templates/podsecuritypolicy.yaml b/external/grafana/templates/podsecuritypolicy.yaml index 7de6c021..eed7af95 100644 --- a/external/grafana/templates/podsecuritypolicy.yaml +++ b/external/grafana/templates/podsecuritypolicy.yaml @@ -1,8 +1,8 @@ -{{- if .Values.rbac.pspEnabled }} +{{- if and .Values.rbac.pspEnabled (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: - name: {{ template "grafana.fullname" . }} + name: {{ include "grafana.fullname" . }} labels: {{- include "grafana.labels" . | nindent 4 }} annotations: diff --git a/external/grafana/templates/pvc.yaml b/external/grafana/templates/pvc.yaml index 8d93f5c2..0a4613ed 100644 --- a/external/grafana/templates/pvc.yaml +++ b/external/grafana/templates/pvc.yaml @@ -2,17 +2,20 @@ apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.persistence.extraPvcLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} {{- with .Values.persistence.annotations }} annotations: -{{ toYaml . | indent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} {{- with .Values.persistence.finalizers }} finalizers: -{{ toYaml . | indent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} spec: accessModes: @@ -22,12 +25,15 @@ spec: resources: requests: storage: {{ .Values.persistence.size | quote }} - {{- if .Values.persistence.storageClassName }} - storageClassName: {{ .Values.persistence.storageClassName }} - {{- end -}} + {{- if and (.Values.persistence.lookupVolumeName) (lookup "v1" "PersistentVolumeClaim" (include "grafana.namespace" .) (include "grafana.fullname" .)) }} + volumeName: {{ (lookup "v1" "PersistentVolumeClaim" (include "grafana.namespace" .) (include "grafana.fullname" .)).spec.volumeName }} + {{- end }} + {{- with .Values.persistence.storageClassName }} + storageClassName: {{ . }} + {{- end }} {{- with .Values.persistence.selectorLabels }} selector: matchLabels: -{{ toYaml . | indent 6 }} + {{- toYaml . | nindent 6 }} {{- end }} -{{- end -}} +{{- end }} diff --git a/external/grafana/templates/role.yaml b/external/grafana/templates/role.yaml index 6a1890fb..4b5edd97 100644 --- a/external/grafana/templates/role.yaml +++ b/external/grafana/templates/role.yaml @@ -1,31 +1,31 @@ {{- if and .Values.rbac.create (not .Values.rbac.useExistingRole) -}} -apiVersion: {{ template "grafana.rbac.apiVersion" . }} +apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} + {{- 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))) }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if or .Values.rbac.pspEnabled (and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled .Values.sidecar.datasources.enabled .Values.sidecar.plugins.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}} + {{- if and .Values.rbac.pspEnabled (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} + - apiGroups: ['extensions'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ include "grafana.fullname" . }}] + {{- end }} + {{- if and .Values.rbac.namespaced (or .Values.sidecar.dashboards.enabled .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled) }} + - apiGroups: [""] # "" indicates the core API group + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] + {{- end }} + {{- with .Values.rbac.extraRoleRules }} + {{- toYaml . | nindent 2 }} + {{- end}} {{- else }} rules: [] {{- end }} diff --git a/external/grafana/templates/rolebinding.yaml b/external/grafana/templates/rolebinding.yaml index e0107255..58f77c6b 100644 --- a/external/grafana/templates/rolebinding.yaml +++ b/external/grafana/templates/rolebinding.yaml @@ -1,25 +1,25 @@ -{{- if .Values.rbac.create -}} -apiVersion: {{ template "grafana.rbac.apiVersion" . }} +{{- if .Values.rbac.create }} +apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} + {{- with .Values.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} roleRef: apiGroup: rbac.authorization.k8s.io kind: Role -{{- if (not .Values.rbac.useExistingRole) }} - name: {{ template "grafana.fullname" . }} -{{- else }} + {{- if .Values.rbac.useExistingRole }} name: {{ .Values.rbac.useExistingRole }} -{{- end }} + {{- else }} + name: {{ include "grafana.fullname" . }} + {{- end }} subjects: - kind: ServiceAccount - name: {{ template "grafana.serviceAccountName" . }} - namespace: {{ template "grafana.namespace" . }} -{{- end -}} + name: {{ include "grafana.serviceAccountName" . }} + namespace: {{ include "grafana.namespace" . }} +{{- end }} diff --git a/external/grafana/templates/secret-env.yaml b/external/grafana/templates/secret-env.yaml index 5c09313e..eb14aac7 100644 --- a/external/grafana/templates/secret-env.yaml +++ b/external/grafana/templates/secret-env.yaml @@ -2,13 +2,13 @@ apiVersion: v1 kind: Secret metadata: - name: {{ template "grafana.fullname" . }}-env - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }}-env + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} type: Opaque data: {{- range $key, $val := .Values.envRenderSecret }} - {{ $key }}: {{ $val | b64enc | quote }} -{{- end -}} + {{ $key }}: {{ tpl ($val | toString) $ | b64enc | quote }} +{{- end }} {{- end }} diff --git a/external/grafana/templates/secret.yaml b/external/grafana/templates/secret.yaml index c8aa750a..fd2ca50f 100644 --- a/external/grafana/templates/secret.yaml +++ b/external/grafana/templates/secret.yaml @@ -2,25 +2,15 @@ apiVersion: v1 kind: Secret metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} + {{- with .Values.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} + {{- toYaml . | nindent 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 }} + {{- include "grafana.secretsData" . | nindent 2 }} {{- end }} diff --git a/external/grafana/templates/service.yaml b/external/grafana/templates/service.yaml index ba84ef97..022328c1 100644 --- a/external/grafana/templates/service.yaml +++ b/external/grafana/templates/service.yaml @@ -1,51 +1,67 @@ -{{ if .Values.service.enabled }} +{{- if .Values.service.enabled }} +{{- $root := . }} apiVersion: v1 kind: Service metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} -{{- if .Values.service.labels }} -{{ toYaml .Values.service.labels | indent 4 }} -{{- end }} -{{- with .Values.service.annotations }} + {{- with .Values.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.service.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} + {{- tpl (toYaml . | nindent 4) $root }} + {{- end }} spec: -{{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }} + {{- 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 }} + {{- with .Values.service.clusterIP }} + clusterIP: {{ . }} {{- end }} - {{- if .Values.service.loadBalancerSourceRanges }} + {{- else if eq .Values.service.type "LoadBalancer" }} + type: LoadBalancer + {{- with .Values.service.loadBalancerIP }} + loadBalancerIP: {{ . }} + {{- end }} + {{- with .Values.service.loadBalancerClass }} + loadBalancerClass: {{ . }} + {{- end }} + {{- with .Values.service.loadBalancerSourceRanges }} loadBalancerSourceRanges: -{{ toYaml .Values.service.loadBalancerSourceRanges | indent 4 }} - {{- end -}} -{{- else }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- else }} type: {{ .Values.service.type }} -{{- end }} -{{- if .Values.service.externalIPs }} + {{- end }} + {{- if .Values.service.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }} + {{- end }} + {{- if .Values.service.ipFamilies }} + ipFamilies: {{ .Values.service.ipFamilies | toYaml | nindent 2 }} + {{- end }} + {{- with .Values.service.externalIPs }} externalIPs: -{{ toYaml .Values.service.externalIPs | indent 4 }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.service.externalTrafficPolicy }} + externalTrafficPolicy: {{ . }} + {{- 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 }} + {{- with .Values.service.appProtocol }} + appProtocol: {{ . }} + {{- end }} + {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + {{- with .Values.extraExposePorts }} + {{- tpl (toYaml . | nindent 4) $root }} + {{- end }} selector: {{- include "grafana.selectorLabels" . | nindent 4 }} -{{ end }} +{{- end }} diff --git a/external/grafana/templates/serviceaccount.yaml b/external/grafana/templates/serviceaccount.yaml index 7576eeef..ffca0717 100644 --- a/external/grafana/templates/serviceaccount.yaml +++ b/external/grafana/templates/serviceaccount.yaml @@ -1,13 +1,17 @@ {{- if .Values.serviceAccount.create }} apiVersion: v1 kind: ServiceAccount +automountServiceAccountToken: {{ .Values.serviceAccount.autoMount | default .Values.serviceAccount.automountServiceAccountToken }} metadata: labels: {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.serviceAccount.annotations }} + {{- with .Values.serviceAccount.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.serviceAccount.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} - name: {{ template "grafana.serviceAccountName" . }} - namespace: {{ template "grafana.namespace" . }} + {{- tpl (toYaml . | nindent 4) $ }} + {{- end }} + name: {{ include "grafana.serviceAccountName" . }} + namespace: {{ include "grafana.namespace" . }} {{- end }} diff --git a/external/grafana/templates/servicemonitor.yaml b/external/grafana/templates/servicemonitor.yaml index a18c6d33..03590135 100644 --- a/external/grafana/templates/servicemonitor.yaml +++ b/external/grafana/templates/servicemonitor.yaml @@ -3,16 +3,16 @@ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: - name: {{ template "grafana.fullname" . }} + name: {{ include "grafana.fullname" . }} {{- if .Values.serviceMonitor.namespace }} - namespace: {{ .Values.serviceMonitor.namespace }} + namespace: {{ tpl .Values.serviceMonitor.namespace . }} {{- else }} - namespace: {{ template "grafana.namespace" . }} + namespace: {{ include "grafana.namespace" . }} {{- end }} labels: {{- include "grafana.labels" . | nindent 4 }} - {{- if .Values.serviceMonitor.labels }} - {{- toYaml .Values.serviceMonitor.labels | nindent 4 }} + {{- with .Values.serviceMonitor.labels }} + {{- tpl (toYaml . | nindent 4) $ }} {{- end }} spec: endpoints: @@ -26,19 +26,27 @@ spec: honorLabels: true path: {{ .Values.serviceMonitor.path }} scheme: {{ .Values.serviceMonitor.scheme }} - {{- if .Values.serviceMonitor.tlsConfig }} + {{- with .Values.serviceMonitor.tlsConfig }} tlsConfig: - {{- toYaml .Values.serviceMonitor.tlsConfig | nindent 6 }} + {{- toYaml . | nindent 6 }} {{- end }} - {{- if .Values.serviceMonitor.relabelings }} + {{- with .Values.serviceMonitor.relabelings }} relabelings: - {{- toYaml .Values.serviceMonitor.relabelings | nindent 4 }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 6 }} {{- end }} jobLabel: "{{ .Release.Name }}" selector: matchLabels: - {{- include "grafana.selectorLabels" . | nindent 8 }} + {{- include "grafana.selectorLabels" . | nindent 6 }} namespaceSelector: matchNames: - - {{ .Release.Namespace }} + - {{ include "grafana.namespace" . }} + {{- with .Values.serviceMonitor.targetLabels }} + targetLabels: + {{- toYaml . | nindent 4 }} + {{- end }} {{- end }} diff --git a/external/grafana/templates/statefulset.yaml b/external/grafana/templates/statefulset.yaml index ad3dd069..e6c944a4 100644 --- a/external/grafana/templates/statefulset.yaml +++ b/external/grafana/templates/statefulset.yaml @@ -1,40 +1,43 @@ -{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "statefulset")}} +{{- $sts := list "sts" "StatefulSet" "statefulset" -}} +{{- if (or (.Values.useStatefulSet) (and .Values.persistence.enabled (not .Values.persistence.existingClaim) (has .Values.persistence.type $sts)))}} apiVersion: apps/v1 kind: StatefulSet metadata: - name: {{ template "grafana.fullname" . }} - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }} + namespace: {{ include "grafana.namespace" . }} labels: {{- include "grafana.labels" . | nindent 4 }} -{{- with .Values.annotations }} + {{- with .Values.annotations }} annotations: -{{ toYaml . | indent 4 }} -{{- end }} + {{- toYaml . | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.replicas }} selector: matchLabels: {{- include "grafana.selectorLabels" . | nindent 6 }} - serviceName: {{ template "grafana.fullname" . }}-headless + serviceName: {{ include "grafana.fullname" . }}-headless template: metadata: labels: {{- include "grafana.selectorLabels" . | nindent 8 }} -{{- with .Values.podLabels }} -{{ toYaml . | indent 8 }} -{{- end }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 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) }} + {{- 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 }} + {{- end }} + kubectl.kubernetes.io/default-container: {{ .Chart.Name }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} spec: {{- include "grafana.pod" . | nindent 6 }} + {{- if .Values.persistence.enabled}} volumeClaimTemplates: - metadata: name: storage @@ -47,6 +50,7 @@ spec: {{- with .Values.persistence.selectorLabels }} selector: matchLabels: -{{ toYaml . | indent 10 }} + {{- toYaml . | nindent 10 }} {{- end }} + {{- end }} {{- end }} diff --git a/external/grafana/templates/tests/test-configmap.yaml b/external/grafana/templates/tests/test-configmap.yaml index ff53aaf1..01c96c92 100644 --- a/external/grafana/templates/tests/test-configmap.yaml +++ b/external/grafana/templates/tests/test-configmap.yaml @@ -2,16 +2,19 @@ apiVersion: v1 kind: ConfigMap metadata: - name: {{ template "grafana.fullname" . }}-test - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }}-test + namespace: {{ include "grafana.namespace" . }} + annotations: + "helm.sh/hook": test-success + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" labels: {{- include "grafana.labels" . | nindent 4 }} data: run.sh: |- @test "Test Health" { - url="http://{{ template "grafana.fullname" . }}/api/health" + url="http://{{ include "grafana.fullname" . }}/api/health" - code=$(wget --server-response --spider --timeout 10 --tries 1 ${url} 2>&1 | awk '/^ HTTP/{print $2}') + code=$(wget --server-response --spider --timeout 90 --tries 10 ${url} 2>&1 | awk '/^ HTTP/{print $2}') [ "$code" == "200" ] } {{- end }} diff --git a/external/grafana/templates/tests/test-podsecuritypolicy.yaml b/external/grafana/templates/tests/test-podsecuritypolicy.yaml index 58b46498..1821772a 100644 --- a/external/grafana/templates/tests/test-podsecuritypolicy.yaml +++ b/external/grafana/templates/tests/test-podsecuritypolicy.yaml @@ -1,8 +1,11 @@ -{{- if and .Values.testFramework.enabled .Values.rbac.pspEnabled }} +{{- if and (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") .Values.testFramework.enabled .Values.rbac.pspEnabled }} apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: - name: {{ template "grafana.fullname" . }}-test + name: {{ include "grafana.fullname" . }}-test + annotations: + "helm.sh/hook": test-success + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" labels: {{- include "grafana.labels" . | nindent 4 }} spec: @@ -20,10 +23,10 @@ spec: runAsUser: rule: RunAsAny volumes: - - configMap - - downwardAPI - - emptyDir - - projected - - csi - - secret + - configMap + - downwardAPI + - emptyDir + - projected + - csi + - secret {{- end }} diff --git a/external/grafana/templates/tests/test-role.yaml b/external/grafana/templates/tests/test-role.yaml index 6b10677a..cb4c7820 100644 --- a/external/grafana/templates/tests/test-role.yaml +++ b/external/grafana/templates/tests/test-role.yaml @@ -1,14 +1,17 @@ -{{- if and .Values.testFramework.enabled .Values.rbac.pspEnabled -}} +{{- if and (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") .Values.testFramework.enabled .Values.rbac.pspEnabled }} apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: - name: {{ template "grafana.fullname" . }}-test - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }}-test + namespace: {{ include "grafana.namespace" . }} + annotations: + "helm.sh/hook": test-success + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" labels: {{- include "grafana.labels" . | nindent 4 }} rules: -- apiGroups: ['policy'] - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: [{{ template "grafana.fullname" . }}-test] + - apiGroups: ['policy'] + resources: ['podsecuritypolicies'] + verbs: ['use'] + resourceNames: [{{ include "grafana.fullname" . }}-test] {{- end }} diff --git a/external/grafana/templates/tests/test-rolebinding.yaml b/external/grafana/templates/tests/test-rolebinding.yaml index 58fa5e78..f40d791f 100644 --- a/external/grafana/templates/tests/test-rolebinding.yaml +++ b/external/grafana/templates/tests/test-rolebinding.yaml @@ -1,17 +1,20 @@ -{{- if and .Values.testFramework.enabled .Values.rbac.pspEnabled -}} +{{- if and (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") .Values.testFramework.enabled .Values.rbac.pspEnabled }} apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: {{ template "grafana.fullname" . }}-test - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.fullname" . }}-test + namespace: {{ include "grafana.namespace" . }} + annotations: + "helm.sh/hook": test-success + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" labels: {{- include "grafana.labels" . | nindent 4 }} roleRef: apiGroup: rbac.authorization.k8s.io kind: Role - name: {{ template "grafana.fullname" . }}-test + name: {{ include "grafana.fullname" . }}-test subjects: -- kind: ServiceAccount - name: {{ template "grafana.serviceAccountNameTest" . }} - namespace: {{ template "grafana.namespace" . }} + - kind: ServiceAccount + name: {{ include "grafana.serviceAccountNameTest" . }} + namespace: {{ include "grafana.namespace" . }} {{- end }} diff --git a/external/grafana/templates/tests/test-serviceaccount.yaml b/external/grafana/templates/tests/test-serviceaccount.yaml index 5c335073..38fba359 100644 --- a/external/grafana/templates/tests/test-serviceaccount.yaml +++ b/external/grafana/templates/tests/test-serviceaccount.yaml @@ -4,6 +4,9 @@ kind: ServiceAccount metadata: labels: {{- include "grafana.labels" . | nindent 4 }} - name: {{ template "grafana.serviceAccountNameTest" . }} - namespace: {{ template "grafana.namespace" . }} + name: {{ include "grafana.serviceAccountNameTest" . }} + namespace: {{ include "grafana.namespace" . }} + annotations: + "helm.sh/hook": test-success + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" {{- end }} diff --git a/external/grafana/templates/tests/test.yaml b/external/grafana/templates/tests/test.yaml index 638132e9..9e88afcf 100644 --- a/external/grafana/templates/tests/test.yaml +++ b/external/grafana/templates/tests/test.yaml @@ -1,49 +1,53 @@ {{- if .Values.testFramework.enabled }} +{{- $root := . }} apiVersion: v1 kind: Pod metadata: - name: {{ template "grafana.fullname" . }}-test + name: {{ include "grafana.fullname" . }}-test labels: {{- include "grafana.labels" . | nindent 4 }} annotations: "helm.sh/hook": test-success "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" - namespace: {{ template "grafana.namespace" . }} + namespace: {{ include "grafana.namespace" . }} spec: - serviceAccountName: {{ template "grafana.serviceAccountNameTest" . }} - {{- if .Values.testFramework.securityContext }} - securityContext: {{ toYaml .Values.testFramework.securityContext | nindent 4 }} + serviceAccountName: {{ include "grafana.serviceAccountNameTest" . }} + {{- with .Values.testFramework.securityContext }} + securityContext: + {{- toYaml . | nindent 4 }} {{- end }} - {{- if .Values.image.pullSecrets }} + {{- if or .Values.image.pullSecrets .Values.global.imagePullSecrets }} imagePullSecrets: - {{- range .Values.image.pullSecrets }} - - name: {{ . }} - {{- end}} + {{- include "grafana.imagePullSecrets" (dict "root" $root "imagePullSecrets" .Values.image.pullSecrets) | nindent 4 }} {{- end }} {{- with .Values.nodeSelector }} nodeSelector: -{{ toYaml . | indent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} {{- with .Values.affinity }} affinity: -{{ toYaml . | indent 4 }} + {{- tpl (toYaml .) $root | nindent 4 }} {{- end }} {{- with .Values.tolerations }} tolerations: -{{ toYaml . | indent 4 }} + {{- toYaml . | nindent 4 }} {{- end }} containers: - name: {{ .Release.Name }}-test - image: "{{ .Values.testFramework.image}}:{{ .Values.testFramework.tag }}" + image: "{{ .Values.global.imageRegistry | default .Values.testFramework.image.registry }}/{{ .Values.testFramework.image.repository }}:{{ .Values.testFramework.image.tag }}" imagePullPolicy: "{{ .Values.testFramework.imagePullPolicy}}" command: ["/opt/bats/bin/bats", "-t", "/tests/run.sh"] volumeMounts: - mountPath: /tests name: tests readOnly: true + {{- with .Values.testFramework.resources }} + resources: + {{- toYaml . | nindent 8 }} + {{- end }} volumes: - - name: tests - configMap: - name: {{ template "grafana.fullname" . }}-test + - name: tests + configMap: + name: {{ include "grafana.fullname" . }}-test restartPolicy: Never {{- end }} diff --git a/external/grafana/values.yaml b/external/grafana/values.yaml index 6a2da1a8..0eb4dbb1 100644 --- a/external/grafana/values.yaml +++ b/external/grafana/values.yaml @@ -1,9 +1,28 @@ +global: + # -- Overrides the Docker registry globally for all images + imageRegistry: null + + # To help compatibility with other charts which use global.imagePullSecrets. + # Allow either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style). + # Can be tempalted. + # global: + # imagePullSecrets: + # - name: pullSecret1 + # - name: pullSecret2 + # or + # global: + # imagePullSecrets: + # - pullSecret1 + # - pullSecret2 + imagePullSecrets: [] + rbac: create: true ## Use an existing ClusterRole/Role (depending on rbac.namespaced false/true) - # useExistingRole: name-of-some-(cluster)role - pspEnabled: true - pspUseAppArmor: true + # useExistingRole: name-of-some-role + # useExistingClusterRole: name-of-some-clusterRole + pspEnabled: false + pspUseAppArmor: false namespaced: false extraRoleRules: [] # - apiGroups: [] @@ -17,34 +36,38 @@ serviceAccount: create: true name: nameTest: -# annotations: -# eks.amazonaws.com/role-arn: arn:aws:iam::123456789000:role/iam-role-name-here - autoMount: true + ## ServiceAccount labels. + labels: {} + ## Service account annotations. Can be templated. + # annotations: + # eks.amazonaws.com/role-arn: arn:aws:iam::123456789000:role/iam-role-name-here + + ## autoMount is deprecated in favor of automountServiceAccountToken + # autoMount: false + automountServiceAccountToken: false replicas: 1 ## Create a headless service for the deployment headlessService: false +## Should the service account be auto mounted on the pod +automountServiceAccountToken: true + ## 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 + minReplicas: 1 + maxReplicas: 5 + targetCPU: "60" + targetMemory: "" + behavior: {} ## See `kubectl explain poddisruptionbudget.spec` for more ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ podDisruptionBudget: {} +# apiVersion: "" # minAvailable: 1 # maxUnavailable: 1 @@ -72,33 +95,69 @@ livenessProbe: # schedulerName: "default-scheduler" image: + # -- The Docker registry + registry: docker.io + # -- Docker image repository repository: grafana/grafana - tag: 8.5.0 + # Overrides the Grafana image tag whose default is the chart appVersion + tag: "" 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: + pullSecrets: [] # - myRegistrKeySecretName testFramework: enabled: true - image: "bats/bats" - tag: "v1.4.1" + image: + # -- The Docker registry + registry: docker.io + repository: bats/bats + tag: "v1.4.1" imagePullPolicy: IfNotPresent securityContext: {} + resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +# dns configuration for pod +dnsPolicy: ~ +dnsConfig: {} + # nameservers: + # - 8.8.8.8 + # options: + # - name: ndots + # value: "2" + # - name: edns0 securityContext: + runAsNonRoot: true runAsUser: 472 runAsGroup: 472 fsGroup: 472 containerSecurityContext: - {} - + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + +# Enable creating the grafana configmap +createConfigmap: true + +# Extra configmaps to mount in grafana pods +# Values are templated. extraConfigmapMounts: [] # - name: certs-configmap # mountPath: /etc/grafana/ssl/ @@ -119,8 +178,10 @@ extraLabels: {} # priorityClassName: downloadDashboardsImage: + # -- The Docker registry + registry: docker.io repository: curlimages/curl - tag: 7.73.0 + tag: 7.85.0 sha: "" pullPolicy: IfNotPresent @@ -128,15 +189,31 @@ downloadDashboards: env: {} envFromSecret: "" resources: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + envValueFrom: {} + # ENV_NAME: + # configMapKeyRef: + # name: configmap-name + # key: value_key ## Pod Annotations # podAnnotations: {} +## ConfigMap Annotations +# configMapAnnotations: {} + # argocd.argoproj.io/sync-options: Replace=true + ## Pod Labels # podLabels: {} podPortName: grafana - +gossipPortName: gossip ## Deployment annotations # annotations: {} @@ -147,32 +224,43 @@ podPortName: grafana service: enabled: true type: ClusterIP + # Set the ip family policy to configure dual-stack see [Configure dual-stack](https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services) + ipFamilyPolicy: "" + # Sets the families that should be supported and the order in which they should be applied to ClusterIP as well. Can be IPv4 and/or IPv6. + ipFamilies: [] + loadBalancerIP: "" + loadBalancerClass: "" + loadBalancerSourceRanges: [] port: 80 targetPort: 3000 # targetPort: 4181 To be used with a proxy extraContainer + ## Service annotations. Can be templated. annotations: {} labels: {} portName: service + # Adds the appProtocol field to the service. This allows to work with istio protocol selection. Ex: "http" or "tcp" + appProtocol: "" serviceMonitor: - ## If true, a ServiceMonitor CRD is created for a prometheus operator + ## If true, a ServiceMonitor CR 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 + interval: 30s scheme: http tlsConfig: {} scrapeTimeout: 30s relabelings: [] + metricRelabelings: [] + targetLabels: [] extraExposePorts: [] # - name: keycloak # port: 8080 # targetPort: 8080 - # type: ClusterIP # overrides pod.spec.hostAliases in the grafana deployment's pods hostAliases: [] @@ -236,11 +324,16 @@ nodeSelector: {} ## tolerations: [] -## Affinity for pod assignment +## Affinity for pod assignment (evaluated as template) ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity ## affinity: {} +## Topology Spread Constraints +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ +## +topologySpreadConstraints: [] + ## Additional init containers (evaluated as template) ## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ ## @@ -286,8 +379,13 @@ persistence: 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: + ## Extra labels to apply to a PVC. + extraPvcLabels: {} + disableWarning: false ## If persistence is not enabled, this allows to mount the ## local storage in-memory to improve performance @@ -300,16 +398,22 @@ persistence: ## # sizeLimit: 300Mi + ## If 'lookupVolumeName' is set to true, Helm will attempt to retrieve + ## the current value of 'spec.volumeName' and incorporate it into the template. + lookupVolumeName: true + initChownData: ## If false, data ownership will not be reset at startup - ## This allows the prometheus-server to be run with an arbitrary user + ## This allows the grafana-server to be run with an arbitrary user ## enabled: true ## initChownData container image ## image: - repository: busybox + # -- The Docker registry + registry: docker.io + repository: library/busybox tag: "1.31.1" sha: "" pullPolicy: IfNotPresent @@ -324,7 +428,14 @@ initChownData: # requests: # cpu: 100m # memory: 128Mi - + securityContext: + runAsNonRoot: false + runAsUser: 0 + seccompProfile: + type: RuntimeDefault + capabilities: + add: + - CHOWN # Administrator credentials when not using an existing secret (see below) adminUser: admin @@ -332,6 +443,7 @@ adminUser: admin # Use an existing secret for the admin user. admin: + ## Name of the secret. Can be templated. existingSecret: "" userKey: admin-user passwordKey: admin-password @@ -343,10 +455,13 @@ admin: # - "sh" # - "/run.sh" -## Use an alternate scheduler, e.g. "stork". -## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: +## Optionally define args if command is used +## Needed if using `hashicorp/envconsul` to manage secrets +## By default no arguments are set +# args: +# - "-secret" +# - "secret/grafana" +# - "./grafana" ## Extra environment variables that will be pass onto deployment pods ## @@ -391,7 +506,9 @@ envValueFrom: {} envFromSecret: "" ## Sensible environment variables that will be rendered as new secret object -## This can be useful for auth tokens, etc +## This can be useful for auth tokens, etc. +## If the secret values contains "{{", they'll need to be properly escaped so that they are not interpreted by Helm +## ref: https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-tpl-function envRenderSecret: {} ## The names of secrets in the same kubernetes namespace which contain values to be added to the environment @@ -399,6 +516,7 @@ envRenderSecret: {} ## Name is templated. envFromSecrets: [] ## - name: secret-name +## prefix: prefix ## optional: true ## The names of conifgmaps in the same kubernetes namespace which contain values to be added to the environment @@ -407,6 +525,7 @@ envFromSecrets: [] ## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#configmapenvsource-v1-core envFromConfigMaps: [] ## - name: configmap-name +## prefix: prefix ## optional: true # Inject Kubernetes services as environment variables. @@ -452,11 +571,26 @@ 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/ + # - name: grafana-secrets + # mountPath: /mnt/volume2 + +## Additional Grafana server volumes +extraVolumes: [] + # - name: extra-volume-0 + # existingClaim: volume-claim + # - name: extra-volume-1 + # hostPath: + # path: /usr/shared/ + # type: "" + # - name: grafana-secrets + # csi: + # driver: secrets-store.csi.k8s.io + # readOnly: true + # volumeAttributes: + # secretProviderClass: "grafana-env-spc" ## Container Lifecycle Hooks. Execute a specific bash command or make an HTTP request lifecycleHooks: {} @@ -469,6 +603,9 @@ lifecycleHooks: {} plugins: [] # - digrich-bubblechart-panel # - grafana-clock-panel + ## You can also use other plugin download URL, as long as they are valid zip files, + ## and specify the name of the plugin after the semicolon. Like this: + # - https://grafana.com/api/plugins/marcusolsson-json-datasource/versions/1.3.2/download;marcusolsson-json-datasource ## Configure grafana datasources ## ref: http://docs.grafana.org/administration/provisioning/#datasources @@ -490,6 +627,74 @@ datasources: {} # jsonData: # authType: default # defaultRegion: us-east-1 +# deleteDatasources: [] +# - name: Prometheus + +## Configure grafana alerting (can be templated) +## ref: http://docs.grafana.org/administration/provisioning/#alerting +## +alerting: {} + # rules.yaml: + # apiVersion: 1 + # groups: + # - orgId: 1 + # name: '{{ .Chart.Name }}_my_rule_group' + # folder: my_first_folder + # interval: 60s + # rules: + # - uid: my_id_1 + # title: my_first_rule + # condition: A + # data: + # - refId: A + # datasourceUid: '-100' + # model: + # conditions: + # - evaluator: + # params: + # - 3 + # type: gt + # operator: + # type: and + # query: + # params: + # - A + # reducer: + # type: last + # type: query + # datasource: + # type: __expr__ + # uid: '-100' + # expression: 1==0 + # intervalMs: 1000 + # maxDataPoints: 43200 + # refId: A + # type: math + # dashboardUid: my_dashboard + # panelId: 123 + # noDataState: Alerting + # for: 60s + # annotations: + # some_key: some_value + # labels: + # team: sre_team_1 + # contactpoints.yaml: + # secret: + # apiVersion: 1 + # contactPoints: + # - orgId: 1 + # name: cp_1 + # receivers: + # - uid: first_uid + # type: pagerduty + # settings: + # integrationKey: XXX + # severity: critical + # class: ping failure + # component: Grafana + # group: app-stack + # summary: | + # {{ `{{ include "default.message" . }}` }} ## Configure notifiers ## ref: http://docs.grafana.org/administration/provisioning/#alert-notification-channels @@ -551,6 +756,16 @@ dashboards: {} # url: https://example.com/repository/test-b64.json # token: '' # b64content: true + # local-dashboard-gitlab: + # url: https://example.com/repository/test-gitlab.json + # gitlabToken: '' + # local-dashboard-bitbucket: + # url: https://example.com/repository/test-bitbucket.json + # bearerToken: '' + # local-dashboard-azure: + # url: https://example.com/repository/test-azure.json + # basic: '' + # acceptHeader: '*/*' ## 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. @@ -579,6 +794,8 @@ grafana.ini: mode: console grafana_net: url: https://grafana.net + server: + domain: "{{ if (and .Values.ingress.enabled .Values.ingress.hosts) }}{{ .Values.ingress.hosts | first }}{{ else }}''{{ end }}" ## 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 @@ -639,8 +856,10 @@ smtp: ## 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 + # -- The Docker registry + registry: quay.io + repository: kiwigrid/k8s-sidecar + tag: 1.26.1 sha: "" imagePullPolicy: IfNotPresent resources: {} @@ -650,17 +869,88 @@ sidecar: # requests: # cpu: 50m # memory: 50Mi - securityContext: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault # skipTlsVerify Set to true to skip tls verification for kube api calls # skipTlsVerify: true enableUniqueFilenames: false + readinessProbe: {} + livenessProbe: {} + # Log level default for all sidecars. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. Defaults to INFO + # logLevel: INFO + alerts: + enabled: false + # Additional environment variables for the alerts sidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true + # label that the configmaps with alert are marked with + label: grafana_alert + # value of label that the configmaps with alert are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO + # If specified, the sidecar will search for alert 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 + # 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 + # + # Endpoint to send request to reload alerts + reloadURL: "http://localhost:3000/api/admin/provisioning/alerting/reload" + # Absolute path to shell script to execute after a alert got reloaded + script: null + skipReload: false + # This is needed if skipReload is true, to load any alerts defined at startup time. + # Deploy the alert sidecar as an initContainer. + initAlerts: false + # Additional alert sidecar volume mounts + extraMounts: [] + # Sets the size limit of the alert sidecar emptyDir volume + sizeLimit: {} dashboards: enabled: false + # Additional environment variables for the dashboards sidecar + 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 + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: 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 + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO # 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 @@ -676,8 +966,11 @@ sidecar: # 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 + # Endpoint to send request to reload alerts + reloadURL: "http://localhost:3000/api/admin/provisioning/dashboards/reload" # Absolute path to shell script to execute after a configmap got reloaded script: null + skipReload: false # 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 @@ -696,6 +989,8 @@ sidecar: orgid: 1 # folder in which the dashboards should be imported in grafana folder: '' + # folder UID. will be automatically generated if not specified + folderUid: '' # type of the provider type: file # disableDelete to activate a import-only behaviour @@ -706,12 +1001,33 @@ sidecar: foldersFromFilesStructure: false # Additional dashboard sidecar volume mounts extraMounts: [] + # Sets the size limit of the dashboard sidecar emptyDir volume + sizeLimit: {} datasources: enabled: false + # Additional environment variables for the datasourcessidecar + 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 + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: 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 + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO # 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 @@ -720,18 +1036,38 @@ sidecar: watchMethod: WATCH # search in configmap, secret or both resource: both + # 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 + # # Endpoint to send request to reload datasources reloadURL: "http://localhost:3000/api/admin/provisioning/datasources/reload" + # Absolute path to shell script to execute after a datasource got reloaded + script: null 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. + # Deploy the datasources sidecar as an initContainer. initDatasources: false + # Sets the size limit of the datasource sidecar emptyDir volume + sizeLimit: {} plugins: enabled: false + # Additional environment variables for the plugins sidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true # 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 + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO # 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 @@ -740,22 +1076,66 @@ sidecar: watchMethod: WATCH # search in configmap, secret or both resource: both + # 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 + # # Endpoint to send request to reload plugins reloadURL: "http://localhost:3000/api/admin/provisioning/plugins/reload" + # Absolute path to shell script to execute after a plugin got reloaded + script: null 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 + # Additional environment variables for the notifierssidecar + env: {} + # Do not reprocess already processed unchanged resources on k8s API reconnect. + # ignoreAlreadyProcessed: true # label that the configmaps with notifiers are marked with label: grafana_notifier + # value of label that the configmaps with notifiers are set to + labelValue: "" + # Log level. Can be one of: DEBUG, INFO, WARN, ERROR, CRITICAL. + # logLevel: INFO # 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 + # 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 + # 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 + # + # Endpoint to send request to reload notifiers + reloadURL: "http://localhost:3000/api/admin/provisioning/notifications/reload" + # Absolute path to shell script to execute after a notifier got reloaded + script: null + skipReload: false + # Deploy the notifier sidecar as an initContainer in addition to a container. + # This is needed if skipReload is true, to load any notifiers defined at startup time. + initNotifiers: false + # Sets the size limit of the notifier sidecar emptyDir volume + sizeLimit: {} ## Override the deployment namespace ## @@ -767,10 +1147,20 @@ revisionHistoryLimit: 10 ## Add a seperate remote image renderer deployment/service imageRenderer: + deploymentStrategy: {} # Enable the image-renderer deployment & service enabled: false replicas: 1 + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 5 + targetCPU: "60" + targetMemory: "" + behavior: {} image: + # -- The Docker registry + registry: docker.io # image-renderer Image repository repository: grafana/grafana-image-renderer # image-renderer Image tag @@ -785,10 +1175,35 @@ imageRenderer: # RENDERING_ARGS: --no-sandbox,--disable-gpu,--window-size=1280x758 # RENDERING_MODE: clustered # IGNORE_HTTPS_ERRORS: true + + ## "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 + # image-renderer deployment serviceAccount serviceAccountName: "" # image-renderer deployment securityContext securityContext: {} + # image-renderer deployment container securityContext + containerSecurityContext: + seccompProfile: + type: RuntimeDefault + capabilities: + drop: ['ALL'] + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + ## image-renderer pod annotation + podAnnotations: {} # image-renderer deployment Host Aliases hostAliases: [] # image-renderer deployment priority class @@ -801,6 +1216,25 @@ imageRenderer: # image-renderer service port used by both service and deployment port: 8081 targetPort: 8081 + # Adds the appProtocol field to the image-renderer service. This allows to work with istio protocol selection. Ex: "http" or "tcp" + appProtocol: "" + 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: [] + # See: https://doc.crds.dev/github.com/prometheus-operator/kube-prometheus/monitoring.coreos.com/ServiceMonitor/v1@v0.11.0#spec-targetLabels + targetLabels: [] + # - targetLabel1 + # - targetLabel2 # 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 @@ -814,6 +1248,8 @@ imageRenderer: limitIngress: true # Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods limitEgress: false + # Allow additional services to access image-renderer (eg. Prometheus operator when ServiceMonitor is enabled) + extraIngressSelectors: [] resources: {} # limits: # cpu: 100m @@ -831,11 +1267,28 @@ imageRenderer: ## tolerations: [] - ## Affinity for pod assignment + ## Affinity for pod assignment (evaluated as template) ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity ## affinity: {} + ## Use an alternate scheduler, e.g. "stork". + ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ + ## + # schedulerName: "default-scheduler" + + # Extra configmaps to mount in image-renderer pods + extraConfigmapMounts: [] + + # Extra secrets to mount in image-renderer pods + extraSecretMounts: [] + + # Extra volumes to mount in image-renderer pods + extraVolumeMounts: [] + + # Extra volumes for image-renderer pods + extraVolumes: [] + networkPolicy: ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. ## @@ -846,6 +1299,10 @@ networkPolicy: ## When true, grafana will accept connections from any source ## (with the correct destination port). ## + ingress: true + ## @param networkPolicy.ingress When true enables the creation + ## an ingress network policy + ## 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 @@ -861,10 +1318,45 @@ networkPolicy: ## - {key: role, operator: In, values: [frontend]} ## explicitNamespacesSelector: {} + ## + ## + ## + ## + ## + ## + egress: + ## @param networkPolicy.egress.enabled When enabled, an egress network policy will be + ## created allowing grafana to connect to external data sources from kubernetes cluster. + enabled: false + ## + ## @param networkPolicy.egress.blockDNSResolution When enabled, DNS resolution will be blocked + ## for all pods in the grafana namespace. + blockDNSResolution: false + ## + ## @param networkPolicy.egress.ports Add individual ports to be allowed by the egress + ports: [] + ## Add ports to the egress by specifying - port: + ## E.X. + ## - port: 80 + ## - port: 443 + ## + ## @param networkPolicy.egress.to Allow egress traffic to specific destinations + to: [] + ## Add destinations to the egress by specifying - ipBlock: + ## E.X. + ## to: + ## - namespaceSelector: + ## matchExpressions: + ## - {key: role, operator: In, values: [grafana]} + ## + ## + ## + ## + ## # Enable backward compatibility of kubernetes where version below 1.13 doesn't have the enableServiceLinks option enableKubeBackwardCompatibility: false - +useStatefulSet: false # Create a dynamic manifests via values: extraObjects: [] # - apiVersion: "kubernetes-client.io/v1" @@ -876,3 +1368,13 @@ extraObjects: [] # data: # - key: grafana-admin-password # name: adminPassword + +# assertNoLeakedSecrets is a helper function defined in _helpers.tpl that checks if secret +# values are not exposed in the rendered grafana.ini configmap. It is enabled by default. +# +# To pass values into grafana.ini without exposing them in a configmap, use variable expansion: +# https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#variable-expansion +# +# Alternatively, if you wish to allow secret values to be exposed in the rendered grafana.ini configmap, +# you can disable this check by setting assertNoLeakedSecrets to false. +assertNoLeakedSecrets: true