Merge "Update python-ceilometerclient to support Keystone V3 API"
This commit is contained in:
@@ -10,38 +10,133 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from keystoneclient.v2_0 import client as ksclient
|
||||
from keystoneclient.auth.identity import v2 as v2_auth
|
||||
from keystoneclient.auth.identity import v3 as v3_auth
|
||||
from keystoneclient import discover
|
||||
from keystoneclient import session
|
||||
import six
|
||||
|
||||
from ceilometerclient.common import utils
|
||||
from ceilometerclient import exc
|
||||
|
||||
|
||||
def _get_ksclient(**kwargs):
|
||||
"""Get an endpoint and auth token from Keystone.
|
||||
def _get_keystone_session(**kwargs):
|
||||
# TODO(fabgia): the heavy lifting here should be really done by Keystone.
|
||||
# Unfortunately Keystone does not support a richer method to perform
|
||||
# discovery and return a single viable URL. A bug against Keystone has
|
||||
# been filed: https://bugs.launchpad.net/pyhton-keystoneclient/+bug/1330677
|
||||
|
||||
:param kwargs: keyword args containing credentials:
|
||||
* username: name of user
|
||||
* password: user's password
|
||||
* auth_url: endpoint to authenticate against
|
||||
* cacert: path of CA TLS certificate
|
||||
* insecure: allow insecure SSL (no cert verification)
|
||||
* tenant_{name|id}: name or ID of tenant
|
||||
"""
|
||||
return ksclient.Client(username=kwargs.get('username'),
|
||||
password=kwargs.get('password'),
|
||||
tenant_id=kwargs.get('tenant_id'),
|
||||
tenant_name=kwargs.get('tenant_name'),
|
||||
auth_url=kwargs.get('auth_url'),
|
||||
region_name=kwargs.get('region_name'),
|
||||
cacert=kwargs.get('cacert'),
|
||||
insecure=kwargs.get('insecure'))
|
||||
# first create a Keystone session
|
||||
cacert = kwargs.pop('cacert', None)
|
||||
cert = kwargs.pop('cert', None)
|
||||
key = kwargs.pop('key', None)
|
||||
insecure = kwargs.pop('insecure', False)
|
||||
auth_url = kwargs.pop('auth_url', None)
|
||||
project_id = kwargs.pop('project_id', None)
|
||||
project_name = kwargs.pop('project_name', None)
|
||||
|
||||
if insecure:
|
||||
verify = False
|
||||
else:
|
||||
verify = cacert or True
|
||||
|
||||
if cert and key:
|
||||
# passing cert and key together is deprecated in favour of the
|
||||
# requests lib form of having the cert and key as a tuple
|
||||
cert = (cert, key)
|
||||
|
||||
# create the keystone client session
|
||||
ks_session = session.Session(verify=verify, cert=cert)
|
||||
|
||||
try:
|
||||
# discover the supported keystone versions using the auth endpoint url
|
||||
ks_discover = discover.Discover(session=ks_session, auth_url=auth_url)
|
||||
# Determine which authentication plugin to use.
|
||||
v2_auth_url = ks_discover.url_for('2.0')
|
||||
v3_auth_url = ks_discover.url_for('3.0')
|
||||
except Exception:
|
||||
raise exc.CommandError('Unable to determine the Keystone version '
|
||||
'to authenticate with using the given '
|
||||
'auth_url: %s' % auth_url)
|
||||
|
||||
username = kwargs.pop('username', None)
|
||||
user_id = kwargs.pop('user_id', None)
|
||||
user_domain_name = kwargs.pop('user_domain_name', None)
|
||||
user_domain_id = kwargs.pop('user_domain_id', None)
|
||||
project_domain_name = kwargs.pop('project_domain_name', None)
|
||||
project_domain_id = kwargs.pop('project_domain_id', None)
|
||||
auth = None
|
||||
|
||||
if v3_auth_url and v2_auth_url:
|
||||
# the auth_url does not have the versions specified
|
||||
# e.g. http://no.where:5000
|
||||
# Keystone will return both v2 and v3 as viable options
|
||||
# but we need to decide based on the arguments passed
|
||||
# what version is callable
|
||||
if (user_domain_name or user_domain_id or project_domain_name or
|
||||
project_domain_id):
|
||||
# domain is supported only in v3
|
||||
auth = v3_auth.Password(
|
||||
v3_auth_url,
|
||||
username=username,
|
||||
user_id=user_id,
|
||||
user_domain_name=user_domain_name,
|
||||
user_domain_id=user_domain_id,
|
||||
project_domain_name=project_domain_name,
|
||||
project_domain_id=project_domain_id,
|
||||
**kwargs)
|
||||
else:
|
||||
# no domain, then use v2
|
||||
auth = v2_auth.Password(
|
||||
v2_auth_url,
|
||||
username,
|
||||
kwargs.pop('password', None),
|
||||
tenant_id=project_id,
|
||||
tenant_name=project_name)
|
||||
elif v3_auth_url:
|
||||
# the auth_url as v3 specified
|
||||
# e.g. http://no.where:5000/v3
|
||||
# Keystone will return only v3 as viable option
|
||||
auth = v3_auth.Password(
|
||||
v3_auth_url,
|
||||
username=username,
|
||||
user_id=user_id,
|
||||
user_domain_name=user_domain_name,
|
||||
user_domain_id=user_domain_id,
|
||||
project_domain_name=project_domain_name,
|
||||
project_domain_id=project_domain_id,
|
||||
**kwargs)
|
||||
elif v2_auth_url:
|
||||
# the auth_url as v2 specified
|
||||
# e.g. http://no.where:5000/v2.0
|
||||
# Keystone will return only v2 as viable option
|
||||
auth = v2_auth.Password(
|
||||
v2_auth_url,
|
||||
username,
|
||||
kwargs.pop('password', None),
|
||||
tenant_id=project_id,
|
||||
tenant_name=project_name)
|
||||
else:
|
||||
raise exc.CommandError('Unable to determine the Keystone version '
|
||||
'to authenticate with using the given '
|
||||
'auth_url.')
|
||||
|
||||
ks_session.auth = auth
|
||||
return ks_session
|
||||
|
||||
|
||||
def _get_endpoint(client, **kwargs):
|
||||
"""Get an endpoint using the provided keystone client."""
|
||||
return client.service_catalog.url_for(
|
||||
service_type=kwargs.get('service_type') or 'metering',
|
||||
endpoint_type=kwargs.get('endpoint_type') or 'publicURL')
|
||||
def _get_endpoint(ks_session, **kwargs):
|
||||
"""Get an endpoint using the provided keystone session."""
|
||||
|
||||
# set service specific endpoint types
|
||||
endpoint_type = kwargs.get('endpoint_type') or 'publicURL'
|
||||
service_type = kwargs.get('service_type') or 'metering'
|
||||
|
||||
endpoint = ks_session.get_endpoint(service_type=service_type,
|
||||
endpoint_type=endpoint_type,
|
||||
region_name=kwargs.get('region_name'))
|
||||
|
||||
return endpoint
|
||||
|
||||
|
||||
def get_client(api_version, **kwargs):
|
||||
@@ -55,10 +150,19 @@ def get_client(api_version, **kwargs):
|
||||
or:
|
||||
* os_username: name of user
|
||||
* os_password: user's password
|
||||
* os_user_id: user's id
|
||||
* os_user_domain_id: the domain id of the user
|
||||
* os_user_domain_name: the domain name of the user
|
||||
* os_project_id: the user project id
|
||||
* os_tenant_id: V2 alternative to os_project_id
|
||||
* os_project_name: the user project name
|
||||
* os_tenant_name: V2 alternative to os_project_name
|
||||
* os_project_domain_name: domain name for the user project
|
||||
* os_project_domain_id: domain id for the user project
|
||||
* os_auth_url: endpoint to authenticate against
|
||||
* os_cacert: path of CA TLS certificate
|
||||
* os_cert|os_cacert: path of CA TLS certificate
|
||||
* os_key: SSL private key
|
||||
* insecure: allow insecure SSL (no cert verification)
|
||||
* os_tenant_{name|id}: name or ID of tenant
|
||||
"""
|
||||
token = kwargs.get('os_auth_token')
|
||||
if token and not six.callable(token):
|
||||
@@ -66,36 +170,41 @@ def get_client(api_version, **kwargs):
|
||||
|
||||
if token and kwargs.get('ceilometer_url'):
|
||||
endpoint = kwargs.get('ceilometer_url')
|
||||
elif (kwargs.get('os_username') and
|
||||
kwargs.get('os_password') and
|
||||
kwargs.get('os_auth_url') and
|
||||
(kwargs.get('os_tenant_id') or kwargs.get('os_tenant_name'))):
|
||||
|
||||
else:
|
||||
project_id = kwargs.get('os_project_id') or kwargs.get('os_tenant_id')
|
||||
project_name = (kwargs.get('os_project_name') or
|
||||
kwargs.get('os_tenant_name'))
|
||||
ks_kwargs = {
|
||||
'username': kwargs.get('os_username'),
|
||||
'password': kwargs.get('os_password'),
|
||||
'tenant_id': kwargs.get('os_tenant_id'),
|
||||
'tenant_name': kwargs.get('os_tenant_name'),
|
||||
'user_id': kwargs.get('os_user_id'),
|
||||
'user_domain_id': kwargs.get('os_user_domain_id'),
|
||||
'user_domain_name': kwargs.get('os_user_domain_name'),
|
||||
'project_id': project_id,
|
||||
'project_name': project_name,
|
||||
'project_domain_name': kwargs.get('os_project_domain_name'),
|
||||
'project_domain_id': kwargs.get('os_project_domain_id'),
|
||||
'auth_url': kwargs.get('os_auth_url'),
|
||||
'region_name': kwargs.get('os_region_name'),
|
||||
'service_type': kwargs.get('os_service_type'),
|
||||
'endpoint_type': kwargs.get('os_endpoint_type'),
|
||||
'cacert': kwargs.get('os_cacert'),
|
||||
'insecure': kwargs.get('insecure'),
|
||||
'cert': kwargs.get('os_cert'),
|
||||
'key': kwargs.get('os_key'),
|
||||
'insecure': kwargs.get('insecure')
|
||||
}
|
||||
_ksclient = _get_ksclient(**ks_kwargs)
|
||||
token = token or (lambda: _ksclient.auth_token)
|
||||
|
||||
# retrieve session
|
||||
ks_session = _get_keystone_session(**ks_kwargs)
|
||||
token = token or (lambda: ks_session.get_token())
|
||||
|
||||
endpoint = kwargs.get('ceilometer_url') or \
|
||||
_get_endpoint(_ksclient, **ks_kwargs)
|
||||
_get_endpoint(ks_session, **ks_kwargs)
|
||||
|
||||
cli_kwargs = {
|
||||
'token': token,
|
||||
'insecure': kwargs.get('insecure'),
|
||||
'timeout': kwargs.get('timeout'),
|
||||
'cacert': kwargs.get('os_cacert'),
|
||||
'cert_file': kwargs.get('cert_file'),
|
||||
'key_file': kwargs.get('key_file'),
|
||||
'cert_file': kwargs.get('os_cert'),
|
||||
'key_file': kwargs.get('os_key')
|
||||
}
|
||||
|
||||
return Client(api_version, endpoint, **cli_kwargs)
|
||||
|
||||
@@ -32,6 +32,157 @@ from ceilometerclient.openstack.common import strutils
|
||||
|
||||
class CeilometerShell(object):
|
||||
|
||||
def _append_identity_args(self, parser):
|
||||
# FIXME(fabgia): identity related parameters should be passed by the
|
||||
# Keystone client itself to avoid constant update in all the services
|
||||
# clients. When this fix is merged this method can be made obsolete.
|
||||
# Bug: https://bugs.launchpad.net/python-keystoneclient/+bug/1332337
|
||||
parser.add_argument('-k', '--insecure',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help="Explicitly allow ceilometerclient to "
|
||||
"perform \"insecure\" SSL (https) requests. "
|
||||
"The server's certificate will "
|
||||
"not be verified against any certificate "
|
||||
"authorities. This option should be used with "
|
||||
"caution.")
|
||||
|
||||
# User related options
|
||||
parser.add_argument('--os-username',
|
||||
default=cliutils.env('OS_USERNAME'),
|
||||
help='Defaults to env[OS_USERNAME].')
|
||||
|
||||
parser.add_argument('--os_username',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-user-id',
|
||||
default=cliutils.env('OS_USER_ID'),
|
||||
help='Defaults to env[OS_USER_ID].')
|
||||
|
||||
parser.add_argument('--os-password',
|
||||
default=cliutils.env('OS_PASSWORD'),
|
||||
help='Defaults to env[OS_PASSWORD].')
|
||||
|
||||
parser.add_argument('--os_password',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
# Domain related options
|
||||
parser.add_argument('--os-user-domain-id',
|
||||
default=cliutils.env('OS_USER_DOMAIN_ID'),
|
||||
help='Defaults to env[OS_USER_DOMAIN_ID].')
|
||||
|
||||
parser.add_argument('--os-user-domain-name',
|
||||
default=cliutils.env('OS_USER_DOMAIN_NAME'),
|
||||
help='Defaults to env[OS_USER_DOMAIN_NAME].')
|
||||
|
||||
parser.add_argument('--os-project-domain-id',
|
||||
default=cliutils.env('OS_PROJECT_DOMAIN_ID'),
|
||||
help='Defaults to env[OS_PROJECT_DOMAIN_ID].')
|
||||
|
||||
parser.add_argument('--os-project-domain-name',
|
||||
default=cliutils.env('OS_PROJECT_DOMAIN_NAME'),
|
||||
help='Defaults to env[OS_PROJECT_DOMAIN_NAME].')
|
||||
|
||||
# Project V3 or Tenant V2 related options
|
||||
parser.add_argument('--os-project-id',
|
||||
default=cliutils.env('OS_PROJECT_ID'),
|
||||
help='Another way to specify tenant ID. '
|
||||
'This option is mutually exclusive with '
|
||||
' --os-tenant-id. '
|
||||
'Defaults to env[OS_PROJECT_ID].')
|
||||
|
||||
parser.add_argument('--os-project-name',
|
||||
default=cliutils.env('OS_PROJECT_NAME'),
|
||||
help='Another way to specify tenant name. '
|
||||
'This option is mutually exclusive with '
|
||||
' --os-tenant-name. '
|
||||
'Defaults to env[OS_PROJECT_NAME].')
|
||||
|
||||
parser.add_argument('--os-tenant-id',
|
||||
default=cliutils.env('OS_TENANT_ID'),
|
||||
help='This option is mutually exclusive with '
|
||||
' --os-project-id. '
|
||||
'Defaults to env[OS_PROJECT_ID].')
|
||||
|
||||
parser.add_argument('--os_tenant_id',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-tenant-name',
|
||||
default=cliutils.env('OS_TENANT_NAME'),
|
||||
help='Defaults to env[OS_TENANT_NAME].')
|
||||
|
||||
parser.add_argument('--os_tenant_name',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
# Auth related options
|
||||
parser.add_argument('--os-auth-url',
|
||||
default=cliutils.env('OS_AUTH_URL'),
|
||||
help='Defaults to env[OS_AUTH_URL].')
|
||||
|
||||
parser.add_argument('--os_auth_url',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-auth-token',
|
||||
default=cliutils.env('OS_AUTH_TOKEN'),
|
||||
help='Defaults to env[OS_AUTH_TOKEN].')
|
||||
|
||||
parser.add_argument('--os_auth_token',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-cacert',
|
||||
metavar='<ca-certificate-file>',
|
||||
dest='os_cacert',
|
||||
default=cliutils.env('OS_CACERT'),
|
||||
help='Path of CA TLS certificate(s) used to verify'
|
||||
'the remote server\'s certificate. Without this '
|
||||
'option ceilometer looks for the default system '
|
||||
'CA certificates.')
|
||||
|
||||
parser.add_argument('--os-cert',
|
||||
help='Path of certificate file to use in SSL '
|
||||
'connection. This file can optionally be '
|
||||
'prepended with the private key.')
|
||||
|
||||
parser.add_argument('--os-key',
|
||||
help='Path of client key to use in SSL '
|
||||
'connection. This option is not necessary '
|
||||
'if your key is prepended to your cert file.')
|
||||
|
||||
# Service Catalog related options
|
||||
parser.add_argument('--os-service-type',
|
||||
default=cliutils.env('OS_SERVICE_TYPE'),
|
||||
help='Defaults to env[OS_SERVICE_TYPE].')
|
||||
|
||||
parser.add_argument('--os_service_type',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-endpoint-type',
|
||||
default=cliutils.env('OS_ENDPOINT_TYPE'),
|
||||
help='Defaults to env[OS_ENDPOINT_TYPE].')
|
||||
|
||||
parser.add_argument('--os_endpoint_type',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-region-name',
|
||||
default=cliutils.env('OS_REGION_NAME'),
|
||||
help='Defaults to env[OS_REGION_NAME].')
|
||||
|
||||
parser.add_argument('--os_region_name',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
# Deprecated options
|
||||
parser.add_argument('--ca-file',
|
||||
dest='os_cacert',
|
||||
help='DEPRECATED! Use --os-cacert.')
|
||||
|
||||
parser.add_argument('--cert-file',
|
||||
dest='os_cert',
|
||||
help='DEPRECATED! Use --os-cert.')
|
||||
|
||||
parser.add_argument('--key-file',
|
||||
dest='os_key',
|
||||
help='DEPRECATED! Use --os-key.')
|
||||
|
||||
def get_base_parser(self):
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='ceilometer',
|
||||
@@ -62,91 +213,10 @@ class CeilometerShell(object):
|
||||
default=False, action="store_true",
|
||||
help="Print more verbose output.")
|
||||
|
||||
parser.add_argument('-k', '--insecure',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help="Explicitly allow ceilometerclient to "
|
||||
"perform \"insecure\" SSL (https) requests. "
|
||||
"The server's certificate will "
|
||||
"not be verified against any certificate "
|
||||
"authorities. This option should be used with "
|
||||
"caution.")
|
||||
|
||||
parser.add_argument('--cert-file',
|
||||
help='Path of certificate file to use in SSL '
|
||||
'connection. This file can optionally be prepended'
|
||||
' with the private key.')
|
||||
|
||||
parser.add_argument('--key-file',
|
||||
help='Path of client key to use in SSL connection.'
|
||||
' This option is not necessary if your key is '
|
||||
'prepended to your cert file.')
|
||||
|
||||
parser.add_argument('--os-cacert',
|
||||
metavar='<ca-certificate-file>',
|
||||
dest='os_cacert',
|
||||
default=cliutils.env('OS_CACERT'),
|
||||
help='Path of CA TLS certificate(s) used to verify'
|
||||
'the remote server\'s certificate. Without this '
|
||||
'option ceilometer looks for the default system '
|
||||
'CA certificates.')
|
||||
parser.add_argument('--ca-file',
|
||||
dest='os_cacert',
|
||||
help='DEPRECATED! Use --os-cacert.')
|
||||
|
||||
parser.add_argument('--timeout',
|
||||
default=600,
|
||||
help='Number of seconds to wait for a response.')
|
||||
|
||||
parser.add_argument('--os-username',
|
||||
default=cliutils.env('OS_USERNAME'),
|
||||
help='Defaults to env[OS_USERNAME].')
|
||||
|
||||
parser.add_argument('--os_username',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-password',
|
||||
default=cliutils.env('OS_PASSWORD'),
|
||||
help='Defaults to env[OS_PASSWORD].')
|
||||
|
||||
parser.add_argument('--os_password',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-tenant-id',
|
||||
default=cliutils.env('OS_TENANT_ID'),
|
||||
help='Defaults to env[OS_TENANT_ID].')
|
||||
|
||||
parser.add_argument('--os_tenant_id',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-tenant-name',
|
||||
default=cliutils.env('OS_TENANT_NAME'),
|
||||
help='Defaults to env[OS_TENANT_NAME].')
|
||||
|
||||
parser.add_argument('--os_tenant_name',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-auth-url',
|
||||
default=cliutils.env('OS_AUTH_URL'),
|
||||
help='Defaults to env[OS_AUTH_URL].')
|
||||
|
||||
parser.add_argument('--os_auth_url',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-region-name',
|
||||
default=cliutils.env('OS_REGION_NAME'),
|
||||
help='Defaults to env[OS_REGION_NAME].')
|
||||
|
||||
parser.add_argument('--os_region_name',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-auth-token',
|
||||
default=cliutils.env('OS_AUTH_TOKEN'),
|
||||
help='Defaults to env[OS_AUTH_TOKEN].')
|
||||
|
||||
parser.add_argument('--os_auth_token',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--ceilometer-url',
|
||||
default=cliutils.env('CEILOMETER_URL'),
|
||||
help='Defaults to env[CEILOMETER_URL].')
|
||||
@@ -163,19 +233,9 @@ class CeilometerShell(object):
|
||||
parser.add_argument('--ceilometer_api_version',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-service-type',
|
||||
default=cliutils.env('OS_SERVICE_TYPE'),
|
||||
help='Defaults to env[OS_SERVICE_TYPE].')
|
||||
|
||||
parser.add_argument('--os_service_type',
|
||||
help=argparse.SUPPRESS)
|
||||
|
||||
parser.add_argument('--os-endpoint-type',
|
||||
default=cliutils.env('OS_ENDPOINT_TYPE'),
|
||||
help='Defaults to env[OS_ENDPOINT_TYPE].')
|
||||
|
||||
parser.add_argument('--os_endpoint_type',
|
||||
help=argparse.SUPPRESS)
|
||||
# FIXME(fabgia): identity related parameters should be passed by the
|
||||
# Keystone client itself.
|
||||
self._append_identity_args(parser)
|
||||
|
||||
return parser
|
||||
|
||||
@@ -247,6 +307,14 @@ class CeilometerShell(object):
|
||||
# Return parsed args
|
||||
return api_version, subcommand_parser.parse_args(argv)
|
||||
|
||||
def no_project_and_domain_set(self, args):
|
||||
if not (args.os_project_id or (args.os_project_name and
|
||||
(args.os_user_domain_name or args.os_user_domain_id)) or
|
||||
(args.os_tenant_id or args.os_tenant_name)):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def main(self, argv):
|
||||
parsed = self.parse_args(argv)
|
||||
if parsed == 0:
|
||||
@@ -272,10 +340,17 @@ class CeilometerShell(object):
|
||||
"either --os-password or via "
|
||||
"env[OS_PASSWORD]")
|
||||
|
||||
if not (args.os_tenant_id or args.os_tenant_name):
|
||||
raise exc.CommandError("You must provide a tenant_id via "
|
||||
"either --os-tenant-id or via "
|
||||
"env[OS_TENANT_ID]")
|
||||
if self.no_project_and_domain_set(args):
|
||||
# steer users towards Keystone V3 API
|
||||
raise exc.CommandError("You must provide a project_id via "
|
||||
"either --os-project-id or via "
|
||||
"env[OS_PROJECT_ID] and "
|
||||
"a domain_name via either "
|
||||
"--os-user-domain-name or via "
|
||||
"env[OS_USER_DOMAIN_NAME] or "
|
||||
"a domain_id via either "
|
||||
"--os-user-domain-id or via "
|
||||
"env[OS_USER_DOMAIN_ID]")
|
||||
|
||||
if not args.os_auth_url:
|
||||
raise exc.CommandError("You must provide an auth url via "
|
||||
|
||||
@@ -20,7 +20,7 @@ from ceilometerclient.v2 import client as v2client
|
||||
FAKE_ENV = {'os_username': 'username',
|
||||
'os_password': 'password',
|
||||
'os_tenant_name': 'tenant_name',
|
||||
'os_auth_url': 'http://no.where',
|
||||
'os_auth_url': 'http://no.where:5000/',
|
||||
'os_auth_token': '1234',
|
||||
'ceilometer_url': 'http://no.where'}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import re
|
||||
import sys
|
||||
|
||||
import fixtures
|
||||
from keystoneclient.v2_0 import client as ksclient
|
||||
from keystoneclient import session as ks_session
|
||||
import mock
|
||||
import six
|
||||
from testtools import matchers
|
||||
@@ -24,25 +24,31 @@ from ceilometerclient import shell as ceilometer_shell
|
||||
from ceilometerclient.tests import utils
|
||||
from ceilometerclient.v1 import client as v1client
|
||||
|
||||
FAKE_ENV = {'OS_USERNAME': 'username',
|
||||
'OS_PASSWORD': 'password',
|
||||
'OS_TENANT_NAME': 'tenant_name',
|
||||
'OS_AUTH_URL': 'http://no.where'}
|
||||
FAKE_V2_ENV = {'OS_USERNAME': 'username',
|
||||
'OS_PASSWORD': 'password',
|
||||
'OS_TENANT_NAME': 'tenant_name',
|
||||
'OS_AUTH_URL': 'http://localhost:5000/v2.0'}
|
||||
|
||||
FAKE_V3_ENV = {'OS_USERNAME': 'username',
|
||||
'OS_PASSWORD': 'password',
|
||||
'OS_USER_DOMAIN_NAME': 'domain_name',
|
||||
'OS_PROJECT_ID': '1234567890',
|
||||
'OS_AUTH_URL': 'http://localhost:5000/v3'}
|
||||
|
||||
|
||||
class ShellTest(utils.BaseTestCase):
|
||||
re_options = re.DOTALL | re.MULTILINE
|
||||
|
||||
# Patch os.environ to avoid required auth info.
|
||||
def make_env(self, exclude=None):
|
||||
env = dict((k, v) for k, v in FAKE_ENV.items() if k != exclude)
|
||||
def make_env(self, env_version, exclude=None):
|
||||
env = dict((k, v) for k, v in env_version.items() if k != exclude)
|
||||
self.useFixture(fixtures.MonkeyPatch('os.environ', env))
|
||||
|
||||
def setUp(self):
|
||||
super(ShellTest, self).setUp()
|
||||
|
||||
@mock.patch('sys.stdout', new=six.StringIO())
|
||||
@mock.patch.object(ksclient, 'Client')
|
||||
@mock.patch.object(ks_session, 'Session')
|
||||
@mock.patch.object(v1client.http.HTTPClient, 'json_request')
|
||||
@mock.patch.object(v1client.http.HTTPClient, 'raw_request')
|
||||
def shell(self, argstr, mock_ksclient, mock_json, mock_raw):
|
||||
@@ -85,28 +91,60 @@ class ShellTest(utils.BaseTestCase):
|
||||
self.assertThat(help_text,
|
||||
matchers.MatchesRegex(r, self.re_options))
|
||||
|
||||
|
||||
class ShellKeystoneV2Test(ShellTest):
|
||||
|
||||
def test_auth_param(self):
|
||||
self.make_env(exclude='OS_USERNAME')
|
||||
self.make_env(FAKE_V2_ENV, exclude='OS_USERNAME')
|
||||
self.test_help()
|
||||
|
||||
@mock.patch.object(ksclient, 'Client')
|
||||
@mock.patch.object(ks_session, 'Session')
|
||||
def test_debug_switch_raises_error(self, mock_ksclient):
|
||||
mock_ksclient.side_effect = exc.HTTPUnauthorized
|
||||
self.make_env()
|
||||
self.make_env(FAKE_V2_ENV)
|
||||
args = ['--debug', 'event-list']
|
||||
self.assertRaises(exc.HTTPUnauthorized, ceilometer_shell.main, args)
|
||||
|
||||
@mock.patch.object(ksclient, 'Client')
|
||||
@mock.patch.object(ks_session, 'Session')
|
||||
def test_dash_d_switch_raises_error(self, mock_ksclient):
|
||||
mock_ksclient.side_effect = exc.CommandError("FAIL")
|
||||
self.make_env()
|
||||
self.make_env(FAKE_V2_ENV)
|
||||
args = ['-d', 'event-list']
|
||||
self.assertRaises(exc.CommandError, ceilometer_shell.main, args)
|
||||
|
||||
@mock.patch('sys.stderr')
|
||||
@mock.patch.object(ksclient, 'Client')
|
||||
@mock.patch.object(ks_session, 'Session')
|
||||
def test_no_debug_switch_no_raises_errors(self, mock_ksclient, __):
|
||||
mock_ksclient.side_effect = exc.HTTPUnauthorized("FAIL")
|
||||
self.make_env()
|
||||
self.make_env(FAKE_V2_ENV)
|
||||
args = ['event-list']
|
||||
self.assertRaises(SystemExit, ceilometer_shell.main, args)
|
||||
|
||||
|
||||
class ShellKeystoneV3Test(ShellTest):
|
||||
|
||||
def test_auth_param(self):
|
||||
self.make_env(FAKE_V3_ENV, exclude='OS_USER_DOMAIN_NAME')
|
||||
self.test_help()
|
||||
|
||||
@mock.patch.object(ks_session, 'Session')
|
||||
def test_debug_switch_raises_error(self, mock_ksclient):
|
||||
mock_ksclient.side_effect = exc.HTTPUnauthorized
|
||||
self.make_env(FAKE_V3_ENV)
|
||||
args = ['--debug', 'event-list']
|
||||
self.assertRaises(exc.HTTPUnauthorized, ceilometer_shell.main, args)
|
||||
|
||||
@mock.patch.object(ks_session, 'Session')
|
||||
def test_dash_d_switch_raises_error(self, mock_ksclient):
|
||||
mock_ksclient.side_effect = exc.CommandError("FAIL")
|
||||
self.make_env(FAKE_V3_ENV)
|
||||
args = ['-d', 'event-list']
|
||||
self.assertRaises(exc.CommandError, ceilometer_shell.main, args)
|
||||
|
||||
@mock.patch('sys.stderr')
|
||||
@mock.patch.object(ks_session, 'Session')
|
||||
def test_no_debug_switch_no_raises_errors(self, mock_ksclient, __):
|
||||
mock_ksclient.side_effect = exc.HTTPUnauthorized("FAIL")
|
||||
self.make_env(FAKE_V3_ENV)
|
||||
args = ['event-list']
|
||||
self.assertRaises(SystemExit, ceilometer_shell.main, args)
|
||||
|
||||
Reference in New Issue
Block a user