Replace oslo_config dependency with argparse
This is for the same reasoning as oslo_log. We don't want to depending on OpenStack libraries. Change-Id: I34e66af578d3f4b5ac5e710554aad91524285816 Signed-off-by: Paul Belanger <pabelanger@redhat.com>
This commit is contained in:
parent
3a66817727
commit
4e643e5d06
@ -16,20 +16,12 @@ files.
|
||||
OPTIONS
|
||||
=======
|
||||
|
||||
-h, --help Show the help.
|
||||
--config-dir DIR Path to a config directory to pull \*.conf files from. This
|
||||
file set is sorted, so as to provide a predictable parse
|
||||
order if individual options are over-ridden. The set is
|
||||
parsed after the file(s) specified via previous
|
||||
--config-file, arguments hence over-ridden options in the
|
||||
directory take precedence.
|
||||
--config-file PATH Path to a config file to use. Multiple config files can be
|
||||
specified, with values in later files taking precedence. The
|
||||
default files used are: None.
|
||||
--debug Print debugging output(set logging level to DEBUG instead
|
||||
of default INFO level).
|
||||
--nodebug The inverse of --debug.
|
||||
--version Show program's version number and exit.
|
||||
-h, --help Show this help message and exit
|
||||
--config-file CONFIG Path to a config file to use. The default files used
|
||||
is: /etc/grafyaml/grafyaml.conf
|
||||
--debug Print debugging output (set logging level to DEBUG
|
||||
instead of default INFO level)
|
||||
--version Show program's version number and exit
|
||||
|
||||
COMMANDS
|
||||
========
|
||||
|
@ -1,28 +1,14 @@
|
||||
[DEFAULT]
|
||||
|
||||
|
||||
[grafana]
|
||||
|
||||
#
|
||||
# From grafyaml.builder
|
||||
#
|
||||
|
||||
# URL for grafana server. (string value)
|
||||
#url = http://grafana.example.org
|
||||
|
||||
# API key for access grafana. (string value)
|
||||
#apikey = <None>
|
||||
|
||||
|
||||
[cache]
|
||||
|
||||
#
|
||||
# From grafyaml.cache
|
||||
#
|
||||
|
||||
# Directory used by grafyaml to store its cache files. (string value)
|
||||
#cachedir = ~/.cache/grafyaml
|
||||
|
||||
# Maintain a special cache that contains an MD5 of every generated
|
||||
# dashboard. (boolean value)
|
||||
#enabled = true
|
||||
|
||||
[grafana]
|
||||
# URL for grafana server. (string value)
|
||||
#url = http://localhost:8080
|
||||
|
||||
# API key for access grafana. (string value)
|
||||
#apikey = <None>
|
||||
|
@ -15,37 +15,44 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from grafana_dashboards.cache import Cache
|
||||
from grafana_dashboards.grafana import Grafana
|
||||
from grafana_dashboards.parser import YamlParser
|
||||
|
||||
grafana_opts = [
|
||||
cfg.StrOpt(
|
||||
'url', default='http://grafana.example.org',
|
||||
help='URL for grafana server.'),
|
||||
cfg.StrOpt(
|
||||
'apikey', default=None,
|
||||
help='API key for access grafana.'),
|
||||
]
|
||||
|
||||
grafana_group = cfg.OptGroup(
|
||||
name='grafana', title='Grafana options')
|
||||
list_opts = lambda: [(grafana_group, grafana_opts), ]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_group(grafana_group)
|
||||
CONF.register_opts(grafana_opts, group='grafana')
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Builder(object):
|
||||
def __init__(self):
|
||||
self.cache = Cache()
|
||||
self.grafana = Grafana(CONF.grafana.url, CONF.grafana.apikey)
|
||||
|
||||
def __init__(self, config):
|
||||
self.grafana = self._setup_grafana(config)
|
||||
self.parser = YamlParser()
|
||||
self.cache = self._setup_cache(config)
|
||||
|
||||
def _setup_cache(self, config):
|
||||
if config.has_option('cache', 'enabled'):
|
||||
self.cache_enabled = config.getboolean('cache', 'enabled')
|
||||
else:
|
||||
self.cache_enabled = True
|
||||
|
||||
if config.has_option('cache', 'cachedir'):
|
||||
cachedir = config.get('cache', 'cachedir')
|
||||
else:
|
||||
cachedir = '~/.cache/grafyaml'
|
||||
|
||||
return Cache(cachedir)
|
||||
|
||||
def _setup_grafana(self, config):
|
||||
if config.has_option('grafana', 'apikey'):
|
||||
key = config.get('grafana', 'apikey')
|
||||
else:
|
||||
key = None
|
||||
|
||||
if config.has_option('grafana', 'url'):
|
||||
url = config.get('grafana', 'url')
|
||||
else:
|
||||
url = 'http://localhost:8080'
|
||||
return Grafana(url, key)
|
||||
|
||||
def load_files(self, path):
|
||||
files_to_process = []
|
||||
@ -66,7 +73,7 @@ class Builder(object):
|
||||
LOG.info('Number of dashboards generated: %d', len(dashboards))
|
||||
for name in dashboards:
|
||||
data, md5 = self.parser.get_dashboard(name)
|
||||
if self.cache.has_changed(name, md5):
|
||||
if self.cache.has_changed(name, md5) or not self.cache_enabled:
|
||||
self.grafana.create_dashboard(name, data, overwrite=True)
|
||||
self.cache.set(name, md5)
|
||||
else:
|
||||
|
@ -16,35 +16,14 @@ import logging
|
||||
import os
|
||||
|
||||
from dogpile.cache.region import make_region
|
||||
from oslo_config import cfg
|
||||
|
||||
cache_opts = [
|
||||
cfg.StrOpt(
|
||||
'cachedir', default='~/.cache/grafyaml',
|
||||
help='Directory used by grafyaml to store its cache files.'),
|
||||
cfg.BoolOpt(
|
||||
'enabled', default=True,
|
||||
help='Maintain a special cache that contains an MD5 of every '
|
||||
'generated dashboard.'),
|
||||
]
|
||||
cache_group = cfg.OptGroup(
|
||||
name='cache', title='Cache options')
|
||||
list_opts = lambda: [(cache_group, cache_opts), ]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(cache_opts)
|
||||
CONF.register_opts(cache_opts, group='cache')
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Cache(object):
|
||||
|
||||
def __init__(self):
|
||||
if not CONF.cache.enabled:
|
||||
return
|
||||
|
||||
cache_dir = self._get_cache_dir()
|
||||
def __init__(self, cachedir):
|
||||
cache_dir = self._get_cache_dir(cachedir)
|
||||
self.region = make_region().configure(
|
||||
'dogpile.cache.dbm',
|
||||
arguments={
|
||||
@ -53,22 +32,19 @@ class Cache(object):
|
||||
)
|
||||
|
||||
def get(self, title):
|
||||
if CONF.cache.enabled:
|
||||
res = self.region.get(title)
|
||||
return res if res else None
|
||||
return None
|
||||
res = self.region.get(title)
|
||||
return res if res else None
|
||||
|
||||
def has_changed(self, title, md5):
|
||||
if CONF.cache.enabled and self.get(title) == md5:
|
||||
if self.get(title) == md5:
|
||||
return False
|
||||
return True
|
||||
|
||||
def set(self, title, md5):
|
||||
if CONF.cache.enabled:
|
||||
self.region.set(title, md5)
|
||||
self.region.set(title, md5)
|
||||
|
||||
def _get_cache_dir(self):
|
||||
path = os.path.expanduser(CONF.cache.cachedir)
|
||||
def _get_cache_dir(self, cachedir):
|
||||
path = os.path.expanduser(cachedir)
|
||||
if not os.path.isdir(path):
|
||||
os.makedirs(path)
|
||||
return path
|
||||
|
@ -12,73 +12,90 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import inspect
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
from oslo_config import cfg
|
||||
from six.moves import configparser as ConfigParser
|
||||
|
||||
from grafana_dashboards.builder import Builder
|
||||
from grafana_dashboards import config
|
||||
from grafana_dashboards import version
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Commands(object):
|
||||
class Client(object):
|
||||
|
||||
def __init__(self):
|
||||
self.builder = Builder()
|
||||
def main(self):
|
||||
self.parse_arguments()
|
||||
self.read_config()
|
||||
self.setup_logging()
|
||||
|
||||
def execute(self):
|
||||
exec_method = getattr(self, CONF.action.name)
|
||||
args = inspect.getargspec(exec_method)
|
||||
args.args.remove('self')
|
||||
kwargs = {}
|
||||
for arg in args.args:
|
||||
kwargs[arg] = getattr(CONF.action, arg)
|
||||
exec_method(**kwargs)
|
||||
self.args.func()
|
||||
|
||||
def update(self, path):
|
||||
LOG.info('Updating dashboards in %s', path)
|
||||
self.builder.update_dashboard(path)
|
||||
def parse_arguments(self):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'--config-file', dest='config', help='Path to a config file to '
|
||||
'use. The default file used is: /etc/grafyaml/grafyaml.conf')
|
||||
parser.add_argument(
|
||||
'--debug', dest='debug', action='store_true',
|
||||
help='Print debugging output (set logging level to DEBUG instead '
|
||||
' of default INFO level)')
|
||||
parser.add_argument(
|
||||
'--version', dest='version', action='version',
|
||||
version=version.version_info.release_string(), help="show "
|
||||
"program's version number and exit")
|
||||
|
||||
def validate(self, path):
|
||||
LOG.info('Validating dashboards in %s', path)
|
||||
subparsers = parser.add_subparsers(
|
||||
title='commands')
|
||||
|
||||
parser_update = subparsers.add_parser('update')
|
||||
parser_update.add_argument(
|
||||
'path', help='colon-separated list of paths to YAML files or'
|
||||
' directories')
|
||||
parser_update.set_defaults(func=self.update)
|
||||
|
||||
parser_validate = subparsers.add_parser('validate')
|
||||
parser_validate.add_argument(
|
||||
'path', help='colon-separated list of paths to YAML files or'
|
||||
' directories')
|
||||
parser_validate.set_defaults(func=self.validate)
|
||||
|
||||
self.args = parser.parse_args()
|
||||
|
||||
def read_config(self):
|
||||
self.config = ConfigParser.ConfigParser()
|
||||
if self.args.config:
|
||||
fp = self.args.config
|
||||
else:
|
||||
fp = '/etc/grafyaml/grafyaml.conf'
|
||||
self.config.read(os.path.expanduser(fp))
|
||||
|
||||
def setup_logging(self):
|
||||
if self.args.debug:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
else:
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
def update(self):
|
||||
LOG.info('Updating dashboards in %s', self.args.path)
|
||||
builder = Builder(self.config)
|
||||
builder.update_dashboard(self.args.path)
|
||||
|
||||
def validate(self):
|
||||
LOG.info('Validating dashboards in %s', self.args.path)
|
||||
builder = Builder(self.config)
|
||||
try:
|
||||
self.builder.load_files(path)
|
||||
builder.load_files(self.args.path)
|
||||
print('SUCCESS!')
|
||||
except Exception as e:
|
||||
print('%s: ERROR: %s' % (path, e))
|
||||
print('%s: ERROR: %s' % (self.args.path, e))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def add_command_parsers(subparsers):
|
||||
parser_update = subparsers.add_parser('update')
|
||||
parser_update.add_argument(
|
||||
'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)
|
||||
logging_opts = cfg.BoolOpt(
|
||||
'debug', default=False, help='Print debugging output (set logging level '
|
||||
'to DEBUG instead of default INFO level).')
|
||||
|
||||
|
||||
def main():
|
||||
CONF.register_cli_opt(command_opt)
|
||||
CONF.register_cli_opt(logging_opts)
|
||||
config.prepare_args(sys.argv)
|
||||
if CONF.debug:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
else:
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
Commands().execute()
|
||||
client = Client()
|
||||
client.main()
|
||||
sys.exit(0)
|
||||
|
@ -1,23 +0,0 @@
|
||||
# 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.
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from grafana_dashboards import version
|
||||
|
||||
|
||||
def prepare_args(argv):
|
||||
cfg.CONF(
|
||||
argv[1:], project='grafana_dashboards',
|
||||
version=version.version_info.release_string())
|
@ -1,6 +1,6 @@
|
||||
dogpile.cache
|
||||
oslo.config>=1.11.0
|
||||
python-slugify
|
||||
PyYAML>=3.1.0
|
||||
requests
|
||||
six>=1.6.0
|
||||
voluptuous>=0.7
|
||||
|
@ -16,13 +16,18 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
import fixtures
|
||||
from six.moves import configparser as ConfigParser
|
||||
import testtools
|
||||
|
||||
from tests import conf_fixture
|
||||
FIXTURE_DIR = os.path.join(
|
||||
os.path.dirname(__file__), 'fixtures')
|
||||
|
||||
|
||||
def get_scenarios(fixtures_path, in_ext='yaml', out_ext='json'):
|
||||
@ -52,5 +57,16 @@ class TestCase(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestCase, self).setUp()
|
||||
self.log_fixture = self.useFixture(fixtures.FakeLogger())
|
||||
self.useFixture(conf_fixture.ConfFixture())
|
||||
self.log_fixture = self.useFixture(fixtures.FakeLogger(
|
||||
level=logging.DEBUG))
|
||||
self.setup_config()
|
||||
self.cachedir = tempfile.mkdtemp()
|
||||
self.config.set('cache', 'cachedir', self.cachedir)
|
||||
self.addCleanup(self.cleanup_cachedir)
|
||||
|
||||
def setup_config(self):
|
||||
self.config = ConfigParser.ConfigParser()
|
||||
self.config.read(os.path.join(FIXTURE_DIR, 'grafyaml.conf'))
|
||||
|
||||
def cleanup_cachedir(self):
|
||||
shutil.rmtree(self.cachedir)
|
||||
|
@ -23,15 +23,6 @@ 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
|
||||
|
5
tests/fixtures/grafyaml.conf
vendored
Normal file
5
tests/fixtures/grafyaml.conf
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
[grafana]
|
||||
url = http://grafana.example.org
|
||||
|
||||
[cache]
|
||||
enabled = true
|
@ -24,7 +24,7 @@ class TestCaseBuilder(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestCaseBuilder, self).setUp()
|
||||
self.builder = builder.Builder()
|
||||
self.builder = builder.Builder(self.config)
|
||||
|
||||
@mock.patch('grafana_dashboards.grafana.Grafana.create_dashboard')
|
||||
def test_update_dashboard(self, mock_grafana):
|
||||
@ -36,7 +36,7 @@ class TestCaseBuilder(TestCase):
|
||||
self.assertEqual(mock_grafana.call_count, 1)
|
||||
|
||||
# Create a new builder to avoid duplicate dashboards.
|
||||
builder2 = builder.Builder()
|
||||
builder2 = builder.Builder(self.config)
|
||||
# Update again with same dashboard, ensure we don't update grafana.
|
||||
builder2.update_dashboard(dashboard)
|
||||
self.assertEqual(mock_grafana.call_count, 1)
|
||||
|
@ -12,13 +12,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from grafana_dashboards import cache
|
||||
from tests.base import TestCase
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class TestCaseCache(TestCase):
|
||||
|
||||
@ -28,10 +24,10 @@ class TestCaseCache(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestCaseCache, self).setUp()
|
||||
self.storage = None
|
||||
cachedir = self.config.get('cache', 'cachedir')
|
||||
self.storage = cache.Cache(cachedir)
|
||||
|
||||
def test_cache_has_changed(self):
|
||||
self.storage = cache.Cache()
|
||||
res = self.storage.has_changed(
|
||||
'hello-world', self.dashboard['hello-world'])
|
||||
self.assertTrue(res)
|
||||
@ -40,28 +36,10 @@ class TestCaseCache(TestCase):
|
||||
'hello-world', self.dashboard['hello-world'])
|
||||
self.assertFalse(res)
|
||||
|
||||
def test_cache_disabled_has_changed(self):
|
||||
CONF.cache.enabled = False
|
||||
self.storage = cache.Cache()
|
||||
res = self.storage.has_changed(
|
||||
'hello-world', self.dashboard['hello-world'])
|
||||
self.assertTrue(res)
|
||||
self.storage.set('hello-world', self.dashboard['hello-world'])
|
||||
res = self.storage.has_changed(
|
||||
'hello-world', self.dashboard['hello-world'])
|
||||
self.assertTrue(res)
|
||||
|
||||
def test_cache_get_empty(self):
|
||||
self.storage = cache.Cache()
|
||||
self.assertEqual(self.storage.get('empty'), None)
|
||||
|
||||
def test_cache_disabled_get_empty(self):
|
||||
CONF.cache.enabled = False
|
||||
self.storage = cache.Cache()
|
||||
self.assertEqual(self.storage.get('disabled'), None)
|
||||
|
||||
def test_cache_set_multiple(self):
|
||||
self.storage = cache.Cache()
|
||||
self.storage.set('hello-world', self.dashboard['hello-world'])
|
||||
self.assertEqual(
|
||||
self.storage.get('hello-world'), self.dashboard['hello-world'])
|
||||
@ -77,15 +55,6 @@ class TestCaseCache(TestCase):
|
||||
self.storage.get('hello-world'), self.dashboard['hello-world'])
|
||||
|
||||
def test_cache_set_single(self):
|
||||
self.storage = cache.Cache()
|
||||
self.storage.set('hello-world', self.dashboard['hello-world'])
|
||||
self.assertEqual(
|
||||
self.storage.get('hello-world'), self.dashboard['hello-world'])
|
||||
|
||||
def test_cache_disabled_set_single(self):
|
||||
CONF.cache.enabled = False
|
||||
self.storage = cache.Cache()
|
||||
self.storage.set('hello-world', self.dashboard['hello-world'])
|
||||
# Make sure cache is empty.
|
||||
self.assertEqual(
|
||||
self.storage.get('hello-world'), None)
|
||||
|
8
tox.ini
8
tox.ini
@ -12,14 +12,6 @@ deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = python setup.py test --slowest --testr-args='{posargs}'
|
||||
|
||||
[testenv:genconfig]
|
||||
commands =
|
||||
oslo-config-generator \
|
||||
--namespace grafyaml.builder \
|
||||
--namespace grafyaml.cache \
|
||||
--namespace oslo.log \
|
||||
--output-file etc/grafyaml.conf
|
||||
|
||||
[testenv:pep8]
|
||||
commands = flake8
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user