add more boilerplate files
Implements: blueprint vitrage-cli Change-Id: I1390ad4dfa40fcbddebaee628d8d928f5aa2bd49
This commit is contained in:
@@ -6,3 +6,4 @@ pbr>=1.6
|
|||||||
Babel>=1.3
|
Babel>=1.3
|
||||||
cliff>=1.14.0
|
cliff>=1.14.0
|
||||||
oslo.utils>=2.0.0
|
oslo.utils>=2.0.0
|
||||||
|
keystoneauth1>=1.0.0
|
||||||
@@ -28,6 +28,9 @@ setup-hooks =
|
|||||||
console_scripts =
|
console_scripts =
|
||||||
vitrage = vitrageclient.shell:main
|
vitrage = vitrageclient.shell:main
|
||||||
|
|
||||||
|
keystoneauth1.plugin =
|
||||||
|
vitrage-noauth = vitrageclient.noauth:VitrageNoAuthLoader
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
source-dir = doc/source
|
source-dir = doc/source
|
||||||
build-dir = doc/build
|
build-dir = doc/build
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
from vitrageclient.common import utils
|
from vitrageclient.common import utils
|
||||||
|
|
||||||
|
|
||||||
def get_client_class(version, *args, **kwargs):
|
def get_client(version, *args, **kwargs):
|
||||||
module = utils.import_versioned_module(version, 'client')
|
module = utils.import_versioned_module(version, 'client')
|
||||||
client_class = getattr(module, 'Client')
|
client_class = getattr(module, 'Client')
|
||||||
return client_class(*args, **kwargs)
|
return client_class(*args, **kwargs)
|
||||||
|
|||||||
@@ -11,15 +11,22 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
|
||||||
class VitrageBaseException(Exception):
|
class ClientException(Exception):
|
||||||
"""An error occurred."""
|
"""The base exception class for all exceptions this library raises."""
|
||||||
def __init__(self, message=None, *args, **kwargs):
|
message = 'Unknown Error'
|
||||||
super(BaseException, self).__init__(*args, **kwargs)
|
|
||||||
self.message = message
|
# noinspection PyMissingConstructor
|
||||||
|
def __init__(self, code, message=None, request_id=None,
|
||||||
|
url=None, method=None):
|
||||||
|
self.code = code
|
||||||
|
self.message = message or self.__class__.message
|
||||||
|
self.request_id = request_id
|
||||||
|
self.url = url
|
||||||
|
self.method = method
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.message or self.__class__.__doc__
|
formatted_string = "%s (HTTP %s)" % (self.message, self.code)
|
||||||
|
if self.request_id:
|
||||||
|
formatted_string += " (Request-ID: %s)" % self.request_id
|
||||||
|
|
||||||
|
return formatted_string
|
||||||
class VitrageClientException(VitrageBaseException):
|
|
||||||
pass
|
|
||||||
|
|||||||
73
vitrageclient/noauth.py
Normal file
73
vitrageclient/noauth.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#
|
||||||
|
# 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 os
|
||||||
|
|
||||||
|
from keystoneauth1 import loading
|
||||||
|
from keystoneauth1 import plugin
|
||||||
|
|
||||||
|
|
||||||
|
class VitrageNoAuthPlugin(plugin.BaseAuthPlugin):
|
||||||
|
# noinspection PyMissingConstructor
|
||||||
|
def __init__(self, user_id, project_id, roles, endpoint):
|
||||||
|
self._user_id = user_id
|
||||||
|
self._project_id = project_id
|
||||||
|
self._endpoint = endpoint
|
||||||
|
self._roles = roles
|
||||||
|
|
||||||
|
def get_token(self, session, **kwargs):
|
||||||
|
return '<no-token-needed>'
|
||||||
|
|
||||||
|
def get_headers(self, session, **kwargs):
|
||||||
|
return {'x-user-id': self._user_id,
|
||||||
|
'x-project-id': self._project_id,
|
||||||
|
'x-roles': self._roles}
|
||||||
|
|
||||||
|
def get_user_id(self, session, **kwargs):
|
||||||
|
return self._user_id
|
||||||
|
|
||||||
|
def get_project_id(self, session, **kwargs):
|
||||||
|
return self._project_id
|
||||||
|
|
||||||
|
def get_endpoint(self, session, **kwargs):
|
||||||
|
return self._endpoint
|
||||||
|
|
||||||
|
|
||||||
|
class VitrageOpt(loading.Opt):
|
||||||
|
@property
|
||||||
|
def argparse_args(self):
|
||||||
|
return ['--%s' % o.name for o in self._all_opts]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def argparse_default(self):
|
||||||
|
# select the first ENV that is not false-y or return None
|
||||||
|
for o in self._all_opts:
|
||||||
|
v = os.environ.get('VITRAGE_%s' % o.name.replace('-', '_').upper())
|
||||||
|
if v:
|
||||||
|
return v
|
||||||
|
return self.default
|
||||||
|
|
||||||
|
|
||||||
|
class VitrageNoAuthLoader(loading.BaseLoader):
|
||||||
|
plugin_class = VitrageNoAuthPlugin
|
||||||
|
|
||||||
|
def get_options(self):
|
||||||
|
options = super(VitrageNoAuthLoader, self).get_options()
|
||||||
|
options.extend([
|
||||||
|
VitrageOpt('user-id', help='User ID', required=True),
|
||||||
|
VitrageOpt('project-id', help='Project ID', required=True),
|
||||||
|
VitrageOpt('roles', help='Roles', default="admin"),
|
||||||
|
VitrageOpt('vitrage-endpoint', help='Vitrage endpoint',
|
||||||
|
dest="endpoint", required=True),
|
||||||
|
])
|
||||||
|
return options
|
||||||
@@ -16,11 +16,17 @@ Vitrage command line interface
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
import client
|
||||||
|
import logging
|
||||||
|
import noauth
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import warnings
|
||||||
|
|
||||||
from cliff import app
|
from cliff import app
|
||||||
from cliff import commandmanager
|
from cliff import commandmanager
|
||||||
|
from keystoneauth1 import exceptions
|
||||||
import sys
|
from keystoneauth1 import loading
|
||||||
from v1 import topology
|
from v1 import topology
|
||||||
from vitrageclient import __version__
|
from vitrageclient import __version__
|
||||||
|
|
||||||
@@ -45,8 +51,128 @@ class VitrageShell(app.App):
|
|||||||
deferred_help=True,
|
deferred_help=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def run(self, args):
|
def build_option_parser(self, description, version, **argparse_kwargs):
|
||||||
|
"""Return an argparse option parser for this application.
|
||||||
|
|
||||||
|
Subclasses may override this method to extend
|
||||||
|
the parser with more global options.
|
||||||
|
|
||||||
|
:param description: full description of the application
|
||||||
|
:paramtype description: str
|
||||||
|
:param version: version number for the application
|
||||||
|
:paramtype version: str
|
||||||
|
:param argparse_kwargs: extra keyword argument passed to the
|
||||||
|
ArgumentParser constructor
|
||||||
|
:paramtype extra_kwargs: dict
|
||||||
|
"""
|
||||||
|
|
||||||
|
parser = super(VitrageShell, self).build_option_parser(description,
|
||||||
|
version)
|
||||||
|
# Global arguments, one day this should go to keystoneauth1
|
||||||
|
parser.add_argument(
|
||||||
|
'--os-region-name',
|
||||||
|
metavar='<auth-region-name>',
|
||||||
|
dest='region_name',
|
||||||
|
default=os.environ.get('OS_REGION_NAME'),
|
||||||
|
help='Authentication region name (Env: OS_REGION_NAME)')
|
||||||
|
parser.add_argument(
|
||||||
|
'--os-interface',
|
||||||
|
metavar='<interface>',
|
||||||
|
dest='interface',
|
||||||
|
choices=['admin', 'public', 'internal'],
|
||||||
|
default=os.environ.get('OS_INTERFACE'),
|
||||||
|
help='Select an interface type.'
|
||||||
|
' Valid interface types: [admin, public, internal].'
|
||||||
|
' (Env: OS_INTERFACE)')
|
||||||
|
parser.add_argument(
|
||||||
|
'--vitrage-api-version',
|
||||||
|
default=os.environ.get('VITRAGE_API_VERSION', '1'),
|
||||||
|
help='Defaults to env[VITRAGE_API_VERSION] or 1.')
|
||||||
|
loading.register_session_argparse_arguments(parser=parser)
|
||||||
|
plugin = loading.register_auth_argparse_arguments(
|
||||||
|
parser=parser, argv=sys.argv, default="password")
|
||||||
|
|
||||||
|
if not isinstance(plugin, noauth.VitrageNoAuthLoader):
|
||||||
|
parser.add_argument(
|
||||||
|
'--vitrage-endpoint',
|
||||||
|
metavar='<endpoint>',
|
||||||
|
dest='endpoint',
|
||||||
|
default=os.environ.get('VITRAGE_ENDPOINT'),
|
||||||
|
help='Vitrage endpoint (Env: VITRAGE_ENDPOINT)')
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
@property
|
||||||
|
def client(self):
|
||||||
|
if self._client is None:
|
||||||
|
if hasattr(self.options, "endpoint"):
|
||||||
|
endpoint_override = self.options.endpoint
|
||||||
|
else:
|
||||||
|
endpoint_override = None
|
||||||
|
auth_plugin = loading.load_auth_from_argparse_arguments(
|
||||||
|
self.options)
|
||||||
|
session = loading.load_session_from_argparse_arguments(
|
||||||
|
self.options, auth=auth_plugin)
|
||||||
|
|
||||||
|
# noinspection PyAttributeOutsideInit
|
||||||
|
self._client = client.get_client(
|
||||||
|
self.options.vitrage_api_version,
|
||||||
|
session=session,
|
||||||
|
interface=self.options.interface,
|
||||||
|
region_name=self.options.region_name,
|
||||||
|
endpoint_override=endpoint_override)
|
||||||
|
|
||||||
|
return self._client
|
||||||
|
|
||||||
|
def clean_up(self, cmd, result, err):
|
||||||
|
if err and isinstance(err, exceptions.HttpError):
|
||||||
|
try:
|
||||||
|
error = err.response.json()
|
||||||
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
print(error['description'])
|
||||||
|
|
||||||
|
def configure_logging(self):
|
||||||
|
if self.options.debug:
|
||||||
|
# --debug forces verbose_level 3
|
||||||
|
# Set this here so cliff.app.configure_logging() can work
|
||||||
|
self.options.verbose_level = 3
|
||||||
|
|
||||||
|
super(VitrageShell, self).configure_logging()
|
||||||
|
root_logger = logging.getLogger('')
|
||||||
|
|
||||||
|
# Set logging to the requested level
|
||||||
|
if self.options.verbose_level == 0:
|
||||||
|
# --quiet
|
||||||
|
root_logger.setLevel(logging.ERROR)
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
elif self.options.verbose_level == 1:
|
||||||
|
# This is the default case, no --debug, --verbose or --quiet
|
||||||
|
root_logger.setLevel(logging.WARNING)
|
||||||
|
warnings.simplefilter("ignore")
|
||||||
|
elif self.options.verbose_level == 2:
|
||||||
|
# One --verbose
|
||||||
|
root_logger.setLevel(logging.INFO)
|
||||||
|
warnings.simplefilter("once")
|
||||||
|
elif self.options.verbose_level >= 3:
|
||||||
|
# Two or more --verbose
|
||||||
|
root_logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
# Hide some useless message
|
||||||
|
requests_log = logging.getLogger("requests")
|
||||||
|
cliff_log = logging.getLogger('cliff')
|
||||||
|
stevedore_log = logging.getLogger('stevedore')
|
||||||
|
iso8601_log = logging.getLogger("iso8601")
|
||||||
|
|
||||||
|
cliff_log.setLevel(logging.ERROR)
|
||||||
|
stevedore_log.setLevel(logging.ERROR)
|
||||||
|
iso8601_log.setLevel(logging.ERROR)
|
||||||
|
|
||||||
|
if self.options.debug:
|
||||||
|
requests_log.setLevel(logging.DEBUG)
|
||||||
|
else:
|
||||||
|
requests_log.setLevel(logging.ERROR)
|
||||||
|
|
||||||
|
|
||||||
def main(args=None):
|
def main(args=None):
|
||||||
@@ -61,5 +187,6 @@ def main(args=None):
|
|||||||
print(e)
|
print(e)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
# noinspection PyPackageRequirements
|
||||||
from oslotest import base
|
from oslotest import base
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user