Add delete command to CLI
Add the ability to delete dashboards based on the provided yaml file. We also removed the assert_dashboard_exists function, as it didn't really save us code. Change-Id: I417a72fcc5252b36cadfe8881b4f5ca6acb7c753 Signed-off-by: Paul Belanger <pabelanger@redhat.com>
This commit is contained in:
parent
3a32d511bb
commit
fd76590e4b
@ -26,6 +26,13 @@ OPTIONS
|
||||
COMMANDS
|
||||
========
|
||||
|
||||
Delete Command
|
||||
--------------
|
||||
|
||||
``grafana-dashboard`` [options] delete <path>
|
||||
|
||||
Delete each specified dashboard from the parsed yaml files.
|
||||
|
||||
Update Command
|
||||
--------------
|
||||
|
||||
|
@ -54,6 +54,14 @@ class Builder(object):
|
||||
url = 'http://localhost:8080'
|
||||
return Grafana(url, key)
|
||||
|
||||
def delete_dashboard(self, path):
|
||||
self.load_files(path)
|
||||
dashboards = self.parser.data.get('dashboard', {})
|
||||
for name in dashboards:
|
||||
LOG.debug('Deleting grafana dashboard %s', name)
|
||||
self.grafana.dashboard.delete(name)
|
||||
self.cache.set(name, '')
|
||||
|
||||
def load_files(self, path):
|
||||
files_to_process = []
|
||||
if os.path.isdir(path):
|
||||
|
@ -27,6 +27,11 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
class Client(object):
|
||||
|
||||
def delete(self):
|
||||
LOG.info('Deleting dashboards in %s', self.args.path)
|
||||
builder = Builder(self.config)
|
||||
builder.delete_dashboard(self.args.path)
|
||||
|
||||
def main(self):
|
||||
self.parse_arguments()
|
||||
self.read_config()
|
||||
@ -51,6 +56,12 @@ class Client(object):
|
||||
subparsers = parser.add_subparsers(
|
||||
title='commands')
|
||||
|
||||
parser_delete = subparsers.add_parser('delete')
|
||||
parser_delete.add_argument(
|
||||
'path', help='colon-separated list of paths to YAML files or'
|
||||
' directories')
|
||||
parser_delete.set_defaults(func=self.delete)
|
||||
|
||||
parser_update = subparsers.add_parser('update')
|
||||
parser_update.add_argument(
|
||||
'path', help='colon-separated list of paths to YAML files or'
|
||||
@ -87,6 +98,7 @@ class Client(object):
|
||||
def validate(self):
|
||||
LOG.info('Validating dashboards in %s', self.args.path)
|
||||
builder = Builder(self.config)
|
||||
|
||||
try:
|
||||
builder.load_files(self.args.path)
|
||||
print('SUCCESS!')
|
||||
|
@ -28,17 +28,6 @@ class Dashboard(object):
|
||||
self.url = url
|
||||
self.session = session
|
||||
|
||||
def assert_dashboard_exists(self, name):
|
||||
"""Raise an exception if dashboard does not exist
|
||||
|
||||
:param name: URL friendly title of the dashboard
|
||||
:type name: str
|
||||
:raises Exception: if dashboard does not exist
|
||||
|
||||
"""
|
||||
if not self.is_dashboard(name):
|
||||
raise Exception('dashboard[%s] does not exist' % name)
|
||||
|
||||
def create(self, name, data, overwrite=False):
|
||||
"""Create a new dashboard
|
||||
|
||||
@ -62,9 +51,23 @@ class Dashboard(object):
|
||||
|
||||
res = self.session.post(
|
||||
self.url, data=json.dumps(dashboard))
|
||||
|
||||
res.raise_for_status()
|
||||
self.assert_dashboard_exists(name)
|
||||
if not self.is_dashboard(name):
|
||||
raise Exception('dashboard[%s] does not exist' % name)
|
||||
|
||||
def delete(self, name):
|
||||
"""Delete a dashboard
|
||||
|
||||
:param name: URL friendly title of the dashboard
|
||||
:type name: str
|
||||
|
||||
:raises Exception: if dashboard failed to delete
|
||||
|
||||
"""
|
||||
url = urljoin(self.url, name)
|
||||
self.session.delete(url)
|
||||
if self.is_dashboard(name):
|
||||
raise Exception('dashboard[%s] failed to delete' % name)
|
||||
|
||||
def get(self, name):
|
||||
"""Get a dashboard
|
||||
|
34
tests/cmd/test_delete.py
Normal file
34
tests/cmd/test_delete.py
Normal file
@ -0,0 +1,34 @@
|
||||
# Copyright 2015 Red Hat, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import re
|
||||
|
||||
from testtools import matchers
|
||||
|
||||
from tests.cmd.base import TestCase
|
||||
|
||||
|
||||
class TestCaseDelete(TestCase):
|
||||
|
||||
def test_delete_without_path(self):
|
||||
required = [
|
||||
'.*?^usage: grafana-dashboards delete \[-h\] path',
|
||||
'.*?^grafana-dashboards delete: error: (too few arguments|the '
|
||||
'following arguments are required: path)',
|
||||
]
|
||||
stdout, stderr = self.shell('delete', exitcodes=[2])
|
||||
for r in required:
|
||||
self.assertThat(
|
||||
(stdout + stderr),
|
||||
matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE))
|
@ -26,17 +26,34 @@ class TestCaseBuilder(TestCase):
|
||||
super(TestCaseBuilder, self).setUp()
|
||||
self.builder = builder.Builder(self.config)
|
||||
|
||||
@mock.patch('grafana_dashboards.grafana.Dashboard.create')
|
||||
def test_update_dashboard(self, mock_grafana):
|
||||
dashboard = os.path.join(
|
||||
@mock.patch('grafana_dashboards.grafana.Dashboard.delete')
|
||||
def test_delete_dashboard(self, mock_grafana):
|
||||
path = os.path.join(
|
||||
os.path.dirname(__file__), 'fixtures/builder/dashboard-0001.yaml')
|
||||
|
||||
self.builder.update_dashboard(dashboard)
|
||||
# Cache is empty, so we should update grafana.
|
||||
# Create a dashboard.
|
||||
self._update_dashboard(path)
|
||||
# Create a new builder to avoid duplicate dashboards.
|
||||
builder2 = builder.Builder(self.config)
|
||||
# Delete same dashboard, ensure we delete it from grafana.
|
||||
builder2.delete_dashboard(path)
|
||||
self.assertEqual(mock_grafana.call_count, 1)
|
||||
|
||||
@mock.patch('grafana_dashboards.grafana.Dashboard.create')
|
||||
def test_update_dashboard(self, mock_grafana):
|
||||
path = os.path.join(
|
||||
os.path.dirname(__file__), 'fixtures/builder/dashboard-0001.yaml')
|
||||
|
||||
# Create a dashboard.
|
||||
self._update_dashboard(path)
|
||||
# Create a new builder to avoid duplicate dashboards.
|
||||
builder2 = builder.Builder(self.config)
|
||||
# Update again with same dashboard, ensure we don't update grafana.
|
||||
builder2.update_dashboard(dashboard)
|
||||
builder2.update_dashboard(path)
|
||||
self.assertEqual(mock_grafana.call_count, 0)
|
||||
|
||||
@mock.patch('grafana_dashboards.grafana.Dashboard.create')
|
||||
def _update_dashboard(self, path, mock_grafana):
|
||||
self.builder.update_dashboard(path)
|
||||
# Cache is empty, so we should update grafana.
|
||||
self.assertEqual(mock_grafana.call_count, 1)
|
||||
|
@ -58,15 +58,6 @@ class TestCaseGrafana(TestCase):
|
||||
self.assertIn('Authorization', headers)
|
||||
self.assertEqual(headers['Authorization'], 'Bearer %s' % apikey)
|
||||
|
||||
@requests_mock.Mocker()
|
||||
def test_assert_dashboard_exists_failure(self, mock_requests):
|
||||
mock_requests.get(
|
||||
'/api/dashboards/db/new-dashboard', json=DASHBOARD_NOT_FOUND,
|
||||
status_code=404)
|
||||
self.assertRaises(
|
||||
Exception, self.grafana.dashboard.assert_dashboard_exists,
|
||||
'new-dashboard')
|
||||
|
||||
@requests_mock.Mocker()
|
||||
def test_create_dashboard_new(self, mock_requests):
|
||||
def post_callback(request, context):
|
||||
@ -120,3 +111,19 @@ class TestCaseGrafana(TestCase):
|
||||
data=data['dashboard'], overwrite=False)
|
||||
|
||||
self.assertEqual(mock_requests.call_count, 1)
|
||||
|
||||
@requests_mock.Mocker()
|
||||
def test_delete_dashboard(self, mock_requests):
|
||||
mock_requests.delete('/api/dashboards/db/new-dashboard')
|
||||
mock_requests.get(
|
||||
'/api/dashboards/db/new-dashboard', json=DASHBOARD_NOT_FOUND,
|
||||
status_code=404)
|
||||
self.grafana.dashboard.delete('new-dashboard')
|
||||
|
||||
@requests_mock.Mocker()
|
||||
def test_delete_dashboard_failure(self, mock_requests):
|
||||
mock_requests.delete('/api/dashboards/db/new-dashboard')
|
||||
mock_requests.get(
|
||||
'/api/dashboards/db/new-dashboard', json=CREATE_NEW_DASHBOARD)
|
||||
self.assertRaises(
|
||||
Exception, self.grafana.dashboard.delete, name='new-dashboard')
|
||||
|
Loading…
x
Reference in New Issue
Block a user