Adding keystoneauth sessions support

This patch introduces the possibility of instantiating
monascaclient using a keystoneauth session by doing the
following:

* Introduces new SessionClient object;
* Refactor the keystoneclient wrapper module with keystoneauth;
* Updates documentation.

Client code and tests are also updated.

Change-Id: I99ae10b2832869cf68d8219468400a421b6fa12b
Closes-Bug: 1569505
This commit is contained in:
Paulo Ewerton 2016-04-04 17:49:15 +00:00
parent 962f2deb6a
commit 4c103fdf49
10 changed files with 302 additions and 160 deletions

View File

@ -80,10 +80,13 @@ When using Keystone to obtain the token and endpoint::
export OS_PASSWORD=
export OS_USER_DOMAIN_NAME=
export OS_PROJECT_NAME=
export OS_PROJECT_DOMAIN_NAME=
export OS_PROJECT_NAME=
export OS_AUTH_URL=
export OS_REGION_NAME=
When OS_USER_DOMAIN_NAME is not set, then 'Default' is assumed. Alternatively IDs can be used instead of names.
When OS_USER_DOMAIN_NAME and OS_PROJECT_DOMAIN_NAME are not set, then 'Default'
is assumed. Alternatively IDs can be used instead of names.
When using Vagrant Environment with middleware disabled::
@ -102,7 +105,7 @@ You'll find complete documentation on the shell by running
[--os-password OS_PASSWORD] [--os-project-id OS_PROJECT_ID]
[--os-user-domain-id OS_USER_DOMAIN_ID] [--os-user-domain-name OS_USER_DOMAIN_NAME]
[--os-project-name OS_PROJECT_NAME]
[--os-domain-id OS_DOMAIN_ID] [--os-domain-name OS_DOMAIN_NAME]
[--os-project-domain-id OS_PROJECT_DOMAIN_ID] [--os-project-domain-name OS_PROJECT_DOMAIN_NAME]
[--os-auth-url OS_AUTH_URL] [--os-region-name OS_REGION_NAME]
[--os-auth-token OS_AUTH_TOKEN] [--os-no-client-auth]
[--monasca-api-url MONASCA_API_URL]
@ -169,10 +172,10 @@ You'll find complete documentation on the shell by running
Defaults to env[OS_PROJECT_ID].
--os-project-name OS_PROJECT_NAME
Defaults to env[OS_PROJECT_NAME].
--os-domain-id OS_DOMAIN_ID
Defaults to env[OS_DOMAIN_ID].
--os-domain-name OS_DOMAIN_NAME
Defaults to env[OS_DOMAIN_NAME].
--os-project-domain-id OS_PROJECT_DOMAIN_ID
Defaults to env[OS_PROJECT_DOMAIN_ID].
--os-project-domain-name OS_PROJECT_DOMAIN_NAME
Defaults to env[OS_PROJECT_DOMAIN_NAME].
--os-auth-url OS_AUTH_URL Defaults to env[OS_AUTH_URL].
--os-region-name OS_REGION_NAME
Defaults to env[OS_REGION_NAME].
@ -340,14 +343,20 @@ Python API
There's also a complete Python API.
In order to use the python api directly, you must pass in a valid auth token and
monasca api endpoint, or you can pass in the credentials required by the keystone
client and let the Python API do the authentication. The user can obtain the token
and endpoint using the keystone client api:
http://docs.openstack.org/developer/python-keystoneclient/.
monasca api endpoint or, preferably, a `keystoneauth session
<http://docs.openstack.org/developer/keystoneauth/using-sessions.html>`.
Alternatively, you can pass in the credentials required by the keystoneauth
and let the Python API do the authentication. The user can obtain the session,
token and endpoint using the keystoneauth api:
http://docs.openstack.org/developer/keystoneauth.
The service catalog name for our API endpoint is "monasca".
Start using the monascaclient API by constructing the monascaclient client.Client class.
The Client class takes these parameters: api_version, endpoint, and token.
The Client class takes these parameters:
#. api_version, session
#. api_version, endpoint, and token (when using the client without a session)
The Client class is used to call all monasca-api resource commands (i.e.
client.Client.metrics.create(fields)).
@ -358,7 +367,9 @@ up to the user to get a new token from keystone which can be passed
into the client.Client.replace_token(token) method. If you constructed
the Client with all the keystone credentials needed to authenticate,
then the API will automatically try one time to re-authenticate with
keystone whenever the token expires.
keystone whenever the token expires. When using a session, though, this case
will be handled by keystoneauth and replacing the session token will
not be supported.
The api_version matches the version of the Monasca API. Currently it is 'v2_0'.
@ -377,10 +388,13 @@ Refer to the example in python-monascaclient/client_api_example.py for more deta
# Authenticate to Keystone
keystone_url = 'http://keystone:5000/v3'
ks = ksclient.KSClient(auth_url=keystone_url, username='user', password='password')
ks = ksclient.KSClient(auth_url=keystone_url, username='user',
password='password', project_name='project_name',
project_domain_name='project_domain_name',
user_domain_name='user_domain_name')
# construct the mon client
monasca_client = client.Client(api_version, ks.monasca_url, token=ks.token)
monasca_client = client.Client(api_version, session=ks.session)
# call the metric-create command
dimensions = {'instance_id': '12345', 'service': 'hello'}

