Merge lp:~jacekn/charms/trusty/grafana/layer-grafana into lp:~canonical-is-sa/charms/trusty/grafana/layer-grafana

Proposed by Jacek Nykis
Status: Merged
Merged at revision: 40
Proposed branch: lp:~jacekn/charms/trusty/grafana/layer-grafana
Merge into: lp:~canonical-is-sa/charms/trusty/grafana/layer-grafana
Diff against target: 180 lines (+128/-1)
4 files modified
config.yaml (+13/-1)
files/dashboards_backup (+41/-0)
reactive/grafana.py (+69/-0)
templates/juju-dashboards-backup.j2 (+5/-0)
To merge this branch: bzr merge lp:~jacekn/charms/trusty/grafana/layer-grafana
Reviewer Review Type Date Requested Status
Canonical IS SAs Pending
Review via email: mp+300088@code.launchpad.net

Description of the change

Added dashboards backup support

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'config.yaml'
--- config.yaml 2016-05-06 20:42:51 +0000
+++ config.yaml 2016-07-14 15:09:02 +0000
@@ -78,4 +78,16 @@
78 default: ""78 default: ""
79 type: string79 type: string
80 description: |80 description: |
81 Grafana admin password. Default, pwgen(16) random password81 Grafana admin password. Default, pwgen(16) random password.
82 See also README.md for instructions how to retrieve automatically
83 generated password
84 dashboards_backup_schedule:
85 default: ""
86 type: string
87 description: |
88 Cron schedule for dashboards backups
89 dashboards_backup_dir:
90 default: "/srv/backups"
91 type: string
92 description: |
93 Location where to put dashboard dumps
8294
=== added directory 'files'
=== added file 'files/dashboards_backup'
--- files/dashboards_backup 1970-01-01 00:00:00 +0000
+++ files/dashboards_backup 2016-07-14 15:09:02 +0000
@@ -0,0 +1,41 @@
1#!/usr/bin/env python
2
3import os
4import argparse
5import requests
6import string
7import datetime
8
9
10def get_backup_filename(directory, org_name, uri):
11 valid_chars = '-_(){}{}'.format(string.ascii_letters, string.digits)
12 dashboard = uri.split('/')[1]
13 filename = ''.join(c if c in valid_chars else '_' for c in dashboard)
14 filename += '.json.' + datetime.datetime.utcnow().strftime('%Y%m%d_%H%M%S')
15 org_name = ''.join(c if c in valid_chars else '_' for c in org_name)
16 return os.path.join(directory, org_name, filename)
17
18
19def main(args):
20 base_url = 'http://localhost:3000/api/'
21 for key in args.api_keys:
22 headers = {'Authorization': 'Bearer {}'.format(key)}
23 org_name = requests.get(base_url+'org', headers=headers).json()['name']
24 r = requests.get(base_url+'search', headers=headers).json()
25 uris = [i['uri'] for i in r]
26 for d in uris:
27 backup_file = get_backup_filename(args.directory, org_name, d)
28 if not os.path.isdir(os.path.dirname(backup_file)):
29 os.mkdir(os.path.dirname(backup_file))
30 dashboard = requests.get(base_url+'dashboards/'+d, headers=headers).json()['dashboard']
31 with open(backup_file, 'w') as f:
32 f.write(str(dashboard))
33
34
35if __name__ == '__main__':
36 parser = argparse.ArgumentParser(description='Back up grafana dashboards to disk')
37 parser.add_argument('-d', '--directory', help='Directory where to store backups',
38 default='/srv/backups')
39 parser.add_argument('api_keys', help='List of API keys to use for backups', nargs='+')
40 args = parser.parse_args()
41 main(args)
042
=== modified file 'reactive/grafana.py'
--- reactive/grafana.py 2016-05-09 16:26:12 +0000
+++ reactive/grafana.py 2016-07-14 15:09:02 +0000
@@ -4,7 +4,9 @@
4import hashlib4import hashlib
5import datetime5import datetime
6import requests6import requests
7import json
7import subprocess8import subprocess
9import base64
8from time import sleep10from time import sleep
9from charmhelpers import fetch11from charmhelpers import fetch
10from charmhelpers.core import host, hookenv, unitdata12from charmhelpers.core import host, hookenv, unitdata
@@ -33,6 +35,8 @@
33GRAFANA_INI = '/etc/grafana/grafana.ini'35GRAFANA_INI = '/etc/grafana/grafana.ini'
34GRAFANA_INI_TMPL = 'grafana.ini.j2'36GRAFANA_INI_TMPL = 'grafana.ini.j2'
35GRAFANA_DEPS = ['libfontconfig1']37GRAFANA_DEPS = ['libfontconfig1']
38DASHBOARDS_BACKUP_CRON = '/etc/cron.d/juju-dashboards-backup'
39DASHBOARDS_BACKUP_CRON_TMPL = 'juju-dashboards-backup.j2'
3640
3741
38def install_packages():42def install_packages():
@@ -64,6 +68,57 @@
64 kv.set('grafana.port', new_port)68 kv.set('grafana.port', new_port)
6569
6670
71def select_query(query, params=None):
72 conn = sqlite3.connect('/var/lib/grafana/grafana.db', timeout=30)
73 cur = conn.cursor()
74 if params:
75 return cur.execute(query, params).fetchall()
76 else:
77 return cur.execute(query).fetchall()
78
79
80def insert_query(query, params=None):
81 conn = sqlite3.connect('/var/lib/grafana/grafana.db', timeout=30)
82 cur = conn.cursor()
83 if params:
84 cur.execute(query, params)
85 else:
86 cur.execute(query)
87 conn.commit()
88
89
90def add_backup_api_keys():
91 name = 'juju-dashboards-backup'
92 passwd = host.pwgen(32)
93 hpasswd = hpwgen(passwd, name)
94 hookenv.log('Adding backup API keys for all organizations...')
95 for i in select_query('SELECT id FROM org'):
96 org_id = i[0]
97 if select_query('SELECT id FROM api_key WHERE org_id=? AND name=?', [org_id, name]):
98 hookenv.log('API key {} in org {} already exists, skipping'.format(name, org_id))
99 continue
100 j = {'n': name,
101 'k': passwd,
102 'id': org_id}
103 encoded = base64.b64encode(json.dumps(j).encode('ascii')).decode('ascii')
104 stmt = 'INSERT INTO api_key (org_id, name, key, role, created, updated)' + \
105 ' VALUES (?,?,?,"Viewer",?,?)'
106 dtime = datetime.datetime.today().strftime("%F %T")
107 params = [org_id, name, hpasswd, dtime, dtime]
108 insert_query(stmt, params)
109
110 kv = unitdata.kv()
111 backup_keys = kv.get('grafana.dashboards_backup_keys', False)
112 if not backup_keys:
113 backup_keys = [encoded]
114 else:
115 backup_keys.append(encoded)
116 kv.set('grafana.dashboards_backup_keys', backup_keys)
117
118 kv = unitdata.kv()
119 return kv.get('grafana.dashboards_backup_keys')
120
121
67@when_not('grafana.started')122@when_not('grafana.started')
68def setup_grafana():123def setup_grafana():
69 hookenv.status_set('maintenance', 'Configuring grafana')124 hookenv.status_set('maintenance', 'Configuring grafana')
@@ -76,6 +131,20 @@
76 owner='root', group='grafana',131 owner='root', group='grafana',
77 perms=0o640,132 perms=0o640,
78 )133 )
134 if config.get('dashboards_backup_schedule', False):
135 hookenv.log('Setting up dashboards backup job...')
136 host.rsync('files/dashboards_backup', '/usr/local/bin/dashboards_backup')
137 host.mkdir(config.get('dashboards_backup_dir'))
138 settings = {'schedule': config.get('dashboards_backup_schedule'),
139 'directory': config.get('dashboards_backup_dir'),
140 'backup_keys': ' '.join(add_backup_api_keys())}
141 render(source=DASHBOARDS_BACKUP_CRON_TMPL,
142 target=DASHBOARDS_BACKUP_CRON,
143 context=settings,
144 owner='root', group='root',
145 perms=0o640,
146 )
147 # copy script, create cronjob, ensure directory exists
79 check_ports(config.get('port'))148 check_ports(config.get('port'))
80 set_state('grafana.start')149 set_state('grafana.start')
81 hookenv.status_set('active', 'Ready')150 hookenv.status_set('active', 'Ready')
82151
=== added file 'templates/juju-dashboards-backup.j2'
--- templates/juju-dashboards-backup.j2 1970-01-01 00:00:00 +0000
+++ templates/juju-dashboards-backup.j2 2016-07-14 15:09:02 +0000
@@ -0,0 +1,5 @@
1#
2# Please do not edit. Juju will overwrite it.
3#
4{{ schedule }} root /usr/local/bin/dashboards_backup -d {{ directory }} {{ backup_keys }}
5

Subscribers

People subscribed via source and target branches

to all changes: