Add base Cliff application
This patch a mechanism for launching a Cliff application which loads its commands as python entry-points. Blueprint: re-thinking-fuel-client Change-Id: I77fc4b0f18f4c5781cd1bb4efa1a2841b210cb56
This commit is contained in:
0
fuelclient/actions/__init__.py
Normal file
0
fuelclient/actions/__init__.py
Normal file
17
fuel → fuelclient/actions/fuel_version.py
Executable file → Normal file
17
fuel → fuelclient/actions/fuel_version.py
Executable file → Normal file
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright 2013-2014 Mirantis, Inc.
|
||||
# Copyright 2015 Mirantis, 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
|
||||
@@ -13,7 +12,15 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from fuelclient.cli.parser import main
|
||||
import argparse
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
from fuelclient import client
|
||||
|
||||
|
||||
class FuelVersionAction(argparse._VersionAction):
|
||||
"""Custom argparse._VersionAction subclass to compute fuel server version
|
||||
|
||||
:returns: prints fuel server version
|
||||
"""
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
parser.exit(message=client.APIClient.get_fuel_version())
|
||||
76
fuelclient/main.py
Normal file
76
fuelclient/main.py
Normal file
@@ -0,0 +1,76 @@
|
||||
# Copyright 2015 Mirantis, 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 logging
|
||||
import sys
|
||||
|
||||
from cliff import app
|
||||
from cliff.commandmanager import CommandManager
|
||||
|
||||
from fuelclient.actions import fuel_version
|
||||
from fuelclient.cli.error import exceptions_decorator
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FuelClient(app.App):
|
||||
"""Main cliff application class.
|
||||
|
||||
Performs initialization of the command manager and
|
||||
configuration of basic engines.
|
||||
|
||||
"""
|
||||
|
||||
def build_option_parser(self, description, version, argparse_kwargs=None):
|
||||
"""Overrides default options for backwards compatibility."""
|
||||
p_inst = super(FuelClient, self)
|
||||
parser = p_inst.build_option_parser(description=description,
|
||||
version=version,
|
||||
argparse_kwargs=argparse_kwargs)
|
||||
|
||||
parser.add_argument(
|
||||
'--fuel-version',
|
||||
action=fuel_version.FuelVersionAction,
|
||||
help="show Fuel server's version number and exit"
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def configure_logging(self):
|
||||
super(FuelClient, self).configure_logging()
|
||||
|
||||
# there is issue with management url processing by keystone client
|
||||
# code in our workflow, so we have to mute appropriate keystone
|
||||
# loggers in order to get rid from unprocessable errors
|
||||
logging.getLogger('keystoneclient.httpclient').setLevel(logging.ERROR)
|
||||
|
||||
# increase level of loggin for urllib3 to avoid of displaying
|
||||
# of useless messages. List of logger names is needed for
|
||||
# consistency on different execution environments that could have
|
||||
# installed requests packages (which is used urllib3) of different
|
||||
# versions in turn
|
||||
for logger_name in ('requests.packages.urllib3.connectionpool',
|
||||
'urllib3.connectionpool'):
|
||||
logging.getLogger(logger_name).setLevel(logging.WARNING)
|
||||
|
||||
|
||||
@exceptions_decorator
|
||||
def main(argv=sys.argv[1:]):
|
||||
fuelclient_app = FuelClient(
|
||||
description='Command line interface and Python API wrapper for Fuel.',
|
||||
version='6.0.0',
|
||||
command_manager=CommandManager('fuelclient', convert_underscores=True)
|
||||
)
|
||||
return fuelclient_app.run(argv)
|
||||
0
fuelclient/tests/cli/__init__.py
Normal file
0
fuelclient/tests/cli/__init__.py
Normal file
57
fuelclient/tests/cli/test_v2_engine.py
Normal file
57
fuelclient/tests/cli/test_v2_engine.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2015 Mirantis, 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 mock
|
||||
|
||||
from fuelclient import main as main_mod
|
||||
from fuelclient.tests import base
|
||||
|
||||
|
||||
class BaseCLITest(base.UnitTestCase):
|
||||
def exec_v2_command(self, *args, **kwargs):
|
||||
"""Executes fuelclient with the specified arguments."""
|
||||
|
||||
return main_mod.main(argv=args)
|
||||
|
||||
def exec_v2_command_interactive(self, commands):
|
||||
"""Executes specified commands in one sesstion of interactive mode
|
||||
|
||||
Starts Fuel Client's interactive console and passes
|
||||
supplied commands there.
|
||||
|
||||
:param commands: The list of commands to execute in the
|
||||
Fuel Client's console.
|
||||
:type commands: list of str
|
||||
|
||||
"""
|
||||
with mock.patch.object(sys, 'stdin') as m_stdin:
|
||||
m_stdin.readline.side_effect = commands
|
||||
self.exec_v2_command()
|
||||
|
||||
@mock.patch('cliff.commandmanager.CommandManager.find_command')
|
||||
def test_command_non_interactive(self, m_find_command):
|
||||
args = ['help']
|
||||
self.exec_v2_command(*args)
|
||||
m_find_command.assert_called_once_with(args)
|
||||
|
||||
@mock.patch('cliff.commandmanager.CommandManager.find_command')
|
||||
def test_command_interactive(self, m_find_command):
|
||||
commands = ['quit']
|
||||
|
||||
self.exec_v2_command_interactive(commands)
|
||||
m_find_command.assert_called_once_with(commands)
|
||||
0
fuelclient/v1/__init__.py
Normal file
0
fuelclient/v1/__init__.py
Normal file
@@ -1,4 +1,5 @@
|
||||
argparse==1.2.1
|
||||
cliff>=1.9.0
|
||||
pbr>=0.6,!=0.7,<1.0
|
||||
python-keystoneclient>=0.7.1,<=0.7.2
|
||||
PyYAML==3.10
|
||||
|
||||
Reference in New Issue
Block a user