View File

@ -16,6 +16,7 @@
""" An example using monascaclient via the Python API """
from monascaclient import client
from monascaclient import ksclient
import monascaclient.exc as exc
import time
@ -27,15 +28,14 @@ endpoint = 'http://192.168.10.4:8080/v2.0'
api_version = '2_0'
# Pass in the keystone authentication kwargs to construct a monasca client.
# The monasca_client will try to authenticate with keystone one time
# when it sees a 401 unauthorized resp, to take care of a stale token.
# In this example no token is input, so it will get a 401 when executing the
# first metrics.create request, and will authenticate and try again.
auth_kwargs = {'username': 'mini-mon',
'password': 'password',
'user_domain_name': 'mini-mon',
'project_name': 'mini-mon',
'project_domain_name': 'mini-mon',
'auth_url': 'http://192.168.10.5:35357/v3/'}
monasca_client = client.Client(api_version, endpoint, **auth_kwargs)
ksclient = ksclient.KSClient(**auth_kwargs)
monasca_client = client.Client(api_version, session=ksclient.session)
# you can reference the monascaclient.v2_0.shell.py
# do_commands for command field initialization.

2
debian/control vendored
View File

@ -11,5 +11,5 @@ X-Python-Version: >= 2.6
Package: python-monclient
Architecture: all
Section: python
Depends: ${misc:Depends}, ${python:Depends}, libpython2.7, python-pkg-resources, python-pbr, python-keystoneclient, python-yaml, python-requests, python-prettytable, python-six
Depends: ${misc:Depends}, ${python:Depends}, libpython2.7, python-pkg-resources, python-pbr, keystoneauth1, python-yaml, python-requests, python-prettytable, python-six
Description: CLI for Monitoring

View File

