Proof of concept

This commit is contained in:
Major Hayden 2017-02-21 11:25:27 -05:00
parent 2f4fc4f174
commit 5f9ddd6dba
16 changed files with 314 additions and 2 deletions

3
.coveragerc Normal file
View File

@ -0,0 +1,3 @@
[run]
branch = True
source = monitorstack

24
.travis.yml Normal file
View File

@ -0,0 +1,24 @@
sudo: false
language: python
cache: pip
matrix:
include:
- python: "2.7"
env: TOXENV=py27
- python: "3.3"
env: TOXENV=py33
- python: "3.4"
env: TOXENV=py34
- python: "pypy"
env: TOXENV=pypy
- python: 2.7
env: TOXENV=pep8
- python: 3.3
env: TOXENV=py3pep8
before_install:
pip install codecov
after_success:
codecov
install:
- "pip install tox"
script: "tox"

1
AUTHORS Normal file
View File

@ -0,0 +1 @@
Major Hayden <major@mhtx.net>

7
ChangeLog Normal file
View File

@ -0,0 +1,7 @@
CHANGES
=======
* Uptime class
* Update README
* Import
* Initial commit

View File

@ -1,2 +0,0 @@
# monitorstack
Monitoring plugins for OpenStack

6
README.rst Normal file
View File

@ -0,0 +1,6 @@
monitorstack
============
Monitoring plugins for OpenStack.
*Work in progress.*

0
monitorstack/__init__.py Normal file
View File

113
monitorstack/cli.py Executable file
View File

@ -0,0 +1,113 @@
#!/usr/bin/env python
# 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.
"""Handle all shell commands/arguments/options."""
import json
import os
import sys
import click
CONTEXT_SETTINGS = dict(auto_envvar_prefix='MonitorStack')
class Context(object):
"""Set up a context object that we can pass."""
def __init__(self):
"""Initialize class."""
self.verbose = False
self.home = os.getcwd()
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):
"""Log a message to stderr only if verbose is enabled."""
if self.verbose:
self.log(msg, *args)
pass_context = click.make_pass_decorator(Context, ensure=True)
cmd_folder = os.path.abspath(os.path.join(os.path.dirname(__file__),
'plugins'))
class MonitorStackCLI(click.MultiCommand):
"""Create a complex command finder."""
def list_commands(self, ctx):
"""Get a list of all available commands."""
rv = []
for filename in os.listdir(cmd_folder):
if filename.endswith('.py') and not filename.startswith('__'):
rv.append(filename[:-3])
rv.sort()
return rv
def get_command(self, ctx, name):
"""Load a command and run it."""
try:
if sys.version_info[0] == 2:
name = name.encode('ascii', 'replace')
mod = __import__('monitorstack.plugins.' + name,
None, None, ['cli'])
except ImportError:
return
return mod.cli
VALID_OUTPUT_FORMATS = [
'json',
'line',
]
@click.command(cls=MonitorStackCLI, context_settings=CONTEXT_SETTINGS)
@click.option(
'-f', '--format', 'output_format',
type=click.Choice(VALID_OUTPUT_FORMATS),
default='json',
help="Output format (valid options: {}".format(
', '.join(VALID_OUTPUT_FORMATS)
),
)
@click.option('-v', '--verbose', is_flag=True, help='Enables verbose mode.')
@pass_context
def cli(ctx, output_format, verbose):
"""A complex command line interface."""
ctx.verbose = verbose
pass
@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 == 'csv':
pass
if __name__ == '__main__':
cli()

View File

View File

@ -0,0 +1,34 @@
#!/usr/bin/env python
# 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.
"""Base monitoring class."""
import click
from monitorstack.cli import pass_context
@click.command('uptime', short_help='Get system uptime')
@pass_context
def cli(ctx):
"""Get system uptime."""
with open('/proc/uptime', 'r') as f:
output = f.read()
uptime = output.split()[0]
output = {
'exit_code': 0,
'message': 'uptime is ok',
'variables': {
'uptime': uptime
}
}
return output

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
click
six
stevedore

28
setup.cfg Normal file
View File

@ -0,0 +1,28 @@
[metadata]
name = monitorstack
summary = Monitoring plugins for OpenStack
description-file =
README.rst
author = Major Hayden
author-email = major@mhtx.net
home-page = https://github.com/major/monitorstack
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
Intended Audience :: System Administrators
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3.4
Programming Language :: Python :: 3.5
[files]
packages =
monitorstack
[entry_points]
console_scripts =
monitorstack = monitorstack.cli:cli

29
setup.py Normal file
View File

@ -0,0 +1,29 @@
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
#
# 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.
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools
# In python < 2.7.4, a lazy loading of package `pbr` will break
# setuptools if some other modules registered functions in `atexit`.
# solution from: http://bugs.python.org/issue15881#msg170215
try:
import multiprocessing # noqa
except ImportError:
pass
setuptools.setup(
setup_requires=['pbr>=1.8'],
pbr=True)

2
test-requirements.txt Normal file
View File

@ -0,0 +1,2 @@
pytest
tox

32
tests/test_uptime.py Normal file
View File

@ -0,0 +1,32 @@
# 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 class."""
import click
from click.testing import CliRunner
import json
from monitorstack.cli import cli
class TestUptime(object):
"""Tests for the uptime monitor class."""
def test_run(self):
"""Ensure the run() method works."""
runner = CliRunner()
result = runner.invoke(cli, ['-f', 'json', 'uptime'])
result_json = json.loads(result.output)
assert 'uptime' in result_json['variables']
assert result.exit_code == 0

32
tox.ini Normal file
View File

@ -0,0 +1,32 @@
[tox]
envlist = {pypy,pep8,py3pep8,py26,py27,py33,py34}
[testenv]
deps =
coverage
-rrequirements.txt
-rtest-requirements.txt
setenv =
commands =
coverage run -m pytest --capture=no --strict {posargs}
coverage report -m --omit="*/test*"
[testenv:pep8]
deps =
flake8
flake8-import-order
pep8-naming
commands =
flake8 .
[testenv:py3pep8]
basepython = python3.3
deps =
flake8
flake8-import-order
pep8-naming
commands =
flake8 .
[flake8]
exclude = .tox,*.egg,.git,_build,docs-rst