Add entry points for kb client
Created initial directory structure for KB commands to work. Modify setup.cfg to add entry point. Refactored shell.py to display help, bash-completion and exceptions for invalid credentials. Add testcases for the same. Change-Id: I8d31aef2722c73572074754f7a608b720ce2f678
This commit is contained in:
parent
f6e549f9be
commit
fda1462d75
5
kingbirdclient/commands/README.rst
Normal file
5
kingbirdclient/commands/README.rst
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
===============================
|
||||||
|
Commands
|
||||||
|
================================
|
||||||
|
|
||||||
|
This module helps in mapping kingbird commands to APIs.
|
0
kingbirdclient/commands/__init__.py
Normal file
0
kingbirdclient/commands/__init__.py
Normal file
@ -38,3 +38,12 @@ class IllegalArgumentException(KingbirdClientException):
|
|||||||
def __init__(self, message=None):
|
def __init__(self, message=None):
|
||||||
if message:
|
if message:
|
||||||
self.message = message
|
self.message = message
|
||||||
|
|
||||||
|
|
||||||
|
class CommandError(KingbirdClientException):
|
||||||
|
message = "CommandErrorException occurred"
|
||||||
|
code = "COMMAND_ERROR_EXCEPTION"
|
||||||
|
|
||||||
|
def __init__(self, message=None):
|
||||||
|
if message:
|
||||||
|
self.message = message
|
||||||
|
@ -21,6 +21,7 @@ import sys
|
|||||||
|
|
||||||
from kingbirdclient import __version__ as kingbird_version
|
from kingbirdclient import __version__ as kingbird_version
|
||||||
from kingbirdclient.api import client
|
from kingbirdclient.api import client
|
||||||
|
from kingbirdclient import exceptions
|
||||||
from kingbirdclient.openstack.common import cliutils as c
|
from kingbirdclient.openstack.common import cliutils as c
|
||||||
|
|
||||||
from cliff import app
|
from cliff import app
|
||||||
@ -289,19 +290,6 @@ class KingbirdShell(app.App):
|
|||||||
'(Env: KINGBIRDCLIENT_INSECURE)'
|
'(Env: KINGBIRDCLIENT_INSECURE)'
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
'--profile',
|
|
||||||
dest='profile',
|
|
||||||
metavar='HMAC_KEY',
|
|
||||||
help='HMAC key to use for encrypting context data for performance '
|
|
||||||
'profiling of operation. This key should be one of the '
|
|
||||||
'values configured for the osprofiler middleware in mistral, '
|
|
||||||
'it is specified in the profiler section of the mistral '
|
|
||||||
'configuration (i.e. /etc/kingbird/kingbird.conf). '
|
|
||||||
'Without the key, profiling will not be triggered even if '
|
|
||||||
'osprofiler is enabled on the server side.'
|
|
||||||
)
|
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def initialize_app(self, argv):
|
def initialize_app(self, argv):
|
||||||
@ -311,19 +299,33 @@ class KingbirdShell(app.App):
|
|||||||
|
|
||||||
self._set_shell_commands(self._get_commands(ver))
|
self._set_shell_commands(self._get_commands(ver))
|
||||||
|
|
||||||
do_help = ('help' in argv) or ('-h' in argv) or not argv
|
do_help = ['help', '-h', 'bash-completion']
|
||||||
|
|
||||||
# Set default for auth_url if not supplied. The default is not
|
|
||||||
# set at the parser to support use cases where auth is not enabled.
|
|
||||||
# An example use case would be a developer's environment.
|
|
||||||
if not self.options.auth_url:
|
|
||||||
if self.options.password or self.options.token:
|
|
||||||
self.options.auth_url = 'http://localhost:35357/v3'
|
|
||||||
|
|
||||||
# bash-completion should not require authentication.
|
# bash-completion should not require authentication.
|
||||||
if do_help or ('bash-completion' in argv):
|
skip_auth = ''.join(argv) in do_help
|
||||||
|
|
||||||
|
if skip_auth:
|
||||||
self.options.auth_url = None
|
self.options.auth_url = None
|
||||||
|
|
||||||
|
if self.options.auth_url and not self.options.token \
|
||||||
|
and not skip_auth:
|
||||||
|
if not self.options.tenant_name:
|
||||||
|
raise exceptions.CommandError(
|
||||||
|
("You must provide a tenant_name "
|
||||||
|
"via --os-tenantname env[OS_TENANT_NAME]")
|
||||||
|
)
|
||||||
|
if not self.options.username:
|
||||||
|
raise exceptions.CommandError(
|
||||||
|
("You must provide a username "
|
||||||
|
"via --os-username env[OS_USERNAME]")
|
||||||
|
)
|
||||||
|
|
||||||
|
if not self.options.password:
|
||||||
|
raise exceptions.CommandError(
|
||||||
|
("You must provide a password "
|
||||||
|
"via --os-password env[OS_PASSWORD]")
|
||||||
|
)
|
||||||
|
|
||||||
self.client = client.client(
|
self.client = client.client(
|
||||||
kingbird_url=self.options.kingbird_url,
|
kingbird_url=self.options.kingbird_url,
|
||||||
username=self.options.username,
|
username=self.options.username,
|
||||||
@ -335,10 +337,17 @@ class KingbirdShell(app.App):
|
|||||||
service_type=self.options.service_type,
|
service_type=self.options.service_type,
|
||||||
auth_token=self.options.token,
|
auth_token=self.options.token,
|
||||||
cacert=self.options.cacert,
|
cacert=self.options.cacert,
|
||||||
insecure=self.options.insecure,
|
insecure=self.options.insecure
|
||||||
profile=self.options.profile
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not self.options.auth_url and not skip_auth:
|
||||||
|
raise exceptions.CommandError(
|
||||||
|
("You must provide an auth url via either"
|
||||||
|
"--os-auth-url or env[OS_AUTH_URL] or "
|
||||||
|
"specify an auth_system which defines a"
|
||||||
|
" default url with --os-auth-system or env[OS_AUTH_SYSTEM]")
|
||||||
|
)
|
||||||
|
|
||||||
def _set_shell_commands(self, cmds_dict):
|
def _set_shell_commands(self, cmds_dict):
|
||||||
for k, v in cmds_dict.items():
|
for k, v in cmds_dict.items():
|
||||||
self.command_manager.add_command(k, v)
|
self.command_manager.add_command(k, v)
|
||||||
|
38
kingbirdclient/tests/test_help_and_bash_completion.py
Normal file
38
kingbirdclient/tests/test_help_and_bash_completion.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Copyright 2016 Ericsson AB.
|
||||||
|
#
|
||||||
|
# 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 re
|
||||||
|
|
||||||
|
from testtools import matchers
|
||||||
|
|
||||||
|
from kingbirdclient.tests import base_shell_test as base
|
||||||
|
|
||||||
|
|
||||||
|
class TestCLIBashCompletionV1(base.BaseShellTests):
|
||||||
|
def test_bash_completion(self):
|
||||||
|
bash_completion, stderr = self.shell('bash-completion')
|
||||||
|
self.assertIn('bash-completion', bash_completion)
|
||||||
|
self.assertFalse(stderr)
|
||||||
|
|
||||||
|
|
||||||
|
class TestCLIHelp(base.BaseShellTests):
|
||||||
|
def test_help(self):
|
||||||
|
required = [
|
||||||
|
'.*?^usage: ',
|
||||||
|
'.*?^\s+help\s+print detailed help for another command'
|
||||||
|
]
|
||||||
|
kb_help, stderr = self.shell('help')
|
||||||
|
for r in required:
|
||||||
|
self.assertThat((kb_help + stderr),
|
||||||
|
matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE))
|
133
kingbirdclient/tests/test_shell.py
Normal file
133
kingbirdclient/tests/test_shell.py
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
# Copyright 2016 EricssonAB.
|
||||||
|
#
|
||||||
|
# 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 mock
|
||||||
|
|
||||||
|
from kingbirdclient.tests import base_shell_test as base
|
||||||
|
|
||||||
|
|
||||||
|
class TestShell(base.BaseShellTests):
|
||||||
|
|
||||||
|
@mock.patch('kingbirdclient.api.client.determine_client_version')
|
||||||
|
def test_kingbird_version(self, mock):
|
||||||
|
self.shell(
|
||||||
|
'--os-kingbird-version=v1 quota-defaults'
|
||||||
|
)
|
||||||
|
self.assertTrue(mock.called)
|
||||||
|
kingbird_version = mock.call_args
|
||||||
|
self.assertEqual('v1', kingbird_version[0][0])
|
||||||
|
|
||||||
|
@mock.patch('kingbirdclient.api.client.determine_client_version')
|
||||||
|
def test_default_kingbird_version(self, mock):
|
||||||
|
default_version = 'v1.0'
|
||||||
|
self.shell('quota-defaults')
|
||||||
|
self.assertTrue(mock.called)
|
||||||
|
kingbird_version = mock.call_args
|
||||||
|
self.assertEqual(default_version, kingbird_version[0][0])
|
||||||
|
|
||||||
|
@mock.patch('kingbirdclient.api.client.client')
|
||||||
|
def test_env_variables(self, mock):
|
||||||
|
self.shell(
|
||||||
|
'--os-auth-url=https://127.0.0.1:35357/v3 '
|
||||||
|
'--os-username=admin '
|
||||||
|
'--os-password=1234 '
|
||||||
|
'--os-tenant-name=admin '
|
||||||
|
'quota-defaults'
|
||||||
|
)
|
||||||
|
self.assertTrue(mock.called)
|
||||||
|
params = mock.call_args
|
||||||
|
self.assertEqual('https://127.0.0.1:35357/v3', params[1]['auth_url'])
|
||||||
|
self.assertEqual('admin', params[1]['username'])
|
||||||
|
self.assertEqual('admin', params[1]['project_name'])
|
||||||
|
|
||||||
|
@mock.patch('kingbirdclient.api.client.client')
|
||||||
|
def test_env_without_auth_url(self, mock):
|
||||||
|
self.shell(
|
||||||
|
'--os-username=admin '
|
||||||
|
'--os-password=1234 '
|
||||||
|
'--os-tenant-name=admin '
|
||||||
|
'quota-defaults'
|
||||||
|
)
|
||||||
|
self.assertTrue(mock.called)
|
||||||
|
params = mock.call_args
|
||||||
|
self.assertEqual('', params[1]['auth_url'])
|
||||||
|
self.assertEqual('admin', params[1]['username'])
|
||||||
|
self.assertEqual('admin', params[1]['project_name'])
|
||||||
|
|
||||||
|
@mock.patch('kingbirdclient.api.client.client')
|
||||||
|
def test_kb_service_type(self, mock):
|
||||||
|
self.shell('--os-service-type=synchronization')
|
||||||
|
self.assertTrue(mock.called)
|
||||||
|
parameters = mock.call_args
|
||||||
|
self.assertEqual('synchronization', parameters[1]['service_type'])
|
||||||
|
|
||||||
|
@mock.patch('kingbirdclient.api.client.client')
|
||||||
|
def test_kb_default_service_type(self, mock):
|
||||||
|
self.shell('quota-defaults')
|
||||||
|
self.assertTrue(mock.called)
|
||||||
|
params = mock.call_args
|
||||||
|
# Default service type is synchronization
|
||||||
|
self.assertEqual('synchronization', params[1]['service_type'])
|
||||||
|
|
||||||
|
@mock.patch('kingbirdclient.api.client.client')
|
||||||
|
def test_kb_endpoint_type(self, mock):
|
||||||
|
self.shell('--os-kingbird-endpoint-type=adminURL quota-defaults')
|
||||||
|
self.assertTrue(mock.called)
|
||||||
|
params = mock.call_args
|
||||||
|
self.assertEqual('adminURL', params[1]['endpoint_type'])
|
||||||
|
|
||||||
|
@mock.patch('kingbirdclient.api.client.client')
|
||||||
|
def test_kb_default_endpoint_type(self, mock):
|
||||||
|
self.shell('quota-defaults')
|
||||||
|
self.assertTrue(mock.called)
|
||||||
|
params = mock.call_args
|
||||||
|
self.assertEqual('publicURL', params[1]['endpoint_type'])
|
||||||
|
|
||||||
|
@mock.patch('kingbirdclient.api.client.client')
|
||||||
|
def test_os_auth_token(self, mock):
|
||||||
|
self.shell(
|
||||||
|
'--os-auth-token=abcd1234 '
|
||||||
|
'quota-defaults'
|
||||||
|
)
|
||||||
|
self.assertTrue(mock.called)
|
||||||
|
params = mock.call_args
|
||||||
|
self.assertEqual('abcd1234', params[1]['auth_token'])
|
||||||
|
|
||||||
|
@mock.patch('kingbirdclient.api.client.client')
|
||||||
|
def test_command_without_kingbird_url(self, mock):
|
||||||
|
self.shell(
|
||||||
|
'quota-defaults'
|
||||||
|
)
|
||||||
|
self.assertTrue(mock.called)
|
||||||
|
params = mock.call_args
|
||||||
|
self.assertEqual('', params[1]['kingbird_url'])
|
||||||
|
|
||||||
|
@mock.patch('kingbirdclient.api.client.client')
|
||||||
|
def test_command_with_kingbird_url(self, mock):
|
||||||
|
self.shell(
|
||||||
|
'--os-kingbird-url=http://localhost:8118/v1 quota-defaults'
|
||||||
|
)
|
||||||
|
self.assertTrue(mock.called)
|
||||||
|
params = mock.call_args
|
||||||
|
self.assertEqual('http://localhost:8118/v1',
|
||||||
|
params[1]['kingbird_url'])
|
||||||
|
|
||||||
|
@mock.patch('kingbirdclient.api.client.client')
|
||||||
|
def test_command_without_project_name(self, mock):
|
||||||
|
self.shell(
|
||||||
|
'quota-defaults'
|
||||||
|
)
|
||||||
|
self.assertTrue(mock.called)
|
||||||
|
params = mock.call_args
|
||||||
|
self.assertEqual('', params[1]['project_name'])
|
@ -23,6 +23,10 @@ classifier =
|
|||||||
packages =
|
packages =
|
||||||
kingbirdclient
|
kingbirdclient
|
||||||
|
|
||||||
|
[entry_points]
|
||||||
|
console_scripts =
|
||||||
|
kingbird = kingbirdclient.shell:main
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
source-dir = doc/source
|
source-dir = doc/source
|
||||||
build-dir = doc/build
|
build-dir = doc/build
|
||||||
@ -48,4 +52,4 @@ output_file = kingbirdclient/locale/kingbirdclient.pot
|
|||||||
[build_releasenotes]
|
[build_releasenotes]
|
||||||
all_files = 1
|
all_files = 1
|
||||||
build-dir = releasenotes/build
|
build-dir = releasenotes/build
|
||||||
source-dir = releasenotes/source
|
source-dir = releasenotes/source
|
||||||
|
Loading…
x
Reference in New Issue
Block a user