Merge "Add validate command"

This commit is contained in:
Jenkins 2015-10-03 18:34:43 +00:00 committed by Gerrit Code Review
commit ff3a9f3b5e
11 changed files with 174 additions and 57 deletions

View File

@ -45,8 +45,11 @@ class Builder(object):
self.grafana = Grafana(CONF.grafana.url, CONF.grafana.apikey)
self.parser = YamlParser()
def update_dashboard(self, path):
def load_files(self, path):
self.parser.parse(path)
def update_dashboard(self, path):
self.load_files(path)
dashboards = self.parser.data.get('dashboard', {})
for item in dashboards:
data, md5 = self.parser.get_dashboard(item)

View File

@ -42,6 +42,14 @@ class Commands(object):
def update(self, path):
self.builder.update_dashboard(path)
def validate(self, path):
try:
self.builder.load_files(path)
print('SUCCESS!')
except Exception as e:
print('%s: ERROR: %s' % (path, e))
sys.exit(1)
def add_command_parsers(subparsers):
parser_update = subparsers.add_parser('update')
@ -49,6 +57,11 @@ def add_command_parsers(subparsers):
'path', help='colon-separated list of paths to YAML files or'
' directories')
parser_validate = subparsers.add_parser('validate')
parser_validate.add_argument(
'path', help='colon-separated list of paths to YAML files or'
' directories')
command_opt = cfg.SubCommandOpt('action', handler=add_command_parsers)

View File

@ -16,12 +16,37 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import re
import fixtures
import testtools
from tests import conf_fixture
def get_scenarios(fixtures_path, in_ext='yaml', out_ext='json'):
scenarios = []
files = []
for dirpath, dirs, fs in os.walk(fixtures_path):
files.extend([os.path.join(dirpath, f) for f in fs])
input_files = [f for f in files if re.match(r'.*\.{0}$'.format(in_ext), f)]
for input_filename in input_files:
output_candidate = re.sub(
r'\.{0}$'.format(in_ext), '.{0}'.format(out_ext), input_filename)
if output_candidate not in files:
output_candidate = None
scenarios.append((input_filename, {
'in_filename': input_filename,
'out_filename': output_candidate,
}))
return scenarios
class TestCase(testtools.TestCase):
"""Test case base class for all unit tests."""

0
tests/cmd/__init__.py Normal file
View File

55
tests/cmd/base.py Normal file
View File

@ -0,0 +1,55 @@
# 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 sys
import fixtures
import six
from grafana_dashboards import cmd
from tests.base import TestCase
class TestCase(TestCase):
def setUp(self):
super(TestCase, self).setUp()
def clear():
cmd.CONF.reset()
cmd.CONF.unregister_opt(cmd.command_opt)
cmd.CONF.reset()
self.addCleanup(clear)
def shell(self, argstr, exitcodes=(0,)):
orig = sys.stdout
orig_stderr = sys.stderr
try:
sys.stdout = six.StringIO()
sys.stderr = six.StringIO()
argv = ['grafana-dashboards']
argv += argstr.split()
self.useFixture(fixtures.MonkeyPatch('sys.argv', argv))
cmd.main()
except SystemExit:
exc_type, exc_value, exc_trackback = sys.exc_info()
self.assertIn(exc_value.code, exitcodes)
finally:
stdout = sys.stdout.getvalue()
sys.stdout.close()
sys.stdout = orig
stderr = sys.stderr.getvalue()
sys.stderr.close()
sys.stderr = orig_stderr
return (stdout, stderr)

View File

@ -0,0 +1,71 @@
# 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 os
import re
from testscenarios.testcase import TestWithScenarios
from testtools import matchers
from tests.base import get_scenarios
from tests.cmd.base import TestCase
class TestCaseValidateScenarios(TestWithScenarios, TestCase):
fixtures_path = os.path.join(
os.path.dirname(__file__), '../fixtures/cmd/validate')
scenarios = get_scenarios(fixtures_path)
def test_command(self):
if os.path.basename(self.in_filename).startswith('good-'):
self._validate_success()
else:
self._validate_failure()
def _validate_failure(self):
required = [
'%s: ERROR:' % self.in_filename,
]
stdout, stderr = self.shell(
'validate %s' % self.in_filename, exitcodes=[1])
for r in required:
self.assertThat(
(stdout + stderr),
matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE))
def _validate_success(self):
required = [
'SUCCESS!',
]
stdout, stderr = self.shell(
'validate %s' % self.in_filename, exitcodes=[0])
for r in required:
self.assertThat(
(stdout + stderr),
matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE))
class TestCaseValidate(TestCase):
def test_validate_without_path(self):
required = [
'.*?^usage: grafana-dashboards validate \[-h\] path',
'.*?^grafana-dashboards validate: error: (too few arguments|the '
'following arguments are required: path)',
]
stdout, stderr = self.shell('validate', exitcodes=[2])
for r in required:
self.assertThat(
(stdout + stderr),
matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE))

View File

@ -0,0 +1,2 @@
board:
title: New dashboard

View File

@ -0,0 +1,2 @@
dashboard:
title: New dashboard

View File

@ -17,8 +17,6 @@
# under the License.
import json
import os
import re
import doctest
import testtools
@ -26,28 +24,6 @@ import testtools
from grafana_dashboards.parser import YamlParser
def get_scenarios(fixtures_path, in_ext='yaml', out_ext='json'):
scenarios = []
files = []
for dirpath, dirs, fs in os.walk(fixtures_path):
files.extend([os.path.join(dirpath, f) for f in fs])
input_files = [f for f in files if re.match(r'.*\.{0}$'.format(in_ext), f)]
for input_filename in input_files:
output_candidate = re.sub(
r'\.{0}$'.format(in_ext), '.{0}'.format(out_ext), input_filename)
if output_candidate not in files:
output_candidate = None
scenarios.append((input_filename, {
'in_filename': input_filename,
'out_filename': output_candidate,
}))
return scenarios
class TestCase(object):
"""Test case base class for all unit tests."""

View File

@ -17,7 +17,7 @@ import os
from testscenarios.testcase import TestWithScenarios
from testtools import TestCase
from tests.schema.base import get_scenarios
from tests.base import get_scenarios
from tests.schema.base import TestCase as BaseTestCase

View File

@ -13,44 +13,14 @@
# under the License.
import re
import sys
import fixtures
import six
from testtools import matchers
from grafana_dashboards import cmd
from tests.base import TestCase
from tests.cmd.base import TestCase
class TestCaseCmd(TestCase):
def setUp(self):
super(TestCaseCmd, self).setUp()
cmd.CONF.reset()
def shell(self, argstr, exitcodes=(0,)):
orig = sys.stdout
orig_stderr = sys.stderr
try:
sys.stdout = six.StringIO()
sys.stderr = six.StringIO()
argv = ['grafana-dashboards']
argv += argstr.split()
self.useFixture(fixtures.MonkeyPatch('sys.argv', argv))
cmd.main()
except SystemExit:
exc_type, exc_value, exc_trackback = sys.exc_info()
self.assertIn(exc_value.code, exitcodes)
finally:
stdout = sys.stdout.getvalue()
sys.stdout.close()
sys.stdout = orig
stderr = sys.stderr.getvalue()
sys.stderr.close()
sys.stderr = orig_stderr
return (stdout, stderr)
def test_update_without_path(self):
required = [
'.*?^usage: grafana-dashboards update \[-h\] path',