Skip to content

Commit fd3378c

Browse files
committed
feat(drycc-addons):add grafana
1 parent b35e4ce commit fd3378c

28 files changed

Lines changed: 3303 additions & 0 deletions

addons/grafana/10/README.md

Lines changed: 692 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
annotations:
2+
category: Analytics
3+
apiVersion: v2
4+
appVersion: 9.1.7
5+
dependencies:
6+
- name: common
7+
repository: oci://registry.drycc.cc/charts
8+
tags:
9+
- drycc-common
10+
version: ~1.1.2
11+
description: Grafana is an open source metric analytics and visualization suite for visualizing time series data that supports various types of data sources.
12+
engine: gotpl
13+
home: https://github.com/drycc/charts/tree/master/drycc/grafana
14+
icon: https://drycc.com/assets/stacks/grafana/img/grafana-stack-220x234.png
15+
keywords:
16+
- analytics
17+
- monitoring
18+
- metrics
19+
- logs
20+
maintainers:
21+
- name: Bitnami
22+
url: https://github.com/drycc/charts
23+
name: grafana
24+
sources:
25+
- https://github.com/drycc/containers/tree/main/drycc/grafana
26+
- https://grafana.com/
27+
version: 8.2.11
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"type": "object",
4+
"properties": {
5+
"imagePullPolicy": {
6+
"type": "string",
7+
"enum": ["Always", "IfNotPresent", "Never"],
8+
"default": "IfNotPresent",
9+
"title": "Image pull policy"
10+
}
11+
}
12+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
CHART NAME: {{ .Chart.Name }}
2+
CHART VERSION: {{ .Chart.Version }}
3+
APP VERSION: {{ .Chart.AppVersion }}
4+
5+
** Please be patient while the chart is being deployed **
6+
7+
1. Get the application URL by running these commands:
8+
9+
{{- if .Values.ingress.enabled }}
10+
{{ ternary "https" "http" .Values.ingress.tls }}://{{ .Values.ingress.hostname }}{{ .Values.ingress.path }}
11+
{{- else if contains "NodePort" .Values.service.type }}
12+
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "common.names.fullname" . }})
13+
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
14+
echo http://$NODE_IP:$NODE_PORT
15+
{{- else if contains "LoadBalancer" .Values.service.type }}
16+
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
17+
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "common.names.fullname" . }}'
18+
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "common.names.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
19+
echo http://$SERVICE_IP:{{ .Values.service.ports.grafana }}
20+
{{- else if contains "ClusterIP" .Values.service.type }}
21+
echo "Browse to http://127.0.0.1:8080"
22+
kubectl port-forward svc/{{ include "common.names.fullname" . }} 8080:{{ .Values.service.ports.grafana }} &
23+
{{- end }}
24+
25+
2. Get the admin credentials:
26+
27+
echo "User: {{ .Values.admin.user }}"
28+
echo "Password: $(kubectl get secret {{ include "grafana.adminSecretName" . }} --namespace {{ .Release.Namespace }} -o jsonpath="{.data.{{ include "grafana.adminSecretPasswordKey" . }}}" | base64 -d)"
29+
30+
{{- include "common.warnings.rollingTag" .Values.image }}
31+
{{- include "common.warnings.rollingTag" .Values.imageRenderer.image }}
32+
{{- include "common.warnings.rollingTag" .Values.volumePermissions.image }}
33+
{{ include "grafana.validateValues" . }}
34+
{{ include "grafana.validateValues.database" . }}
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
{{/* vim: set filetype=mustache: */}}
2+
3+
{{/*
4+
Return the proper Grafana image name
5+
*/}}
6+
{{- define "grafana.image" -}}
7+
{{- include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) -}}
8+
{{- end -}}
9+
10+
{{/*
11+
Return the proper Grafana Image Renderer image name
12+
*/}}
13+
{{- define "grafana.imageRenderer.image" -}}
14+
{{- include "common.images.image" (dict "imageRoot" .Values.imageRenderer.image "global" .Values.global) -}}
15+
{{- end -}}
16+
17+
{{/*
18+
Return the proper image name (for the init container volume-permissions image)
19+
*/}}
20+
{{- define "volumePermissions.image" -}}
21+
{{- include "common.images.image" ( dict "imageRoot" .Values.volumePermissions.image "global" .Values.global ) -}}
22+
{{- end -}}
23+
24+
{{/*
25+
Return the proper Docker Image Registry Secret Names
26+
*/}}
27+
{{- define "grafana.imagePullSecrets" -}}
28+
{{- include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.imageRenderer.image) "global" .Values.global) -}}
29+
{{- end }}
30+
31+
{{/*
32+
Return the proper Storage Class
33+
*/}}
34+
{{- define "grafana.storageClass" -}}
35+
{{- include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) -}}
36+
{{- end -}}
37+
38+
{{/*
39+
Return the Grafana admin credentials secret
40+
*/}}
41+
{{- define "grafana.adminSecretName" -}}
42+
{{- if .Values.admin.existingSecret -}}
43+
{{- printf "%s" (tpl .Values.admin.existingSecret $) -}}
44+
{{- else -}}
45+
{{- printf "%s-admin" (include "common.names.fullname" .) -}}
46+
{{- end -}}
47+
{{- end -}}
48+
49+
{{/*
50+
Return the Grafana admin password key
51+
*/}}
52+
{{- define "grafana.adminSecretPasswordKey" -}}
53+
{{- if and .Values.admin.existingSecret .Values.admin.existingSecretPasswordKey -}}
54+
{{- printf "%s" (tpl .Values.admin.existingSecretPasswordKey $) -}}
55+
{{- else -}}
56+
{{- printf "GF_SECURITY_ADMIN_PASSWORD" -}}
57+
{{- end -}}
58+
{{- end -}}
59+
60+
{{/*
61+
Return true if a secret object should be created
62+
*/}}
63+
{{- define "grafana.createAdminSecret" -}}
64+
{{- if not .Values.admin.existingSecret }}
65+
{{- true -}}
66+
{{- else -}}
67+
{{- end -}}
68+
{{- end -}}
69+
70+
{{/*
71+
Return the Grafana SMTP credentials secret
72+
*/}}
73+
{{- define "grafana.smtpSecretName" -}}
74+
{{- if .Values.smtp.existingSecret }}
75+
{{- printf "%s" (tpl .Values.smtp.existingSecret $) -}}
76+
{{- else -}}
77+
{{- printf "%s-smtp" (include "common.names.fullname" .) -}}
78+
{{- end -}}
79+
{{- end -}}
80+
81+
{{/*
82+
Return the Grafana SMTP user key
83+
*/}}
84+
{{- define "grafana.smtpSecretUserKey" -}}
85+
{{- if and .Values.smtp.existingSecret .Values.smtp.existingSecretUserKey -}}
86+
{{- printf "%s" (tpl .Values.smtp.existingSecretUserKey $) -}}
87+
{{- else -}}
88+
{{- printf "GF_SMTP_USER" -}}
89+
{{- end -}}
90+
{{- end -}}
91+
92+
{{/*
93+
Return the Grafana SMTP password key
94+
*/}}
95+
{{- define "grafana.smtpSecretPasswordKey" -}}
96+
{{- if and .Values.smtp.existingSecret .Values.smtp.existingSecretPasswordKey -}}
97+
{{- printf "%s" (tpl .Values.smtp.existingSecretPasswordKey $) -}}
98+
{{- else -}}
99+
{{- printf "GF_SMTP_PASSWORD" -}}
100+
{{- end -}}
101+
{{- end -}}
102+
103+
{{/*
104+
Return true if a secret object should be created
105+
*/}}
106+
{{- define "grafana.createSMTPSecret" -}}
107+
{{- if and .Values.smtp.enabled (not .Values.smtp.existingSecret) }}
108+
{{- true -}}
109+
{{- else -}}
110+
{{- end -}}
111+
{{- end -}}
112+
113+
{{/*
114+
Returns the proper service account name depending if an explicit service account name is set
115+
in the values file. If the name is not set it will default to either common.names.fullname if serviceAccount.create
116+
is true or default otherwise.
117+
*/}}
118+
{{- define "grafana.serviceAccountName" -}}
119+
{{- if .Values.serviceAccount.create -}}
120+
{{ default (include "common.names.fullname" .) .Values.serviceAccount.name }}
121+
{{- else -}}
122+
{{ default "default" .Values.serviceAccount.name }}
123+
{{- end -}}
124+
{{- end -}}
125+
126+
{{/*
127+
Validate values for Grafana.
128+
*/}}
129+
{{- define "grafana.validateValues" -}}
130+
{{- $messages := list -}}
131+
{{- $messages := append $messages (include "grafana.validateValues.configmapsOrSecrets" .) -}}
132+
{{- $messages := append $messages (include "grafana.validateValues.ldap.configuration" .) -}}
133+
{{- $messages := append $messages (include "grafana.validateValues.ldap.configmapsecret" .) -}}
134+
{{- $messages := append $messages (include "grafana.validateValues.ldap.tls" .) -}}
135+
{{- $messages := without $messages "" -}}
136+
{{- $message := join "\n" $messages -}}
137+
138+
{{- if $message -}}
139+
{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}}
140+
{{- end -}}
141+
{{- end -}}
142+
143+
{{/* Validate values of Grafana - A ConfigMap or Secret name must be provided when loading a custom grafana.ini file */}}
144+
{{- define "grafana.validateValues.configmapsOrSecrets" -}}
145+
{{- if and .Values.config.useGrafanaIniFile (not .Values.config.grafanaIniSecret) (not .Values.config.grafanaIniConfigMap) -}}
146+
grafana: config.useGrafanaIniFile config.grafanaIniSecret and config.grafanaIniConfigMap
147+
You enabled config.useGrafanaIniFile but did not specify config.grafanaIniSecret nor config.grafanaIniConfigMap
148+
{{- end -}}
149+
{{- end -}}
150+
151+
{{/* Validate values of Grafana - A custom ldap.toml file must be provided when enabling LDAP */}}
152+
{{- define "grafana.validateValues.ldap.configuration" -}}
153+
{{- if and .Values.ldap.enabled (empty .Values.ldap.uri) (empty .Values.ldap.basedn) (empty .Values.ldap.configuration) (empty .Values.ldap.configMapName) (empty .Values.ldap.secretName) -}}
154+
grafana: ldap.enabled ldap.uri ldap.basedn ldap.configuration ldap.configMapName and ldap.secretName
155+
You must provide the uri and basedn of your LDAP Sever (--set ldap.uri="aaa" --set ldap.basedn="bbb")
156+
or the content of your custom ldap.toml file when enabling LDAP (--set ldap.configuration="xxx")
157+
As an alternative, you can set the name of an existing ConfigMap (--set ldap.configMapName="yyy") or
158+
an an existing Secret (--set ldap.secretName="zzz") containging the custom ldap.toml file.
159+
{{- end -}}
160+
{{- end -}}
161+
162+
{{/* Validate values of Grafana - Only a ConfigMap or Secret name must be provided when loading a custom ldap.toml file */}}
163+
{{- define "grafana.validateValues.ldap.configmapsecret" -}}
164+
{{- if and .Values.ldap.enabled (not (empty .Values.ldap.configMapName)) (not (empty .Values.ldap.secretName)) -}}
165+
grafana: ldap.enabled ldap.configMapName and ldap.secretName
166+
You cannot load a custom ldap.toml file both from a ConfigMap and a Secret simultaneously
167+
{{- end -}}
168+
{{- end -}}
169+
170+
{{/* Validate values of Grafana - LDAP TLS validation */}}
171+
{{- define "grafana.validateValues.ldap.tls" -}}
172+
{{- if and .Values.ldap.enabled .Values.ldap.tls.enabled (empty .Values.ldap.tls.certificatesSecret) (or (not (empty .Values.ldap.tls.CAFilename)) (not (empty .Values.ldap.tls.certFilename)) (not (empty .Values.ldap.tls.certKeyFilename))) -}}
173+
grafana: ldap.enabled ldap.tls.enabled ldap.tls.certificatesSecret ldap.tls.CAFilename ldap.tls.certFilename and ldap.tls.certKeyFilename
174+
You must set ldap.tls.certificatesSecret if you want to specify any certificate for LDAP TLS connection
175+
{{- end -}}
176+
{{- end -}}
177+
178+
{{/*
179+
Return LDAP configuration generated from ldap properties.
180+
*/}}
181+
{{- define "grafana.ldap.config" -}}
182+
{{- $hostPort := get (urlParse (required "You must set ldap.uri" .Values.ldap.uri)) "host" -}}
183+
[[servers]]
184+
# Ldap server host (specify multiple hosts space separated)
185+
host = {{ index (splitList ":" $hostPort) 0 | quote }}
186+
# Default port is 389 or 636 if use_ssl = true
187+
port = {{ index (splitList ":" $hostPort) 1 | default 389 }}
188+
# Set to true if LDAP server should use an encrypted TLS connection (either with STARTTLS or LDAPS)
189+
{{- if .Values.ldap.tls.enabled }}
190+
use_ssl = {{ .Values.ldap.tls.enabled }}
191+
ssl_skip_verify = {{ .Values.ldap.tls.skipVerify }}
192+
# If set to true, use LDAP with STARTTLS instead of LDAPS
193+
start_tls = {{ .Values.ldap.tls.startTls }}
194+
{{- if .Values.ldap.tls.CAFilename }}
195+
# set to the path to your root CA certificate or leave unset to use system defaults
196+
root_ca_cert = {{ printf "%s/%s" .Values.ldap.tls.certificatesMountPath .Values.ldap.tls.CAFilename | quote }}
197+
{{- end }}
198+
{{- if .Values.ldap.tls.certFilename }}
199+
# Authentication against LDAP servers requiring client certificates
200+
client_cert = {{ printf "%s/%s" .Values.ldap.tls.certificatesMountPath .Values.ldap.tls.certFilename | quote }}
201+
client_key = {{ printf "%s/%s" .Values.ldap.tls.certificatesMountPath (required "ldap.tls.certKeyFilename is required when ldap.tls.certFilename is defined" .Values.ldap.tls.certKeyFilename) | quote }}
202+
{{- end }}
203+
{{- end }}
204+
{{- if .Values.ldap.binddn }}
205+
# Search user bind dn
206+
bind_dn = {{ .Values.ldap.binddn | quote }}
207+
{{- end }}
208+
{{- if .Values.ldap.bindpw }}
209+
# Search user bind password
210+
# If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
211+
bind_password = {{ .Values.ldap.bindpw | quote }}
212+
{{- end }}
213+
214+
# User search filter, for example "(cn=%s)" or "(sAMAccountName=%s)" or "(uid=%s)"
215+
# Allow login from email or username, example "(|(sAMAccountName=%s)(userPrincipalName=%s))"
216+
{{- if .Values.ldap.searchFilter }}
217+
search_filter = {{ .Values.ldap.searchFilter | quote }}
218+
{{- else if .Values.ldap.searchAttribute }}
219+
search_filter = "({{ .Values.ldap.searchAttribute }}=%s)"
220+
{{- end }}
221+
# An array of base dns to search through
222+
search_base_dns = [{{ (required "You must set ldap.basedn" .Values.ldap.basedn) | quote }}]
223+
224+
{{ .Values.ldap.extraConfiguration }}
225+
{{- end -}}
226+
227+
{{/* Validate values of Grafana - Requirements to use an external database */}}
228+
{{- define "grafana.validateValues.database" -}}
229+
{{- $replicaCount := int .Values.grafana.replicaCount }}
230+
{{- if gt $replicaCount 1 -}}
231+
grafana: replicaCount
232+
Using more than one replica requires using an external database to share data between Grafana instances.
233+
By default Grafana uses an internal sqlite3 per instance but you can configure an external MySQL or PostgreSQL.
234+
Please, ensure you provide a configuration file configuring the external database to share data between replicas.
235+
{{- end -}}
236+
{{- end -}}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: {{ include "common.names.fullname" . }}-envvars
5+
namespace: {{ .Release.Namespace | quote }}
6+
labels: {{- include "common.labels.standard" . | nindent 4 }}
7+
{{- if .Values.commonLabels }}
8+
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
9+
{{- end }}
10+
app.kubernetes.io/component: grafana
11+
{{- if .Values.commonAnnotations }}
12+
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
13+
{{- end }}
14+
data:
15+
GF_SECURITY_ADMIN_USER: {{ .Values.admin.user | quote }}
16+
{{- if .Values.imageRenderer.enabled }}
17+
{{- $domain := .Values.clusterDomain }}
18+
{{- $namespace := .Release.Namespace }}
19+
GF_RENDERING_SERVER_URL: "http://{{ include "common.names.fullname" . }}-image-renderer.{{ $namespace }}.svc.{{ $domain }}:{{ .Values.imageRenderer.service.ports.imageRenderer }}/render"
20+
GF_RENDERING_CALLBACK_URL: "http://{{ include "common.names.fullname" . }}.{{ $namespace }}.svc.{{ $domain }}:{{ .Values.service.ports.grafana }}/"
21+
{{- end }}
22+
{{- if .Values.plugins }}
23+
GF_INSTALL_PLUGINS: {{ .Values.plugins | quote }}
24+
{{- else }}
25+
GF_INSTALL_PLUGINS: ""
26+
{{- end }}
27+
GF_PATHS_PLUGINS: "/opt/drycc/grafana/data/plugins"
28+
GF_AUTH_LDAP_ENABLED: {{ .Values.ldap.enabled | quote }}
29+
GF_AUTH_LDAP_CONFIG_FILE: "/opt/drycc/grafana/conf/ldap.toml"
30+
GF_AUTH_LDAP_ALLOW_SIGN_UP: {{ .Values.ldap.allowSignUp | quote }}
31+
GF_PATHS_PROVISIONING: "/opt/drycc/grafana/conf/provisioning"
32+
GF_PATHS_CONFIG: "/opt/drycc/grafana/conf/grafana.ini"
33+
GF_PATHS_DATA: "/opt/drycc/grafana/data"
34+
GF_PATHS_LOGS: "/opt/drycc/grafana/logs"
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{{- if and .Values.dashboardsProvider.enabled (not .Values.dashboardsProvider.configMapName) }}
2+
apiVersion: v1
3+
kind: ConfigMap
4+
metadata:
5+
name: {{ include "common.names.fullname" . }}-provider
6+
namespace: {{ .Release.Namespace | quote }}
7+
labels: {{- include "common.labels.standard" . | nindent 4 }}
8+
{{- if .Values.commonLabels }}
9+
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
10+
{{- end }}
11+
app.kubernetes.io/component: grafana
12+
{{- if .Values.commonAnnotations }}
13+
annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
14+
{{- end }}
15+
data:
16+
default-provider.yaml: |-
17+
apiVersion: 1
18+
19+
providers:
20+
# <string> an unique provider name
21+
- name: 'default-provider'
22+
# <int> org id. will default to orgId 1 if not specified
23+
orgId: 1
24+
# <string, required> name of the dashboard folder. Required
25+
folder: dashboards
26+
# <string> folder UID. will be automatically generated if not specified
27+
folderUid: ''
28+
# <string, required> provider type. Required
29+
type: file
30+
# <bool> disable dashboard deletion
31+
disableDeletion: false
32+
# <bool> enable dashboard editing
33+
editable: true
34+
# <int> how often Grafana will scan for changed dashboards
35+
updateIntervalSeconds: 10
36+
options:
37+
# <string, required> path to dashboard files on disk. Required
38+
path: /opt/drycc/grafana/dashboards
39+
# <bool> enable folders creation for dashboards
40+
#foldersFromFilesStructure: true
41+
{{- end }}

0 commit comments

Comments
 (0)