From baff705eeeb0d18eab0a1f20bd4ec05363364e47 Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Sun, 6 Sep 2026 08:57:22 +0530 Subject: [PATCH] Add Grafana; expose VictoriaMetrics' own vmui UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Grafana: real dashboards over VictoriaMetrics. Provisioned rather than clicked through: a VictoriaMetrics datasource (type: prometheus — VM speaks that query API, which is the whole point of it existing) is baked into the chart's own datasource-provisioning config, so a fresh install has it working with no manual setup. Admin credentials from Vault via ExternalSecret (secretstores/grafana-admin-credentials.yaml in devops-infra-argo-config), same pattern as every other admin credential in this project — never plaintext in this repo. 1Gi local-path PVC for dashboards/Grafana's own state (VictoriaMetrics holds the actual metric data, not this). Dual LAN+Tailscale Ingress hosts, same convention as everything externally reachable here. Found and fixed while vendoring: helm-templates/grafana already held a fully-vendored old Grafana chart (v6.58.7, appVersion 10.0.3) from the original Meesho monorepo import (commit b8575bb) — generic production config (fullnameOverride: grafana-infra-prd, GKE-shaped RBAC/PSP defaults) unrelated to this homelab, same class of leftover as victoria-metrics-single's collision two commits ago. Removed and re-vendored fresh (10.5.15) as a thin wrapper, matching every other official-chart component in this repo now. vmui: VictoriaMetrics' own built-in UI (ad-hoc PromQL + graphs, no saved dashboards — what Grafana is for) is served on the same pod/port, so exposing it cost one ingress block on the victoria-metrics-single values already committed. No new component, no new RAM. Verified with `helm template` against the real charts for both components individually (Grafana: admin env vars correctly reference the ExternalSecret's keys, datasource ConfigMap renders the intended VictoriaMetrics URL, PVC/resources/ingress hosts all match; vmui: ingress renders both hostnames pointing at the existing Service's named http port) and again for the whole generic-argo-apps-chart appSpec list — 12 Applications render, including grafana. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Wajog7nELA3i8JWTjxYGHF --- .../grafana/custom-values.yaml | 1374 +---------------- .../custom-values.yaml | 20 + helm-templates/grafana/.helmignore | 23 - helm-templates/grafana/Chart.lock | 6 + helm-templates/grafana/Chart.yaml | 49 +- helm-templates/grafana/README.md | 686 -------- .../grafana/charts/grafana-10.5.15.tgz | Bin 0 -> 50028 bytes helm-templates/grafana/ci/default-values.yaml | 1 - .../grafana/ci/with-affinity-values.yaml | 16 - .../ci/with-dashboard-json-values.yaml | 53 - .../grafana/ci/with-dashboard-values.yaml | 19 - .../ci/with-extraconfigmapmounts-values.yaml | 7 - .../ci/with-image-renderer-values.yaml | 19 - .../grafana/ci/with-persistence.yaml | 3 - .../grafana/dashboards/custom-dashboard.json | 1 - helm-templates/grafana/templates/NOTES.txt | 55 - helm-templates/grafana/templates/_helpers.tpl | 265 ---- helm-templates/grafana/templates/_pod.tpl | 1173 -------------- .../grafana/templates/clusterrole.yaml | 25 - .../grafana/templates/clusterrolebinding.yaml | 24 - .../configmap-dashboard-provider.yaml | 29 - .../grafana/templates/configmap.yaml | 138 -- .../templates/dashboards-json-configmap.yaml | 35 - .../grafana/templates/deployment.yaml | 51 - .../grafana/templates/external-secret.yaml | 20 - .../grafana/templates/extra-manifests.yaml | 4 - .../grafana/templates/headless-service.yaml | 22 - helm-templates/grafana/templates/hpa.yaml | 52 - .../templates/image-renderer-deployment.yaml | 130 -- .../grafana/templates/image-renderer-hpa.yaml | 47 - .../image-renderer-network-policy.yaml | 79 - .../templates/image-renderer-service.yaml | 31 - .../image-renderer-servicemonitor.yaml | 48 - helm-templates/grafana/templates/ingress.yaml | 78 - .../grafana/templates/networkpolicy.yaml | 52 - .../templates/poddisruptionbudget.yaml | 22 - .../grafana/templates/podsecuritypolicy.yaml | 49 - helm-templates/grafana/templates/pvc.yaml | 36 - helm-templates/grafana/templates/role.yaml | 32 - .../grafana/templates/rolebinding.yaml | 25 - .../grafana/templates/secret-env.yaml | 14 - helm-templates/grafana/templates/secret.yaml | 26 - helm-templates/grafana/templates/service.yaml | 55 - .../grafana/templates/serviceaccount.yaml | 17 - .../grafana/templates/servicemonitor.yaml | 48 - .../grafana/templates/statefulset.yaml | 56 - .../templates/tests/test-configmap.yaml | 20 - .../tests/test-podsecuritypolicy.yaml | 32 - .../grafana/templates/tests/test-role.yaml | 17 - .../templates/tests/test-rolebinding.yaml | 20 - .../templates/tests/test-serviceaccount.yaml | 12 - .../grafana/templates/tests/test.yaml | 49 - helm-templates/grafana/values.yaml | 1247 --------------- 53 files changed, 89 insertions(+), 6323 deletions(-) delete mode 100644 helm-templates/grafana/.helmignore create mode 100644 helm-templates/grafana/Chart.lock delete mode 100644 helm-templates/grafana/README.md create mode 100644 helm-templates/grafana/charts/grafana-10.5.15.tgz delete mode 100644 helm-templates/grafana/ci/default-values.yaml delete mode 100644 helm-templates/grafana/ci/with-affinity-values.yaml delete mode 100644 helm-templates/grafana/ci/with-dashboard-json-values.yaml delete mode 100644 helm-templates/grafana/ci/with-dashboard-values.yaml delete mode 100644 helm-templates/grafana/ci/with-extraconfigmapmounts-values.yaml delete mode 100644 helm-templates/grafana/ci/with-image-renderer-values.yaml delete mode 100644 helm-templates/grafana/ci/with-persistence.yaml delete mode 100644 helm-templates/grafana/dashboards/custom-dashboard.json delete mode 100644 helm-templates/grafana/templates/NOTES.txt delete mode 100644 helm-templates/grafana/templates/_helpers.tpl delete mode 100644 helm-templates/grafana/templates/_pod.tpl delete mode 100644 helm-templates/grafana/templates/clusterrole.yaml delete mode 100644 helm-templates/grafana/templates/clusterrolebinding.yaml delete mode 100644 helm-templates/grafana/templates/configmap-dashboard-provider.yaml delete mode 100644 helm-templates/grafana/templates/configmap.yaml delete mode 100644 helm-templates/grafana/templates/dashboards-json-configmap.yaml delete mode 100644 helm-templates/grafana/templates/deployment.yaml delete mode 100644 helm-templates/grafana/templates/external-secret.yaml delete mode 100644 helm-templates/grafana/templates/extra-manifests.yaml delete mode 100644 helm-templates/grafana/templates/headless-service.yaml delete mode 100644 helm-templates/grafana/templates/hpa.yaml delete mode 100644 helm-templates/grafana/templates/image-renderer-deployment.yaml delete mode 100644 helm-templates/grafana/templates/image-renderer-hpa.yaml delete mode 100644 helm-templates/grafana/templates/image-renderer-network-policy.yaml delete mode 100644 helm-templates/grafana/templates/image-renderer-service.yaml delete mode 100644 helm-templates/grafana/templates/image-renderer-servicemonitor.yaml delete mode 100644 helm-templates/grafana/templates/ingress.yaml delete mode 100644 helm-templates/grafana/templates/networkpolicy.yaml delete mode 100644 helm-templates/grafana/templates/poddisruptionbudget.yaml delete mode 100644 helm-templates/grafana/templates/podsecuritypolicy.yaml delete mode 100644 helm-templates/grafana/templates/pvc.yaml delete mode 100644 helm-templates/grafana/templates/role.yaml delete mode 100644 helm-templates/grafana/templates/rolebinding.yaml delete mode 100644 helm-templates/grafana/templates/secret-env.yaml delete mode 100644 helm-templates/grafana/templates/secret.yaml delete mode 100644 helm-templates/grafana/templates/service.yaml delete mode 100644 helm-templates/grafana/templates/serviceaccount.yaml delete mode 100644 helm-templates/grafana/templates/servicemonitor.yaml delete mode 100644 helm-templates/grafana/templates/statefulset.yaml delete mode 100644 helm-templates/grafana/templates/tests/test-configmap.yaml delete mode 100644 helm-templates/grafana/templates/tests/test-podsecuritypolicy.yaml delete mode 100644 helm-templates/grafana/templates/tests/test-role.yaml delete mode 100644 helm-templates/grafana/templates/tests/test-rolebinding.yaml delete mode 100644 helm-templates/grafana/templates/tests/test-serviceaccount.yaml delete mode 100644 helm-templates/grafana/templates/tests/test.yaml delete mode 100644 helm-templates/grafana/values.yaml diff --git a/helm-overrides/k8s-admin-prd-ase1/grafana/custom-values.yaml b/helm-overrides/k8s-admin-prd-ase1/grafana/custom-values.yaml index 151f59f..61b471d 100644 --- a/helm-overrides/k8s-admin-prd-ase1/grafana/custom-values.yaml +++ b/helm-overrides/k8s-admin-prd-ase1/grafana/custom-values.yaml @@ -1,1335 +1,51 @@ -global: - # 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: [] - -fullnameOverride: grafana-infra-prd -rbac: - create: true - ## Use an existing ClusterRole/Role (depending on rbac.namespaced false/true) - # useExistingRole: name-of-some-(cluster)role - pspEnabled: false - pspUseAppArmor: false - namespaced: false - extraRoleRules: [] - # - apiGroups: [] - # resources: [] - # verbs: [] - extraClusterRoleRules: [] - # - apiGroups: [] - # resources: [] - # verbs: [] -serviceAccount: - create: true - name: - nameTest: - ## ServiceAccount labels. - labels: {} -## Service account annotations. Can be templated. - annotations: {} - autoMount: true - -replicas: 2 -dedicatedValue: false - -## Create a headless service for the deployment -headlessService: true - -## Create HorizontalPodAutoscaler object for deployment type -# -autoscaling: - enabled: true - minReplicas: 4 - maxReplicas: 20 - targetCPU: "60" - targetMemory: "" - behavior: {} - -## See `kubectl explain poddisruptionbudget.spec` for more -## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/ -podDisruptionBudget: - minAvailable: 1 -# minAvailable: 1 -# maxUnavailable: 1 - -## See `kubectl explain deployment.spec.strategy` for more -## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy -deploymentStrategy: - type: RollingUpdate - -readinessProbe: - httpGet: - path: /api/health - port: 3000 - -livenessProbe: - httpGet: - path: /api/health - port: 3000 - initialDelaySeconds: 60 - timeoutSeconds: 30 - failureThreshold: 10 - -## Use an alternate scheduler, e.g. "stork". -## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: "default-scheduler" - -image: - repository: docker.io/grafana/grafana - # 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: [] - # - myRegistrKeySecretName - -testFramework: - enabled: true - image: docker.io/bats/bats - tag: "v1.4.1" - imagePullPolicy: IfNotPresent - securityContext: {} - -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/ - # subPath: certificates.crt # (optional) - # configMap: certs-configmap - # readOnly: true - - -extraEmptyDirMounts: [] - # - name: provisioning-notifiers - # mountPath: /etc/grafana/provisioning/notifiers - - -# Apply extra labels to common labels. -extraLabels: - bu: "infra" - team: "sre" - service: "grafana-infra-prd" - env: "prd" - priority: "p0" - type: "grafana" - - -## Assign a PriorityClassName to pods if set -# priorityClassName: - -downloadDashboardsImage: - repository: docker.io/curlimages/curl - tag: 7.85.0 - sha: "" - pullPolicy: IfNotPresent - -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: {} - -## Pod Labels -podLabels: - bu: "infra" - team: "sre" - service: "grafana-infra-prd" - env: "prd" - priority: "p0" - type: "grafana" - - -podPortName: grafana -gossipPortName: gossip -## Deployment annotations -# annotations: {} - -## Expose the grafana service to be accessed from outside the cluster (LoadBalancer service). -## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it. -## ref: http://kubernetes.io/docs/user-guide/services/ -## -service: - enabled: true - type: ClusterIP - port: 80 - targetPort: 3000 - # targetPort: 4181 To be used with a proxy extraContainer - ## 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 - ## 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: [] - targetLabels: [] - -extraExposePorts: [] - # - name: keycloak - # port: 8080 - # targetPort: 8080 - # type: ClusterIP - -# overrides pod.spec.hostAliases in the grafana deployment's pods -hostAliases: [] - # - ip: "1.2.3.4" - # hostnames: - # - "my.host.com" - -ingress: - enabled: true - # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName - # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress - ingressClassName: nginx-internal - # Values can be templated - annotations: - nginx.ingress.kubernetes.io/force-ssl-redirect: "false" - nginx.ingress.kubernetes.io/ssl-redirect: "false" - nginx.ingress.kubernetes.io/client_header_buffer_size: "512k" - nginx.ingress.kubernetes.io/large_client_header_buffers: "4 512k" - nginx.ingress.kubernetes.io/proxy-body-size: "0" - - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - labels: {} - path: / - - # pathType is only for k8s >= 1.1= - pathType: Prefix - - hosts: - - grafana-prd.meeshogcp.in - ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. - extraPaths: [] - # - path: /* - # backend: - # serviceName: ssl-redirect - # servicePort: use-annotation - ## Or for k8s > 1.19 - # - path: /* - # pathType: Prefix - # backend: - # service: - # name: ssl-redirect - # port: - # name: use-annotation - - - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -resources: - # limits: - # cpu: 3 - # memory: 50Gi - requests: - cpu: 4 - memory: 16i - -# ## Node labels for pod assignment -# ## ref: https://kubernetes.io/docs/user-guide/node-selection/ -# # -# nodeSelector: {} - -# ## Tolerations for pod assignment -# ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -# ## -# tolerations: [] - -nodeSelector: - dedicated: "sre-shared-tmp" - -tolerations: - - key: "dedicated" - operator: "Equal" - value: "sre-shared-tmp" - effect: "NoSchedule" - -## 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: - - maxSkew: 1 - topologyKey: topology.kubernetes.io/zone - whenUnsatisfiable: ScheduleAnyway - labelSelector: - matchLabels: - type: grafana - - maxSkew: 1 - topologyKey: kubernetes.io/hostname - whenUnsatisfiable: DoNotSchedule - labelSelector: - matchLabels: - type: grafana - -## Additional init containers (evaluated as template) -## ref: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/ -## -extraInitContainers: [] - -## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod -extraContainers: "" -# extraContainers: | -# - name: proxy -# image: quay.io/gambol99/keycloak-proxy:latest -# args: -# - -provider=github -# - -client-id= -# - -client-secret= -# - -github-org= -# - -email-domain=* -# - -cookie-secret= -# - -http-address=http://0.0.0.0:4181 -# - -upstream-url=http://127.0.0.1:3000 -# ports: -# - name: proxy-web -# containerPort: 4181 - -## Volumes that can be used in init containers that will not be mounted to deployment pods -extraContainerVolumes: [] -# - name: volume-from-secret -# secret: -# secretName: secret-to-mount -# - name: empty-dir-volume -# emptyDir: {} - -## Enable persistence using Persistent Volume Claims -## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ -## -persistence: - type: pvc - enabled: false - # storageClassName: default - accessModes: - - ReadWriteOnce - size: 10Gi - # annotations: {} - finalizers: - - kubernetes.io/pvc-protection - # selectorLabels: {} - ## Sub-directory of the PV to mount. Can be templated. - # subPath: "" - ## Name of an existing PVC. Can be templated. - # existingClaim: - ## Extra labels to apply to a PVC. - extraPvcLabels: {} - - ## If persistence is not enabled, this allows to mount the - ## local storage in-memory to improve performance - ## - inMemory: - enabled: false - ## The maximum usage on memory medium EmptyDir would be - ## the minimum value between the SizeLimit specified - ## here and the sum of memory limits of all containers in a pod - ## - # sizeLimit: 300Mi - -initChownData: - ## If false, data ownership will not be reset at startup - ## This allows the grafana-server to be run with an arbitrary user - ## - enabled: true - - ## initChownData container image - ## - image: - repository: docker.io/library/busybox - tag: "1.31.1" - sha: "" - pullPolicy: IfNotPresent - - ## initChownData resource requests and limits - ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # 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 -# adminPassword: strongpassword - -# Use an existing secret for the admin user. -admin: - ## Name of the secret. Can be templated. - existingSecret: "" - userKey: admin-user - passwordKey: admin-password - -## For Vault Configuration -externalSecrets: - refreshInterval: "150s" - secretStoreRef: - name: vault-backend - kind: ClusterSecretStore - dataFrom: - secretKey: "admin/common-infra/grafana-infra-prd" - - -## Define command to be executed at startup by grafana container -## Needed if using `vault-env` to manage secrets (ref: https://banzaicloud.com/blog/inject-secrets-into-pods-vault/) -## Default is "run.sh" as defined in grafana's Dockerfile -# command: -# - "sh" -# - "/run.sh" - -## 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 -## -## to provide grafana with access to CloudWatch on AWS EKS: -## 1. create an iam role of type "Web identity" with provider oidc.eks.* (note the provider for later) -## 2. edit the "Trust relationships" of the role, add a line inside the StringEquals clause using the -## same oidc eks provider as noted before (same as the existing line) -## also, replace NAMESPACE and prometheus-operator-grafana with the service account namespace and name -## -## "oidc.eks.us-east-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:sub": "system:serviceaccount:NAMESPACE:prometheus-operator-grafana", -## -## 3. attach a policy to the role, you can use a built in policy called CloudWatchReadOnlyAccess -## 4. use the following env: (replace 123456789000 and iam-role-name-here with your aws account number and role name) -## -## env: -## AWS_ROLE_ARN: arn:aws:iam::123456789000:role/iam-role-name-here -## AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token -## AWS_REGION: us-east-1 -## -## 5. uncomment the EKS section in extraSecretMounts: below -## 6. uncomment the annotation section in the serviceAccount: above -## make sure to replace arn:aws:iam::123456789000:role/iam-role-name-here with your role arn - -env: {} - -## "valueFrom" environment variable references that will be added to deployment pods. Name is templated. -## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core -## Renders in container spec as: -## env: -## ... -## - name: -## valueFrom: -## -envValueFrom: {} - # ENV_NAME: - # configMapKeyRef: - # name: configmap-name - # key: value_key - -## The name of a secret in the same kubernetes namespace which contain values to be added to the environment -## This can be useful for auth tokens, etc. Value is templated. -envFromSecret: "" - -## Sensible environment variables that will be rendered as new secret object -## This can be useful for auth tokens, etc. -## 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 -## Each entry should contain a name key, and can optionally specify whether the secret must be defined with an optional key. -## Name is templated. -envFromSecrets: - - name: grafana-infra-prd-secret - optional: false -## - name: secret-name -## optional: true - -## The names of conifgmaps in the same kubernetes namespace which contain values to be added to the environment -## Each entry should contain a name key, and can optionally specify whether the configmap must be defined with an optional key. -## Name is templated. -## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#configmapenvsource-v1-core -envFromConfigMaps: [] -## - name: configmap-name -## optional: true - -# Inject Kubernetes services as environment variables. -# See https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/#environment-variables -enableServiceLinks: true - -## Additional grafana server secret mounts -# Defines additional mounts with secrets. Secrets must be manually created in the namespace. -extraSecretMounts: [] - # - name: secret-files - # mountPath: /etc/secrets - # secretName: grafana-secret-files - # readOnly: true - # subPath: "" - # - # for AWS EKS (cloudwatch) use the following (see also instruction in env: above) - # - name: aws-iam-token - # mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount - # readOnly: true - # projected: - # defaultMode: 420 - # sources: - # - serviceAccountToken: - # audience: sts.amazonaws.com - # expirationSeconds: 86400 - # path: token - # - # for CSI e.g. Azure Key Vault use the following - # - name: secrets-store-inline - # mountPath: /run/secrets - # readOnly: true - # csi: - # driver: secrets-store.csi.k8s.io - # readOnly: true - # volumeAttributes: - # secretProviderClass: "akv-grafana-spc" - # nodePublishSecretRef: # Only required when using service principal mode - # name: grafana-akv-creds # Only required when using service principal mode - -## Additional grafana server volume mounts -# Defines additional volume mounts. -extraVolumeMounts: [] - # - name: extra-volume-0 - # mountPath: /mnt/volume0 - # readOnly: true - # existingClaim: volume-claim - # - name: extra-volume-1 - # mountPath: /mnt/volume1 - # readOnly: true - # hostPath: /usr/shared/ - # - name: grafana-secrets - # mountPath: /mnt/volume2 - # csi: true - # data: - # 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: {} - # postStart: - # exec: - # command: [] - -## Pass the plugins you want installed as a list. -## -plugins: - - grafana-piechart-panel - - grafana-googlesheets-datasource - - jeanbaptistewatenberg-percent-panel - - camptocamp-prometheus-alertmanager-datasource - - grafana-clock-panel - - marcusolsson-csv-datasource - - grafana-bigquery-datasource - - yesoreyeram-infinity-datasource - # - 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 -## -datasources: {} -# datasources.yaml: -# apiVersion: 1 -# datasources: -# - name: Prometheus -# type: prometheus -# url: http://prometheus-prometheus-server -# access: proxy -# isDefault: true -# - name: CloudWatch -# type: cloudwatch -# access: proxy -# uid: cloudwatch -# editable: false -# jsonData: -# authType: default -# defaultRegion: us-east-1 -# 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: - # 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 -## -notifiers: {} -# notifiers.yaml: -# notifiers: -# - name: email-notifier -# type: email -# uid: email1 -# # either: -# org_id: 1 -# # or -# org_name: Main Org. -# is_default: true -# settings: -# addresses: an_email_address@example.com -# delete_notifiers: - -## Configure grafana dashboard providers -## ref: http://docs.grafana.org/administration/provisioning/#dashboards -## -## `path` must be /var/lib/grafana/dashboards/ -## -dashboardProviders: {} -# dashboardproviders.yaml: -# apiVersion: 1 -# providers: -# - name: 'default' -# orgId: 1 -# folder: '' -# type: file -# disableDeletion: false -# editable: true -# options: -# path: /var/lib/grafana/dashboards/default - -## Configure grafana dashboard to import -## NOTE: To use dashboards you must also enable/configure dashboardProviders -## ref: https://grafana.com/dashboards -## -## dashboards per provider, use provider name as key. -## -dashboards: {} - # default: - # some-dashboard: - # json: | - # $RAW_JSON - # custom-dashboard: - # file: dashboards/custom-dashboard.json - # prometheus-stats: - # gnetId: 2 - # revision: 2 - # datasource: Prometheus - # local-dashboard: - # url: https://example.com/repository/test.json - # token: '' - # local-dashboard-base64: - # url: https://example.com/repository/test-b64.json - # token: '' - # b64content: true - # 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. -## ConfigMap data example: -## -## data: -## example-dashboard.json: | -## RAW_JSON -## -dashboardsConfigMaps: {} -# default: "" - -## Grafana's primary configuration -## NOTE: values in map will be converted to ini format -## ref: http://docs.grafana.org/installation/configuration/ -## -grafana.ini: - paths: - data: /var/lib/grafana/ - logs: /var/log/grafana - plugins: /var/lib/grafana/plugins - provisioning: /etc/grafana/provisioning - analytics: - check_for_updates: true - log: - mode: console - grafana_net: - url: https://grafana.net - database: - max_idle_conn: 5 - dataproxy: - timeout: 300 - keep_alive_seconds: 60 - dashboards: - min_refresh_interval: 60s - security: - allow_embedding: true - server: - domain: "{{ if (and .Values.ingress.enabled .Values.ingress.hosts) }}{{ .Values.ingress.hosts | first }}{{ else }}''{{ end }}" - http_addr: "0.0.0.0" - root_url: "https://{{ if (and .Values.ingress.enabled .Values.ingress.hosts) }}{{ .Values.ingress.hosts | first }}{{ else }}''{{ end }}" - enable_gzip: true - users: - auto_assign_org_role: "Editor" - auth.proxy: +grafana: + # From Vault via ExternalSecret (devops-infra-argo-config/secretstores/ + # grafana-admin-credentials.yaml), same pattern as gitea/harbor/jenkins + # admin credentials elsewhere in this project — never a plaintext + # adminPassword in this file. + admin: + existingSecret: grafana-admin-credentials + userKey: username + passwordKey: password + + persistence: + # local-path-provisioner, this cluster's default StorageClass — + # installed right after Cilium precisely because kubeadm ships no + # default (unlike k3s). 1Gi, not the chart's 10Gi default: this is + # dashboards, folders and Grafana's own sqlite state, not metric + # data — VictoriaMetrics holds that. Not resizable in place with + # this provisioner, so sized deliberately rather than grown later. enabled: true - header_name: "X-WEBAUTH-USER" - header_property: "username" - unified_alerting: - enabled: true - ha_peers: grafana-infra-prd-headless:9094 - ha_listen_address: ${POD_IP}:9094 - ha_advertise_address: ${POD_IP}:9094 - alerting: - enabled: false -## grafana Authentication can be enabled with the following values on grafana.ini - # server: - # The full public facing url you use in browser, used for redirects and emails - # root_url: - # https://grafana.com/docs/grafana/latest/auth/github/#enable-github-in-grafana - # auth.github: - # enabled: false - # allow_sign_up: false - # scopes: user:email,read:org - # auth_url: https://github.com/login/oauth/authorize - # token_url: https://github.com/login/oauth/access_token - # api_url: https://api.github.com/user - # team_ids: - # allowed_organizations: - # client_id: - # client_secret: -## LDAP Authentication can be enabled with the following values on grafana.ini -## NOTE: Grafana will fail to start if the value for ldap.toml is invalid - # auth.ldap: - # enabled: true - # allow_sign_up: true - # config_file: /etc/grafana/ldap.toml + storageClassName: local-path + size: 1Gi -## Grafana's LDAP configuration -## Templated by the template in _helpers.tpl -## NOTE: To enable the grafana.ini must be configured with auth.ldap.enabled -## ref: http://docs.grafana.org/installation/configuration/#auth-ldap -## ref: http://docs.grafana.org/installation/ldap/#configuration -ldap: - enabled: false - # `existingSecret` is a reference to an existing secret containing the ldap configuration - # for Grafana in a key `ldap-toml`. - existingSecret: "" - # `config` is the content of `ldap.toml` that will be stored in the created secret - config: "" - # config: |- - # verbose_logging = true + resources: + requests: + cpu: 50m + memory: 128Mi + limits: + memory: 384Mi - # [[servers]] - # host = "my-ldap-server" - # port = 636 - # use_ssl = true - # start_tls = false - # ssl_skip_verify = false - # bind_dn = "uid=%s,ou=users,dc=myorg,dc=com" - -## Grafana's SMTP configuration -## NOTE: To enable, grafana.ini must be configured with smtp.enabled -## ref: http://docs.grafana.org/installation/configuration/#smtp -smtp: - # `existingSecret` is a reference to an existing secret containing the smtp configuration - # for Grafana. - existingSecret: "" - userKey: "user" - passwordKey: "password" - -## Sidecars that collect the configmaps with specified label and stores the included files them into the respective folders -## Requires at least Grafana 5 to work and can't be used together with parameters dashboardProviders, datasources and dashboards -sidecar: - image: - repository: quay.io/kiwigrid/k8s-sidecar - tag: 1.24.6 - sha: "" - imagePullPolicy: IfNotPresent - resources: {} -# limits: -# cpu: 100m -# memory: 100Mi -# requests: -# cpu: 50m -# memory: 50Mi - 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 - # Deploy the alert sidecar as an initContainer in addition to a container. - # 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: {} - # 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: "" - # 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 - defaultFolderName: null - # Namespaces list. If specified, the sidecar will search for config-maps/secrets inside these namespaces. - # Otherwise the namespace in which the sidecar is running will be used. - # It's also possible to specify ALL to search in all namespaces. - searchNamespace: null - # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. - watchMethod: WATCH - # search in configmap, secret or both - resource: both - # If specified, the sidecar will look for annotation with this name to create folder and put graph here. - # You can use this parameter together with `provider.foldersFromFilesStructure`to annotate configmaps and create folder structure. - folderAnnotation: null - # 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 - # - # watchClientTimeout: is a client-side timeout, configuring your local socket. - # If you have a network outage dropping all packets with no RST/FIN, - # this is how long your client waits before realizing & dropping the connection. - # defaults to 66sec (sic!) - # watchClientTimeout: 60 - # - # provider configuration that lets grafana manage the dashboards - provider: - # name of the provider, should be unique - name: sidecarProvider - # orgid as configured in grafana - orgid: 1 - # folder in which the dashboards should be imported in grafana - folder: '' - # type of the provider - type: file - # disableDelete to activate a import-only behaviour - disableDelete: false - # allow updating provisioned dashboards from the UI - allowUiUpdates: false - # allow Grafana to replicate dashboard structure from filesystem - foldersFromFilesStructure: false - # Additional dashboard sidecar volume mounts - extraMounts: [] - # Sets the size limit of the dashboard sidecar emptyDir volume - sizeLimit: {} + # Provisioned at boot, not clicked through in the UI — the same reason + # every other credential/config in this project is committed rather + # than set by hand: it survives a pod restart and a fresh install gets + # it automatically. VictoriaMetrics speaks Prometheus's own query API, + # so `type: prometheus` here is correct even though the URL is VM's — + # see devops-infra-helm-charts' victoria-metrics-single chart for why. datasources: - enabled: false - # Additional environment variables for the datasourcessidecar - env: {} - # 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: "" - # 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 - 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 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. - 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: "" - # 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 - 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 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: {} + datasources.yaml: + apiVersion: 1 + datasources: + - name: VictoriaMetrics + type: prometheus + access: proxy + url: http://victoria-metrics-single-server.monitoring.svc.cluster.local:8428 + isDefault: true -## Override the deployment namespace -## -namespaceOverride: "" - -## Number of old ReplicaSets to retain -## -revisionHistoryLimit: 10 - -## Add a seperate remote image renderer deployment/service -imageRenderer: - deploymentStrategy: {} - # Enable the image-renderer deployment & service - enabled: false - replicas: 2 - autoscaling: - enabled: false - minReplicas: 2 - maxReplicas: 5 - targetCPU: "60" - targetMemory: "" - behavior: {} - image: - # image-renderer Image repository - repository: docker.io/grafana/grafana-image-renderer - # image-renderer Image tag - tag: latest - # image-renderer Image sha (optional) - sha: "" - # image-renderer ImagePullPolicy - pullPolicy: Always - # extra environment variables - env: - HTTP_HOST: "0.0.0.0" - # RENDERING_ARGS: --no-sandbox,--disable-gpu,--window-size=1280x758 - # RENDERING_MODE: clustered - # IGNORE_HTTPS_ERRORS: true - - ## "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 deployment Host Aliases - hostAliases: [] - # image-renderer deployment priority class - priorityClassName: '' - service: - # Enable the image-renderer service + ingress: enabled: true - # image-renderer service port name - portName: 'http' - # 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 - grafanaSubPath: "" - # name of the image-renderer port on the pod - podPortName: http - # number of image-renderer replica sets to keep - revisionHistoryLimit: 10 - networkPolicy: - # Enable a NetworkPolicy to limit inbound traffic to only the created grafana pods - limitIngress: true - # Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods - limitEgress: false - # Allow additional services to access image-renderer (eg. Prometheus operator when ServiceMonitor is enabled) - extraIngressSelectors: [] - resources: {} -# limits: -# cpu: 100m -# memory: 100Mi -# requests: -# cpu: 50m -# memory: 50Mi - ## Node labels for pod assignment - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - # - nodeSelector: {} - - ## Tolerations for pod assignment - ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - ## - tolerations: [] - - ## Affinity for pod assignment (evaluated as template) - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity - ## - affinity: {} - - ## Use an alternate scheduler, e.g. "stork". - ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ - ## - # schedulerName: "default-scheduler" - -networkPolicy: - ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. - ## - enabled: false - ## @param networkPolicy.allowExternal Don't require client label for connections - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to grafana port defined. - ## When true, grafana will accept connections from any source - ## (with the correct destination port). - ## - 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 - ## and that match other criteria, the ones that have the good label, can reach the grafana. - ## But sometimes, we want the grafana to be accessible to clients from other namespaces, in this case, we can use this - ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added. - ## - ## Example: - ## explicitNamespacesSelector: - ## matchLabels: - ## role: frontend - ## matchExpressions: - ## - {key: role, operator: In, values: [frontend]} - ## - explicitNamespacesSelector: {} - ## - ## - ## - ## - ## - ## - 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.ports Add individual ports to be allowed by the egress - ports: [] - ## Add ports to the egress by specifying - port: - ## E.X. - ## ports: - ## - port: 80 - ## - port: 443 - ## - ## - ## - ## - ## - ## - -# 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" - # kind: ExternalSecret - # metadata: - # name: grafana-secrets - # spec: - # backendType: gcpSecretsManager - # data: - # - key: grafana-admin-password - # name: adminPassword + ingressClassName: contour + path: / + hosts: + - grafana.192.168.1.7.nip.io + - grafana.100.90.248.118.nip.io diff --git a/helm-overrides/k8s-admin-prd-ase1/victoria-metrics-single/custom-values.yaml b/helm-overrides/k8s-admin-prd-ase1/victoria-metrics-single/custom-values.yaml index 51cf699..0d31f1c 100644 --- a/helm-overrides/k8s-admin-prd-ase1/victoria-metrics-single/custom-values.yaml +++ b/helm-overrides/k8s-admin-prd-ase1/victoria-metrics-single/custom-values.yaml @@ -22,3 +22,23 @@ victoria-metrics-single: memory: 128Mi limits: memory: 512Mi + + # vmui — VictoriaMetrics' own built-in UI, served at /vmui/ on the + # same server. Ad-hoc PromQL queries and graphs only, no saved + # dashboards; Grafana (separate release) is what those need. Exposed + # anyway since it costs nothing extra to run — it's the same + # pod/port, not a new component — and is useful on its own for + # poking at a metric without opening Grafana. + # + # Dual LAN + Tailscale hostnames, same convention as every other + # externally-reachable service in this homelab. + ingress: + enabled: true + ingressClassName: contour + hosts: + - name: vm.192.168.1.7.nip.io + path: ["/"] + port: http + - name: vm.100.90.248.118.nip.io + path: ["/"] + port: http diff --git a/helm-templates/grafana/.helmignore b/helm-templates/grafana/.helmignore deleted file mode 100644 index 8cade13..0000000 --- a/helm-templates/grafana/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*~ -# Various IDEs -.vscode -.project -.idea/ -*.tmproj -OWNERS diff --git a/helm-templates/grafana/Chart.lock b/helm-templates/grafana/Chart.lock new file mode 100644 index 0000000..daf1a1e --- /dev/null +++ b/helm-templates/grafana/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: grafana + repository: https://grafana.github.io/helm-charts + version: 10.5.15 +digest: sha256:3fd0080197abb0a1968d174ead7180f962c939cab8037f1b8ead6dd3adfa7490 +generated: "2026-09-06T08:54:21.395461+05:30" diff --git a/helm-templates/grafana/Chart.yaml b/helm-templates/grafana/Chart.yaml index 2bf45f3..f6c7f47 100644 --- a/helm-templates/grafana/Chart.yaml +++ b/helm-templates/grafana/Chart.yaml @@ -1,33 +1,20 @@ apiVersion: v2 name: grafana -version: 6.58.7 -appVersion: 10.0.3 -kubeVersion: "^1.8.0-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 -sources: - - https://github.com/grafana/grafana - - https://github.com/grafana/helm-charts -annotations: - "artifacthub.io/license": AGPL-3.0-only - "artifacthub.io/links": | - - name: Chart Source - url: https://github.com/grafana/helm-charts - - name: Upstream Project - url: https://github.com/grafana/grafana -maintainers: - - name: zanhsieh - email: zanhsieh@gmail.com - - name: rtluckie - email: rluckie@cisco.com - - name: maorfr - email: maor.friedman@redhat.com - - name: Xtigyro - email: miroslav.hadzhiev@gmail.com - - name: torstenwalter - email: mail@torstenwalter.de -type: application -keywords: - - monitoring - - metric +version: 1.0.0 +dependencies: + - name: grafana + # Pinned to the latest stable at the time this was vendored (2026-09). + # Bump deliberately later, with a changelog read first, same as any + # other chart bump in this repo. + # + # This directory already held a fully-vendored copy of an old Grafana + # chart (v6.58.7, appVersion 10.0.3) from the original Meesho monorepo + # import (commit b8575bb) — generic production config + # (fullnameOverride: grafana-infra-prd, GKE-shaped RBAC/PSP defaults), + # not anything built for this homelab. Removed and re-vendored fresh + # as a thin wrapper, matching the pattern every other official-chart + # component in this repo now uses (vault, victoria-metrics-single, + # vmagent, node-exporter) — a Chart.yaml dependency plus a committed + # .tgz, no local templates to silently drift from upstream. + version: 10.5.15 + repository: https://grafana.github.io/helm-charts diff --git a/helm-templates/grafana/README.md b/helm-templates/grafana/README.md deleted file mode 100644 index bcf0923..0000000 --- a/helm-templates/grafana/README.md +++ /dev/null @@ -1,686 +0,0 @@ -# Grafana Helm Chart - -* Installs the web dashboarding system [Grafana](http://grafana.org/) - -## Get Repo Info - -```console -helm repo add grafana https://grafana.github.io/helm-charts -helm repo update -``` - -_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```console -helm install my-release grafana/grafana -``` - -## Uninstalling the Chart - -To uninstall/delete the my-release deployment: - -```console -helm delete my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -## Upgrading an existing Release to a new major version - -A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an -incompatible breaking change needing manual actions. - -### To 4.0.0 (And 3.12.1) - -This version requires Helm >= 2.12.0. - -### To 5.0.0 - -You have to add --force to your helm upgrade command as the labels of the chart have changed. - -### To 6.0.0 - -This version requires Helm >= 3.1.0. - -## Configuration - -| Parameter | Description | Default | -|-------------------------------------------|-----------------------------------------------|---------------------------------------------------------| -| `replicas` | Number of nodes | `1` | -| `podDisruptionBudget.minAvailable` | Pod disruption minimum available | `nil` | -| `podDisruptionBudget.maxUnavailable` | Pod disruption maximum unavailable | `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.repository` | Image repository | `grafana/grafana` | -| `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 (can be templated) | `[]` | -| `service.enabled` | Enable grafana service | `true` | -| `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 (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 | `[]` | -| `headlessService` | Create a headless service | `false` | -| `extraExposePorts` | Additional service ports for sidecar containers| `[]` | -| `hostAliases` | adds rules to the pod's /etc/hosts | `[]` | -| `ingress.enabled` | Enables Ingress | `false` | -| `ingress.annotations` | Ingress annotations (values are templated) | `{}` | -| `ingress.labels` | Custom labels | `{}` | -| `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.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 | `[]` | -| `affinity` | Affinity settings for pod assignment | `{}` | -| `extraInitContainers` | Init containers to add to the grafana pod | `{}` | -| `extraContainers` | Sidecar containers to add to the grafana pod | `""` | -| `extraContainerVolumes` | Volumes that can be mounted in sidecar containers | `[]` | -| `extraLabels` | Custom labels for all manifests | `{}` | -| `schedulerName` | Name of the k8s scheduler (other than default) | `nil` | -| `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 (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.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` | -| `initChownData.enabled` | If false, don't reset data ownership at startup | true | -| `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)| `""` | -| `initChownData.image.pullPolicy` | init-chown-data container image pull policy | `IfNotPresent` | -| `initChownData.resources` | init-chown-data pod resource requests & limits | `{}` | -| `schedulerName` | Alternate scheduler name | `nil` | -| `env` | Extra environment variables passed to pods | `{}` | -| `envValueFrom` | Environment variables 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 | `{}` | -| `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. (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 | `[]` | -| `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.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 | `""` | -| `annotations` | Deployment annotations | `{}` | -| `labels` | Deployment labels | `{}` | -| `podAnnotations` | Pod annotations | `{}` | -| `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.24.6` | -| `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.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 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.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` | -| `sidecar.dashboards.provider.foldersFromFilesStructure` | Allow Grafana to replicate dashboard structure from filesystem. | `false` | -| `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 | `""` | -| `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.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 | `""` | -| `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.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 (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.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) | `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` | -| `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.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.tag` | Curl docker image tag | `7.73.0` | -| `downloadDashboardsImage.sha` | Curl docker image sha (optional) | `""` | -| `downloadDashboardsImage.pullPolicy` | Curl docker image pull policy | `IfNotPresent` | -| `namespaceOverride` | Override the deployment namespace | `""` (`Release.Namespace`) | -| `serviceMonitor.enabled` | Use servicemonitor from prometheus operator | `false` | -| `serviceMonitor.namespace` | Namespace this servicemonitor is installed in | | -| `serviceMonitor.interval` | How frequently Prometheus should scrape | `1m` | -| `serviceMonitor.path` | Path to scrape | `/metrics` | -| `serviceMonitor.scheme` | Scheme to use for metrics scraping | `http` | -| `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. | `[]` | -| `revisionHistoryLimit` | Number of old ReplicaSets to retain | `10` | -| `imageRenderer.enabled` | Enable the image-renderer deployment & service | `false` | -| `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.serviceAccountName` | image-renderer deployment serviceAccountName | `""` | -| `imageRenderer.securityContext` | image-renderer deployment securityContext | `{}` | -| `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 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 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: - domain: monitoring.example.com - root_url: "%(protocol)s://%(domain)s/grafana" - serve_from_sub_path: true -ingress: - enabled: true - hosts: - - "monitoring.example.com" - path: "/grafana" -``` - -### Example of extraVolumeMounts - -Volume can be type persistentVolumeClaim or hostPath but not both at same time. -If neither existingClaim or hostPath argument is given then type is emptyDir. - -```yaml -- 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 -``` - -## 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: - -```yaml -dashboards: - default: - some-dashboard: - json: | - { - "annotations": - - ... - # Complete json file here - ... - - "title": "Some Dashboard", - "uid": "abcd1234", - "version": 1 - } - custom-dashboard: - # This is a path to a file inside the dashboards directory inside the chart directory - file: dashboards/custom-dashboard.json - prometheus-stats: - # Ref: https://grafana.com/dashboards/2 - 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 -``` - -## BASE64 dashboards - -Dashboards could be stored on a server that does not return JSON directly and instead of it returns a Base64 encoded file (e.g. Gerrit) -A new parameter has been added to the url use case so if you specify a b64content value equals to true after the url entry a Base64 decoding is applied before save the file to disk. -If this entry is not set or is equals to false not decoding is applied to the file before saving it to disk. - -### Gerrit use case - -Gerrit API for download files has the following schema: where {project-name} and -{file-id} usually has '/' in their values and so they MUST be replaced by %2F so if project-name is user/repo, branch-id is master and file-id is equals to dir1/dir2/dashboard -the url value is - -## Sidecar for dashboards - -If the parameter `sidecar.dashboards.enabled` is set, a sidecar container is deployed in the grafana -pod. This container watches all configmaps (or secrets) in the cluster and filters out the ones with -a label as defined in `sidecar.dashboards.label`. The files defined in those configmaps are written -to a folder and accessed by grafana. Changes to the configmaps are monitored and the imported -dashboards are deleted/updated. - -A recommendation is to use one configmap per dashboard, as a reduction of multiple dashboards inside -one configmap is currently not properly mirrored in grafana. - -Example dashboard config: - -```yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: sample-grafana-dashboard - labels: - grafana_dashboard: "1" -data: - k8s-dashboard.json: |- - [...] -``` - -## Sidecar for datasources - -If the parameter `sidecar.datasources.enabled` is set, an init container is deployed in the grafana -pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and -filters out the ones with a label as defined in `sidecar.datasources.label`. The files defined in -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 -datasources: - datasources.yaml: - apiVersion: 1 - datasources: - # name of the datasource. Required - - name: Graphite - # datasource type. Required - type: graphite - # access mode. proxy or direct (Server or Browser in the UI). Required - access: proxy - # org id. will default to orgId 1 if not specified - orgId: 1 - # url - url: http://localhost:8080 - # database password, if used - password: - # database user, if used - user: - # database name, if used - database: - # enable/disable basic auth - basicAuth: - # basic auth username - basicAuthUser: - # basic auth password - basicAuthPassword: - # enable/disable with credentials headers - withCredentials: - # mark as default datasource. Max one per org - isDefault: - # fields that will be converted to json and stored in json_data - jsonData: - graphiteVersion: "1.1" - tlsAuth: true - tlsAuthWithCACert: true - # json object of data that will be encrypted. - secureJsonData: - tlsCACert: "..." - tlsClientCert: "..." - tlsClientKey: "..." - version: 1 - # allow users to edit datasources from the UI. - editable: false -``` - -## Sidecar for notifiers - -If the parameter `sidecar.notifiers.enabled` is set, an init container is deployed in the grafana -pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and -filters out the ones with a label as defined in `sidecar.notifiers.label`. The files defined in -those secrets are written to a folder and accessed by grafana on startup. Using these yaml files, -the notification channels in grafana can be imported. The secrets must be created before -`helm install` so that the notifiers init container can list the secrets. - -Secrets are recommended over configmaps for this usecase because alert notification channels usually contain -private data like SMTP usernames and passwords. Secrets are the more appropriate cluster resource to manage those. - -Example datasource config adapted from [Grafana](https://grafana.com/docs/grafana/latest/administration/provisioning/#alert-notification-channels): - -```yaml -notifiers: - - name: notification-channel-1 - type: slack - uid: notifier1 - # either - org_id: 2 - # or - org_name: Main Org. - is_default: true - send_reminder: true - frequency: 1h - disable_resolve_message: false - # See `Supported Settings` section for settings supporter for each - # alert notification type. - settings: - recipient: 'XXX' - token: 'xoxb' - uploadImage: true - url: https://slack.com - -delete_notifiers: - - name: notification-channel-1 - uid: notifier1 - org_id: 2 - - name: notification-channel-2 - # default org_id: 1 -``` - -## Provision alert rules, contact points, notification policies and notification templates - -There are two methods to 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" . }}` }}' -``` - -There are two possibilities: - -* Inlining the file contents as described in the example `values.yaml` and the official [Grafana documentation](https://grafana.com/docs/grafana/next/alerting/set-up/provision-alerting-resources/file-provisioning/). -* Importing a file using a relative path starting from the chart root directory. - -### Important notes 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. - -```yaml -ingress: - enabled: true - annotations: - kubernetes.io/ingress.class: "nginx" - nginx.ingress.kubernetes.io/rewrite-target: /$1 - nginx.ingress.kubernetes.io/use-regex: "true" - - path: /grafana/?(.*) - hosts: - - k8s.example.dev - -grafana.ini: - server: - root_url: http://localhost:3000/grafana # this host can be localhost -``` - -## How to securely reference secrets in grafana.ini - -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: - -```yaml -grafana.ini: - [auth.generic_oauth] - enabled = true - client_id = $__file{/etc/secrets/auth_generic_oauth/client_id} - client_secret = $__file{/etc/secrets/auth_generic_oauth/client_secret} -``` - -Existing secret, or created along with helm: - -```yaml ---- -apiVersion: v1 -kind: Secret -metadata: - name: auth-generic-oauth-secret -type: Opaque -stringData: - client_id: - client_secret: -``` - -Include in the `extraSecretMounts` configuration flag: - -```yaml -- extraSecretMounts: - - name: auth-generic-oauth-secret-mount - secretName: auth-generic-oauth-secret - defaultMode: 0440 - mountPath: /etc/secrets/auth_generic_oauth - readOnly: true -``` - -### extraSecretMounts using a Container Storage Interface (CSI) provider - -This example uses a CSI driver e.g. retrieving secrets using [Azure Key Vault Provider](https://github.com/Azure/secrets-store-csi-driver-provider-azure) - -```yaml -- extraSecretMounts: - - name: secrets-store-inline - mountPath: /run/secrets - readOnly: true - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: "my-provider" - nodePublishSecretRef: - name: akv-creds -``` - -## Image Renderer Plug-In - -This chart supports enabling [remote image rendering](https://github.com/grafana/grafana-image-renderer/blob/master/README.md#run-in-docker) - -```yaml -imageRenderer: - enabled: true -``` - -### Image Renderer NetworkPolicy - -By default the image-renderer pods will have a network policy which only allows ingress traffic from the created grafana instance - -### High Availability for unified alerting - -If you want to run Grafana in a high availability cluster you need to enable -the headless service by setting `headlessService: true` in your `values.yaml` -file. - -As next step you have to setup the `grafana.ini` in your `values.yaml` in a way -that it will make use of the headless service to obtain all the IPs of the -cluster. You should replace ``{{ Name }}`` with the name of your helm deployment. - -```yaml -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/helm-templates/grafana/charts/grafana-10.5.15.tgz b/helm-templates/grafana/charts/grafana-10.5.15.tgz new file mode 100644 index 0000000000000000000000000000000000000000..057cb6763e4f4e45190bb159605e6fefc392bdce GIT binary patch literal 50028 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 literal 0 HcmV?d00001 diff --git a/helm-templates/grafana/ci/default-values.yaml b/helm-templates/grafana/ci/default-values.yaml deleted file mode 100644 index fc2ba60..0000000 --- a/helm-templates/grafana/ci/default-values.yaml +++ /dev/null @@ -1 +0,0 @@ -# Leave this file empty to ensure that CI runs builds against the default configuration in values.yaml. diff --git a/helm-templates/grafana/ci/with-affinity-values.yaml b/helm-templates/grafana/ci/with-affinity-values.yaml deleted file mode 100644 index f5b9b53..0000000 --- a/helm-templates/grafana/ci/with-affinity-values.yaml +++ /dev/null @@ -1,16 +0,0 @@ -affinity: - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchLabels: - app.kubernetes.io/instance: grafana-test - app.kubernetes.io/name: grafana - topologyKey: failure-domain.beta.kubernetes.io/zone - weight: 100 - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchLabels: - app.kubernetes.io/instance: grafana-test - app.kubernetes.io/name: grafana - topologyKey: kubernetes.io/hostname diff --git a/helm-templates/grafana/ci/with-dashboard-json-values.yaml b/helm-templates/grafana/ci/with-dashboard-json-values.yaml deleted file mode 100644 index e0c4e41..0000000 --- a/helm-templates/grafana/ci/with-dashboard-json-values.yaml +++ /dev/null @@ -1,53 +0,0 @@ -dashboards: - my-provider: - my-awesome-dashboard: - # An empty but valid dashboard - json: | - { - "__inputs": [], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "6.3.5" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "id": null, - "links": [], - "panels": [], - "schemaVersion": 19, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": ["5s"] - }, - "timezone": "", - "title": "Dummy Dashboard", - "uid": "IdcYQooWk", - "version": 1 - } - datasource: Prometheus diff --git a/helm-templates/grafana/ci/with-dashboard-values.yaml b/helm-templates/grafana/ci/with-dashboard-values.yaml deleted file mode 100644 index 7b662c5..0000000 --- a/helm-templates/grafana/ci/with-dashboard-values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -dashboards: - my-provider: - my-awesome-dashboard: - gnetId: 10000 - revision: 1 - datasource: Prometheus -dashboardProviders: - dashboardproviders.yaml: - apiVersion: 1 - providers: - - name: 'my-provider' - orgId: 1 - folder: '' - type: file - updateIntervalSeconds: 10 - disableDeletion: true - editable: true - options: - path: /var/lib/grafana/dashboards/my-provider diff --git a/helm-templates/grafana/ci/with-extraconfigmapmounts-values.yaml b/helm-templates/grafana/ci/with-extraconfigmapmounts-values.yaml deleted file mode 100644 index 5cc44a0..0000000 --- a/helm-templates/grafana/ci/with-extraconfigmapmounts-values.yaml +++ /dev/null @@ -1,7 +0,0 @@ -extraConfigmapMounts: - - name: '{{ include "grafana.fullname" . }}' - configMap: '{{ include "grafana.fullname" . }}' - mountPath: /var/lib/grafana/dashboards/test-dashboard.json - # This is not a realistic test, but for this we only care about extraConfigmapMounts not being empty and pointing to an existing ConfigMap - subPath: grafana.ini - readOnly: true diff --git a/helm-templates/grafana/ci/with-image-renderer-values.yaml b/helm-templates/grafana/ci/with-image-renderer-values.yaml deleted file mode 100644 index 32f3074..0000000 --- a/helm-templates/grafana/ci/with-image-renderer-values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -podLabels: - customLableA: Aaaaa -imageRenderer: - enabled: true - env: - RENDERING_ARGS: --disable-gpu,--window-size=1280x758 - RENDERING_MODE: clustered - podLabels: - customLableB: Bbbbb - networkPolicy: - limitIngress: true - limitEgress: true - resources: - limits: - cpu: 1000m - memory: 1000Mi - requests: - cpu: 500m - memory: 50Mi diff --git a/helm-templates/grafana/ci/with-persistence.yaml b/helm-templates/grafana/ci/with-persistence.yaml deleted file mode 100644 index b92ca02..0000000 --- a/helm-templates/grafana/ci/with-persistence.yaml +++ /dev/null @@ -1,3 +0,0 @@ -persistence: - type: pvc - enabled: true diff --git a/helm-templates/grafana/dashboards/custom-dashboard.json b/helm-templates/grafana/dashboards/custom-dashboard.json deleted file mode 100644 index 9e26dfe..0000000 --- a/helm-templates/grafana/dashboards/custom-dashboard.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/helm-templates/grafana/templates/NOTES.txt b/helm-templates/grafana/templates/NOTES.txt deleted file mode 100644 index d86419f..0000000 --- a/helm-templates/grafana/templates/NOTES.txt +++ /dev/null @@ -1,55 +0,0 @@ -1. Get your '{{ .Values.adminUser }}' user password by running: - - 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: - - {{ 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: - ``` - securityContext: - runAsUser: 0 - runAsGroup: 0 - fsGroup: 0 - - command: - - "setcap" - - "'cap_net_bind_service=+ep'" - - "/usr/sbin/grafana-server &&" - - "sh" - - "/run.sh" - ``` - Details refer to https://grafana.com/docs/installation/configuration/#http-port. - Or grafana would always crash. - - From outside the cluster, the server URL(s) are: - {{- range .Values.ingress.hosts }} - http://{{ . }} - {{- end }} -{{- else }} - Get the Grafana URL to visit by running these commands in the same shell: - {{- if contains "NodePort" .Values.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ 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 }} - 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 {{ 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 {{ 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 }} -################################################################################# -###### WARNING: Persistence is disabled!!! You will lose your data when ##### -###### the Grafana pod is terminated. ##### -################################################################################# -{{- end }} diff --git a/helm-templates/grafana/templates/_helpers.tpl b/helm-templates/grafana/templates/_helpers.tpl deleted file mode 100644 index 3046891..0000000 --- a/helm-templates/grafana/templates/_helpers.tpl +++ /dev/null @@ -1,265 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "grafana.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "grafana.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Maintainer - Akshay Gupta -Tolerations and nodeSelector via Resources Requests. -*/}} -{{- define "meesho.grafana.getCpu" -}} -{{- $cpu := toString .Values.resources.requests.cpu -}} -{{- if contains "m" $cpu -}} -{{- $cpu := trimAll "m" $cpu | float64 -}} -{{- $cpu := $cpu | float64 -}} -{{- printf "%f" $cpu -}} -{{- else -}} -{{- $cpu := mulf $cpu 1000.000 -}} -{{- printf "%f" $cpu -}} -{{- end -}} -{{- end -}} - -{{- define "meesho.grafana.getMem" -}} -{{- $mem := toString .Values.resources.requests.memory -}} -{{- if contains "Mi" $mem -}} -{{- $mem := trimAll "Mi" $mem | float64 -}} -{{- printf "%f" $mem -}} -{{- else if contains "Gi" $mem -}} -{{- $mem := trimAll "Gi" $mem | float64 -}} -{{- $mem := mulf $mem 1024.000 -}} -{{- printf "%f" $mem -}} -{{- end -}} -{{- end -}} - -{{- define "meesho.grafana.getRatio" -}} -{{- $cpu := (include "meesho.grafana.getCpu" .) -}} -{{- $mem := (include "meesho.grafana.getMem" .) -}} -{{- $ratio := divf $mem $cpu -}} -{{- if gt $ratio 4.00 -}} -{{- printf "1to8" -}} -{{- else if gt $ratio 2.00 -}} -{{- printf "1to4" -}} -{{- else -}} -{{- printf "1to2" -}} -{{- end -}} -{{- end -}} - -{{- define "meesho.grafana.dedicatedValue" -}} -{{- if (index .Values.extraLabels "arch") -}} -{{- if (index .Values.extraLabels "runpod") -}} -{{- $cpu := (include "meesho.grafana.getCpu" .) -}} -{{- $mem := (include "meesho.grafana.getMem" .) -}} -{{- $ratio := (include "meesho.grafana.getRatio" .) -}} -{{- $arch := .Values.extraLabels.arch -}} -{{- $runPod := .Values.extraLabels.runpod -}} -{{- printf "%s-%s-%s" $ratio $arch $runPod -}} -{{- else -}} -{{- printf "missing-runpod-label" -}} -{{- end -}} -{{- else -}} -{{- printf "missing-arch-label" -}} -{{- end -}} -{{- end -}} - - - - - - - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "grafana.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create the name of the service account -*/}} -{{- define "grafana.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "grafana.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} - -{{- define "grafana.serviceAccountNameTest" -}} -{{- if .Values.serviceAccount.create }} -{{- default (print (include "grafana.fullname" .) "-test") .Values.serviceAccount.nameTest }} -{{- else }} -{{- default "default" .Values.serviceAccount.nameTest }} -{{- end }} -{{- end }} - -{{/* -Allow the release namespace to be overridden for multi-namespace deployments in combined charts -*/}} -{{- define "grafana.namespace" -}} -{{- if .Values.namespaceOverride }} -{{- .Values.namespaceOverride }} -{{- else }} -{{- .Release.Namespace }} -{{- end }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "grafana.labels" -}} -helm.sh/chart: {{ include "grafana.chart" . }} -{{ include "grafana.selectorLabels" . }} -{{- if or .Chart.AppVersion .Values.image.tag }} -app.kubernetes.io/version: {{ mustRegexReplaceAllLiteral "@sha.*" .Values.image.tag "" | default .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- with .Values.extraLabels }} -{{ toYaml . }} -{{- end }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "grafana.selectorLabels" -}} -app.kubernetes.io/name: {{ include "grafana.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "grafana.imageRenderer.labels" -}} -helm.sh/chart: {{ include "grafana.chart" . }} -{{ include "grafana.imageRenderer.selectorLabels" . }} -{{- if or .Chart.AppVersion .Values.image.tag }} -app.kubernetes.io/version: {{ mustRegexReplaceAllLiteral "@sha.*" .Values.image.tag "" | default .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels ImageRenderer -*/}} -{{- define "grafana.imageRenderer.selectorLabels" -}} -app.kubernetes.io/name: {{ include "grafana.name" . }}-image-renderer -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Looks if there's an existing secret and reuse its password. If not it generates -new password and use it. -*/}} -{{- define "grafana.password" -}} -{{- $secret := (lookup "v1" "Secret" (include "grafana.namespace" .) (include "grafana.fullname" .) ) }} -{{- if $secret }} -{{- index $secret "data" "admin-password" }} -{{- else }} -{{- (randAlphaNum 40) | b64enc | quote }} -{{- end }} -{{- end }} - -{{/* -Return the appropriate apiVersion for rbac. -*/}} -{{- define "grafana.rbac.apiVersion" -}} -{{- if $.Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1" }} -{{- print "rbac.authorization.k8s.io/v1" }} -{{- else }} -{{- print "rbac.authorization.k8s.io/v1beta1" }} -{{- end }} -{{- end }} - -{{/* -Return the appropriate apiVersion for ingress. -*/}} -{{- define "grafana.ingress.apiVersion" -}} -{{- if and ($.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" .Capabilities.KubeVersion.Version) }} -{{- print "networking.k8s.io/v1" }} -{{- else if $.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} -{{- print "networking.k8s.io/v1beta1" }} -{{- else }} -{{- print "extensions/v1beta1" }} -{{- end }} -{{- end }} - -{{/* -Return the appropriate apiVersion for Horizontal Pod Autoscaler. -*/}} -{{- define "grafana.hpa.apiVersion" -}} -{{- if $.Capabilities.APIVersions.Has "autoscaling/v2/HorizontalPodAutoscaler" }} -{{- print "autoscaling/v2" }} -{{- else if $.Capabilities.APIVersions.Has "autoscaling/v2beta2/HorizontalPodAutoscaler" }} -{{- print "autoscaling/v2beta2" }} -{{- else }} -{{- print "autoscaling/v2beta1" }} -{{- end }} -{{- end }} - -{{/* -Return the appropriate apiVersion for podDisruptionBudget. -*/}} -{{- define "grafana.podDisruptionBudget.apiVersion" -}} -{{- 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 }} - -{{/* -Return if ingress supports ingressClassName. -*/}} -{{- define "grafana.ingress.supportsIngressClassName" -}} -{{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) }} -{{- end }} - -{{/* -Return if ingress supports pathType. -*/}} -{{- define "grafana.ingress.supportsPathType" -}} -{{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) }} -{{- end }} - -{{/* -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 }} diff --git a/helm-templates/grafana/templates/_pod.tpl b/helm-templates/grafana/templates/_pod.tpl deleted file mode 100644 index 7362d18..0000000 --- a/helm-templates/grafana/templates/_pod.tpl +++ /dev/null @@ -1,1173 +0,0 @@ -{{- define "grafana.pod" -}} -{{- $sts := list "sts" "StatefulSet" "statefulset" -}} -{{- $root := . -}} -{{- with .Values.schedulerName }} -schedulerName: "{{ . }}" -{{- end }} -serviceAccountName: {{ include "grafana.serviceAccountName" . }} -automountServiceAccountToken: {{ .Values.serviceAccount.autoMount }} -{{- with .Values.securityContext }} -securityContext: - {{- toYaml . | nindent 2 }} -{{- end }} -{{- with .Values.hostAliases }} -hostAliases: - {{- toYaml . | nindent 2 }} -{{- end }} -{{- with .Values.priorityClassName }} -priorityClassName: {{ . }} -{{- end }} -{{- if ( or .Values.persistence.enabled .Values.dashboards .Values.extraInitContainers (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 - {{- if .Values.initChownData.image.sha }} - image: "{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}@sha256:{{ .Values.initChownData.image.sha }}" - {{- else }} - image: "{{ .Values.initChownData.image.repository }}:{{ .Values.initChownData.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.initChownData.image.pullPolicy }} - {{- with .Values.initChownData.securityContext }} - securityContext: - {{- toYaml . | nindent 6 }} - {{- end }} - command: - - chown - - -R - - {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.runAsGroup }} - - /var/lib/grafana - {{- with .Values.initChownData.resources }} - resources: - {{- toYaml . | nindent 6 }} - {{- end }} - volumeMounts: - - name: storage - mountPath: "/var/lib/grafana" - {{- with .Values.persistence.subPath }} - subPath: {{ tpl . $root }} - {{- end }} -{{- end }} -{{- if .Values.dashboards }} - - name: download-dashboards - {{- if .Values.downloadDashboardsImage.sha }} - image: "{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}@sha256:{{ .Values.downloadDashboardsImage.sha }}" - {{- else }} - image: "{{ .Values.downloadDashboardsImage.repository }}:{{ .Values.downloadDashboardsImage.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.downloadDashboardsImage.pullPolicy }} - command: ["/bin/sh"] - args: [ "-c", "mkdir -p /var/lib/grafana/dashboards/default && /bin/sh -x /etc/grafana/download_dashboards.sh" ] - {{- with .Values.downloadDashboards.resources }} - resources: - {{- toYaml . | nindent 6 }} - {{- end }} - env: - {{- range $key, $value := .Values.downloadDashboards.env }} - - name: "{{ $key }}" - value: "{{ $value }}" - {{- 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 . $root }} - {{- end }} - volumeMounts: - - name: config - mountPath: "/etc/grafana/download_dashboards.sh" - subPath: download_dashboards.sh - - name: storage - mountPath: "/var/lib/grafana" - {{- with .Values.persistence.subPath }} - subPath: {{ tpl . $root }} - {{- end }} - {{- range .Values.extraSecretMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - readOnly: {{ .readOnly }} - {{- end }} -{{- end }} -{{- if and .Values.sidecar.datasources.enabled .Values.sidecar.datasources.initDatasources }} - - name: {{ include "grafana.name" . }}-init-sc-datasources - {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - {{- range $key, $value := .Values.sidecar.datasources.env }} - - name: "{{ $key }}" - value: "{{ $value }}" - {{- end }} - {{- if .Values.sidecar.datasources.ignoreAlreadyProcessed }} - - name: IGNORE_ALREADY_PROCESSED - value: "true" - {{- end }} - - name: METHOD - value: "LIST" - - name: LABEL - value: "{{ .Values.sidecar.datasources.label }}" - {{- with .Values.sidecar.datasources.labelValue }} - - name: LABEL_VALUE - 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 }} - {{- with .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ . }}" - {{- end }} - {{- if .Values.sidecar.datasources.searchNamespace }} - - name: NAMESPACE - value: "{{ tpl (.Values.sidecar.datasources.searchNamespace | join ",") . }}" - {{- end }} - {{- with .Values.sidecar.skipTlsVerify }} - - name: SKIP_TLS_VERIFY - value: "{{ . }}" - {{- end }} - {{- with .Values.sidecar.resources }} - resources: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.securityContext }} - securityContext: - {{- toYaml . | nindent 6 }} - {{- end }} - volumeMounts: - - name: sc-datasources-volume - mountPath: "/etc/grafana/provisioning/datasources" -{{- end }} -{{- if and .Values.sidecar.notifiers.enabled .Values.sidecar.notifiers.initNotifiers }} - - name: {{ include "grafana.name" . }}-init-sc-notifiers - {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - {{- 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 }} - {{- with .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ . }}" - {{- end }} - {{- with .Values.sidecar.notifiers.searchNamespace }} - - name: NAMESPACE - value: "{{ tpl (. | join ",") $root }}" - {{- end }} - {{- with .Values.sidecar.skipTlsVerify }} - - name: SKIP_TLS_VERIFY - 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 . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.securityContext }} - securityContext: - {{- toYaml . | nindent 6 }} - {{- end }} - volumeMounts: - - name: sc-notifiers-volume - mountPath: "/etc/grafana/provisioning/notifiers" -{{- end}} -{{- with .Values.extraInitContainers }} - {{- tpl (toYaml .) $root | nindent 2 }} -{{- end }} -{{- if or .Values.image.pullSecrets .Values.global.imagePullSecrets }} -imagePullSecrets: - {{- include "grafana.imagePullSecrets" (dict "root" $root "imagePullSecrets" .Values.image.pullSecrets) | nindent 2 }} -{{- end }} -{{- if not .Values.enableKubeBackwardCompatibility }} -enableServiceLinks: {{ .Values.enableServiceLinks }} -{{- end }} -containers: -{{- if .Values.sidecar.alerts.enabled }} - - name: {{ include "grafana.name" . }}-sc-alerts - {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - {{- 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: {{ include "grafana.name" . }}-sc-dashboard - {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - {{- range $key, $value := .Values.sidecar.dashboards.env }} - - name: "{{ $key }}" - value: "{{ $value }}" - {{- 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 }}" - {{- with .Values.sidecar.dashboards.labelValue }} - - name: LABEL_VALUE - 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 }} - {{- with .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ . }}" - {{- end }} - {{- with .Values.sidecar.dashboards.searchNamespace }} - - name: NAMESPACE - value: "{{ tpl (. | join ",") $root }}" - {{- end }} - {{- with .Values.sidecar.skipTlsVerify }} - - name: SKIP_TLS_VERIFY - value: "{{ . }}" - {{- end }} - {{- with .Values.sidecar.dashboards.folderAnnotation }} - - name: FOLDER_ANNOTATION - value: "{{ . }}" - {{- end }} - {{- with .Values.sidecar.dashboards.script }} - - name: 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 | 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-dashboard-volume - mountPath: {{ .Values.sidecar.dashboards.folder | quote }} - {{- with .Values.sidecar.dashboards.extraMounts }} - {{- toYaml . | trim | nindent 6 }} - {{- end }} -{{- end}} -{{- if .Values.sidecar.datasources.enabled }} - - name: {{ include "grafana.name" . }}-sc-datasources - {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - {{- range $key, $value := .Values.sidecar.datasources.env }} - - name: "{{ $key }}" - value: "{{ $value }}" - {{- 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 }}" - {{- with .Values.sidecar.datasources.labelValue }} - - name: LABEL_VALUE - 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 }} - {{- with .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ . }}" - {{- end }} - {{- with .Values.sidecar.datasources.searchNamespace }} - - name: NAMESPACE - 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: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.userKey | default "admin-user" }} - {{- end }} - {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} - - name: REQ_PASSWORD - valueFrom: - secretKeyRef: - name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.passwordKey | default "admin-password" }} - {{- end }} - {{- if not .Values.sidecar.datasources.skipReload }} - - name: REQ_URL - value: {{ .Values.sidecar.datasources.reloadURL }} - - name: REQ_METHOD - value: POST - {{- end }} - {{- if .Values.sidecar.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 . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.securityContext }} - securityContext: - {{- 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 - {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - {{- 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: {{ include "grafana.name" . }}-sc-plugins - {{- if .Values.sidecar.image.sha }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}@sha256:{{ .Values.sidecar.image.sha }}" - {{- else }} - image: "{{ .Values.sidecar.image.repository }}:{{ .Values.sidecar.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.sidecar.imagePullPolicy }} - env: - {{- 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 - value: "{{ .Values.sidecar.plugins.label }}" - {{- if .Values.sidecar.plugins.labelValue }} - - 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 }} - {{- with .Values.sidecar.enableUniqueFilenames }} - - name: UNIQUE_FILENAMES - value: "{{ . }}" - {{- end }} - {{- with .Values.sidecar.plugins.searchNamespace }} - - name: NAMESPACE - value: "{{ tpl (. | join ",") $root }}" - {{- end }} - {{- with .Values.sidecar.plugins.script }} - - name: SCRIPT - value: "{{ . }}" - {{- end }} - {{- with .Values.sidecar.skipTlsVerify }} - - name: SKIP_TLS_VERIFY - 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: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.userKey | default "admin-user" }} - {{- end }} - {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} - - name: REQ_PASSWORD - valueFrom: - secretKeyRef: - name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.passwordKey | default "admin-password" }} - {{- end }} - {{- if not .Values.sidecar.plugins.skipReload }} - - name: REQ_URL - value: {{ .Values.sidecar.plugins.reloadURL }} - - name: REQ_METHOD - value: POST - {{- end }} - {{- if .Values.sidecar.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 . | nindent 6 }} - {{- end }} - {{- with .Values.sidecar.securityContext }} - securityContext: - {{- toYaml . | nindent 6 }} - {{- end }} - volumeMounts: - - name: sc-plugins-volume - mountPath: "/etc/grafana/provisioning/plugins" -{{- end}} - - name: {{ .Chart.Name }} - {{- if .Values.image.sha }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}@sha256:{{ .Values.image.sha }}" - {{- else }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - {{- end }} - imagePullPolicy: {{ .Values.image.pullPolicy }} - {{- if .Values.command }} - command: - {{- range .Values.command }} - - {{ . | quote }} - {{- end }} - {{- end }} - {{- if .Values.args }} - args: - {{- range .Values.args }} - - {{ . | quote }} - {{- end }} - {{- end }} - {{- with .Values.containerSecurityContext }} - securityContext: - {{- toYaml . | nindent 6 }} - {{- end }} - volumeMounts: - - name: config - mountPath: "/etc/grafana/grafana.ini" - subPath: grafana.ini - {{- if .Values.ldap.enabled }} - - name: ldap - mountPath: "/etc/grafana/ldap.toml" - subPath: ldap.toml - {{- end }} - {{- range .Values.extraConfigmapMounts }} - - name: {{ tpl .name $root }} - mountPath: {{ tpl .mountPath $root }} - subPath: {{ tpl (.subPath | default "") $root }} - readOnly: {{ .readOnly }} - {{- end }} - - name: storage - mountPath: "/var/lib/grafana" - {{- 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 }} - {{- with .Values.dashboardsConfigMaps }} - {{- range (keys . | sortAlpha) }} - - name: dashboards-{{ . }} - mountPath: "/var/lib/grafana/dashboards/{{ . }}" - {{- end }} - {{- end }} - {{- with .Values.datasources }} - {{- range (keys . | sortAlpha) }} - - name: config - mountPath: "/etc/grafana/provisioning/datasources/{{ . }}" - subPath: {{ . | quote }} - {{- end }} - {{- end }} - {{- with .Values.notifiers }} - {{- range (keys . | sortAlpha) }} - - name: config - mountPath: "/etc/grafana/provisioning/notifiers/{{ . }}" - subPath: {{ . | quote }} - {{- end }} - {{- end }} - {{- with .Values.alerting }} - {{- range (keys . | sortAlpha) }} - - name: config - mountPath: "/etc/grafana/provisioning/alerting/{{ . }}" - subPath: {{ . | quote }} - {{- end }} - {{- end }} - {{- with .Values.dashboardProviders }} - {{- range (keys . | sortAlpha) }} - - name: config - mountPath: "/etc/grafana/provisioning/dashboards/{{ . }}" - subPath: {{ . | quote }} - {{- 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 }} - - name: sc-dashboard-provider - mountPath: "/etc/grafana/provisioning/dashboards/sc-dashboardproviders.yaml" - subPath: provider.yaml - {{- end}} - {{- end}} - {{- if .Values.sidecar.datasources.enabled }} - - name: sc-datasources-volume - mountPath: "/etc/grafana/provisioning/datasources" - {{- end}} - {{- if .Values.sidecar.plugins.enabled }} - - name: sc-plugins-volume - mountPath: "/etc/grafana/provisioning/plugins" - {{- end}} - {{- if .Values.sidecar.notifiers.enabled }} - - name: sc-notifiers-volume - mountPath: "/etc/grafana/provisioning/notifiers" - {{- end}} - {{- range .Values.extraSecretMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - readOnly: {{ .readOnly }} - subPath: {{ .subPath | default "" }} - {{- end }} - {{- range .Values.extraVolumeMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - subPath: {{ .subPath | default "" }} - readOnly: {{ .readOnly }} - {{- end }} - {{- range .Values.extraEmptyDirMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - {{- end }} - ports: - - name: {{ .Values.podPortName }} - 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: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.userKey | default "admin-user" }} - {{- end }} - {{- if and (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) }} - - name: GF_SECURITY_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: {{ (tpl .Values.admin.existingSecret .) | default (include "grafana.fullname" .) }} - key: {{ .Values.admin.passwordKey | default "admin-password" }} - {{- end }} - {{- if .Values.plugins }} - - name: GF_INSTALL_PLUGINS - valueFrom: - configMapKeyRef: - name: {{ include "grafana.fullname" . }} - key: plugins - {{- end }} - {{- if .Values.smtp.existingSecret }} - - name: GF_SMTP_USER - valueFrom: - secretKeyRef: - name: {{ .Values.smtp.existingSecret }} - key: {{ .Values.smtp.userKey | default "user" }} - - name: GF_SMTP_PASSWORD - valueFrom: - secretKeyRef: - name: {{ .Values.smtp.existingSecret }} - key: {{ .Values.smtp.passwordKey | default "password" }} - {{- end }} - {{- if .Values.imageRenderer.enabled }} - - name: GF_RENDERING_SERVER_URL - value: http://{{ include "grafana.fullname" . }}-image-renderer.{{ include "grafana.namespace" . }}:{{ .Values.imageRenderer.service.port }}/render - - name: GF_RENDERING_CALLBACK_URL - 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 }} - - name: GF_PATHS_LOGS - value: {{ (get .Values "grafana.ini").paths.logs }} - - name: GF_PATHS_PLUGINS - value: {{ (get .Values "grafana.ini").paths.plugins }} - - name: GF_PATHS_PROVISIONING - value: {{ (get .Values "grafana.ini").paths.provisioning }} - {{- range $key, $value := .Values.envValueFrom }} - - name: {{ $key | quote }} - valueFrom: - {{- tpl (toYaml $value) $ | nindent 10 }} - {{- end }} - {{- range $key, $value := .Values.env }} - - name: "{{ tpl $key $ }}" - value: "{{ tpl (print $value) $ }}" - {{- end }} - {{- if or .Values.envFromSecret (or .Values.envRenderSecret .Values.envFromSecrets) .Values.envFromConfigMaps }} - envFrom: - {{- if .Values.envFromSecret }} - - secretRef: - name: {{ tpl .Values.envFromSecret . }} - {{- end }} - {{- if .Values.envRenderSecret }} - - secretRef: - name: {{ include "grafana.fullname" . }}-env - {{- end }} - {{- range .Values.envFromSecrets }} - - secretRef: - name: {{ tpl .name $ }} - optional: {{ .optional | default false }} - {{- end }} - {{- range .Values.envFromConfigMaps }} - - configMapRef: - name: {{ tpl .name $ }} - optional: {{ .optional | default false }} - {{- end }} - {{- end }} - {{- with .Values.livenessProbe }} - livenessProbe: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.readinessProbe }} - readinessProbe: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.lifecycleHooks }} - lifecycle: - {{- tpl (toYaml .) $root | nindent 6 }} - {{- end }} - {{- with .Values.resources }} - resources: - {{- toYaml . | nindent 6 }} - {{- end }} -{{- with .Values.extraContainers }} - {{- tpl . $ | nindent 2 }} -{{- end }} -{{- with .Values.affinity }} -affinity: - {{- tpl (toYaml .) $root | nindent 2 }} -{{- end }} -{{- with .Values.topologySpreadConstraints }} -topologySpreadConstraints: - {{- toYaml . | nindent 2 }} -{{- end }} -nodeSelector: -{{- if .Values.dedicatedValue }} - dedicated: {{ include "meesho.grafana.dedicatedValue" . }} -{{- else }} -{{- with .Values.nodeSelector }} -{{ toYaml . | nindent 2 }} -{{- end }} -{{- end }} -tolerations: -{{- if .Values.dedicatedValue }} - - key: "dedicated" - operator: "Equal" - value: {{ include "meesho.grafana.dedicatedValue" . }} - effect: "NoSchedule" -{{- else }} -{{- with .Values.tolerations }} -{{ toYaml . | nindent 2 }} -{{- end }} -{{- end }} -volumes: - - name: config - configMap: - name: {{ include "grafana.fullname" . }} - {{- range .Values.extraConfigmapMounts }} - - name: {{ tpl .name $root }} - configMap: - name: {{ tpl .configMap $root }} - {{- with .items }} - items: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- end }} - {{- if .Values.dashboards }} - {{- range (keys .Values.dashboards | sortAlpha) }} - - name: dashboards-{{ . }} - configMap: - name: {{ include "grafana.fullname" $ }}-dashboards-{{ . }} - {{- end }} - {{- end }} - {{- if .Values.dashboardsConfigMaps }} - {{- range $provider, $name := .Values.dashboardsConfigMaps }} - - name: dashboards-{{ $provider }} - configMap: - name: {{ tpl $name $root }} - {{- end }} - {{- end }} - {{- if .Values.ldap.enabled }} - - name: ldap - secret: - {{- if .Values.ldap.existingSecret }} - secretName: {{ .Values.ldap.existingSecret }} - {{- else }} - secretName: {{ include "grafana.fullname" . }} - {{- end }} - items: - - key: ldap-toml - path: ldap.toml - {{- end }} - {{- if and .Values.persistence.enabled (eq .Values.persistence.type "pvc") }} - - name: storage - persistentVolumeClaim: - claimName: {{ tpl (.Values.persistence.existingClaim | default (include "grafana.fullname" .)) . }} - {{- else if and .Values.persistence.enabled (has .Values.persistence.type $sts) }} - {{/* nothing */}} - {{- else }} - - name: storage - {{- if .Values.persistence.inMemory.enabled }} - emptyDir: - medium: Memory - {{- with .Values.persistence.inMemory.sizeLimit }} - sizeLimit: {{ . }} - {{- end }} - {{- else }} - emptyDir: {} - {{- 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: - {{- with .Values.sidecar.dashboards.sizeLimit }} - sizeLimit: {{ . }} - {{- else }} - {} - {{- end }} - {{- if .Values.sidecar.dashboards.SCProvider }} - - name: sc-dashboard-provider - configMap: - name: {{ include "grafana.fullname" . }}-config-dashboards - {{- end }} - {{- end }} - {{- if .Values.sidecar.datasources.enabled }} - - name: sc-datasources-volume - emptyDir: - {{- with .Values.sidecar.datasources.sizeLimit }} - sizeLimit: {{ . }} - {{- else }} - {} - {{- end }} - {{- end }} - {{- if .Values.sidecar.plugins.enabled }} - - name: sc-plugins-volume - emptyDir: - {{- with .Values.sidecar.plugins.sizeLimit }} - sizeLimit: {{ . }} - {{- else }} - {} - {{- end }} - {{- end }} - {{- if .Values.sidecar.notifiers.enabled }} - - name: sc-notifiers-volume - emptyDir: - {{- with .Values.sidecar.notifiers.sizeLimit }} - sizeLimit: {{ . }} - {{- else }} - {} - {{- end }} - {{- end }} - {{- range .Values.extraSecretMounts }} - {{- if .secretName }} - - name: {{ .name }} - secret: - secretName: {{ .secretName }} - defaultMode: {{ .defaultMode }} - {{- with .items }} - items: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- else if .projected }} - - name: {{ .name }} - projected: - {{- toYaml .projected | nindent 6 }} - {{- else if .csi }} - - name: {{ .name }} - csi: - {{- toYaml .csi | nindent 6 }} - {{- end }} - {{- end }} - {{- range .Values.extraVolumeMounts }} - - name: {{ .name }} - {{- if .existingClaim }} - persistentVolumeClaim: - claimName: {{ .existingClaim }} - {{- else if .hostPath }} - hostPath: - path: {{ .hostPath }} - {{- else if .csi }} - csi: - {{- toYaml .data | nindent 6 }} - {{- else }} - emptyDir: {} - {{- end }} - {{- end }} - {{- range .Values.extraEmptyDirMounts }} - - name: {{ .name }} - emptyDir: {} - {{- end }} - {{- with .Values.extraContainerVolumes }} - {{- tpl (toYaml .) $root | nindent 2 }} - {{- end }} -{{- end }} diff --git a/helm-templates/grafana/templates/clusterrole.yaml b/helm-templates/grafana/templates/clusterrole.yaml deleted file mode 100644 index 2c9a180..0000000 --- a/helm-templates/grafana/templates/clusterrole.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if and .Values.rbac.create (or (not .Values.rbac.namespaced) .Values.rbac.extraClusterRoleRules) (not .Values.rbac.useExistingRole) }} -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.annotations }} - annotations: - {{- 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 .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}} -{{- end}} diff --git a/helm-templates/grafana/templates/clusterrolebinding.yaml b/helm-templates/grafana/templates/clusterrolebinding.yaml deleted file mode 100644 index b848e8c..0000000 --- a/helm-templates/grafana/templates/clusterrolebinding.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- if and .Values.rbac.create (or (not .Values.rbac.namespaced) .Values.rbac.extraClusterRoleRules) }} -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ include "grafana.fullname" . }}-clusterrolebinding - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -subjects: - - kind: ServiceAccount - name: {{ include "grafana.serviceAccountName" . }} - namespace: {{ include "grafana.namespace" . }} -roleRef: - kind: ClusterRole - {{- if .Values.rbac.useExistingRole }} - name: {{ .Values.rbac.useExistingRole }} - {{- else }} - name: {{ include "grafana.fullname" . }}-clusterrole - {{- end }} - apiGroup: rbac.authorization.k8s.io -{{- end }} diff --git a/helm-templates/grafana/templates/configmap-dashboard-provider.yaml b/helm-templates/grafana/templates/configmap-dashboard-provider.yaml deleted file mode 100644 index 1f706a8..0000000 --- a/helm-templates/grafana/templates/configmap-dashboard-provider.yaml +++ /dev/null @@ -1,29 +0,0 @@ -{{- if and .Values.sidecar.dashboards.enabled .Values.sidecar.dashboards.SCProvider }} -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.annotations }} - annotations: - {{- 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 }} diff --git a/helm-templates/grafana/templates/configmap.yaml b/helm-templates/grafana/templates/configmap.yaml deleted file mode 100644 index b5f21e8..0000000 --- a/helm-templates/grafana/templates/configmap.yaml +++ /dev/null @@ -1,138 +0,0 @@ -{{- if .Values.createConfigmap }} -{{- $files := .Files }} -{{- $root := . -}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "grafana.fullname" . }} - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -data: - {{- with .Values.plugins }} - plugins: {{ join "," . }} - {{- end }} - grafana.ini: | - {{- range $elem, $elemVal := index .Values "grafana.ini" }} - {{- if not (kindIs "map" $elemVal) }} - {{- if kindIs "invalid" $elemVal }} - {{ $elem }} = - {{- else if kindIs "string" $elemVal }} - {{ $elem }} = {{ tpl $elemVal $ }} - {{- else }} - {{ $elem }} = {{ $elemVal }} - {{- end }} - {{- end }} - {{- end }} - {{- range $key, $value := index .Values "grafana.ini" }} - {{- if kindIs "map" $value }} - [{{ $key }}] - {{- range $elem, $elemVal := $value }} - {{- if kindIs "invalid" $elemVal }} - {{ $elem }} = - {{- else if kindIs "string" $elemVal }} - {{ $elem }} = {{ tpl $elemVal $ }} - {{- else }} - {{ $elem }} = {{ $elemVal }} - {{- end }} - {{- end }} - {{- end }} - {{- end }} - - {{- range $key, $value := .Values.datasources }} - {{- $key | nindent 2 }}: | - {{- tpl (toYaml $value | nindent 4) $root }} - {{- end }} - - {{- range $key, $value := .Values.notifiers }} - {{- $key | nindent 2 }}: | - {{- toYaml $value | nindent 4 }} - {{- end }} - - {{- range $key, $value := .Values.alerting }} - {{- if (hasKey $value "file") }} - {{- $key | nindent 2 }}: - {{- toYaml ( $files.Get $value.file ) | nindent 4}} - {{- else }} - {{- $key | nindent 2 }}: | - {{- tpl (toYaml $value | nindent 4) $root }} - {{- end }} - {{- end }} - - {{- range $key, $value := .Values.dashboardProviders }} - {{- $key | nindent 2 }}: | - {{- toYaml $value | nindent 4 }} - {{- 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 }} - {{- if not $value.acceptHeader }} - -H "Accept: application/json" \ - {{- else }} - -H "Accept: {{ $value.acceptHeader }}" \ - {{- end }} - {{- if $value.token }} - -H "Authorization: token {{ $value.token }}" \ - {{- end }} - {{- if $value.bearerToken }} - -H "Authorization: Bearer {{ $value.bearerToken }}" \ - {{- end }} - {{- if $value.basic }} - -H "Authorization: Basic {{ $value.basic }}" \ - {{- end }} - {{- if $value.gitlabToken }} - -H "PRIVATE-TOKEN: {{ $value.gitlabToken }}" \ - {{- 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 }} - {{- if kindIs "string" $value.datasource }} - | sed '/-- .* --/! s/"datasource":.*,/"datasource": "{{ $value.datasource }}",/g' \ - {{- end }} - {{- if kindIs "slice" $value.datasource }} - {{- range $value.datasource }} - | sed '/-- .* --/! s/${{"{"}}{{ .name }}}/{{ .value }}/g' \ - {{- end }} - {{- end }} - {{- end }} - {{- if $value.b64content }} - | base64 -d \ - {{- end }} - > "{{- if $dpPath -}}{{ $dpPath }}{{- else -}}/var/lib/grafana/dashboards/{{ $provider }}{{- end -}}/{{ $key }}.json" - {{ end }} - {{- end }} - {{- end }} -{{- end }} -{{- end }} diff --git a/helm-templates/grafana/templates/dashboards-json-configmap.yaml b/helm-templates/grafana/templates/dashboards-json-configmap.yaml deleted file mode 100644 index df0ed0d..0000000 --- a/helm-templates/grafana/templates/dashboards-json-configmap.yaml +++ /dev/null @@ -1,35 +0,0 @@ -{{- if .Values.dashboards }} -{{ $files := .Files }} -{{- range $provider, $dashboards := .Values.dashboards }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "grafana.fullname" $ }}-dashboards-{{ $provider }} - namespace: {{ include "grafana.namespace" $ }} - labels: - {{- include "grafana.labels" $ | nindent 4 }} - dashboard-provider: {{ $provider }} -{{- if $dashboards }} -data: -{{- $dashboardFound := false }} -{{- range $key, $value := $dashboards }} -{{- if (or (hasKey $value "json") (hasKey $value "file")) }} -{{- $dashboardFound = true }} - {{- print $key | nindent 2 }}.json: - {{- if hasKey $value "json" }} - |- - {{- $value.json | nindent 6 }} - {{- end }} - {{- if hasKey $value "file" }} - {{- toYaml ( $files.Get $value.file ) | nindent 4}} - {{- end }} -{{- end }} -{{- end }} -{{- if not $dashboardFound }} - {} -{{- end }} -{{- end }} ---- -{{- end }} - -{{- end }} diff --git a/helm-templates/grafana/templates/deployment.yaml b/helm-templates/grafana/templates/deployment.yaml deleted file mode 100644 index bfa26bb..0000000 --- a/helm-templates/grafana/templates/deployment.yaml +++ /dev/null @@ -1,51 +0,0 @@ -{{- if (and (not .Values.useStatefulSet) (or (not .Values.persistence.enabled) (eq .Values.persistence.type "pvc"))) }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "grafana.fullname" . }} - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if and (not .Values.autoscaling.enabled) (.Values.replicas) }} - replicas: {{ .Values.replicas }} - {{- end }} - revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} - selector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 6 }} - {{- with .Values.deploymentStrategy }} - strategy: - {{- toYaml . | trim | nindent 4 }} - {{- end }} - template: - metadata: - labels: - {{- include "grafana.selectorLabels" . | nindent 8 }} - {{- 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) }} - 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 }} - kubectl.kubernetes.io/default-container: {{ .Chart.Name }} - {{- with .Values.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - {{- include "grafana.pod" . | nindent 6 }} -{{- end }} diff --git a/helm-templates/grafana/templates/external-secret.yaml b/helm-templates/grafana/templates/external-secret.yaml deleted file mode 100644 index dfb4bc8..0000000 --- a/helm-templates/grafana/templates/external-secret.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if .Values.externalSecrets -}} -apiVersion: external-secrets.io/v1beta1 -kind: ExternalSecret -metadata: - name: {{ include "grafana.fullname" . }}-secret - namespace: "{{ include "grafana.namespace" . }}" -spec: - refreshInterval: {{ .Values.externalSecrets.refreshInterval }} - secretStoreRef: - name: {{ .Values.externalSecrets.secretStoreRef.name }} - kind: {{ .Values.externalSecrets.secretStoreRef.kind }} - target: - creationPolicy: Owner - deletionPolicy: Retain - name: {{ include "grafana.fullname" . }}-secret - dataFrom: - - extract: - conversionStrategy: Default - key: {{ .Values.externalSecrets.dataFrom.secretKey }} -{{- end -}} \ No newline at end of file diff --git a/helm-templates/grafana/templates/extra-manifests.yaml b/helm-templates/grafana/templates/extra-manifests.yaml deleted file mode 100644 index a9bb3b6..0000000 --- a/helm-templates/grafana/templates/extra-manifests.yaml +++ /dev/null @@ -1,4 +0,0 @@ -{{ range .Values.extraObjects }} ---- -{{ tpl (toYaml .) $ }} -{{ end }} diff --git a/helm-templates/grafana/templates/headless-service.yaml b/helm-templates/grafana/templates/headless-service.yaml deleted file mode 100644 index 3028589..0000000 --- a/helm-templates/grafana/templates/headless-service.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- $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: {{ include "grafana.fullname" . }}-headless - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - clusterIP: None - selector: - {{- include "grafana.selectorLabels" . | nindent 4 }} - type: ClusterIP - ports: - - name: {{ .Values.gossipPortName }}-tcp - port: 9094 -{{- end }} diff --git a/helm-templates/grafana/templates/hpa.yaml b/helm-templates/grafana/templates/hpa.yaml deleted file mode 100644 index 46bbcb4..0000000 --- a/helm-templates/grafana/templates/hpa.yaml +++ /dev/null @@ -1,52 +0,0 @@ -{{- $sts := list "sts" "StatefulSet" "statefulset" -}} -{{- if .Values.autoscaling.enabled }} -apiVersion: {{ include "grafana.hpa.apiVersion" . }} -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "grafana.fullname" . }} - namespace: {{ include "grafana.namespace" . }} - labels: - 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 - {{- end }} - name: {{ include "grafana.fullname" . }} - minReplicas: {{ .Values.autoscaling.minReplicas }} - maxReplicas: {{ .Values.autoscaling.maxReplicas }} - metrics: - {{- 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/helm-templates/grafana/templates/image-renderer-deployment.yaml b/helm-templates/grafana/templates/image-renderer-deployment.yaml deleted file mode 100644 index 93d20e8..0000000 --- a/helm-templates/grafana/templates/image-renderer-deployment.yaml +++ /dev/null @@ -1,130 +0,0 @@ -{{ if .Values.imageRenderer.enabled }} -{{- $root := . -}} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "grafana.fullname" . }}-image-renderer - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.imageRenderer.labels" . | nindent 4 }} - {{- with .Values.imageRenderer.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.imageRenderer.annotations }} - annotations: - {{- 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 }} - strategy: - {{- toYaml . | trim | nindent 4 }} - {{- end }} - template: - metadata: - labels: - {{- include "grafana.imageRenderer.selectorLabels" . | nindent 8 }} - {{- with .Values.imageRenderer.podLabels }} - {{- toYaml . | nindent 8 }} - {{- end }} - annotations: - checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} - {{- with .Values.imageRenderer.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - spec: - {{- with .Values.imageRenderer.schedulerName }} - schedulerName: "{{ . }}" - {{- end }} - {{- with .Values.imageRenderer.serviceAccountName }} - serviceAccountName: "{{ . }}" - {{- end }} - {{- with .Values.imageRenderer.securityContext }} - securityContext: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.imageRenderer.hostAliases }} - hostAliases: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.imageRenderer.priorityClassName }} - priorityClassName: {{ . }} - {{- end }} - {{- with .Values.imageRenderer.image.pullSecrets }} - imagePullSecrets: - {{- range . }} - - name: {{ tpl . $root }} - {{- end}} - {{- end }} - containers: - - name: {{ .Chart.Name }}-image-renderer - {{- if .Values.imageRenderer.image.sha }} - image: "{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}@sha256:{{ .Values.imageRenderer.image.sha }}" - {{- else }} - image: "{{ .Values.imageRenderer.image.repository }}:{{ .Values.imageRenderer.image.tag }}" - {{- end }} - imagePullPolicy: {{ .Values.imageRenderer.image.pullPolicy }} - {{- if .Values.imageRenderer.command }} - command: - {{- range .Values.imageRenderer.command }} - - {{ . }} - {{- end }} - {{- end}} - ports: - - name: {{ .Values.imageRenderer.service.portName }} - containerPort: {{ .Values.imageRenderer.service.targetPort }} - protocol: TCP - livenessProbe: - httpGet: - path: / - port: {{ .Values.imageRenderer.service.portName }} - env: - - name: HTTP_PORT - 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: - {{- toYaml . | nindent 12 }} - {{- end }} - volumeMounts: - - mountPath: /tmp - name: image-renderer-tmpfs - {{- with .Values.imageRenderer.resources }} - resources: - {{- toYaml . | nindent 12 }} - {{- end }} - {{- with .Values.imageRenderer.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.imageRenderer.affinity }} - affinity: - {{- tpl (toYaml .) $root | nindent 8 }} - {{- end }} - {{- with .Values.imageRenderer.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} - volumes: - - name: image-renderer-tmpfs - emptyDir: {} -{{- end }} diff --git a/helm-templates/grafana/templates/image-renderer-hpa.yaml b/helm-templates/grafana/templates/image-renderer-hpa.yaml deleted file mode 100644 index b0f0059..0000000 --- a/helm-templates/grafana/templates/image-renderer-hpa.yaml +++ /dev/null @@ -1,47 +0,0 @@ -{{- if and .Values.imageRenderer.enabled .Values.imageRenderer.autoscaling.enabled }} -apiVersion: {{ include "grafana.hpa.apiVersion" . }} -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "grafana.fullname" . }}-image-renderer - namespace: {{ include "grafana.namespace" . }} - labels: - app.kubernetes.io/name: {{ include "grafana.name" . }}-image-renderer - helm.sh/chart: {{ include "grafana.chart" . }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - app.kubernetes.io/instance: {{ .Release.Name }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "grafana.fullname" . }}-image-renderer - minReplicas: {{ .Values.imageRenderer.autoscaling.minReplicas }} - maxReplicas: {{ .Values.imageRenderer.autoscaling.maxReplicas }} - metrics: - {{- if .Values.imageRenderer.autoscaling.targetMemory }} - - type: Resource - resource: - name: memory - {{- if eq (include "grafana.hpa.apiVersion" .) "autoscaling/v2beta1" }} - targetAverageUtilization: {{ .Values.imageRenderer.autoscaling.targetMemory }} - {{- else }} - target: - type: Utilization - averageUtilization: {{ .Values.imageRenderer.autoscaling.targetMemory }} - {{- end }} - {{- end }} - {{- if .Values.imageRenderer.autoscaling.targetCPU }} - - type: Resource - resource: - name: cpu - {{- if eq (include "grafana.hpa.apiVersion" .) "autoscaling/v2beta1" }} - targetAverageUtilization: {{ .Values.imageRenderer.autoscaling.targetCPU }} - {{- else }} - target: - type: Utilization - averageUtilization: {{ .Values.imageRenderer.autoscaling.targetCPU }} - {{- end }} - {{- end }} - {{- if .Values.imageRenderer.autoscaling.behavior }} - behavior: {{ toYaml .Values.imageRenderer.autoscaling.behavior | nindent 4 }} - {{- end }} -{{- end }} diff --git a/helm-templates/grafana/templates/image-renderer-network-policy.yaml b/helm-templates/grafana/templates/image-renderer-network-policy.yaml deleted file mode 100644 index d1a0eb3..0000000 --- a/helm-templates/grafana/templates/image-renderer-network-policy.yaml +++ /dev/null @@ -1,79 +0,0 @@ -{{- if and .Values.imageRenderer.enabled .Values.imageRenderer.networkPolicy.limitIngress }} ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - 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 }} - {{- with .Values.imageRenderer.podLabels }} - {{- toYaml . | nindent 6 }} - {{- end }} - - policyTypes: - - Ingress - ingress: - - ports: - - port: {{ .Values.imageRenderer.service.targetPort }} - protocol: TCP - from: - - namespaceSelector: - matchLabels: - kubernetes.io/metadata.name: {{ include "grafana.namespace" . }} - podSelector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 14 }} - {{- with .Values.podLabels }} - {{- toYaml . | nindent 14 }} - {{- end }} - {{- with .Values.imageRenderer.networkPolicy.extraIngressSelectors -}} - {{ toYaml . | nindent 8 }} - {{- end }} -{{- end }} - -{{- if and .Values.imageRenderer.enabled .Values.imageRenderer.networkPolicy.limitEgress }} ---- -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - 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 }} - {{- with .Values.imageRenderer.podLabels }} - {{- toYaml . | nindent 6 }} - {{- end }} - - policyTypes: - - Egress - egress: - # allow dns resolution - - ports: - - port: 53 - protocol: UDP - - port: 53 - protocol: TCP - # talk only to grafana - - ports: - - port: {{ .Values.service.targetPort }} - protocol: TCP - to: - - namespaceSelector: - matchLabels: - name: {{ include "grafana.namespace" . }} - podSelector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 14 }} - {{- with .Values.podLabels }} - {{- toYaml . | nindent 14 }} - {{- end }} -{{- end }} diff --git a/helm-templates/grafana/templates/image-renderer-service.yaml b/helm-templates/grafana/templates/image-renderer-service.yaml deleted file mode 100644 index f8da127..0000000 --- a/helm-templates/grafana/templates/image-renderer-service.yaml +++ /dev/null @@ -1,31 +0,0 @@ -{{- if and .Values.imageRenderer.enabled .Values.imageRenderer.service.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "grafana.fullname" . }}-image-renderer - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.imageRenderer.labels" . | nindent 4 }} - {{- with .Values.imageRenderer.service.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.imageRenderer.service.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - type: ClusterIP - {{- 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 }} diff --git a/helm-templates/grafana/templates/image-renderer-servicemonitor.yaml b/helm-templates/grafana/templates/image-renderer-servicemonitor.yaml deleted file mode 100644 index 5d9f09d..0000000 --- a/helm-templates/grafana/templates/image-renderer-servicemonitor.yaml +++ /dev/null @@ -1,48 +0,0 @@ -{{- if .Values.imageRenderer.serviceMonitor.enabled }} ---- -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ include "grafana.fullname" . }}-image-renderer - {{- if .Values.imageRenderer.serviceMonitor.namespace }} - namespace: {{ tpl .Values.imageRenderer.serviceMonitor.namespace . }} - {{- else }} - namespace: {{ include "grafana.namespace" . }} - {{- end }} - labels: - {{- include "grafana.imageRenderer.labels" . | nindent 4 }} - {{- with .Values.imageRenderer.serviceMonitor.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - endpoints: - - port: {{ .Values.imageRenderer.service.portName }} - {{- with .Values.imageRenderer.serviceMonitor.interval }} - interval: {{ . }} - {{- end }} - {{- with .Values.imageRenderer.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ . }} - {{- end }} - honorLabels: true - path: {{ .Values.imageRenderer.serviceMonitor.path }} - scheme: {{ .Values.imageRenderer.serviceMonitor.scheme }} - {{- with .Values.imageRenderer.serviceMonitor.tlsConfig }} - tlsConfig: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.imageRenderer.serviceMonitor.relabelings }} - relabelings: - {{- toYaml . | nindent 6 }} - {{- end }} - jobLabel: "{{ .Release.Name }}-image-renderer" - selector: - matchLabels: - {{- include "grafana.imageRenderer.selectorLabels" . | nindent 6 }} - namespaceSelector: - matchNames: - - {{ include "grafana.namespace" . }} - {{- with .Values.imageRenderer.serviceMonitor.targetLabels }} - targetLabels: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/helm-templates/grafana/templates/ingress.yaml b/helm-templates/grafana/templates/ingress.yaml deleted file mode 100644 index 063cdfa..0000000 --- a/helm-templates/grafana/templates/ingress.yaml +++ /dev/null @@ -1,78 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $ingressApiIsStable := eq (include "grafana.ingress.isStable" .) "true" -}} -{{- $ingressSupportsIngressClassName := eq (include "grafana.ingress.supportsIngressClassName" .) "true" -}} -{{- $ingressSupportsPathType := eq (include "grafana.ingress.supportsPathType" .) "true" -}} -{{- $fullName := include "grafana.fullname" . -}} -{{- $servicePort := .Values.service.port -}} -{{- $ingressPath := .Values.ingress.path -}} -{{- $ingressPathType := .Values.ingress.pathType -}} -{{- $extraPaths := .Values.ingress.extraPaths -}} -apiVersion: {{ include "grafana.ingress.apiVersion" . }} -kind: Ingress -metadata: - name: {{ $fullName }} - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.ingress.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.ingress.annotations }} - annotations: - {{- range $key, $value := . }} - {{ $key }}: {{ tpl $value $ | quote }} - {{- end }} - {{- end }} -spec: - {{- if and $ingressSupportsIngressClassName .Values.ingress.ingressClassName }} - ingressClassName: {{ .Values.ingress.ingressClassName }} - {{- end -}} - {{- with .Values.ingress.tls }} - tls: - {{- tpl (toYaml .) $ | nindent 4 }} - {{- end }} - rules: - {{- if .Values.ingress.hosts }} - {{- range .Values.ingress.hosts }} - - host: {{ tpl . $ }} - http: - paths: - {{- with $extraPaths }} - {{- toYaml . | nindent 10 }} - {{- end }} - - path: {{ $ingressPath }} - {{- if $ingressSupportsPathType }} - pathType: {{ $ingressPathType }} - {{- end }} - backend: - {{- if $ingressApiIsStable }} - service: - name: {{ $fullName }} - port: - number: {{ $servicePort }} - {{- else }} - serviceName: {{ $fullName }} - servicePort: {{ $servicePort }} - {{- end }} - {{- end }} - {{- else }} - - http: - paths: - - backend: - {{- if $ingressApiIsStable }} - service: - name: {{ $fullName }} - port: - number: {{ $servicePort }} - {{- else }} - serviceName: {{ $fullName }} - servicePort: {{ $servicePort }} - {{- end }} - {{- with $ingressPath }} - path: {{ . }} - {{- end }} - {{- if $ingressSupportsPathType }} - pathType: {{ $ingressPathType }} - {{- end }} - {{- end -}} -{{- end }} diff --git a/helm-templates/grafana/templates/networkpolicy.yaml b/helm-templates/grafana/templates/networkpolicy.yaml deleted file mode 100644 index ea4578b..0000000 --- a/helm-templates/grafana/templates/networkpolicy.yaml +++ /dev/null @@ -1,52 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -apiVersion: networking.k8s.io/v1 -kind: NetworkPolicy -metadata: - name: {{ include "grafana.fullname" . }} - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.annotations }} - annotations: - {{- 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 }} - - {{- if .Values.networkPolicy.egress.enabled }} - egress: - - ports: - {{ .Values.networkPolicy.egress.ports | toJson }} - {{- end }} - {{- if .Values.networkPolicy.ingress }} - ingress: - - ports: - - port: {{ .Values.service.targetPort }} - {{- if not .Values.networkPolicy.allowExternal }} - from: - - podSelector: - matchLabels: - {{ 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/helm-templates/grafana/templates/poddisruptionbudget.yaml b/helm-templates/grafana/templates/poddisruptionbudget.yaml deleted file mode 100644 index 0525121..0000000 --- a/helm-templates/grafana/templates/poddisruptionbudget.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if .Values.podDisruptionBudget }} -apiVersion: {{ include "grafana.podDisruptionBudget.apiVersion" . }} -kind: PodDisruptionBudget -metadata: - name: {{ include "grafana.fullname" . }} - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- with .Values.podDisruptionBudget.minAvailable }} - minAvailable: {{ . }} - {{- end }} - {{- with .Values.podDisruptionBudget.maxUnavailable }} - maxUnavailable: {{ . }} - {{- end }} - selector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 6 }} -{{- end }} diff --git a/helm-templates/grafana/templates/podsecuritypolicy.yaml b/helm-templates/grafana/templates/podsecuritypolicy.yaml deleted file mode 100644 index eed7af9..0000000 --- a/helm-templates/grafana/templates/podsecuritypolicy.yaml +++ /dev/null @@ -1,49 +0,0 @@ -{{- if and .Values.rbac.pspEnabled (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: {{ include "grafana.fullname" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - annotations: - seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default,runtime/default' - seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default' - {{- if .Values.rbac.pspUseAppArmor }} - apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' - apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default' - {{- end }} -spec: - privileged: false - allowPrivilegeEscalation: false - requiredDropCapabilities: - # Default set from Docker, with DAC_OVERRIDE and CHOWN - - ALL - volumes: - - 'configMap' - - 'emptyDir' - - 'projected' - - 'csi' - - 'secret' - - 'downwardAPI' - - 'persistentVolumeClaim' - hostNetwork: false - hostIPC: false - hostPID: false - runAsUser: - rule: 'RunAsAny' - seLinux: - rule: 'RunAsAny' - supplementalGroups: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 1 - max: 65535 - fsGroup: - rule: 'MustRunAs' - ranges: - # Forbid adding the root group. - - min: 1 - max: 65535 - readOnlyRootFilesystem: false -{{- end }} diff --git a/helm-templates/grafana/templates/pvc.yaml b/helm-templates/grafana/templates/pvc.yaml deleted file mode 100644 index eb8f87f..0000000 --- a/helm-templates/grafana/templates/pvc.yaml +++ /dev/null @@ -1,36 +0,0 @@ -{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) (eq .Values.persistence.type "pvc")}} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - 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 . | nindent 4 }} - {{- end }} - {{- with .Values.persistence.finalizers }} - finalizers: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - accessModes: - {{- range .Values.persistence.accessModes }} - - {{ . | quote }} - {{- end }} - resources: - requests: - storage: {{ .Values.persistence.size | quote }} - {{- with .Values.persistence.storageClassName }} - storageClassName: {{ . }} - {{- end }} - {{- with .Values.persistence.selectorLabels }} - selector: - matchLabels: - {{- toYaml . | nindent 6 }} - {{- end }} -{{- end }} diff --git a/helm-templates/grafana/templates/role.yaml b/helm-templates/grafana/templates/role.yaml deleted file mode 100644 index df8ac9a..0000000 --- a/helm-templates/grafana/templates/role.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if and .Values.rbac.create (not .Values.rbac.useExistingRole) -}} -apiVersion: {{ include "grafana.rbac.apiVersion" . }} -kind: Role -metadata: - name: {{ include "grafana.fullname" . }} - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.annotations }} - annotations: - {{- 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 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 }} -{{- end }} diff --git a/helm-templates/grafana/templates/rolebinding.yaml b/helm-templates/grafana/templates/rolebinding.yaml deleted file mode 100644 index cc07bd9..0000000 --- a/helm-templates/grafana/templates/rolebinding.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: {{ include "grafana.rbac.apiVersion" . }} -kind: RoleBinding -metadata: - name: {{ include "grafana.fullname" . }} - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - {{- if .Values.rbac.useExistingRole }} - name: {{ .Values.rbac.useExistingRole }} - {{- else }} - name: {{ include "grafana.fullname" . }} - {{- end }} -subjects: -- kind: ServiceAccount - name: {{ include "grafana.serviceAccountName" . }} - namespace: {{ include "grafana.namespace" . }} -{{- end }} diff --git a/helm-templates/grafana/templates/secret-env.yaml b/helm-templates/grafana/templates/secret-env.yaml deleted file mode 100644 index eb14aac..0000000 --- a/helm-templates/grafana/templates/secret-env.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if .Values.envRenderSecret }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ include "grafana.fullname" . }}-env - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} -type: Opaque -data: -{{- range $key, $val := .Values.envRenderSecret }} - {{ $key }}: {{ tpl ($val | toString) $ | b64enc | quote }} -{{- end }} -{{- end }} diff --git a/helm-templates/grafana/templates/secret.yaml b/helm-templates/grafana/templates/secret.yaml deleted file mode 100644 index 5cbd527..0000000 --- a/helm-templates/grafana/templates/secret.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if or (and (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION)) (and .Values.ldap.enabled (not .Values.ldap.existingSecret)) }} -apiVersion: v1 -kind: Secret -metadata: - name: {{ include "grafana.fullname" . }} - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.annotations }} - annotations: - {{- 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: {{ include "grafana.password" . }} - {{- end }} - {{- end }} - {{- if not .Values.ldap.existingSecret }} - ldap-toml: {{ tpl .Values.ldap.config $ | b64enc | quote }} - {{- end }} -{{- end }} diff --git a/helm-templates/grafana/templates/service.yaml b/helm-templates/grafana/templates/service.yaml deleted file mode 100644 index 43d360b..0000000 --- a/helm-templates/grafana/templates/service.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{- if .Values.service.enabled }} -{{- $root := . }} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "grafana.fullname" . }} - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.service.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.service.annotations }} - annotations: - {{- tpl (toYaml . | nindent 4) $root }} - {{- end }} -spec: - {{- if (or (eq .Values.service.type "ClusterIP") (empty .Values.service.type)) }} - type: ClusterIP - {{- with .Values.service.clusterIP }} - clusterIP: {{ . }} - {{- end }} - {{- else if eq .Values.service.type "LoadBalancer" }} - type: {{ .Values.service.type }} - {{- with .Values.service.loadBalancerIP }} - loadBalancerIP: {{ . }} - {{- end }} - {{- with .Values.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- else }} - type: {{ .Values.service.type }} - {{- end }} - {{- with .Values.service.externalIPs }} - externalIPs: - {{- toYaml . | nindent 4 }} - {{- end }} - ports: - - name: {{ .Values.service.portName }} - port: {{ .Values.service.port }} - protocol: TCP - targetPort: {{ .Values.service.targetPort }} - {{- 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 }} diff --git a/helm-templates/grafana/templates/serviceaccount.yaml b/helm-templates/grafana/templates/serviceaccount.yaml deleted file mode 100644 index 784e71b..0000000 --- a/helm-templates/grafana/templates/serviceaccount.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if .Values.serviceAccount.create }} -{{- $root := . -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- tpl (toYaml . | nindent 4) $root }} - {{- end }} - name: {{ include "grafana.serviceAccountName" . }} - namespace: {{ include "grafana.namespace" . }} -{{- end }} diff --git a/helm-templates/grafana/templates/servicemonitor.yaml b/helm-templates/grafana/templates/servicemonitor.yaml deleted file mode 100644 index a4e9f00..0000000 --- a/helm-templates/grafana/templates/servicemonitor.yaml +++ /dev/null @@ -1,48 +0,0 @@ -{{- if .Values.serviceMonitor.enabled }} ---- -apiVersion: monitoring.coreos.com/v1 -kind: ServiceMonitor -metadata: - name: {{ include "grafana.fullname" . }} - {{- if .Values.serviceMonitor.namespace }} - namespace: {{ tpl .Values.serviceMonitor.namespace . }} - {{- else }} - namespace: {{ include "grafana.namespace" . }} - {{- end }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.serviceMonitor.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - endpoints: - - port: {{ .Values.service.portName }} - {{- with .Values.serviceMonitor.interval }} - interval: {{ . }} - {{- end }} - {{- with .Values.serviceMonitor.scrapeTimeout }} - scrapeTimeout: {{ . }} - {{- end }} - honorLabels: true - path: {{ .Values.serviceMonitor.path }} - scheme: {{ .Values.serviceMonitor.scheme }} - {{- with .Values.serviceMonitor.tlsConfig }} - tlsConfig: - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.serviceMonitor.relabelings }} - relabelings: - {{- toYaml . | nindent 6 }} - {{- end }} - jobLabel: "{{ .Release.Name }}" - selector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 6 }} - namespaceSelector: - matchNames: - - {{ include "grafana.namespace" . }} - {{- with .Values.serviceMonitor.targetLabels }} - targetLabels: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/helm-templates/grafana/templates/statefulset.yaml b/helm-templates/grafana/templates/statefulset.yaml deleted file mode 100644 index e6c944a..0000000 --- a/helm-templates/grafana/templates/statefulset.yaml +++ /dev/null @@ -1,56 +0,0 @@ -{{- $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: {{ include "grafana.fullname" . }} - namespace: {{ include "grafana.namespace" . }} - labels: - {{- include "grafana.labels" . | nindent 4 }} - {{- with .Values.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - replicas: {{ .Values.replicas }} - selector: - matchLabels: - {{- include "grafana.selectorLabels" . | nindent 6 }} - serviceName: {{ include "grafana.fullname" . }}-headless - template: - metadata: - labels: - {{- include "grafana.selectorLabels" . | nindent 8 }} - {{- 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) }} - checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} - {{- 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 - spec: - accessModes: {{ .Values.persistence.accessModes }} - storageClassName: {{ .Values.persistence.storageClassName }} - resources: - requests: - storage: {{ .Values.persistence.size }} - {{- with .Values.persistence.selectorLabels }} - selector: - matchLabels: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- end }} -{{- end }} diff --git a/helm-templates/grafana/templates/tests/test-configmap.yaml b/helm-templates/grafana/templates/tests/test-configmap.yaml deleted file mode 100644 index 01c96c9..0000000 --- a/helm-templates/grafana/templates/tests/test-configmap.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if .Values.testFramework.enabled }} -apiVersion: v1 -kind: ConfigMap -metadata: - 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://{{ include "grafana.fullname" . }}/api/health" - - code=$(wget --server-response --spider --timeout 90 --tries 10 ${url} 2>&1 | awk '/^ HTTP/{print $2}') - [ "$code" == "200" ] - } -{{- end }} diff --git a/helm-templates/grafana/templates/tests/test-podsecuritypolicy.yaml b/helm-templates/grafana/templates/tests/test-podsecuritypolicy.yaml deleted file mode 100644 index 1821772..0000000 --- a/helm-templates/grafana/templates/tests/test-podsecuritypolicy.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if and (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") .Values.testFramework.enabled .Values.rbac.pspEnabled }} -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - 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: - allowPrivilegeEscalation: true - privileged: false - hostNetwork: false - hostIPC: false - hostPID: false - fsGroup: - rule: RunAsAny - seLinux: - rule: RunAsAny - supplementalGroups: - rule: RunAsAny - runAsUser: - rule: RunAsAny - volumes: - - configMap - - downwardAPI - - emptyDir - - projected - - csi - - secret -{{- end }} diff --git a/helm-templates/grafana/templates/tests/test-role.yaml b/helm-templates/grafana/templates/tests/test-role.yaml deleted file mode 100644 index cb4c782..0000000 --- a/helm-templates/grafana/templates/tests/test-role.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if and (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") .Values.testFramework.enabled .Values.rbac.pspEnabled }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - 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: [{{ include "grafana.fullname" . }}-test] -{{- end }} diff --git a/helm-templates/grafana/templates/tests/test-rolebinding.yaml b/helm-templates/grafana/templates/tests/test-rolebinding.yaml deleted file mode 100644 index f40d791..0000000 --- a/helm-templates/grafana/templates/tests/test-rolebinding.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if and (.Capabilities.APIVersions.Has "policy/v1beta1/PodSecurityPolicy") .Values.testFramework.enabled .Values.rbac.pspEnabled }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - 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: {{ include "grafana.fullname" . }}-test -subjects: - - kind: ServiceAccount - name: {{ include "grafana.serviceAccountNameTest" . }} - namespace: {{ include "grafana.namespace" . }} -{{- end }} diff --git a/helm-templates/grafana/templates/tests/test-serviceaccount.yaml b/helm-templates/grafana/templates/tests/test-serviceaccount.yaml deleted file mode 100644 index 38fba35..0000000 --- a/helm-templates/grafana/templates/tests/test-serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if and .Values.testFramework.enabled .Values.serviceAccount.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - {{- include "grafana.labels" . | nindent 4 }} - 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/helm-templates/grafana/templates/tests/test.yaml b/helm-templates/grafana/templates/tests/test.yaml deleted file mode 100644 index 9fb8842..0000000 --- a/helm-templates/grafana/templates/tests/test.yaml +++ /dev/null @@ -1,49 +0,0 @@ -{{- if .Values.testFramework.enabled }} -{{- $root := . }} -apiVersion: v1 -kind: Pod -metadata: - 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: {{ include "grafana.namespace" . }} -spec: - serviceAccountName: {{ include "grafana.serviceAccountNameTest" . }} - {{- with .Values.testFramework.securityContext }} - securityContext: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- if or .Values.image.pullSecrets .Values.global.imagePullSecrets }} - imagePullSecrets: - {{- include "grafana.imagePullSecrets" (dict "root" $root "imagePullSecrets" .Values.image.pullSecrets) | nindent 4 }} - {{- end }} - {{- with .Values.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.affinity }} - affinity: - {{- tpl (toYaml .) $root | nindent 4 }} - {{- end }} - {{- with .Values.tolerations }} - tolerations: - {{- toYaml . | nindent 4 }} - {{- end }} - containers: - - name: {{ .Release.Name }}-test - image: "{{ .Values.testFramework.image}}:{{ .Values.testFramework.tag }}" - imagePullPolicy: "{{ .Values.testFramework.imagePullPolicy}}" - command: ["/opt/bats/bin/bats", "-t", "/tests/run.sh"] - volumeMounts: - - mountPath: /tests - name: tests - readOnly: true - volumes: - - name: tests - configMap: - name: {{ include "grafana.fullname" . }}-test - restartPolicy: Never -{{- end }} diff --git a/helm-templates/grafana/values.yaml b/helm-templates/grafana/values.yaml deleted file mode 100644 index c1828e8..0000000 --- a/helm-templates/grafana/values.yaml +++ /dev/null @@ -1,1247 +0,0 @@ -global: - # 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: false - pspUseAppArmor: false - namespaced: false - extraRoleRules: [] - # - apiGroups: [] - # resources: [] - # verbs: [] - extraClusterRoleRules: [] - # - apiGroups: [] - # resources: [] - # verbs: [] -serviceAccount: - create: true - name: - nameTest: - ## 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: true - -replicas: 1 - -## Create a headless service for the deployment -headlessService: false - -## Create HorizontalPodAutoscaler object for deployment type -# -autoscaling: - enabled: false - 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: {} -# minAvailable: 1 -# maxUnavailable: 1 - -## See `kubectl explain deployment.spec.strategy` for more -## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy -deploymentStrategy: - type: RollingUpdate - -readinessProbe: - httpGet: - path: /api/health - port: 3000 - -livenessProbe: - httpGet: - path: /api/health - port: 3000 - initialDelaySeconds: 60 - timeoutSeconds: 30 - failureThreshold: 10 - -## Use an alternate scheduler, e.g. "stork". -## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ -## -# schedulerName: "default-scheduler" - -image: - repository: docker.io/grafana/grafana - # 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: [] - # - myRegistrKeySecretName - -testFramework: - enabled: true - image: docker.io/bats/bats - tag: "v1.4.1" - imagePullPolicy: IfNotPresent - securityContext: {} - -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/ - # subPath: certificates.crt # (optional) - # configMap: certs-configmap - # readOnly: true - - -extraEmptyDirMounts: [] - # - name: provisioning-notifiers - # mountPath: /etc/grafana/provisioning/notifiers - - -# Apply extra labels to common labels. -extraLabels: {} - -## Assign a PriorityClassName to pods if set -# priorityClassName: - -downloadDashboardsImage: - repository: docker.io/curlimages/curl - tag: 7.85.0 - sha: "" - pullPolicy: IfNotPresent - -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: {} - -## Pod Labels -# podLabels: {} - -podPortName: grafana -gossipPortName: gossip -## Deployment annotations -# annotations: {} - -## Expose the grafana service to be accessed from outside the cluster (LoadBalancer service). -## or access it from within the cluster (ClusterIP service). Set the service type and the port to serve it. -## ref: http://kubernetes.io/docs/user-guide/services/ -## -service: - enabled: true - type: ClusterIP - port: 80 - targetPort: 3000 - # targetPort: 4181 To be used with a proxy extraContainer - ## 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 - ## 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: [] - targetLabels: [] - -extraExposePorts: [] - # - name: keycloak - # port: 8080 - # targetPort: 8080 - # type: ClusterIP - -# overrides pod.spec.hostAliases in the grafana deployment's pods -hostAliases: [] - # - ip: "1.2.3.4" - # hostnames: - # - "my.host.com" - -ingress: - enabled: false - # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName - # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress - # ingressClassName: nginx - # Values can be templated - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - labels: {} - path: / - - # pathType is only for k8s >= 1.1= - pathType: Prefix - - hosts: - - chart-example.local - ## Extra paths to prepend to every host configuration. This is useful when working with annotation based services. - extraPaths: [] - # - path: /* - # backend: - # serviceName: ssl-redirect - # servicePort: use-annotation - ## Or for k8s > 1.19 - # - path: /* - # pathType: Prefix - # backend: - # service: - # name: ssl-redirect - # port: - # name: use-annotation - - - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - -resources: {} -# limits: -# cpu: 100m -# memory: 128Mi -# requests: -# cpu: 100m -# memory: 128Mi - -## Node labels for pod assignment -## ref: https://kubernetes.io/docs/user-guide/node-selection/ -# -nodeSelector: {} - -## Tolerations for pod assignment -## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ -## -tolerations: [] - -## Affinity for pod assignment (evaluated as template) -## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity -## -affinity: {} - -## 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/ -## -extraInitContainers: [] - -## Enable an Specify container in extraContainers. This is meant to allow adding an authentication proxy to a grafana pod -extraContainers: "" -# extraContainers: | -# - name: proxy -# image: quay.io/gambol99/keycloak-proxy:latest -# args: -# - -provider=github -# - -client-id= -# - -client-secret= -# - -github-org= -# - -email-domain=* -# - -cookie-secret= -# - -http-address=http://0.0.0.0:4181 -# - -upstream-url=http://127.0.0.1:3000 -# ports: -# - name: proxy-web -# containerPort: 4181 - -## Volumes that can be used in init containers that will not be mounted to deployment pods -extraContainerVolumes: [] -# - name: volume-from-secret -# secret: -# secretName: secret-to-mount -# - name: empty-dir-volume -# emptyDir: {} - -## Enable persistence using Persistent Volume Claims -## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ -## -persistence: - type: pvc - enabled: false - # storageClassName: default - accessModes: - - ReadWriteOnce - size: 10Gi - # annotations: {} - finalizers: - - kubernetes.io/pvc-protection - # selectorLabels: {} - ## Sub-directory of the PV to mount. Can be templated. - # subPath: "" - ## Name of an existing PVC. Can be templated. - # existingClaim: - ## Extra labels to apply to a PVC. - extraPvcLabels: {} - - ## If persistence is not enabled, this allows to mount the - ## local storage in-memory to improve performance - ## - inMemory: - enabled: false - ## The maximum usage on memory medium EmptyDir would be - ## the minimum value between the SizeLimit specified - ## here and the sum of memory limits of all containers in a pod - ## - # sizeLimit: 300Mi - -initChownData: - ## If false, data ownership will not be reset at startup - ## This allows the grafana-server to be run with an arbitrary user - ## - enabled: true - - ## initChownData container image - ## - image: - repository: docker.io/library/busybox - tag: "1.31.1" - sha: "" - pullPolicy: IfNotPresent - - ## initChownData resource requests and limits - ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # 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 -# adminPassword: strongpassword - -# Use an existing secret for the admin user. -admin: - ## Name of the secret. Can be templated. - existingSecret: "" - userKey: admin-user - passwordKey: admin-password - -## Define command to be executed at startup by grafana container -## Needed if using `vault-env` to manage secrets (ref: https://banzaicloud.com/blog/inject-secrets-into-pods-vault/) -## Default is "run.sh" as defined in grafana's Dockerfile -# command: -# - "sh" -# - "/run.sh" - -## 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 -## -## to provide grafana with access to CloudWatch on AWS EKS: -## 1. create an iam role of type "Web identity" with provider oidc.eks.* (note the provider for later) -## 2. edit the "Trust relationships" of the role, add a line inside the StringEquals clause using the -## same oidc eks provider as noted before (same as the existing line) -## also, replace NAMESPACE and prometheus-operator-grafana with the service account namespace and name -## -## "oidc.eks.us-east-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:sub": "system:serviceaccount:NAMESPACE:prometheus-operator-grafana", -## -## 3. attach a policy to the role, you can use a built in policy called CloudWatchReadOnlyAccess -## 4. use the following env: (replace 123456789000 and iam-role-name-here with your aws account number and role name) -## -## env: -## AWS_ROLE_ARN: arn:aws:iam::123456789000:role/iam-role-name-here -## AWS_WEB_IDENTITY_TOKEN_FILE: /var/run/secrets/eks.amazonaws.com/serviceaccount/token -## AWS_REGION: us-east-1 -## -## 5. uncomment the EKS section in extraSecretMounts: below -## 6. uncomment the annotation section in the serviceAccount: above -## make sure to replace arn:aws:iam::123456789000:role/iam-role-name-here with your role arn - -env: {} - -## "valueFrom" environment variable references that will be added to deployment pods. Name is templated. -## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#envvarsource-v1-core -## Renders in container spec as: -## env: -## ... -## - name: -## valueFrom: -## -envValueFrom: {} - # ENV_NAME: - # configMapKeyRef: - # name: configmap-name - # key: value_key - -## The name of a secret in the same kubernetes namespace which contain values to be added to the environment -## This can be useful for auth tokens, etc. Value is templated. -envFromSecret: "" - -## Sensible environment variables that will be rendered as new secret object -## This can be useful for auth tokens, etc. -## 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 -## Each entry should contain a name key, and can optionally specify whether the secret must be defined with an optional key. -## Name is templated. -envFromSecrets: [] -## - name: secret-name -## optional: true - -## The names of conifgmaps in the same kubernetes namespace which contain values to be added to the environment -## Each entry should contain a name key, and can optionally specify whether the configmap must be defined with an optional key. -## Name is templated. -## ref: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#configmapenvsource-v1-core -envFromConfigMaps: [] -## - name: configmap-name -## optional: true - -# Inject Kubernetes services as environment variables. -# See https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/#environment-variables -enableServiceLinks: true - -## Additional grafana server secret mounts -# Defines additional mounts with secrets. Secrets must be manually created in the namespace. -extraSecretMounts: [] - # - name: secret-files - # mountPath: /etc/secrets - # secretName: grafana-secret-files - # readOnly: true - # subPath: "" - # - # for AWS EKS (cloudwatch) use the following (see also instruction in env: above) - # - name: aws-iam-token - # mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount - # readOnly: true - # projected: - # defaultMode: 420 - # sources: - # - serviceAccountToken: - # audience: sts.amazonaws.com - # expirationSeconds: 86400 - # path: token - # - # for CSI e.g. Azure Key Vault use the following - # - name: secrets-store-inline - # mountPath: /run/secrets - # readOnly: true - # csi: - # driver: secrets-store.csi.k8s.io - # readOnly: true - # volumeAttributes: - # secretProviderClass: "akv-grafana-spc" - # nodePublishSecretRef: # Only required when using service principal mode - # name: grafana-akv-creds # Only required when using service principal mode - -## Additional grafana server volume mounts -# Defines additional volume mounts. -extraVolumeMounts: [] - # - name: extra-volume-0 - # mountPath: /mnt/volume0 - # readOnly: true - # existingClaim: volume-claim - # - name: extra-volume-1 - # mountPath: /mnt/volume1 - # readOnly: true - # hostPath: /usr/shared/ - # - name: grafana-secrets - # mountPath: /mnt/volume2 - # csi: true - # data: - # 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: {} - # postStart: - # exec: - # command: [] - -## Pass the plugins you want installed as a list. -## -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 -## -datasources: {} -# datasources.yaml: -# apiVersion: 1 -# datasources: -# - name: Prometheus -# type: prometheus -# url: http://prometheus-prometheus-server -# access: proxy -# isDefault: true -# - name: CloudWatch -# type: cloudwatch -# access: proxy -# uid: cloudwatch -# editable: false -# jsonData: -# authType: default -# defaultRegion: us-east-1 -# 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: - # 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 -## -notifiers: {} -# notifiers.yaml: -# notifiers: -# - name: email-notifier -# type: email -# uid: email1 -# # either: -# org_id: 1 -# # or -# org_name: Main Org. -# is_default: true -# settings: -# addresses: an_email_address@example.com -# delete_notifiers: - -## Configure grafana dashboard providers -## ref: http://docs.grafana.org/administration/provisioning/#dashboards -## -## `path` must be /var/lib/grafana/dashboards/ -## -dashboardProviders: {} -# dashboardproviders.yaml: -# apiVersion: 1 -# providers: -# - name: 'default' -# orgId: 1 -# folder: '' -# type: file -# disableDeletion: false -# editable: true -# options: -# path: /var/lib/grafana/dashboards/default - -## Configure grafana dashboard to import -## NOTE: To use dashboards you must also enable/configure dashboardProviders -## ref: https://grafana.com/dashboards -## -## dashboards per provider, use provider name as key. -## -dashboards: {} - # default: - # some-dashboard: - # json: | - # $RAW_JSON - # custom-dashboard: - # file: dashboards/custom-dashboard.json - # prometheus-stats: - # gnetId: 2 - # revision: 2 - # datasource: Prometheus - # local-dashboard: - # url: https://example.com/repository/test.json - # token: '' - # local-dashboard-base64: - # url: https://example.com/repository/test-b64.json - # token: '' - # b64content: true - # 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. -## ConfigMap data example: -## -## data: -## example-dashboard.json: | -## RAW_JSON -## -dashboardsConfigMaps: {} -# default: "" - -## Grafana's primary configuration -## NOTE: values in map will be converted to ini format -## ref: http://docs.grafana.org/installation/configuration/ -## -grafana.ini: - paths: - data: /var/lib/grafana/ - logs: /var/log/grafana - plugins: /var/lib/grafana/plugins - provisioning: /etc/grafana/provisioning - analytics: - check_for_updates: true - log: - 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 - # root_url: - # https://grafana.com/docs/grafana/latest/auth/github/#enable-github-in-grafana - # auth.github: - # enabled: false - # allow_sign_up: false - # scopes: user:email,read:org - # auth_url: https://github.com/login/oauth/authorize - # token_url: https://github.com/login/oauth/access_token - # api_url: https://api.github.com/user - # team_ids: - # allowed_organizations: - # client_id: - # client_secret: -## LDAP Authentication can be enabled with the following values on grafana.ini -## NOTE: Grafana will fail to start if the value for ldap.toml is invalid - # auth.ldap: - # enabled: true - # allow_sign_up: true - # config_file: /etc/grafana/ldap.toml - -## Grafana's LDAP configuration -## Templated by the template in _helpers.tpl -## NOTE: To enable the grafana.ini must be configured with auth.ldap.enabled -## ref: http://docs.grafana.org/installation/configuration/#auth-ldap -## ref: http://docs.grafana.org/installation/ldap/#configuration -ldap: - enabled: false - # `existingSecret` is a reference to an existing secret containing the ldap configuration - # for Grafana in a key `ldap-toml`. - existingSecret: "" - # `config` is the content of `ldap.toml` that will be stored in the created secret - config: "" - # config: |- - # verbose_logging = true - - # [[servers]] - # host = "my-ldap-server" - # port = 636 - # use_ssl = true - # start_tls = false - # ssl_skip_verify = false - # bind_dn = "uid=%s,ou=users,dc=myorg,dc=com" - -## Grafana's SMTP configuration -## NOTE: To enable, grafana.ini must be configured with smtp.enabled -## ref: http://docs.grafana.org/installation/configuration/#smtp -smtp: - # `existingSecret` is a reference to an existing secret containing the smtp configuration - # for Grafana. - existingSecret: "" - userKey: "user" - passwordKey: "password" - -## Sidecars that collect the configmaps with specified label and stores the included files them into the respective folders -## Requires at least Grafana 5 to work and can't be used together with parameters dashboardProviders, datasources and dashboards -sidecar: - image: - repository: quay.io/kiwigrid/k8s-sidecar - tag: 1.24.6 - sha: "" - imagePullPolicy: IfNotPresent - resources: {} -# limits: -# cpu: 100m -# memory: 100Mi -# requests: -# cpu: 50m -# memory: 50Mi - 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 - # Deploy the alert sidecar as an initContainer in addition to a container. - # 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: {} - # 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: "" - # 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 - defaultFolderName: null - # Namespaces list. If specified, the sidecar will search for config-maps/secrets inside these namespaces. - # Otherwise the namespace in which the sidecar is running will be used. - # It's also possible to specify ALL to search in all namespaces. - searchNamespace: null - # Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. - watchMethod: WATCH - # search in configmap, secret or both - resource: both - # If specified, the sidecar will look for annotation with this name to create folder and put graph here. - # You can use this parameter together with `provider.foldersFromFilesStructure`to annotate configmaps and create folder structure. - folderAnnotation: null - # 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 - # - # watchClientTimeout: is a client-side timeout, configuring your local socket. - # If you have a network outage dropping all packets with no RST/FIN, - # this is how long your client waits before realizing & dropping the connection. - # defaults to 66sec (sic!) - # watchClientTimeout: 60 - # - # provider configuration that lets grafana manage the dashboards - provider: - # name of the provider, should be unique - name: sidecarProvider - # orgid as configured in grafana - orgid: 1 - # folder in which the dashboards should be imported in grafana - folder: '' - # type of the provider - type: file - # disableDelete to activate a import-only behaviour - disableDelete: false - # allow updating provisioned dashboards from the UI - allowUiUpdates: false - # allow Grafana to replicate dashboard structure from filesystem - foldersFromFilesStructure: false - # Additional dashboard sidecar volume mounts - extraMounts: [] - # Sets the size limit of the dashboard sidecar emptyDir volume - sizeLimit: {} - datasources: - enabled: false - # Additional environment variables for the datasourcessidecar - env: {} - # 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: "" - # 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 - 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 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. - 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: "" - # 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 - 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 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 -## -namespaceOverride: "" - -## Number of old ReplicaSets to retain -## -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: - # image-renderer Image repository - repository: docker.io/grafana/grafana-image-renderer - # image-renderer Image tag - tag: latest - # image-renderer Image sha (optional) - sha: "" - # image-renderer ImagePullPolicy - pullPolicy: Always - # extra environment variables - env: - HTTP_HOST: "0.0.0.0" - # RENDERING_ARGS: --no-sandbox,--disable-gpu,--window-size=1280x758 - # RENDERING_MODE: clustered - # IGNORE_HTTPS_ERRORS: true - - ## "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 deployment Host Aliases - hostAliases: [] - # image-renderer deployment priority class - priorityClassName: '' - service: - # Enable the image-renderer service - enabled: true - # image-renderer service port name - portName: 'http' - # image-renderer service port used by both service and deployment - port: 8081 - targetPort: 8081 - # 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 - grafanaSubPath: "" - # name of the image-renderer port on the pod - podPortName: http - # number of image-renderer replica sets to keep - revisionHistoryLimit: 10 - networkPolicy: - # Enable a NetworkPolicy to limit inbound traffic to only the created grafana pods - limitIngress: true - # Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods - limitEgress: false - # Allow additional services to access image-renderer (eg. Prometheus operator when ServiceMonitor is enabled) - extraIngressSelectors: [] - resources: {} -# limits: -# cpu: 100m -# memory: 100Mi -# requests: -# cpu: 50m -# memory: 50Mi - ## Node labels for pod assignment - ## ref: https://kubernetes.io/docs/user-guide/node-selection/ - # - nodeSelector: {} - - ## Tolerations for pod assignment - ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ - ## - tolerations: [] - - ## Affinity for pod assignment (evaluated as template) - ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity - ## - affinity: {} - - ## Use an alternate scheduler, e.g. "stork". - ## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ - ## - # schedulerName: "default-scheduler" - -networkPolicy: - ## @param networkPolicy.enabled Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. - ## - enabled: false - ## @param networkPolicy.allowExternal Don't require client label for connections - ## The Policy model to apply. When set to false, only pods with the correct - ## client label will have network access to grafana port defined. - ## When true, grafana will accept connections from any source - ## (with the correct destination port). - ## - 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 - ## and that match other criteria, the ones that have the good label, can reach the grafana. - ## But sometimes, we want the grafana to be accessible to clients from other namespaces, in this case, we can use this - ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added. - ## - ## Example: - ## explicitNamespacesSelector: - ## matchLabels: - ## role: frontend - ## matchExpressions: - ## - {key: role, operator: In, values: [frontend]} - ## - explicitNamespacesSelector: {} - ## - ## - ## - ## - ## - ## - 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.ports Add individual ports to be allowed by the egress - ports: [] - ## Add ports to the egress by specifying - port: - ## E.X. - ## ports: - ## - port: 80 - ## - port: 443 - ## - ## - ## - ## - ## - ## - -# 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" - # kind: ExternalSecret - # metadata: - # name: grafana-secrets - # spec: - # backendType: gcpSecretsManager - # data: - # - key: grafana-admin-password - # name: adminPassword \ No newline at end of file