Improve test coverage (#4)
This commit is contained in:
parent
38eb764c4c
commit
f943e47f70
|
@ -1,6 +1,9 @@
|
|||
CHANGES
|
||||
=======
|
||||
|
||||
* Improve test coverage
|
||||
* Remove sys from uptime test (#3)
|
||||
* Increase test coverage for uptime
|
||||
* Added KVM Metric plugin (#2)
|
||||
* Couple of updates: telegraf line protocol, dynamic imports, metadata (#1)
|
||||
* Proof of concept
|
||||
|
|
|
@ -14,11 +14,9 @@
|
|||
# limitations under the License.
|
||||
"""Handle all shell commands/arguments/options."""
|
||||
import importlib
|
||||
import json
|
||||
import os
|
||||
import pkgutil
|
||||
import sys
|
||||
import time
|
||||
|
||||
import click
|
||||
|
||||
|
@ -26,12 +24,6 @@ import click
|
|||
context_settings = dict(auto_envvar_prefix='MonitorStack')
|
||||
|
||||
|
||||
def current_time():
|
||||
"""Return the current time in nanoseconds"""
|
||||
|
||||
return int(time.time() * 1000000000)
|
||||
|
||||
|
||||
class Context(object):
|
||||
"""Set up a context object that we can pass."""
|
||||
|
||||
|
@ -42,8 +34,6 @@ class Context(object):
|
|||
|
||||
def log(self, msg, *args):
|
||||
"""Log a message to stderr."""
|
||||
if args:
|
||||
msg %= args
|
||||
click.echo(msg, file=sys.stderr)
|
||||
|
||||
def vlog(self, msg, *args):
|
||||
|
@ -60,6 +50,7 @@ class MonitorStackCLI(click.MultiCommand):
|
|||
|
||||
@property
|
||||
def cmd_folder(self):
|
||||
"""Get the path to the plugin directory."""
|
||||
return os.path.abspath(
|
||||
os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
|
@ -115,40 +106,13 @@ def cli(ctx, output_format, verbose):
|
|||
@cli.resultcallback(replace=True)
|
||||
def process_result(result, output_format, verbose):
|
||||
"""Render the output into the proper format."""
|
||||
if output_format == 'json':
|
||||
click.echo(json.dumps(result, indent=2))
|
||||
|
||||
elif output_format == 'line':
|
||||
for key, value in result['variables'].items():
|
||||
click.echo("{} {}".format(key, value))
|
||||
|
||||
elif output_format == 'telegraf':
|
||||
def line_format(sets, quote=False):
|
||||
store = list()
|
||||
for k, v in sets.items():
|
||||
k = k.replace(' ', '_')
|
||||
for v_type in [int, float]:
|
||||
try:
|
||||
v = v_type(v)
|
||||
except ValueError:
|
||||
pass # v was not a int, float, or long
|
||||
else:
|
||||
break
|
||||
if not isinstance(v, (int, float, bool)) and quote:
|
||||
store.append('{}="{}"'.format(k, v))
|
||||
else:
|
||||
store.append('{}={}'.format(k, v))
|
||||
return ','.join(store).rstrip(',')
|
||||
|
||||
resultant = [result['measurement_name']]
|
||||
if 'meta' in result:
|
||||
resultant.append(line_format(sets=result['meta']))
|
||||
resultant.append(line_format(sets=result['variables'], quote=True))
|
||||
resultant.append(current_time())
|
||||
click.echo(' '.join(resultant))
|
||||
|
||||
elif output_format == 'csv':
|
||||
pass
|
||||
module_name = 'monitorstack.common.formatters'
|
||||
method_name = 'write_{}'.format(output_format)
|
||||
output_formatter = getattr(
|
||||
importlib.import_module(module_name),
|
||||
method_name
|
||||
)
|
||||
output_formatter(result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
# Copyright 2017, Major Hayden <major@mhtx.net>
|
||||
#
|
||||
# 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.
|
||||
"""Output methods."""
|
||||
import json
|
||||
import time
|
||||
|
||||
import click
|
||||
|
||||
|
||||
def current_time():
|
||||
"""Return the current time in nanoseconds."""
|
||||
return int(time.time() * 1000000000)
|
||||
|
||||
|
||||
def write_json(result):
|
||||
"""Output in raw JSON format."""
|
||||
output = json.dumps(result, indent=2)
|
||||
click.echo(output)
|
||||
return True
|
||||
|
||||
|
||||
def write_line(result):
|
||||
"""Output in line format."""
|
||||
for key, value in result['variables'].items():
|
||||
click.echo("{} {}".format(key, value))
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def write_telegraf(result):
|
||||
"""Output in telegraf format."""
|
||||
def line_format(sets, quote=False):
|
||||
store = list()
|
||||
for k, v in sets.items():
|
||||
k = k.replace(' ', '_')
|
||||
for v_type in [int, float]:
|
||||
try:
|
||||
v = v_type(v)
|
||||
except ValueError:
|
||||
pass # v was not a int, float, or long
|
||||
else:
|
||||
break
|
||||
if not isinstance(v, (int, float, bool)) and quote:
|
||||
store.append('{}="{}"'.format(k, v))
|
||||
else:
|
||||
store.append('{}={}'.format(k, v))
|
||||
return ','.join(store).rstrip(',')
|
||||
|
||||
resultant = [result['measurement_name']]
|
||||
if 'meta' in result:
|
||||
resultant.append(line_format(sets=result['meta']))
|
||||
resultant.append(line_format(sets=result['variables'], quote=True))
|
||||
resultant.append(str(current_time()))
|
||||
click.echo(' '.join(resultant))
|
||||
|
||||
return True
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright 2017, Kevin Carter <kevin@cloudnull.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -12,6 +11,7 @@
|
|||
# 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.
|
||||
"""Plugin for KVM metrics."""
|
||||
|
||||
import platform
|
||||
import socket
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright 2017, Major Hayden <major@mhtx.net>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -12,8 +11,7 @@
|
|||
# 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.
|
||||
|
||||
"""Base monitoring class."""
|
||||
"""Get system uptime."""
|
||||
|
||||
import platform
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
# Copyright 2017, Major Hayden <major@mhtx.net>
|
||||
#
|
||||
# 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.
|
||||
"""Tests for the base cli module."""
|
||||
import click
|
||||
|
||||
from monitorstack.cli import Context
|
||||
from monitorstack.cli import MonitorStackCLI
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestCLI(object):
|
||||
"""Tests for the base cli module."""
|
||||
|
||||
def test_context_log(self, monkeypatch):
|
||||
"""Test log() method of Context class."""
|
||||
def echofixer(msg, file):
|
||||
return msg
|
||||
monkeypatch.setattr(click, 'echo', echofixer)
|
||||
|
||||
context = Context()
|
||||
result = context.log("TEST", 'test')
|
||||
assert callable(context.log)
|
||||
assert result is None
|
||||
|
||||
def test_context_vlog_verbose_disabled(self, monkeypatch):
|
||||
"""Test vlog() method of Context class."""
|
||||
def echofixer(msg, file):
|
||||
return msg
|
||||
monkeypatch.setattr(click, 'echo', echofixer)
|
||||
|
||||
context = Context()
|
||||
context.verbose = False
|
||||
result = context.vlog("TEST", 'test')
|
||||
assert callable(context.vlog)
|
||||
assert result is None
|
||||
|
||||
def test_context_vlog_verbose_enabled(self, monkeypatch):
|
||||
"""Test vlog() method of Context class."""
|
||||
def echofixer(msg, file):
|
||||
return msg
|
||||
monkeypatch.setattr(click, 'echo', echofixer)
|
||||
|
||||
context = Context()
|
||||
context.verbose = True
|
||||
result = context.vlog("TEST", 'test')
|
||||
assert callable(context.vlog)
|
||||
assert result is None
|
||||
|
||||
def test_get_command_invalid(self):
|
||||
"""Test MonitorStackCLI.get_command()."""
|
||||
ctx = Context()
|
||||
cli = MonitorStackCLI()
|
||||
with pytest.raises(SystemExit) as excinfo:
|
||||
cli.get_command(ctx, 'silly_rabbit_trix_are_for_kids')
|
||||
assert 'silly_rabbit_trix_are_for_kids' in str(excinfo.value)
|
||||
assert 'Not Found' in str(excinfo.value)
|
||||
|
||||
def test_get_command_valid(self):
|
||||
"""Test MonitorStackCLI.get_command()."""
|
||||
ctx = Context()
|
||||
cli = MonitorStackCLI()
|
||||
result = cli.get_command(ctx, 'uptime')
|
||||
assert isinstance(result, object)
|
||||
assert callable(result)
|
||||
|
||||
def test_list_commands(self):
|
||||
"""Test MonitorStackCLI.list_commands()."""
|
||||
ctx = Context()
|
||||
cli = MonitorStackCLI()
|
||||
result = cli.list_commands(ctx)
|
||||
assert isinstance(result, list)
|
||||
assert len(result) > 1
|
||||
assert 'uptime' in result
|
|
@ -0,0 +1,63 @@
|
|||
# Copyright 2017, Major Hayden <major@mhtx.net>
|
||||
#
|
||||
# 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.
|
||||
"""Tests the output methods."""
|
||||
import json
|
||||
import platform
|
||||
|
||||
from monitorstack.common import formatters
|
||||
|
||||
SAMPLE_RESULT = {
|
||||
'exit_code': 0,
|
||||
'message': 'uptime is ok',
|
||||
'measurement_name': 'system_uptime',
|
||||
'meta': {
|
||||
'platform': platform.platform(),
|
||||
},
|
||||
'variables': {
|
||||
'uptime': '29587.75'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestFormatters(object):
|
||||
"""Tests for the base cli module."""
|
||||
|
||||
def test_current_time(self):
|
||||
"""Test current_time()."""
|
||||
result = formatters.current_time()
|
||||
assert isinstance(result, int)
|
||||
assert result > 0
|
||||
|
||||
def test_write_json(self, capsys):
|
||||
"""Test write_json() module."""
|
||||
formatters.write_json(SAMPLE_RESULT)
|
||||
out, err = capsys.readouterr()
|
||||
result_json = json.loads(out)
|
||||
assert isinstance(result_json, dict)
|
||||
assert result_json['measurement_name'] == \
|
||||
SAMPLE_RESULT['measurement_name']
|
||||
|
||||
def test_write_line(self, capsys):
|
||||
"""Test write_line() module."""
|
||||
formatters.write_line(SAMPLE_RESULT)
|
||||
out, err = capsys.readouterr()
|
||||
assert out == "uptime {}\n".format(
|
||||
SAMPLE_RESULT['variables']['uptime']
|
||||
)
|
||||
|
||||
def test_write_telegraf(self, capsys):
|
||||
"""Test write_telegraf() module."""
|
||||
formatters.write_telegraf(SAMPLE_RESULT)
|
||||
out, err = capsys.readouterr()
|
||||
assert out.startswith(SAMPLE_RESULT['measurement_name'])
|
|
@ -11,8 +11,7 @@
|
|||
# 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.
|
||||
|
||||
"""Tests for the base class."""
|
||||
"""Tests for the KVM plugin."""
|
||||
|
||||
import json
|
||||
import sys
|
|
@ -11,8 +11,7 @@
|
|||
# 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.
|
||||
|
||||
"""Tests for the base class."""
|
||||
"""Tests for the uptime plugin."""
|
||||
|
||||
import json
|
||||
|
Loading…
Reference in New Issue