@ -18,6 +18,7 @@ import logging
import os
import socket
from keystoneauth1 import adapter
import requests
import six
@ -53,6 +54,12 @@ def get_system_ca_file():
LOG.warn("System ca file could not be found.")
def unauthorized(resp):
status401 = (resp.status_code == 401)
status500 = (resp.status_code == 500 and "(HTTP 401)" in resp.content)
return status401 or status500
class HTTPClient(object):
def __init__(self, endpoint, write_timeout=None, read_timeout=None, **kwargs):
@ -74,8 +81,8 @@ class HTTPClient(object):
self.project_name = kwargs.get('project_name')
self.region_name = kwargs.get('region_name')
self.project_id = kwargs.get('project_id')
self.domain_id = kwargs.get('domain_id')
self.domain_name = kwargs.get('domain_name')
self.project_domain_id = kwargs.get('project_domain_id')
self.project_domain_name = kwargs.get('project_domain_name')
self.endpoint_type = kwargs.get('endpoint_type')
self.service_type = kwargs.get('service_type')
self.keystone_timeout = kwargs.get('keystone_timeout')
@ -114,8 +121,8 @@ class HTTPClient(object):
'os_cacert': self.ssl_connection_params['os_cacert'],
'project_id': self.project_id,
'project_name': self.project_name,
'domain_id': self.domain_id,
'domain_name': self.domain_name,
'project_domain_id': self.project_domain_id,
'project_domain_name': self.project_domain_name,
'insecure': self.ssl_connection_params['insecure'],
'region_name': self.region_name,
'keystone_timeout': self.keystone_timeout
@ -213,7 +220,7 @@ class HTTPClient(object):
resp = self._make_request(method, url, allow_redirects, timeout,
**kwargs)
if self._unauthorized(resp):
if unauthorized(resp):
try:
# re-authenticate and attempt one more request
self.re_authenticate()
@ -227,13 +234,8 @@ class HTTPClient(object):
self._check_status_code(resp, method, **kwargs)
return resp
def _unauthorized(self, resp):
status401 = (resp.status_code == 401)
status500 = (resp.status_code == 500 and "(HTTP 401)" in resp.content)
return status401 or status500
def _check_status_code(self, resp, method, **kwargs):
if self._unauthorized(resp):
if unauthorized(resp):
message = "Unauthorized error"
raise exc.HTTPUnauthorized(message=message)
elif 400 <= resp.status_code < 600:
@ -338,3 +340,81 @@ class HTTPClient(object):
def patch(self, url, **kwargs):
return self.client_request("PATCH", url, **kwargs)
class SessionClient(adapter.LegacyJsonAdapter):
"""HTTP client based on keystoneauth session."""
def __init__(self, user_agent=USER_AGENT, logger=LOG, *args, **kwargs):
super(SessionClient, self).__init__(*args, **kwargs)
def _http_request(self, url, method, **kwargs):
kwargs.setdefault('user_agent', self.user_agent)
kwargs.setdefault('auth', self.auth)
kwargs.setdefault('endpoint_override', self.endpoint_override)
endpoint_filter = kwargs.setdefault('endpoint_filter', {})
endpoint_filter.setdefault('interface', self.interface)
endpoint_filter.setdefault('service_type', self.service_type)
endpoint_filter.setdefault('region_name', self.region_name)
resp = self.session.request(url, method, raise_exc=False, **kwargs)
if unauthorized(resp):
message = "Unauthorized error"
raise exc.HTTPUnauthorized(message=message)
if 400 <= resp.status_code < 600:
raise exc.from_response(resp)
elif resp.status_code in (301, 302, 305):
# Redirected. Reissue the request to the new location.
location = resp.headers.get('location')
resp = self._http_request(location, method, **kwargs)
elif resp.status_code == 300:
raise exc.from_response(resp)
return resp
def json_request(self, method, url, **kwargs):
kwargs.setdefault('headers', {})
kwargs['headers'].setdefault('Content-Type', 'application/json')
kwargs['headers'].setdefault('Accept', 'application/json')
if 'data' in kwargs:
kwargs['data'] = jsonutils.dumps(kwargs['data'])
resp = self._http_request(url, method, **kwargs)
body = resp.content
content_type = resp.headers.get('content-type', None)
status = resp.status_code
if status == 204 or status == 205 or content_type is None:
return resp, list()
if 'application/json' in content_type:
try:
body = resp.json()
except ValueError:
LOG.error('Could not decode response body as JSON')
else:
body = None
return resp, body
def raw_request(self, method, url, **kwargs):
kwargs.setdefault('headers', {})
kwargs['headers'].setdefault('Content-Type',
'application/octet-stream')
self._http_request(url, method, **kwargs)
def credentials_headers(self):
credentials = self.session.auth.get_cache_id_elements()
username = credentials.get('password_username')
password = credentials.get('password_password')
creds = {}
if username:
creds['X-Auth-User'] = username
if password:
creds['X-Auth-Key'] = password
return creds

View File

