diff --git a/grafana_dashboards/grafana/dashboard.py b/grafana_dashboards/grafana/dashboard.py index aed9990..7775226 100644 --- a/grafana_dashboards/grafana/dashboard.py +++ b/grafana_dashboards/grafana/dashboard.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +import hashlib import json from requests import exceptions @@ -22,9 +23,13 @@ from grafana_dashboards.grafana import utils class Dashboard(object): def __init__(self, url, session): - self.url = utils.urljoin(url, 'api/dashboards/db/') + self.db_url = utils.urljoin(url, 'api/dashboards/db/') + self.uid_url = utils.urljoin(url, 'api/dashboards/uid/') self.session = session + def dashboard_uid(self, name): + return hashlib.sha256(name.encode('utf-8')).hexdigest()[0:10] + def create(self, name, data, overwrite=False, folder_id=0): """Create a new dashboard @@ -41,6 +46,8 @@ class Dashboard(object): :raises Exception: if dashboard already exists """ + uid = self.dashboard_uid(name) + data['uid'] = uid dashboard = { 'dashboard': data, 'folderId': folder_id, @@ -50,7 +57,7 @@ class Dashboard(object): raise Exception('dashboard[%s] already exists' % name) res = self.session.post( - self.url, data=json.dumps(dashboard)) + self.db_url, data=json.dumps(dashboard)) res.raise_for_status() if not self.is_dashboard(name): raise Exception('dashboard[%s] does not exist' % name) @@ -64,10 +71,12 @@ class Dashboard(object): :raises Exception: if dashboard failed to delete """ - url = utils.urljoin(self.url, name) + uid = self.dashboard_uid(name) + url = utils.urljoin(self.uid_url, uid) self.session.delete(url) if self.is_dashboard(name): - raise Exception('dashboard[%s] failed to delete' % name) + raise Exception( + 'dashboard %s (uid: %s) failed to delete' % (name, uid)) def get(self, name): """Get a dashboard @@ -78,14 +87,15 @@ class Dashboard(object): :rtype: dict or None """ - url = utils.urljoin(self.url, name) + url = utils.urljoin(self.uid_url, self.dashboard_uid(name)) try: res = self.session.get(url) res.raise_for_status() except exceptions.HTTPError: return None - return res.json() + json = res.json() + return json if json else None def is_dashboard(self, name): """Check if a dashboard exists @@ -98,6 +108,4 @@ class Dashboard(object): """ res = self.get(name) - if res and res['meta']['slug'] == name: - return True - return False + return True if res else False diff --git a/tests/test_grafana.py b/tests/test_grafana.py index b837e3f..749f2fd 100644 --- a/tests/test_grafana.py +++ b/tests/test_grafana.py @@ -13,6 +13,7 @@ # under the License. import requests_mock +import re from testtools import TestCase from grafana_dashboards.grafana import Grafana @@ -39,6 +40,8 @@ DASHBOARD_NOT_FOUND = { "message": "Dashboard not found" } +UID_URL_MATCHER = re.compile(r'api/dashboards/uid/[a-fA-F\d]{10}') + class TestCaseGrafana(TestCase): @@ -61,14 +64,12 @@ class TestCaseGrafana(TestCase): @requests_mock.Mocker() def test_create_dashboard_new(self, mock_requests): def post_callback(request, context): - mock_requests.get( - '/api/dashboards/db/new-dashboard', json=CREATE_NEW_DASHBOARD) + mock_requests.get(UID_URL_MATCHER, json=CREATE_NEW_DASHBOARD) return True mock_requests.post('/api/dashboards/db/', json=post_callback) mock_requests.get( - '/api/dashboards/db/new-dashboard', json=DASHBOARD_NOT_FOUND, - status_code=404) + UID_URL_MATCHER, json=DASHBOARD_NOT_FOUND, status_code=404) data = { "dashboard": { @@ -83,8 +84,7 @@ class TestCaseGrafana(TestCase): @requests_mock.Mocker() def test_create_dashboard_overwrite(self, mock_requests): mock_requests.post('/api/dashboards/db/') - mock_requests.get( - '/api/dashboards/db/new-dashboard', json=CREATE_NEW_DASHBOARD) + mock_requests.get(UID_URL_MATCHER, json=CREATE_NEW_DASHBOARD) data = { "dashboard": { "title": "New dashboard", @@ -98,8 +98,7 @@ class TestCaseGrafana(TestCase): @requests_mock.Mocker() def test_create_dashboard_existing(self, mock_requests): mock_requests.post('/api/dashboards/db/') - mock_requests.get( - '/api/dashboards/db/new-dashboard', json=CREATE_NEW_DASHBOARD) + mock_requests.get(UID_URL_MATCHER, json=CREATE_NEW_DASHBOARD) data = { "dashboard": { "title": "New dashboard", @@ -114,10 +113,9 @@ class TestCaseGrafana(TestCase): @requests_mock.Mocker() def test_delete_dashboard(self, mock_requests): - mock_requests.delete('/api/dashboards/db/new-dashboard') + mock_requests.delete(UID_URL_MATCHER) mock_requests.get( - '/api/dashboards/db/new-dashboard', json=DASHBOARD_NOT_FOUND, - status_code=404) + UID_URL_MATCHER, json=DASHBOARD_NOT_FOUND, status_code=404) self.grafana.dashboard.delete('new-dashboard') @requests_mock.Mocker()