Skip to content

Commit 07c0a29

Browse files
authored
Add support for putting dashboards in folders. (#232)
* Add support for putting dashboards in folders. Signed-off-by: Tom Wilkie <[email protected]> * Lint Signed-off-by: Tom Wilkie <[email protected]> * Refactor all the Grafana jsonnet. - separate files for then handling of dashboards, datasources, config, deployments etc. - put it in a separate repo so it can be used independantly. : Signed-off-by: Tom Wilkie <[email protected]> * Newlines at end of files. Signed-off-by: Tom Wilkie <[email protected]> * lint Signed-off-by: Tom Wilkie <[email protected]> * Remove old files (forgot to remove before). Signed-off-by: Tom Wilkie <[email protected]> * Make dashboard config map sharding non-optional: its needed for the default install now anyway. Signed-off-by: Tom Wilkie <[email protected]>
1 parent 610b00d commit 07c0a29

File tree

9 files changed

+225
-173
lines changed

9 files changed

+225
-173
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
grafana_config:: {
3+
sections: {
4+
'auth.anonymous': {
5+
enabled: true,
6+
org_role: 'Admin',
7+
},
8+
server: {
9+
http_port: 80,
10+
root_url: $._config.grafana_root_url,
11+
},
12+
analytics: {
13+
reporting_enabled: false,
14+
},
15+
users: {
16+
default_theme: 'light',
17+
},
18+
explore+: {
19+
enabled: true,
20+
},
21+
},
22+
},
23+
24+
local configMap = $.core.v1.configMap,
25+
26+
grafana_config_map:
27+
configMap.new('grafana-config') +
28+
configMap.withData({ 'grafana.ini': std.manifestIni($.grafana_config) }),
29+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
local configMap = $.core.v1.configMap,
3+
4+
_config+:: {
5+
// Shard dashboards across multiple config maps to overcome annotation
6+
// lenght limits.
7+
dashboard_config_maps: 8,
8+
},
9+
10+
// Extension point for you to add your own dashboards.
11+
dashboards+:: {},
12+
grafana_dashboards+:: {},
13+
grafanaDashboards+:: $.dashboards + $.grafana_dashboards,
14+
dashboardsByFolder+:: {},
15+
16+
local materialise_config_map(config_map_name, dashboards) =
17+
configMap.new(config_map_name) +
18+
configMap.withDataMixin({
19+
[name]: std.toString(dashboards[name])
20+
for name in std.objectFields(dashboards)
21+
}) +
22+
configMap.mixin.metadata.withLabels($._config.grafana_dashboard_labels),
23+
24+
// When sharding is enabled, this is a map of config maps, each map named
25+
// "dashboard-0" ... "dashboard-N" and containing dashboards whose name
26+
// hashes to that shard.
27+
dashboards_config_maps: {
28+
['dashboard-%d' % shard]:
29+
materialise_config_map('dashboards-%d' % shard, {
30+
[name]: $.grafanaDashboards[name]
31+
for name in std.objectFields($.grafanaDashboards)
32+
if std.codepoint(std.md5(name)[1]) % $._config.dashboard_config_maps == shard
33+
})
34+
for shard in std.range(0, $._config.dashboard_config_maps - 1)
35+
},
36+
37+
// A map of config maps, one per folder, for dashboards in folders.
38+
dashboard_folders_config_maps: {
39+
['dashboard-%s' % std.asciiLower(folder)]:
40+
materialise_config_map(
41+
'dashboards-%s' % std.asciiLower(folder),
42+
$.dashboardsByFolder[folder]
43+
)
44+
for folder in std.objectFields($.dashboardsByFolder)
45+
},
46+
47+
// Config map containing the dashboard provisioning YAML, telling
48+
// Grafana where to find the dashboard JSONs.
49+
grafana_dashboard_provisioning_config_map:
50+
configMap.new('grafana-dashboard-provisioning') +
51+
configMap.withData({
52+
'dashboards.yml': $.util.manifestYaml({
53+
apiVersion: 1,
54+
providers: [
55+
{
56+
name: 'dashboards',
57+
orgId: 1,
58+
folder: '',
59+
type: 'file',
60+
disableDeletion: true,
61+
editable: false,
62+
options: {
63+
path: '/grafana/dashboards',
64+
},
65+
},
66+
] + [
67+
{
68+
name: 'dashboards-%s' % std.asciiLower(folder),
69+
orgId: 1,
70+
folder: folder,
71+
type: 'file',
72+
disableDeletion: true,
73+
editable: false,
74+
options: {
75+
path: '/grafana/dashboard-folders/%s' % std.asciiLower(folder),
76+
},
77+
}
78+
for folder in std.objectFields($.dashboardsByFolder)
79+
],
80+
}),
81+
}),
82+
}

prometheus-ksonnet/lib/grafana-configmaps.libsonnet renamed to prometheus-ksonnet/grafana/datasources.libsonnet

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,6 @@
11
{
22
local configMap = $.core.v1.configMap,
33

4-
// Extension point for you to add your own dashboards.
5-
dashboards+:: {},
6-
grafana_dashboards+:: {},
7-
grafanaDashboards+:: $.dashboards + $.grafana_dashboards,
8-
9-
dashboards_config_map:
10-
if $._config.dashboard_config_maps > 0
11-
then {}
12-
else
13-
configMap.new('dashboards') +
14-
configMap.withDataMixin({
15-
[name]: std.toString($.grafanaDashboards[name])
16-
for name in std.objectFields($.grafanaDashboards)
17-
}) +
18-
configMap.mixin.metadata.withLabels($._config.grafana_dashboard_labels),
19-
20-
dashboards_config_maps: {
21-
['dashboard-%d' % shard]:
22-
configMap.new('dashboards-%d' % shard) +
23-
configMap.withDataMixin({
24-
[name]: std.toString($.grafanaDashboards[name])
25-
for name in std.objectFields($.grafanaDashboards)
26-
if std.codepoint(std.md5(name)[1]) % $._config.dashboard_config_maps == shard
27-
}) +
28-
configMap.mixin.metadata.withLabels($._config.grafana_dashboard_labels)
29-
for shard in std.range(0, $._config.dashboard_config_maps - 1)
30-
},
31-
324
/*
335
to add datasources:
346
@@ -109,42 +81,4 @@
10981
for name in std.objectFields($.grafanaDatasources)
11082
}) +
11183
configMap.mixin.metadata.withLabels($._config.grafana_datasource_labels),
112-
113-
grafanaNotificationChannels+:: {},
114-
115-
/*
116-
to add a notification channel:
117-
118-
grafanaNotificationChannels+:: {
119-
'my-notification-channel.yml': grafana_add_notification_channel('my-email', 'email', 'my-email', 1, true, true, '1h', false, {addresses: '[email protected]'}),
120-
}
121-
See https://grafana.com/docs/administration/provisioning/#alert-notification-channels
122-
*/
123-
124-
grafana_add_notification_channel(name, type, uid, org_id, settings, is_default=false, send_reminders=true, frequency='1h', disable_resolve_message=false)::
125-
$.util.manifestYaml({
126-
notifiers: [
127-
{
128-
name: name,
129-
type: type,
130-
uid: uid,
131-
org_id: org_id,
132-
is_default: is_default,
133-
send_reminders: send_reminders,
134-
frequency: frequency,
135-
disable_resolve_message: disable_resolve_message,
136-
settings: settings,
137-
},
138-
],
139-
}),
140-
141-
notification_channel_config_map:
142-
configMap.new('grafana-notification-channels') +
143-
configMap.withDataMixin({
144-
[name]: std.toString($.grafanaNotificationChannels[name])
145-
for name in std.objectFields($.grafanaNotificationChannels)
146-
}) +
147-
configMap.mixin.metadata.withLabels($._config.grafana_notification_channel_labels),
148-
149-
grafana_plugins+:: [],
15084
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
grafanaDatasources+:: {
3+
'prometheus.yml': $.grafana_datasource('prometheus',
4+
'http://prometheus.%(namespace)s.svc.%(cluster_dns_suffix)s%(prometheus_web_route_prefix)s' % $._config,
5+
default=true),
6+
},
7+
8+
_config+:: {
9+
// Grafana config options.
10+
grafana_root_url: 'http://nginx.%(namespace)s.svc.%(cluster_dns_suffix)s/grafana' % self,
11+
grafana_provisioning_dir: '/etc/grafana/provisioning',
12+
13+
// Optionally shard dashboards into multiple config maps.
14+
// Set to the number of desired config maps. 0 to disable.
15+
dashboard_config_maps: 0,
16+
17+
// Optionally add labels to grafana config maps.
18+
grafana_dashboard_labels: {},
19+
grafana_datasource_labels: {},
20+
grafana_notification_channel_labels: {},
21+
},
22+
23+
grafana_plugins+:: [],
24+
25+
local container = $.core.v1.container,
26+
27+
grafana_container::
28+
container.new('grafana', $._images.grafana) +
29+
container.withPorts($.core.v1.containerPort.new('grafana', 80)) +
30+
container.withEnvMap({
31+
GF_PATHS_CONFIG: '/etc/grafana-config/grafana.ini',
32+
GF_INSTALL_PLUGINS: std.join(',', $.grafana_plugins),
33+
}) +
34+
$.util.resourcesRequests('10m', '40Mi'),
35+
36+
local deployment = $.apps.v1.deployment,
37+
38+
grafana_deployment:
39+
deployment.new('grafana', 1, [$.grafana_container]) +
40+
deployment.mixin.spec.template.spec.securityContext.withRunAsUser(0) +
41+
$.util.configVolumeMount('grafana-config', '/etc/grafana-config') +
42+
$.util.configVolumeMount('grafana-dashboard-provisioning', '%(grafana_provisioning_dir)s/dashboards' % $._config) +
43+
$.util.configVolumeMount('grafana-datasources', '%(grafana_provisioning_dir)s/datasources' % $._config) +
44+
$.util.configVolumeMount('grafana-notification-channels', '%(grafana_provisioning_dir)s/notifiers' % $._config) +
45+
(
46+
// Mount _all_ the dashboard config map shards.
47+
std.foldr(
48+
function(m, acc) m + acc,
49+
[
50+
$.util.configVolumeMount('dashboards-%d' % shard, '/grafana/dashboards/%d' % shard)
51+
for shard in std.range(0, $._config.dashboard_config_maps - 1)
52+
],
53+
{}
54+
)
55+
) + (
56+
// Add config map mounts for each folder for dashboards.
57+
std.foldr(
58+
function(m, acc) m + acc,
59+
[
60+
$.util.configVolumeMount('dashboards-%s' % std.asciiLower(folder), '/grafana/dashboard-folders/%s' % std.asciiLower(folder))
61+
for folder in std.objectFields($.dashboardsByFolder)
62+
],
63+
{}
64+
)
65+
) +
66+
$.util.podPriority('critical'),
67+
68+
grafana_service:
69+
$.util.serviceFor($.grafana_deployment),
70+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(import 'config.libsonnet') +
2+
(import 'dashboards.libsonnet') +
3+
(import 'datasources.libsonnet') +
4+
(import 'deployment.libsonnet') +
5+
(import 'notifications.libsonnet')
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
local configMap = $.core.v1.configMap,
3+
4+
/*
5+
to add a notification channel:
6+
7+
grafanaNotificationChannels+:: {
8+
'my-notification-channel.yml': grafana_add_notification_channel('my-email', 'email', 'my-email', 1, true, true, '1h', false, {addresses: '[email protected]'}),
9+
}
10+
See https://grafana.com/docs/administration/provisioning/#alert-notification-channels
11+
*/
12+
grafanaNotificationChannels+:: {},
13+
14+
grafana_add_notification_channel(name, type, uid, org_id, settings, is_default=false, send_reminders=true, frequency='1h', disable_resolve_message=false)::
15+
$.util.manifestYaml({
16+
notifiers: [
17+
{
18+
name: name,
19+
type: type,
20+
uid: uid,
21+
org_id: org_id,
22+
is_default: is_default,
23+
send_reminders: send_reminders,
24+
frequency: frequency,
25+
disable_resolve_message: disable_resolve_message,
26+
settings: settings,
27+
},
28+
],
29+
}),
30+
31+
notification_channel_config_map:
32+
configMap.new('grafana-notification-channels') +
33+
configMap.withDataMixin({
34+
[name]: std.toString($.grafanaNotificationChannels[name])
35+
for name in std.objectFields($.grafanaNotificationChannels)
36+
}) +
37+
configMap.mixin.metadata.withLabels($._config.grafana_notification_channel_labels),
38+
}

prometheus-ksonnet/lib/config.libsonnet

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,6 @@
7878
slack_url: 'http://slack',
7979
slack_channel: 'general',
8080

81-
// Grafana config options.
82-
grafana_root_url: 'http://nginx.%(namespace)s.svc.%(cluster_dns_suffix)s/grafana' % self,
83-
grafana_provisioning_dir: '/etc/grafana/provisioning',
84-
8581
// Node exporter options.
8682
node_exporter_mount_root: true,
8783

@@ -106,14 +102,5 @@
106102

107103
// oauth2-proxy
108104
oauth_enabled: false,
109-
110-
// Optionally shard dashboards into multiple config maps.
111-
// Set to the number of desired config maps. 0 to disable.
112-
dashboard_config_maps: 0,
113-
114-
// Optionally add labels to grafana config maps.
115-
grafana_dashboard_labels: {},
116-
grafana_datasource_labels: {},
117-
grafana_notification_channel_labels: {},
118105
},
119106
}

0 commit comments

Comments
 (0)