@ -14,11 +14,15 @@
# limitations under the License.
"""
Wrapper around python keystone client to assist in getting a properly scoped token and the registered service
endpoint for Monasca.
Wrapper around keystoneauth to assist in getting a session, a properly scoped
token and the registered service endpoint for Monasca.
# FIXME(pauloewerton): this is not an appropriate name for this module nor
# for the class. Kept for backwards compatibility.
"""
from keystoneclient.v3 import client
from keystoneauth1.identity import v3
from keystoneauth1 import loading
from monascaclient import exc
@ -26,60 +30,74 @@ from monascaclient import exc
class KSClient(object):
def __init__(self, **kwargs):
"""Get an endpoint and auth token from Keystone.
"""Get a session, an endpoint and auth token from Keystone.
:param username: name of user
:param password: user's password
:param user_domain_id: unique identifier of domain username resides in (optional)
:param user_domain_name: name of domain for username (optional), if user_domain_id not specified
:param user_domain_id: unique identifier of domain the username
resides in (optional)
:param user_domain_name: name of domain for username (optional),
if user_domain_id not specified
:param project_id: unique identifier of project
:param project_name: name of project
:param domain_name: name of domain project is in
:param domain_id: id of domain project is in
:param project_domain_name: name of domain project is in
:param project_domain_id: id of domain project is in
:param auth_url: endpoint to authenticate against
:param token: token to use instead of username/password
"""
kc_args = {'auth_url': kwargs.get('auth_url'),
'insecure': kwargs.get('insecure'),
'timeout': kwargs.get('keystone_timeout')}
auth_params = {
'auth_url': kwargs.get('auth_url'),
'project_id': kwargs.get('project_id'),
'project_name': kwargs.get('project_name'),
'project_domain_id': kwargs.get('project_domain_id'),
'project_domain_name': kwargs.get('project_domain_name')
}
if kwargs.get('os_cacert'):
kc_args['cacert'] = kwargs.get('os_cacert')
if kwargs.get('project_id'):
kc_args['project_id'] = kwargs.get('project_id')
elif kwargs.get('project_name'):
kc_args['project_name'] = kwargs.get('project_name')
if kwargs.get('domain_name'):
kc_args['project_domain_name'] = kwargs.get('domain_name')
if kwargs.get('domain_id'):
kc_args['project_domain_id'] = kwargs.get('domain_id')
password_params = {
'username': kwargs.get('username'),
'password': kwargs.get('password'),
'user_domain_id': kwargs.get('user_domain_id'),
'user_domain_name': kwargs.get('user_domain_name')
}
if kwargs.get('token'):
kc_args['token'] = kwargs.get('token')
token = kwargs.get('token')
if token:
auth_params['token'] = token
auth = v3.Token(**auth_params)
else:
kc_args['username'] = kwargs.get('username')
kc_args['password'] = kwargs.get('password')
# when username not in the default domain (id='default'), supply user domain (as namespace)
if kwargs.get('user_domain_name'):
kc_args['user_domain_name'] = kwargs.get('user_domain_name')
if kwargs.get('user_domain_id'):
kc_args['user_domain_id'] = kwargs.get('user_domain_id')
auth_params.update(password_params)
auth = v3.Password(**auth_params)
session_params = {
'insecure': kwargs.get('insecure'),
'cacert': kwargs.get('os_cacert'),
'cert': kwargs.get('cert_file'),
'key': kwargs.get('key_file')
}
self._session = loading.session.Session().load_from_options(
auth=auth, **session_params)
self._kwargs = kwargs
self._keystone = client.Client(**kc_args)
self._token = None
self._monasca_url = None
@property
def session(self):
"""Return the keystoneauth session object used for authentication."""
return self._session
@property
def token(self):
"""Token property
Validate token is project scoped and return it if it is
project_id and auth_token were fetched when keystone client was created
Validate token is project scoped and return it if its project_id and
token were fetched when keystoneauth session was created
"""
if self._token is None:
if self._keystone.project_id:
self._token = self._keystone.auth_token
if self._session.get_project_id():
self._token = self._session.get_token()
else:
raise exc.CommandError("No project id or project name.")
return self._token
@ -87,15 +105,13 @@ class KSClient(object):
@property
def monasca_url(self):
"""Return the monasca publicURL registered in keystone."""
if self._monasca_url is None:
if self._kwargs.get('region_name'):
self._monasca_url = self._keystone.service_catalog.url_for(
service_type=self._kwargs.get('service_type') or 'monitoring',
attr='region',
filter_value=self._kwargs.get('region_name'),
endpoint_type=self._kwargs.get('endpoint_type') or 'publicURL')
else:
self._monasca_url = self._keystone.service_catalog.url_for(
service_type=self._kwargs.get('service_type') or 'monitoring',
endpoint_type=self._kwargs.get('endpoint_type') or 'publicURL')
service_type = self._kwargs.get('service_type', 'monitoring')
service_name = self._kwargs.get('service_name', 'monasca')
interface = self._kwargs.get('endpoint_type', 'public')
region_name = self._kwargs.get('region_name')
if not self._monasca_url:
self._monasca_url = self._session.get_endpoint(
service_type=service_type, service_name=service_name,
interface=interface, region_name=region_name)
return self._monasca_url

View File

@ -140,18 +140,18 @@ class MonascaShell(object):
parser.add_argument('--os_project_name',
help=argparse.SUPPRESS)
parser.add_argument('--os-domain-id',
default=utils.env('OS_DOMAIN_ID'),
help='Defaults to env[OS_DOMAIN_ID].')
parser.add_argument('--os-project-domain-id',
default=utils.env('OS_PROJECT_DOMAIN_ID'),
help='Defaults to env[OS_PROJECT_DOMAIN_ID].')
parser.add_argument('--os_domain_id',
parser.add_argument('--os_project_domain_id',
help=argparse.SUPPRESS)
parser.add_argument('--os-domain-name',
default=utils.env('OS_DOMAIN_NAME'),
help='Defaults to env[OS_DOMAIN_NAME].')
parser.add_argument('--os-project-domain-name',
default=utils.env('OS_PROJECT_DOMAIN_NAME'),
help='Defaults to env[OS_PROJECT_DOMAIN_NAME].')
parser.add_argument('--os_domain_name',
parser.add_argument('--os_project_domain_name',
help=argparse.SUPPRESS)
parser.add_argument('--os-auth-url',
@ -329,71 +329,50 @@ class MonascaShell(object):
'auth_url': args.os_auth_url,
'service_type': args.os_service_type,
'endpoint_type': args.os_endpoint_type,
'os_cacert': args.os_cacert,
'user_domain_id': args.os_user_domain_id,
'user_domain_name': args.os_user_domain_name,
'project_id': args.os_project_id,
'project_name': args.os_project_name,
'domain_id': args.os_domain_id,
'domain_name': args.os_domain_name,
'project_domain_id': args.os_project_domain_id,
'project_domain_name': args.os_project_domain_name,
'insecure': args.insecure,
'os_cacert': args.os_cacert,
'cert_file': args.cert_file,
'key_file': args.key_file,
'region_name': args.os_region_name,
'keystone_timeout': args.keystone_timeout
}
endpoint = args.monasca_api_url
session = None
if not args.os_no_client_auth:
_ksclient = ksclient.KSClient(**kwargs)
if args.os_auth_token:
token = args.os_auth_token
else:
try:
token = _ksclient.token
except exc.CommandError:
raise exc.CommandError(
"User does not have a default project. "
"You must provide a project id using "
"--os-project-id or via env[OS_PROJECT_ID], "
"or you must provide a project name using "
"--os-project-name or via env[OS_PROJECT_NAME] "
"and a project domain using --os-domain-name, via "
"env[OS_DOMAIN_NAME], using --os-domain-id or "
"via env[OS_DOMAIN_ID]")
kwargs = {
'token': token,
'insecure': args.insecure,
'os_cacert': args.os_cacert,
'cert_file': args.cert_file,
'key_file': args.key_file,
'username': args.os_username,
'password': args.os_password,
'service_type': args.os_service_type,
'endpoint_type': args.os_endpoint_type,
'auth_url': args.os_auth_url,
'keystone_timeout': args.keystone_timeout
}
if args.os_user_domain_name:
kwargs['user_domain_name'] = args.os_user_domain_name
if args.os_user_domain_id:
kwargs['user_domain_id'] = args.os_user_domain_id
if args.os_region_name:
kwargs['region_name'] = args.os_region_name
if args.os_project_name:
kwargs['project_name'] = args.os_project_name
if args.os_project_id:
kwargs['project_id'] = args.os_project_id
if args.os_domain_name:
kwargs['domain_name'] = args.os_domain_name
if args.os_domain_id:
kwargs['domain_id'] = args.os_domain_id
# Kept to check whether the token is indeed project scoped
try:
_ksclient.token
except exc.CommandError:
raise exc.CommandError(
"User does not have a default project. "
"You must provide a project id using "
"--os-project-id or via env[OS_PROJECT_ID], "
"or you must provide a project name using "
"--os-project-name or via env[OS_PROJECT_NAME] "
"and a project domain using --os-project-domain-name, "
"via env[OS_PROJECT_DOMAIN_NAME], using "
"--os-project-domain-id or via "
"env[OS_PROJECT_DOMAIN_ID]")
if not endpoint:
endpoint = _ksclient.monasca_url
client = monasca_client.Client(api_version, endpoint, **kwargs)
session = _ksclient.session
if session:
client = monasca_client.Client(api_version, session=session)
else:
client = monasca_client.Client(api_version, endpoint, **kwargs)
args.func(client, args)

View File

@ -13,24 +13,34 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from keystoneclient.v3 import client as ksclient
from keystoneauth1.identity import v3
from keystoneauth1.loading import session
from oslo_serialization import jsonutils
def script_keystone_client(token=None):
auth_params = {'auth_url': 'http://no.where',
'project_id': 'project_id',
'project_name': 'project_name',
'project_domain_id': 'project_domain_id',
'project_domain_name': 'project_domain_name'}
password_params = {'username': 'username',
'password': 'password',
'user_domain_id': 'user_domain_id',
'user_domain_name': 'user_domain_name'}
if token:
ksclient.Client(auth_url='http://no.where',
insecure=False,
tenant_id='tenant_id',
token=token).AndReturn(FakeKeystone(token, None))
auth_params['token'] = token
auth = v3.Token(**auth_params).AndReturn(FakeKeystoneAuth(token, None))
else:
ksclient.Client(auth_url='http://no.where',
insecure=False,
password='password',
project_name='project_name',
timeout=20,
username='username').AndReturn(FakeKeystone(
'abcd1234', 'test'))
auth_params.update(password_params)
auth = v3.Password(**auth_params).AndReturn(
FakeKeystoneAuth('abcd1234', 'test'))
session.Session().load_from_options(
auth=auth, insecure=False, cacert=None, cert=None, key=None).AndReturn(
FakeSession(auth))
def fake_headers():
@ -40,19 +50,34 @@ def fake_headers():
'User-Agent': 'python-monascaclient'}
class FakeServiceCatalog(object):
class FakeSession():
def url_for(self, endpoint_type, service_type):
def __init__(self, auth):
self.auth = auth
def get_token(self):
return self.auth.auth_token
def get_project_id(self):
return self.auth.project_id
def get_endpoint(self, service_type, service_name, interface, region_name):
return 'http://192.168.1.5:8004/v1/f14b41234'
class FakeKeystone(object):
service_catalog = FakeServiceCatalog()
class FakeKeystoneAuth():
def __init__(self, auth_token, project_id):
self.auth_token = auth_token
self.project_id = project_id
def get_cache_id_elements(self):
creds = {
'password_username': 'username',
'password_password': 'password'
}
return creds
class FakeRaw(object):
version = 110

View File

@ -17,7 +17,8 @@ import re
import sys
import fixtures
from keystoneclient.v3 import client as ksclient
from keystoneauth1.identity import v3
from keystoneauth1.loading import session
from mox3 import mox
import six
import testtools
@ -35,7 +36,7 @@ class TestCase(testtools.TestCase):
'OS_USER_DOMAIN_NAME', 'OS_PROJECT_ID',
'OS_PROJECT_NAME', 'OS_AUTH_URL', 'OS_REGION_NAME',
'OS_AUTH_TOKEN', 'OS_NO_CLIENT_AUTH', 'OS_SERVICE_TYPE',
'OS_DOMAIN_NAME', 'OS_DOMAIN_ID',
'OS_PROJECT_DOMAIN_NAME', 'OS_PROJECT_DOMAIN_ID',
'OS_ENDPOINT_TYPE', 'MONASCA_API_URL')
for key in client_env:
@ -70,9 +71,11 @@ class ShellBase(TestCase):
def setUp(self):
super(ShellBase, self).setUp()
self.m = mox.Mox()
self.m.StubOutWithMock(ksclient, 'Client')
self.m.StubOutWithMock(http.HTTPClient, 'json_request')
self.m.StubOutWithMock(http.HTTPClient, 'raw_request')
self.m.StubOutWithMock(v3, 'Password')
self.m.StubOutWithMock(v3, 'Token')
self.m.StubOutWithMock(session.Session, 'load_from_options')
self.m.StubOutWithMock(http.SessionClient, 'json_request')
self.m.StubOutWithMock(http.SessionClient, 'raw_request')
self.addCleanup(self.m.VerifyAll)
self.addCleanup(self.m.UnsetStubs)
@ -155,7 +158,12 @@ class ShellTestMonascaCommands(ShellBase):
'OS_USERNAME': 'username',
'OS_PASSWORD': 'password',
'OS_PROJECT_NAME': 'project_name',
'OS_PROJECT_ID': 'project_id',
'OS_AUTH_URL': 'http://no.where',
'OS_PROJECT_DOMAIN_ID': 'project_domain_id',
'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
'OS_USER_DOMAIN_ID': 'user_domain_id',
'OS_USER_DOMAIN_NAME': 'user_domain_name',
}
self.set_fake_env(fake_env)
@ -180,7 +188,7 @@ class ShellTestMonascaCommands(ShellBase):
'Created',
{'location': 'http://no.where/v2.0/metrics'},
None)
http.HTTPClient.json_request(
http.SessionClient.json_request(
'POST',
'/metrics',
data={'timestamp': 1395691090,
@ -235,7 +243,7 @@ class ShellTestMonascaCommands(ShellBase):
'Created',
{'location': 'http://no.where/v2.0/notification-methods'},
None)
http.HTTPClient.json_request(
http.SessionClient.json_request(
'POST',
'/notification-methods',
data={'name': 'email1',
@ -261,7 +269,7 @@ class ShellTestMonascaCommands(ShellBase):
'Created',
{'location': 'http://no.where/v2.0/notification-methods'},
None)
http.HTTPClient.json_request(
http.SessionClient.json_request(
'POST',
'/notification-methods',
data={'name': 'mypost',
@ -296,7 +304,7 @@ class ShellTestMonascaCommands(ShellBase):
'Created',
{'location': 'http://no.where/v2.0/notification-methods'},
None)
http.HTTPClient.json_request(
http.SessionClient.json_request(
'PUT',
'/alarm-definitions/' + id,
data={'name': name,

View File

@ -15,6 +15,7 @@
import string
from monascaclient.common import http
from monascaclient import exc
from monascaclient.v2_0 import alarm_definitions
from monascaclient.v2_0 import alarms
from monascaclient.v2_0 import metrics
@ -25,6 +26,7 @@ class Client(object):
"""Client for the Monasca v2_0 API.
:param session: a keystoneauth session object
:param string endpoint: A user-supplied endpoint URL for the monasca api
service.
:param string token: Token for authentication.
@ -37,7 +39,21 @@ class Client(object):
if 'auth_url' in kwargs and 'v2.0' in kwargs['auth_url']:
kwargs['auth_url'] = string.replace(
kwargs['auth_url'], 'v2.0', 'v3')
self.http_client = http.HTTPClient(*args, **kwargs)
session = kwargs.get('session')
if session:
self.http_client = http.SessionClient(
session=session,
service_type=kwargs.get('service_type', 'monitoring'),
service_name=kwargs.get('service_name', 'monasca'),
interface=kwargs.get('endpoint_type', 'public'),
region_name=kwargs.get('region_name'),
endpoint_override=kwargs.get('endpoint'))
else:
# For backward compatibility in case no session is passed
self.http_client = http.HTTPClient(*args, **kwargs)
self.metrics = metrics.MetricsManager(self.http_client)
self.notifications = notifications.NotificationsManager(
self.http_client)
@ -46,4 +62,8 @@ class Client(object):
self.http_client)
def replace_token(self, token):
self.http_client.replace_token(token)
if isinstance(self.http_client, http.SessionClient):
raise exc.CommandError(message='Token replacement is not '
'supported for session client.')
else:
self.http_client.replace_token(token)

View File

@ -10,7 +10,7 @@ oslo.serialization>=1.10.0 # Apache-2.0
oslo.service>=1.0.0 # Apache-2.0
oslo.utils>=3.5.0 # Apache-2.0
python-keystoneclient!=1.8.0,!=2.1.0,>=1.6.0 # Apache-2.0
keystoneauth1>=2.1.0 # Apache-2.0
Babel!=2.3.0,!=2.3.1,!=2.3.2,!=2.3.3,>=1.3 # BSD
iso8601>=0.1.11 # MIT