Remove unused testing files from keystoneclient
This commit is contained in:
parent
7f431a4598
commit
30ddecdd93
@ -1,68 +0,0 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 six
|
||||
|
||||
from keystoneclient.apiclient import exceptions
|
||||
from keystoneclient.tests import utils
|
||||
|
||||
|
||||
class FakeResponse(object):
|
||||
json_data = {}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
for key, value in six.iteritems(kwargs):
|
||||
setattr(self, key, value)
|
||||
|
||||
def json(self):
|
||||
return self.json_data
|
||||
|
||||
|
||||
class ExceptionsArgsTest(utils.TestCase):
|
||||
|
||||
def assert_exception(self, ex_cls, method, url, status_code, json_data):
|
||||
ex = exceptions.from_response(
|
||||
FakeResponse(status_code=status_code,
|
||||
headers={"Content-Type": "application/json"},
|
||||
json_data=json_data),
|
||||
method,
|
||||
url)
|
||||
self.assertIsInstance(ex, ex_cls)
|
||||
self.assertEqual(ex.message, json_data["error"]["message"])
|
||||
self.assertEqual(ex.details, json_data["error"]["details"])
|
||||
self.assertEqual(ex.method, method)
|
||||
self.assertEqual(ex.url, url)
|
||||
self.assertEqual(ex.http_status, status_code)
|
||||
|
||||
def test_from_response_known(self):
|
||||
method = "GET"
|
||||
url = "/fake"
|
||||
status_code = 400
|
||||
json_data = {"error": {"message": "fake message",
|
||||
"details": "fake details"}}
|
||||
self.assert_exception(
|
||||
exceptions.BadRequest, method, url, status_code, json_data)
|
||||
|
||||
def test_from_response_unknown(self):
|
||||
method = "POST"
|
||||
url = "/fake-unknown"
|
||||
status_code = 499
|
||||
json_data = {"error": {"message": "fake unknown message",
|
||||
"details": "fake unknown details"}}
|
||||
self.assert_exception(
|
||||
exceptions.HTTPClientError, method, url, status_code, json_data)
|
||||
status_code = 600
|
||||
self.assert_exception(
|
||||
exceptions.HTTPError, method, url, status_code, json_data)
|
@ -1,257 +0,0 @@
|
||||
# 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 copy
|
||||
|
||||
import httpretty
|
||||
from six.moves import urllib
|
||||
|
||||
from keystoneclient.auth.identity import v2
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.openstack.common import jsonutils
|
||||
from keystoneclient import session
|
||||
from keystoneclient.tests import utils
|
||||
|
||||
|
||||
class V2IdentityPlugin(utils.TestCase):
|
||||
|
||||
TEST_ROOT_URL = 'http://127.0.0.1:5000/'
|
||||
TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v2.0')
|
||||
TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/'
|
||||
TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v2.0')
|
||||
|
||||
TEST_PASS = 'password'
|
||||
|
||||
TEST_SERVICE_CATALOG = [{
|
||||
"endpoints": [{
|
||||
"adminURL": "http://cdn.admin-nets.local:8774/v1.0",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://127.0.0.1:8774/v1.0",
|
||||
"publicURL": "http://cdn.admin-nets.local:8774/v1.0/"
|
||||
}],
|
||||
"type": "nova_compat",
|
||||
"name": "nova_compat"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": "http://nova/novapi/admin",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://nova/novapi/internal",
|
||||
"publicURL": "http://nova/novapi/public"
|
||||
}],
|
||||
"type": "compute",
|
||||
"name": "nova"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": "http://glance/glanceapi/admin",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://glance/glanceapi/internal",
|
||||
"publicURL": "http://glance/glanceapi/public"
|
||||
}],
|
||||
"type": "image",
|
||||
"name": "glance"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": TEST_ADMIN_URL,
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://127.0.0.1:5000/v2.0",
|
||||
"publicURL": "http://127.0.0.1:5000/v2.0"
|
||||
}],
|
||||
"type": "identity",
|
||||
"name": "keystone"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": "http://swift/swiftapi/admin",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://swift/swiftapi/internal",
|
||||
"publicURL": "http://swift/swiftapi/public"
|
||||
}],
|
||||
"type": "object-store",
|
||||
"name": "swift"
|
||||
}]
|
||||
|
||||
def setUp(self):
|
||||
super(V2IdentityPlugin, self).setUp()
|
||||
self.TEST_RESPONSE_DICT = {
|
||||
"access": {
|
||||
"token": {
|
||||
"expires": "2020-01-01T00:00:10.000123Z",
|
||||
"id": self.TEST_TOKEN,
|
||||
"tenant": {
|
||||
"id": self.TEST_TENANT_ID
|
||||
},
|
||||
},
|
||||
"user": {
|
||||
"id": self.TEST_USER
|
||||
},
|
||||
"serviceCatalog": self.TEST_SERVICE_CATALOG,
|
||||
},
|
||||
}
|
||||
|
||||
def stub_auth(self, **kwargs):
|
||||
self.stub_url(httpretty.POST, ['tokens'], **kwargs)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_with_username_password(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
a = v2.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(a)
|
||||
s.get_token()
|
||||
|
||||
req = {'auth': {'passwordCredentials': {'username': self.TEST_USER,
|
||||
'password': self.TEST_PASS}}}
|
||||
self.assertRequestBodyIs(json=req)
|
||||
self.assertRequestHeaderEqual('Content-Type', 'application/json')
|
||||
self.assertRequestHeaderEqual('Accept', 'application/json')
|
||||
self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_with_username_password_scoped(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
a = v2.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS, tenant_id=self.TEST_TENANT_ID)
|
||||
s = session.Session(a)
|
||||
s.get_token()
|
||||
|
||||
req = {'auth': {'passwordCredentials': {'username': self.TEST_USER,
|
||||
'password': self.TEST_PASS},
|
||||
'tenantId': self.TEST_TENANT_ID}}
|
||||
self.assertRequestBodyIs(json=req)
|
||||
self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_with_token(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
a = v2.Token(self.TEST_URL, 'foo')
|
||||
s = session.Session(a)
|
||||
s.get_token()
|
||||
|
||||
req = {'auth': {'token': {'id': 'foo'}}}
|
||||
self.assertRequestBodyIs(json=req)
|
||||
self.assertRequestHeaderEqual('x-Auth-Token', 'foo')
|
||||
self.assertRequestHeaderEqual('Content-Type', 'application/json')
|
||||
self.assertRequestHeaderEqual('Accept', 'application/json')
|
||||
self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def test_with_trust_id(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
a = v2.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS, trust_id='trust')
|
||||
s = session.Session(a)
|
||||
s.get_token()
|
||||
|
||||
req = {'auth': {'passwordCredentials': {'username': self.TEST_USER,
|
||||
'password': self.TEST_PASS},
|
||||
'trust_id': 'trust'}}
|
||||
|
||||
self.assertRequestBodyIs(json=req)
|
||||
self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def _do_service_url_test(self, base_url, endpoint_filter):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
self.stub_url(httpretty.GET, ['path'],
|
||||
base_url=base_url,
|
||||
body='SUCCESS', status=200)
|
||||
|
||||
a = v2.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
resp = s.get('/path', endpoint_filter=endpoint_filter)
|
||||
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
path = "%s/%s" % (urllib.parse.urlparse(base_url).path, 'path')
|
||||
self.assertEqual(httpretty.last_request().path, path)
|
||||
|
||||
def test_service_url(self):
|
||||
endpoint_filter = {'service_type': 'compute',
|
||||
'interface': 'admin',
|
||||
'service_name': 'nova'}
|
||||
self._do_service_url_test('http://nova/novapi/admin', endpoint_filter)
|
||||
|
||||
def test_service_url_defaults_to_public(self):
|
||||
endpoint_filter = {'service_type': 'compute'}
|
||||
self._do_service_url_test('http://nova/novapi/public', endpoint_filter)
|
||||
|
||||
@httpretty.activate
|
||||
def test_endpoint_filter_without_service_type_fails(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
a = v2.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
self.assertRaises(exceptions.EndpointNotFound, s.get, '/path',
|
||||
endpoint_filter={'interface': 'admin'})
|
||||
|
||||
@httpretty.activate
|
||||
def test_full_url_overrides_endpoint_filter(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
self.stub_url(httpretty.GET, [],
|
||||
base_url='http://testurl/',
|
||||
body='SUCCESS', status=200)
|
||||
|
||||
a = v2.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
resp = s.get('http://testurl/',
|
||||
endpoint_filter={'service_type': 'compute'})
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp.text, 'SUCCESS')
|
||||
|
||||
@httpretty.activate
|
||||
def test_invalid_auth_response_dict(self):
|
||||
self.stub_auth(json={'hello': 'world'})
|
||||
|
||||
a = v2.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
self.assertRaises(exceptions.InvalidResponse, s.get, 'http://any',
|
||||
authenticated=True)
|
||||
|
||||
@httpretty.activate
|
||||
def test_invalid_auth_response_type(self):
|
||||
self.stub_url(httpretty.POST, ['tokens'], body='testdata')
|
||||
|
||||
a = v2.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
self.assertRaises(exceptions.InvalidResponse, s.get, 'http://any',
|
||||
authenticated=True)
|
||||
|
||||
@httpretty.activate
|
||||
def test_invalidate_response(self):
|
||||
resp_data1 = copy.deepcopy(self.TEST_RESPONSE_DICT)
|
||||
resp_data2 = copy.deepcopy(self.TEST_RESPONSE_DICT)
|
||||
|
||||
resp_data1['access']['token']['id'] = 'token1'
|
||||
resp_data2['access']['token']['id'] = 'token2'
|
||||
|
||||
auth_responses = [httpretty.Response(body=jsonutils.dumps(resp_data1),
|
||||
status=200),
|
||||
httpretty.Response(body=jsonutils.dumps(resp_data2),
|
||||
status=200)]
|
||||
|
||||
self.stub_auth(responses=auth_responses)
|
||||
|
||||
a = v2.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
self.assertEqual('token1', s.get_token())
|
||||
a.invalidate()
|
||||
self.assertEqual('token2', s.get_token())
|
@ -1,410 +0,0 @@
|
||||
# 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 copy
|
||||
|
||||
import httpretty
|
||||
from six.moves import urllib
|
||||
|
||||
from keystoneclient import access
|
||||
from keystoneclient.auth.identity import v3
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.openstack.common import jsonutils
|
||||
from keystoneclient import session
|
||||
from keystoneclient.tests import utils
|
||||
|
||||
|
||||
class V3IdentityPlugin(utils.TestCase):
|
||||
|
||||
TEST_ROOT_URL = 'http://127.0.0.1:5000/'
|
||||
TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3')
|
||||
TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/'
|
||||
TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v3')
|
||||
|
||||
TEST_PASS = 'password'
|
||||
|
||||
TEST_SERVICE_CATALOG = [{
|
||||
"endpoints": [{
|
||||
"url": "http://cdn.admin-nets.local:8774/v1.0/",
|
||||
"region": "RegionOne",
|
||||
"interface": "public"
|
||||
}, {
|
||||
"url": "http://127.0.0.1:8774/v1.0",
|
||||
"region": "RegionOne",
|
||||
"interface": "internal"
|
||||
}, {
|
||||
"url": "http://cdn.admin-nets.local:8774/v1.0",
|
||||
"region": "RegionOne",
|
||||
"interface": "admin"
|
||||
}],
|
||||
"type": "nova_compat"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"url": "http://nova/novapi/public",
|
||||
"region": "RegionOne",
|
||||
"interface": "public"
|
||||
}, {
|
||||
"url": "http://nova/novapi/internal",
|
||||
"region": "RegionOne",
|
||||
"interface": "internal"
|
||||
}, {
|
||||
"url": "http://nova/novapi/admin",
|
||||
"region": "RegionOne",
|
||||
"interface": "admin"
|
||||
}],
|
||||
"type": "compute",
|
||||
"name": "nova",
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"url": "http://glance/glanceapi/public",
|
||||
"region": "RegionOne",
|
||||
"interface": "public"
|
||||
}, {
|
||||
"url": "http://glance/glanceapi/internal",
|
||||
"region": "RegionOne",
|
||||
"interface": "internal"
|
||||
}, {
|
||||
"url": "http://glance/glanceapi/admin",
|
||||
"region": "RegionOne",
|
||||
"interface": "admin"
|
||||
}],
|
||||
"type": "image",
|
||||
"name": "glance"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"url": "http://127.0.0.1:5000/v3",
|
||||
"region": "RegionOne",
|
||||
"interface": "public"
|
||||
}, {
|
||||
"url": "http://127.0.0.1:5000/v3",
|
||||
"region": "RegionOne",
|
||||
"interface": "internal"
|
||||
}, {
|
||||
"url": TEST_ADMIN_URL,
|
||||
"region": "RegionOne",
|
||||
"interface": "admin"
|
||||
}],
|
||||
"type": "identity"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"url": "http://swift/swiftapi/public",
|
||||
"region": "RegionOne",
|
||||
"interface": "public"
|
||||
}, {
|
||||
"url": "http://swift/swiftapi/internal",
|
||||
"region": "RegionOne",
|
||||
"interface": "internal"
|
||||
}, {
|
||||
"url": "http://swift/swiftapi/admin",
|
||||
"region": "RegionOne",
|
||||
"interface": "admin"
|
||||
}],
|
||||
"type": "object-store"
|
||||
}]
|
||||
|
||||
def setUp(self):
|
||||
super(V3IdentityPlugin, self).setUp()
|
||||
self.TEST_RESPONSE_DICT = {
|
||||
"token": {
|
||||
"methods": [
|
||||
"token",
|
||||
"password"
|
||||
],
|
||||
|
||||
"expires_at": "2020-01-01T00:00:10.000123Z",
|
||||
"project": {
|
||||
"domain": {
|
||||
"id": self.TEST_DOMAIN_ID,
|
||||
"name": self.TEST_DOMAIN_NAME
|
||||
},
|
||||
"id": self.TEST_TENANT_ID,
|
||||
"name": self.TEST_TENANT_NAME
|
||||
},
|
||||
"user": {
|
||||
"domain": {
|
||||
"id": self.TEST_DOMAIN_ID,
|
||||
"name": self.TEST_DOMAIN_NAME
|
||||
},
|
||||
"id": self.TEST_USER,
|
||||
"name": self.TEST_USER
|
||||
},
|
||||
"issued_at": "2013-05-29T16:55:21.468960Z",
|
||||
"catalog": self.TEST_SERVICE_CATALOG
|
||||
},
|
||||
}
|
||||
|
||||
def stub_auth(self, subject_token=None, **kwargs):
|
||||
if not subject_token:
|
||||
subject_token = self.TEST_TOKEN
|
||||
|
||||
self.stub_url(httpretty.POST, ['auth', 'tokens'],
|
||||
X_Subject_Token=subject_token, **kwargs)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_with_username_password(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
a = v3.Password(self.TEST_URL,
|
||||
username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
s.get_token()
|
||||
|
||||
req = {'auth': {'identity':
|
||||
{'methods': ['password'],
|
||||
'password': {'user': {'name': self.TEST_USER,
|
||||
'password': self.TEST_PASS}}}}}
|
||||
|
||||
self.assertRequestBodyIs(json=req)
|
||||
self.assertRequestHeaderEqual('Content-Type', 'application/json')
|
||||
self.assertRequestHeaderEqual('Accept', 'application/json')
|
||||
self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_with_username_password_domain_scoped(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
a = v3.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS, domain_id=self.TEST_DOMAIN_ID)
|
||||
s = session.Session(a)
|
||||
s.get_token()
|
||||
|
||||
req = {'auth': {'identity':
|
||||
{'methods': ['password'],
|
||||
'password': {'user': {'name': self.TEST_USER,
|
||||
'password': self.TEST_PASS}}},
|
||||
'scope': {'domain': {'id': self.TEST_DOMAIN_ID}}}}
|
||||
self.assertRequestBodyIs(json=req)
|
||||
self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_with_username_password_project_scoped(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
a = v3.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS,
|
||||
project_id=self.TEST_DOMAIN_ID)
|
||||
s = session.Session(a)
|
||||
s.get_token()
|
||||
|
||||
req = {'auth': {'identity':
|
||||
{'methods': ['password'],
|
||||
'password': {'user': {'name': self.TEST_USER,
|
||||
'password': self.TEST_PASS}}},
|
||||
'scope': {'project': {'id': self.TEST_DOMAIN_ID}}}}
|
||||
self.assertRequestBodyIs(json=req)
|
||||
self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
|
||||
self.assertEqual(s.auth.auth_ref.project_id, self.TEST_DOMAIN_ID)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_with_token(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
a = v3.Token(self.TEST_URL, self.TEST_TOKEN)
|
||||
s = session.Session(auth=a)
|
||||
s.get_token()
|
||||
|
||||
req = {'auth': {'identity':
|
||||
{'methods': ['token'],
|
||||
'token': {'id': self.TEST_TOKEN}}}}
|
||||
|
||||
self.assertRequestBodyIs(json=req)
|
||||
|
||||
self.assertRequestHeaderEqual('Content-Type', 'application/json')
|
||||
self.assertRequestHeaderEqual('Accept', 'application/json')
|
||||
self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def test_with_expired(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
d = copy.deepcopy(self.TEST_RESPONSE_DICT)
|
||||
d['token']['expires_at'] = '2000-01-01T00:00:10.000123Z'
|
||||
|
||||
a = v3.Password(self.TEST_URL, username='username',
|
||||
password='password')
|
||||
a.auth_ref = access.AccessInfo.factory(body=d)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
s.get_token()
|
||||
|
||||
self.assertEqual(a.auth_ref['expires_at'],
|
||||
self.TEST_RESPONSE_DICT['token']['expires_at'])
|
||||
|
||||
def test_with_domain_and_project_scoping(self):
|
||||
a = v3.Password(self.TEST_URL, username='username',
|
||||
password='password', project_id='project',
|
||||
domain_id='domain')
|
||||
self.assertRaises(exceptions.AuthorizationFailure,
|
||||
a.get_token, None)
|
||||
|
||||
@httpretty.activate
|
||||
def test_with_trust_id(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
a = v3.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS, trust_id='trust')
|
||||
s = session.Session(a)
|
||||
s.get_token()
|
||||
|
||||
req = {'auth': {'identity':
|
||||
{'methods': ['password'],
|
||||
'password': {'user': {'name': self.TEST_USER,
|
||||
'password': self.TEST_PASS}}},
|
||||
'scope': {'OS-TRUST:trust': {'id': 'trust'}}}}
|
||||
self.assertRequestBodyIs(json=req)
|
||||
self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def test_with_multiple_mechanisms_factory(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
p = v3.PasswordMethod(username=self.TEST_USER, password=self.TEST_PASS)
|
||||
t = v3.TokenMethod(token='foo')
|
||||
a = v3.Auth(self.TEST_URL, [p, t], trust_id='trust')
|
||||
s = session.Session(a)
|
||||
s.get_token()
|
||||
|
||||
req = {'auth': {'identity':
|
||||
{'methods': ['password', 'token'],
|
||||
'password': {'user': {'name': self.TEST_USER,
|
||||
'password': self.TEST_PASS}},
|
||||
'token': {'id': 'foo'}},
|
||||
'scope': {'OS-TRUST:trust': {'id': 'trust'}}}}
|
||||
self.assertRequestBodyIs(json=req)
|
||||
self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def test_with_multiple_mechanisms(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
p = v3.PasswordMethod(username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
t = v3.TokenMethod(token='foo')
|
||||
a = v3.Auth(self.TEST_URL, [p, t], trust_id='trust')
|
||||
s = session.Session(auth=a)
|
||||
|
||||
s.get_token()
|
||||
|
||||
req = {'auth': {'identity':
|
||||
{'methods': ['password', 'token'],
|
||||
'password': {'user': {'name': self.TEST_USER,
|
||||
'password': self.TEST_PASS}},
|
||||
'token': {'id': 'foo'}},
|
||||
'scope': {'OS-TRUST:trust': {'id': 'trust'}}}}
|
||||
self.assertRequestBodyIs(json=req)
|
||||
self.assertEqual(s.auth.auth_ref.auth_token, self.TEST_TOKEN)
|
||||
|
||||
def test_with_multiple_scopes(self):
|
||||
s = session.Session()
|
||||
|
||||
a = v3.Password(self.TEST_URL,
|
||||
username=self.TEST_USER, password=self.TEST_PASS,
|
||||
domain_id='x', project_id='x')
|
||||
self.assertRaises(exceptions.AuthorizationFailure, a.get_auth_ref, s)
|
||||
|
||||
a = v3.Password(self.TEST_URL,
|
||||
username=self.TEST_USER, password=self.TEST_PASS,
|
||||
domain_id='x', trust_id='x')
|
||||
self.assertRaises(exceptions.AuthorizationFailure, a.get_auth_ref, s)
|
||||
|
||||
@httpretty.activate
|
||||
def _do_service_url_test(self, base_url, endpoint_filter):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
self.stub_url(httpretty.GET, ['path'],
|
||||
base_url=base_url,
|
||||
body='SUCCESS', status=200)
|
||||
|
||||
a = v3.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
resp = s.get('/path', endpoint_filter=endpoint_filter)
|
||||
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
path = "%s/%s" % (urllib.parse.urlparse(base_url).path, 'path')
|
||||
self.assertEqual(httpretty.last_request().path, path)
|
||||
|
||||
def test_service_url(self):
|
||||
endpoint_filter = {'service_type': 'compute',
|
||||
'interface': 'admin',
|
||||
'service_name': 'nova'}
|
||||
self._do_service_url_test('http://nova/novapi/admin', endpoint_filter)
|
||||
|
||||
def test_service_url_defaults_to_public(self):
|
||||
endpoint_filter = {'service_type': 'compute'}
|
||||
self._do_service_url_test('http://nova/novapi/public', endpoint_filter)
|
||||
|
||||
@httpretty.activate
|
||||
def test_endpoint_filter_without_service_type_fails(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
a = v3.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
self.assertRaises(exceptions.EndpointNotFound, s.get, '/path',
|
||||
endpoint_filter={'interface': 'admin'})
|
||||
|
||||
@httpretty.activate
|
||||
def test_full_url_overrides_endpoint_filter(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
self.stub_url(httpretty.GET, [],
|
||||
base_url='http://testurl/',
|
||||
body='SUCCESS', status=200)
|
||||
|
||||
a = v3.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
resp = s.get('http://testurl/',
|
||||
endpoint_filter={'service_type': 'compute'})
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp.text, 'SUCCESS')
|
||||
|
||||
@httpretty.activate
|
||||
def test_invalid_auth_response_dict(self):
|
||||
self.stub_auth(json={'hello': 'world'})
|
||||
|
||||
a = v3.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
self.assertRaises(exceptions.InvalidResponse, s.get, 'http://any',
|
||||
authenticated=True)
|
||||
|
||||
@httpretty.activate
|
||||
def test_invalid_auth_response_type(self):
|
||||
self.stub_url(httpretty.POST, ['auth', 'tokens'], body='testdata')
|
||||
|
||||
a = v3.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
self.assertRaises(exceptions.InvalidResponse, s.get, 'http://any',
|
||||
authenticated=True)
|
||||
|
||||
@httpretty.activate
|
||||
def test_invalidate_response(self):
|
||||
body = jsonutils.dumps(self.TEST_RESPONSE_DICT)
|
||||
auth_responses = [httpretty.Response(body=body,
|
||||
X_Subject_Token='token1',
|
||||
status=200),
|
||||
httpretty.Response(body=body,
|
||||
X_Subject_Token='token2',
|
||||
status=200)]
|
||||
|
||||
httpretty.register_uri(httpretty.POST,
|
||||
'%s/auth/tokens' % self.TEST_URL,
|
||||
responses=auth_responses)
|
||||
|
||||
a = v3.Password(self.TEST_URL, username=self.TEST_USER,
|
||||
password=self.TEST_PASS)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
self.assertEqual('token1', s.get_token())
|
||||
a.invalidate()
|
||||
self.assertEqual('token2', s.get_token())
|
@ -1,49 +0,0 @@
|
||||
# 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 httpretty
|
||||
|
||||
from keystoneclient.auth import token_endpoint
|
||||
from keystoneclient import session
|
||||
from keystoneclient.tests import utils
|
||||
|
||||
|
||||
class TokenEndpointTest(utils.TestCase):
|
||||
|
||||
TEST_TOKEN = 'aToken'
|
||||
TEST_URL = 'http://server/prefix'
|
||||
|
||||
@httpretty.activate
|
||||
def test_basic_case(self):
|
||||
httpretty.register_uri(httpretty.GET, self.TEST_URL, body='body')
|
||||
|
||||
a = token_endpoint.Token(self.TEST_URL, self.TEST_TOKEN)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
data = s.get(self.TEST_URL, authenticated=True)
|
||||
|
||||
self.assertEqual(data.text, 'body')
|
||||
self.assertRequestHeaderEqual('X-Auth-Token', self.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def test_basic_endpoint_case(self):
|
||||
self.stub_url(httpretty.GET, ['p'], body='body')
|
||||
a = token_endpoint.Token(self.TEST_URL, self.TEST_TOKEN)
|
||||
s = session.Session(auth=a)
|
||||
|
||||
data = s.get('/p',
|
||||
authenticated=True,
|
||||
endpoint_filter={'service': 'identity'})
|
||||
|
||||
self.assertEqual(self.TEST_URL, a.get_endpoint(s))
|
||||
self.assertEqual('body', data.text)
|
||||
self.assertRequestHeaderEqual('X-Auth-Token', self.TEST_TOKEN)
|
@ -1,118 +0,0 @@
|
||||
# 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.
|
||||
|
||||
"""
|
||||
A fake server that "responds" to API methods with pre-canned responses.
|
||||
|
||||
All of these responses come from the spec, so if for some reason the spec's
|
||||
wrong the tests might raise AssertionError. I've indicated in comments the
|
||||
places where actual behavior differs from the spec.
|
||||
"""
|
||||
|
||||
from keystoneclient import access
|
||||
|
||||
|
||||
def assert_has_keys(dict, required=[], optional=[]):
|
||||
keys = dict.keys()
|
||||
for k in required:
|
||||
try:
|
||||
assert k in keys
|
||||
except AssertionError:
|
||||
extra_keys = set(keys).difference(set(required + optional))
|
||||
raise AssertionError("found unexpected keys: %s" %
|
||||
list(extra_keys))
|
||||
|
||||
|
||||
class FakeClient(object):
|
||||
|
||||
def assert_called(self, method, url, body=None, pos=-1):
|
||||
"""Assert than an API method was just called."""
|
||||
expected = (method, url)
|
||||
called = self.callstack[pos][0:2]
|
||||
|
||||
assert self.callstack, ("Expected %s %s but no calls were made." %
|
||||
expected)
|
||||
assert expected == called, ("Expected %s %s; got %s %s" %
|
||||
(expected + called))
|
||||
|
||||
if body is not None:
|
||||
assert self.callstack[pos][2] == body
|
||||
|
||||
def assert_called_anytime(self, method, url, body=None):
|
||||
"""Assert than an API method was called anytime in the test."""
|
||||
expected = (method, url)
|
||||
|
||||
assert self.callstack, ("Expected %s %s but no calls were made." %
|
||||
expected)
|
||||
|
||||
found = False
|
||||
for entry in self.callstack:
|
||||
if expected == entry[0:2]:
|
||||
found = True
|
||||
break
|
||||
|
||||
assert found, ('Expected %s; got %s' %
|
||||
(expected, self.callstack))
|
||||
if body is not None:
|
||||
if entry[2] != body:
|
||||
raise AssertionError('%s != %s' % (entry[2], body))
|
||||
self.callstack = []
|
||||
|
||||
def clear_callstack(self):
|
||||
self.callstack = []
|
||||
|
||||
def authenticate(self, cl_obj):
|
||||
cl_obj.user_id = '1'
|
||||
cl_obj.auth_user_id = '1'
|
||||
cl_obj.project_id = '1'
|
||||
cl_obj.auth_tenant_id = '1'
|
||||
cl_obj.auth_ref = access.AccessInfo.factory(None, {
|
||||
"access": {
|
||||
"token": {
|
||||
"expires": "2012-02-05T00:00:00",
|
||||
"id": "887665443383838",
|
||||
"tenant": {
|
||||
"id": "1",
|
||||
"name": "customer-x"
|
||||
}
|
||||
},
|
||||
"serviceCatalog": [{
|
||||
"endpoints": [{
|
||||
"adminURL": "http://swift.admin-nets.local:8080/",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://127.0.0.1:8080/v1/AUTH_1",
|
||||
"publicURL":
|
||||
"http://swift.publicinternets.com/v1/AUTH_1"
|
||||
}],
|
||||
"type": "object-store",
|
||||
"name": "swift"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": "http://cdn.admin-nets.local/v1.1/1",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://127.0.0.1:7777/v1.1/1",
|
||||
"publicURL": "http://cdn.publicinternets.com/v1.1/1"
|
||||
}],
|
||||
"type": "object-store",
|
||||
"name": "cdn"
|
||||
}],
|
||||
"user": {
|
||||
"id": "1",
|
||||
"roles": [{
|
||||
"tenantId": "1",
|
||||
"id": "3",
|
||||
"name": "Member"
|
||||
}],
|
||||
"name": "joeuser"
|
||||
}
|
||||
}
|
||||
})
|
@ -1,67 +0,0 @@
|
||||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 httpretty
|
||||
|
||||
from keystoneclient.generic import client
|
||||
from keystoneclient.openstack.common import jsonutils
|
||||
from keystoneclient.tests import utils
|
||||
|
||||
BASE_HOST = 'http://keystone.example.com'
|
||||
BASE_URL = "%s:5000/" % BASE_HOST
|
||||
V2_URL = "%sv2.0" % BASE_URL
|
||||
|
||||
EXTENSION_NAMESPACE = "http://docs.openstack.org/identity/api/ext/OS-FAKE/v1.0"
|
||||
EXTENSION_DESCRIBED = {"href": "https://github.com/openstack/identity-api",
|
||||
"rel": "describedby",
|
||||
"type": "text/html"}
|
||||
|
||||
EXTENSION_ALIAS_FOO = "OS-FAKE-FOO"
|
||||
EXTENSION_NAME_FOO = "OpenStack Keystone Fake Extension Foo"
|
||||
EXTENSION_FOO = {"alias": EXTENSION_ALIAS_FOO,
|
||||
"description": "Fake Foo extension to V2.0 API.",
|
||||
"links": [EXTENSION_DESCRIBED],
|
||||
"name": EXTENSION_NAME_FOO,
|
||||
"namespace": EXTENSION_NAMESPACE,
|
||||
"updated": '2014-01-08T00:00:00Z'}
|
||||
|
||||
EXTENSION_ALIAS_BAR = "OS-FAKE-BAR"
|
||||
EXTENSION_NAME_BAR = "OpenStack Keystone Fake Extension Bar"
|
||||
EXTENSION_BAR = {"alias": EXTENSION_ALIAS_BAR,
|
||||
"description": "Fake Bar extension to V2.0 API.",
|
||||
"links": [EXTENSION_DESCRIBED],
|
||||
"name": EXTENSION_NAME_BAR,
|
||||
"namespace": EXTENSION_NAMESPACE,
|
||||
"updated": '2014-01-08T00:00:00Z'}
|
||||
|
||||
|
||||
def _create_extension_list(extensions):
|
||||
return jsonutils.dumps({'extensions': {'values': extensions}})
|
||||
|
||||
|
||||
EXTENSION_LIST = _create_extension_list([EXTENSION_FOO, EXTENSION_BAR])
|
||||
|
||||
|
||||
@httpretty.activate
|
||||
class ClientDiscoveryTests(utils.TestCase):
|
||||
|
||||
def test_discover_extensions_v2(self):
|
||||
httpretty.register_uri(httpretty.GET, "%s/extensions" % V2_URL,
|
||||
body=EXTENSION_LIST)
|
||||
extensions = client.Client().discover_extensions(url=V2_URL)
|
||||
self.assertIn(EXTENSION_ALIAS_FOO, extensions)
|
||||
self.assertEqual(extensions[EXTENSION_ALIAS_FOO], EXTENSION_NAME_FOO)
|
||||
self.assertIn(EXTENSION_ALIAS_BAR, extensions)
|
||||
self.assertEqual(extensions[EXTENSION_ALIAS_BAR], EXTENSION_NAME_BAR)
|
@ -1,129 +0,0 @@
|
||||
# Copyright 2014 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 six import moves
|
||||
|
||||
from keystoneclient.generic import shell
|
||||
from keystoneclient.tests import utils
|
||||
|
||||
|
||||
class DoDiscoverTest(utils.TestCase):
|
||||
"""Unit tests for do_discover function."""
|
||||
foo_version = {
|
||||
'id': 'foo_id',
|
||||
'status': 'foo_status',
|
||||
'url': 'http://foo/url',
|
||||
}
|
||||
bar_version = {
|
||||
'id': 'bar_id',
|
||||
'status': 'bar_status',
|
||||
'url': 'http://bar/url',
|
||||
}
|
||||
foo_extension = {
|
||||
'foo': 'foo_extension',
|
||||
'message': 'extension_message',
|
||||
'bar': 'bar_extension',
|
||||
}
|
||||
stub_message = 'This is a stub message'
|
||||
|
||||
def setUp(self):
|
||||
super(DoDiscoverTest, self).setUp()
|
||||
|
||||
self.client_mock = mock.Mock()
|
||||
self.client_mock.discover.return_value = {}
|
||||
|
||||
def _execute_discover(self):
|
||||
"""Call do_discover function and capture output
|
||||
|
||||
:return: captured output is returned
|
||||
"""
|
||||
with mock.patch('sys.stdout',
|
||||
new_callable=moves.StringIO) as mock_stdout:
|
||||
shell.do_discover(self.client_mock, args=None)
|
||||
output = mock_stdout.getvalue()
|
||||
return output
|
||||
|
||||
def _check_version_print(self, output, version):
|
||||
"""Checks all api version's parameters are present in output."""
|
||||
self.assertIn(version['id'], output)
|
||||
self.assertIn(version['status'], output)
|
||||
self.assertIn(version['url'], output)
|
||||
|
||||
def test_no_keystones(self):
|
||||
# No servers configured for client,
|
||||
# corresponding message should be printed
|
||||
output = self._execute_discover()
|
||||
self.assertIn('No Keystone-compatible endpoint found', output)
|
||||
|
||||
def test_endpoint(self):
|
||||
# Endpoint is configured for client,
|
||||
# client's discover method should be called with that value
|
||||
self.client_mock.endpoint = 'Some non-empty value'
|
||||
shell.do_discover(self.client_mock, args=None)
|
||||
self.client_mock.discover.assert_called_with(self.client_mock.endpoint)
|
||||
|
||||
def test_auth_url(self):
|
||||
# No endpoint provided for client, but there is an auth_url
|
||||
# client's discover method should be called with auth_url value
|
||||
self.client_mock.endpoint = False
|
||||
self.client_mock.auth_url = 'Some non-empty value'
|
||||
shell.do_discover(self.client_mock, args=None)
|
||||
self.client_mock.discover.assert_called_with(self.client_mock.auth_url)
|
||||
|
||||
def test_empty(self):
|
||||
# No endpoint or auth_url is configured for client.
|
||||
# client.discover() should be called without parameters
|
||||
self.client_mock.endpoint = False
|
||||
self.client_mock.auth_url = False
|
||||
shell.do_discover(self.client_mock, args=None)
|
||||
self.client_mock.discover.assert_called_with()
|
||||
|
||||
def test_message(self):
|
||||
# If client.discover() result contains message - it should be printed
|
||||
self.client_mock.discover.return_value = {'message': self.stub_message}
|
||||
output = self._execute_discover()
|
||||
self.assertIn(self.stub_message, output)
|
||||
|
||||
def test_versions(self):
|
||||
# Every version in client.discover() result should be printed
|
||||
# and client.discover_extension() should be called on its url
|
||||
self.client_mock.discover.return_value = {
|
||||
'foo': self.foo_version,
|
||||
'bar': self.bar_version,
|
||||
}
|
||||
self.client_mock.discover_extensions.return_value = {}
|
||||
output = self._execute_discover()
|
||||
self._check_version_print(output, self.foo_version)
|
||||
self._check_version_print(output, self.bar_version)
|
||||
|
||||
discover_extension_calls = [
|
||||
mock.call(self.foo_version['url']),
|
||||
mock.call(self.bar_version['url']),
|
||||
]
|
||||
|
||||
self.client_mock.discover_extensions.assert_has_calls(
|
||||
discover_extension_calls,
|
||||
any_order=True)
|
||||
|
||||
def test_extensions(self):
|
||||
# Every extension's parameters should be printed
|
||||
# Extension's message should be omitted
|
||||
self.client_mock.discover.return_value = {'foo': self.foo_version}
|
||||
self.client_mock.discover_extensions.return_value = self.foo_extension
|
||||
output = self._execute_discover()
|
||||
self.assertIn(self.foo_extension['foo'], output)
|
||||
self.assertIn(self.foo_extension['bar'], output)
|
||||
self.assertNotIn(self.foo_extension['message'], output)
|
@ -1,161 +0,0 @@
|
||||
# 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.
|
||||
|
||||
from keystoneclient import base
|
||||
from keystoneclient.tests import utils
|
||||
from keystoneclient.v2_0 import client
|
||||
from keystoneclient.v2_0 import roles
|
||||
|
||||
|
||||
class HumanReadable(base.Resource):
|
||||
HUMAN_ID = True
|
||||
|
||||
|
||||
class BaseTest(utils.TestCase):
|
||||
|
||||
def test_resource_repr(self):
|
||||
r = base.Resource(None, dict(foo="bar", baz="spam"))
|
||||
self.assertEqual(repr(r), "<Resource baz=spam, foo=bar>")
|
||||
|
||||
def test_getid(self):
|
||||
self.assertEqual(base.getid(4), 4)
|
||||
|
||||
class TmpObject(object):
|
||||
id = 4
|
||||
self.assertEqual(base.getid(TmpObject), 4)
|
||||
|
||||
def test_resource_lazy_getattr(self):
|
||||
self.client = client.Client(username=self.TEST_USER,
|
||||
token=self.TEST_TOKEN,
|
||||
tenant_name=self.TEST_TENANT_NAME,
|
||||
auth_url='http://127.0.0.1:5000',
|
||||
endpoint='http://127.0.0.1:5000')
|
||||
|
||||
self.client.get = self.mox.CreateMockAnything()
|
||||
self.client.get('/OS-KSADM/roles/1').AndRaise(AttributeError)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
f = roles.Role(self.client.roles, {'id': 1, 'name': 'Member'})
|
||||
self.assertEqual(f.name, 'Member')
|
||||
|
||||
# Missing stuff still fails after a second get
|
||||
self.assertRaises(AttributeError, getattr, f, 'blahblah')
|
||||
|
||||
def test_eq(self):
|
||||
# Two resources of the same type with the same id: equal
|
||||
r1 = base.Resource(None, {'id': 1, 'name': 'hi'})
|
||||
r2 = base.Resource(None, {'id': 1, 'name': 'hello'})
|
||||
self.assertEqual(r1, r2)
|
||||
|
||||
# Two resoruces of different types: never equal
|
||||
r1 = base.Resource(None, {'id': 1})
|
||||
r2 = roles.Role(None, {'id': 1})
|
||||
self.assertNotEqual(r1, r2)
|
||||
|
||||
# Two resources with no ID: equal if their info is equal
|
||||
r1 = base.Resource(None, {'name': 'joe', 'age': 12})
|
||||
r2 = base.Resource(None, {'name': 'joe', 'age': 12})
|
||||
self.assertEqual(r1, r2)
|
||||
|
||||
r1 = base.Resource(None, {'id': 1})
|
||||
self.assertNotEqual(r1, object())
|
||||
self.assertNotEqual(r1, {'id': 1})
|
||||
|
||||
def test_human_id(self):
|
||||
r = base.Resource(None, {"name": "1 of !"})
|
||||
self.assertIsNone(r.human_id)
|
||||
r = HumanReadable(None, {"name": "1 of !"})
|
||||
self.assertEqual(r.human_id, "1-of")
|
||||
|
||||
|
||||
class ManagerTest(utils.TestCase):
|
||||
body = {"hello": {"hi": 1}}
|
||||
url = "/test-url"
|
||||
|
||||
def setUp(self):
|
||||
super(ManagerTest, self).setUp()
|
||||
self.client = client.Client(username=self.TEST_USER,
|
||||
token=self.TEST_TOKEN,
|
||||
tenant_name=self.TEST_TENANT_NAME,
|
||||
auth_url='http://127.0.0.1:5000',
|
||||
endpoint='http://127.0.0.1:5000')
|
||||
self.mgr = base.Manager(self.client)
|
||||
self.mgr.resource_class = base.Resource
|
||||
|
||||
def test_api(self):
|
||||
self.assertEqual(self.mgr.api, self.client)
|
||||
|
||||
def test_get(self):
|
||||
self.client.get = self.mox.CreateMockAnything()
|
||||
self.client.get(self.url).AndReturn((None, self.body))
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rsrc = self.mgr._get(self.url, "hello")
|
||||
self.assertEqual(rsrc.hi, 1)
|
||||
|
||||
def test_post(self):
|
||||
self.client.post = self.mox.CreateMockAnything()
|
||||
self.client.post(self.url, body=self.body).AndReturn((None, self.body))
|
||||
self.client.post(self.url, body=self.body).AndReturn((None, self.body))
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rsrc = self.mgr._post(self.url, self.body, "hello")
|
||||
self.assertEqual(rsrc.hi, 1)
|
||||
|
||||
rsrc = self.mgr._post(self.url, self.body, "hello", return_raw=True)
|
||||
self.assertEqual(rsrc["hi"], 1)
|
||||
|
||||
def test_put(self):
|
||||
self.client.put = self.mox.CreateMockAnything()
|
||||
self.client.put(self.url, body=self.body).AndReturn((None, self.body))
|
||||
self.client.put(self.url, body=self.body).AndReturn((None, self.body))
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rsrc = self.mgr._put(self.url, self.body, "hello")
|
||||
self.assertEqual(rsrc.hi, 1)
|
||||
|
||||
rsrc = self.mgr._put(self.url, self.body)
|
||||
self.assertEqual(rsrc.hello["hi"], 1)
|
||||
|
||||
def test_patch(self):
|
||||
self.client.patch = self.mox.CreateMockAnything()
|
||||
self.client.patch(self.url, body=self.body).AndReturn(
|
||||
(None, self.body))
|
||||
self.client.patch(self.url, body=self.body).AndReturn(
|
||||
(None, self.body))
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rsrc = self.mgr._patch(self.url, self.body, "hello")
|
||||
self.assertEqual(rsrc.hi, 1)
|
||||
|
||||
rsrc = self.mgr._patch(self.url, self.body)
|
||||
self.assertEqual(rsrc.hello["hi"], 1)
|
||||
|
||||
def test_update(self):
|
||||
self.client.patch = self.mox.CreateMockAnything()
|
||||
self.client.put = self.mox.CreateMockAnything()
|
||||
self.client.patch(
|
||||
self.url, body=self.body, management=False).AndReturn((None,
|
||||
self.body))
|
||||
self.client.put(self.url, body=None, management=True).AndReturn(
|
||||
(None, self.body))
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rsrc = self.mgr._update(
|
||||
self.url, body=self.body, response_key="hello", method="PATCH",
|
||||
management=False)
|
||||
self.assertEqual(rsrc.hi, 1)
|
||||
|
||||
rsrc = self.mgr._update(
|
||||
self.url, body=None, response_key="hello", method="PUT",
|
||||
management=True)
|
||||
self.assertEqual(rsrc.hi, 1)
|
@ -1,149 +0,0 @@
|
||||
# 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
|
||||
import subprocess
|
||||
|
||||
import mock
|
||||
import testresources
|
||||
from testtools import matchers
|
||||
|
||||
from keystoneclient.common import cms
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.tests import client_fixtures
|
||||
from keystoneclient.tests import utils
|
||||
|
||||
|
||||
class CMSTest(utils.TestCase, testresources.ResourcedTestCase):
|
||||
|
||||
"""Unit tests for the keystoneclient.common.cms module."""
|
||||
|
||||
resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)]
|
||||
|
||||
def test_cms_verify(self):
|
||||
self.assertRaises(exceptions.CertificateConfigError,
|
||||
cms.cms_verify,
|
||||
'data',
|
||||
'no_exist_cert_file',
|
||||
'no_exist_ca_file')
|
||||
|
||||
def test_token_tocms_to_token(self):
|
||||
with open(os.path.join(client_fixtures.CMSDIR,
|
||||
'auth_token_scoped.pem')) as f:
|
||||
AUTH_TOKEN_SCOPED_CMS = f.read()
|
||||
|
||||
self.assertEqual(cms.token_to_cms(self.examples.SIGNED_TOKEN_SCOPED),
|
||||
AUTH_TOKEN_SCOPED_CMS)
|
||||
|
||||
tok = cms.cms_to_token(cms.token_to_cms(
|
||||
self.examples.SIGNED_TOKEN_SCOPED))
|
||||
self.assertEqual(tok, self.examples.SIGNED_TOKEN_SCOPED)
|
||||
|
||||
def test_asn1_token(self):
|
||||
self.assertTrue(cms.is_asn1_token(self.examples.SIGNED_TOKEN_SCOPED))
|
||||
self.assertFalse(cms.is_asn1_token('FOOBAR'))
|
||||
|
||||
def test_cms_sign_token_no_files(self):
|
||||
self.assertRaises(subprocess.CalledProcessError,
|
||||
cms.cms_sign_token,
|
||||
self.examples.TOKEN_SCOPED_DATA,
|
||||
'/no/such/file', '/no/such/key')
|
||||
|
||||
def test_cms_sign_token_no_files_pkiz(self):
|
||||
self.assertRaises(subprocess.CalledProcessError,
|
||||
cms.pkiz_sign,
|
||||
self.examples.TOKEN_SCOPED_DATA,
|
||||
'/no/such/file', '/no/such/key')
|
||||
|
||||
def test_cms_sign_token_success(self):
|
||||
self.assertTrue(
|
||||
cms.pkiz_sign(self.examples.TOKEN_SCOPED_DATA,
|
||||
self.examples.SIGNING_CERT_FILE,
|
||||
self.examples.SIGNING_KEY_FILE))
|
||||
|
||||
def test_cms_verify_token_no_files(self):
|
||||
self.assertRaises(exceptions.CertificateConfigError,
|
||||
cms.cms_verify,
|
||||
self.examples.SIGNED_TOKEN_SCOPED,
|
||||
'/no/such/file', '/no/such/key')
|
||||
|
||||
def test_cms_verify_token_no_oserror(self):
|
||||
import errno
|
||||
|
||||
def raise_OSError(*args):
|
||||
e = OSError()
|
||||
e.errno = errno.EPIPE
|
||||
raise e
|
||||
|
||||
with mock.patch('subprocess.Popen.communicate', new=raise_OSError):
|
||||
try:
|
||||
cms.cms_verify("x", '/no/such/file', '/no/such/key')
|
||||
except subprocess.CalledProcessError as e:
|
||||
self.assertIn('/no/such/file', e.output)
|
||||
self.assertIn('Hit OSError ', e.output)
|
||||
else:
|
||||
self.fail('Expected subprocess.CalledProcessError')
|
||||
|
||||
def test_cms_verify_token_scoped(self):
|
||||
cms_content = cms.token_to_cms(self.examples.SIGNED_TOKEN_SCOPED)
|
||||
self.assertTrue(cms.cms_verify(cms_content,
|
||||
self.examples.SIGNING_CERT_FILE,
|
||||
self.examples.SIGNING_CA_FILE))
|
||||
|
||||
def test_cms_verify_token_scoped_expired(self):
|
||||
cms_content = cms.token_to_cms(
|
||||
self.examples.SIGNED_TOKEN_SCOPED_EXPIRED)
|
||||
self.assertTrue(cms.cms_verify(cms_content,
|
||||
self.examples.SIGNING_CERT_FILE,
|
||||
self.examples.SIGNING_CA_FILE))
|
||||
|
||||
def test_cms_verify_token_unscoped(self):
|
||||
cms_content = cms.token_to_cms(self.examples.SIGNED_TOKEN_UNSCOPED)
|
||||
self.assertTrue(cms.cms_verify(cms_content,
|
||||
self.examples.SIGNING_CERT_FILE,
|
||||
self.examples.SIGNING_CA_FILE))
|
||||
|
||||
def test_cms_verify_token_v3_scoped(self):
|
||||
cms_content = cms.token_to_cms(self.examples.SIGNED_v3_TOKEN_SCOPED)
|
||||
self.assertTrue(cms.cms_verify(cms_content,
|
||||
self.examples.SIGNING_CERT_FILE,
|
||||
self.examples.SIGNING_CA_FILE))
|
||||
|
||||
def test_cms_hash_token_no_token_id(self):
|
||||
token_id = None
|
||||
self.assertThat(cms.cms_hash_token(token_id), matchers.Is(None))
|
||||
|
||||
def test_cms_hash_token_not_pki(self):
|
||||
"""If the token_id is not a PKI token then it returns the token_id."""
|
||||
token = 'something'
|
||||
self.assertFalse(cms.is_asn1_token(token))
|
||||
self.assertThat(cms.cms_hash_token(token), matchers.Is(token))
|
||||
|
||||
def test_cms_hash_token_default_md5(self):
|
||||
"""The default hash method is md5."""
|
||||
token = self.examples.SIGNED_TOKEN_SCOPED
|
||||
token_id_default = cms.cms_hash_token(token)
|
||||
token_id_md5 = cms.cms_hash_token(token, mode='md5')
|
||||
self.assertThat(token_id_default, matchers.Equals(token_id_md5))
|
||||
# md5 hash is 32 chars.
|
||||
self.assertThat(token_id_default, matchers.HasLength(32))
|
||||
|
||||
def test_cms_hash_token_sha256(self):
|
||||
"""Can also hash with sha256."""
|
||||
token = self.examples.SIGNED_TOKEN_SCOPED
|
||||
token_id = cms.cms_hash_token(token, mode='sha256')
|
||||
# sha256 hash is 64 chars.
|
||||
self.assertThat(token_id, matchers.HasLength(64))
|
||||
|
||||
|
||||
def load_tests(loader, tests, pattern):
|
||||
return testresources.OptimisingTestSuite(tests)
|
@ -1,790 +0,0 @@
|
||||
# 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 httpretty
|
||||
import six
|
||||
from testtools import matchers
|
||||
|
||||
from keystoneclient import _discover
|
||||
from keystoneclient import client
|
||||
from keystoneclient import discover
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.openstack.common import jsonutils
|
||||
from keystoneclient.tests import utils
|
||||
from keystoneclient.v2_0 import client as v2_client
|
||||
from keystoneclient.v3 import client as v3_client
|
||||
|
||||
|
||||
BASE_HOST = 'http://keystone.example.com'
|
||||
BASE_URL = "%s:5000/" % BASE_HOST
|
||||
UPDATED = '2013-03-06T00:00:00Z'
|
||||
|
||||
TEST_SERVICE_CATALOG = [{
|
||||
"endpoints": [{
|
||||
"adminURL": "%s:8774/v1.0" % BASE_HOST,
|
||||
"region": "RegionOne",
|
||||
"internalURL": "%s://127.0.0.1:8774/v1.0" % BASE_HOST,
|
||||
"publicURL": "%s:8774/v1.0/" % BASE_HOST
|
||||
}],
|
||||
"type": "nova_compat",
|
||||
"name": "nova_compat"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": "http://nova/novapi/admin",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://nova/novapi/internal",
|
||||
"publicURL": "http://nova/novapi/public"
|
||||
}],
|
||||
"type": "compute",
|
||||
"name": "nova"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": "http://glance/glanceapi/admin",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://glance/glanceapi/internal",
|
||||
"publicURL": "http://glance/glanceapi/public"
|
||||
}],
|
||||
"type": "image",
|
||||
"name": "glance"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": "%s:35357/v2.0" % BASE_HOST,
|
||||
"region": "RegionOne",
|
||||
"internalURL": "%s:5000/v2.0" % BASE_HOST,
|
||||
"publicURL": "%s:5000/v2.0" % BASE_HOST
|
||||
}],
|
||||
"type": "identity",
|
||||
"name": "keystone"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": "http://swift/swiftapi/admin",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://swift/swiftapi/internal",
|
||||
"publicURL": "http://swift/swiftapi/public"
|
||||
}],
|
||||
"type": "object-store",
|
||||
"name": "swift"
|
||||
}]
|
||||
|
||||
V2_URL = "%sv2.0" % BASE_URL
|
||||
V2_DESCRIBED_BY_HTML = {'href': 'http://docs.openstack.org/api/'
|
||||
'openstack-identity-service/2.0/content/',
|
||||
'rel': 'describedby',
|
||||
'type': 'text/html'}
|
||||
V2_DESCRIBED_BY_PDF = {'href': 'http://docs.openstack.org/api/openstack-ident'
|
||||
'ity-service/2.0/identity-dev-guide-2.0.pdf',
|
||||
'rel': 'describedby',
|
||||
'type': 'application/pdf'}
|
||||
|
||||
V2_VERSION = {'id': 'v2.0',
|
||||
'links': [{'href': V2_URL, 'rel': 'self'},
|
||||
V2_DESCRIBED_BY_HTML, V2_DESCRIBED_BY_PDF],
|
||||
'status': 'stable',
|
||||
'updated': UPDATED}
|
||||
|
||||
V2_AUTH_RESPONSE = jsonutils.dumps({
|
||||
"access": {
|
||||
"token": {
|
||||
"expires": "2020-01-01T00:00:10.000123Z",
|
||||
"id": 'fakeToken',
|
||||
"tenant": {
|
||||
"id": '1'
|
||||
},
|
||||
},
|
||||
"user": {
|
||||
"id": 'test'
|
||||
},
|
||||
"serviceCatalog": TEST_SERVICE_CATALOG,
|
||||
},
|
||||
})
|
||||
|
||||
V3_URL = "%sv3" % BASE_URL
|
||||
V3_MEDIA_TYPES = [{'base': 'application/json',
|
||||
'type': 'application/vnd.openstack.identity-v3+json'},
|
||||
{'base': 'application/xml',
|
||||
'type': 'application/vnd.openstack.identity-v3+xml'}]
|
||||
|
||||
V3_VERSION = {'id': 'v3.0',
|
||||
'links': [{'href': V3_URL, 'rel': 'self'}],
|
||||
'media-types': V3_MEDIA_TYPES,
|
||||
'status': 'stable',
|
||||
'updated': UPDATED}
|
||||
|
||||
V3_TOKEN = six.u('3e2813b7ba0b4006840c3825860b86ed'),
|
||||
V3_AUTH_RESPONSE = jsonutils.dumps({
|
||||
"token": {
|
||||
"methods": [
|
||||
"token",
|
||||
"password"
|
||||
],
|
||||
|
||||
"expires_at": "2020-01-01T00:00:10.000123Z",
|
||||
"project": {
|
||||
"domain": {
|
||||
"id": '1',
|
||||
"name": 'test-domain'
|
||||
},
|
||||
"id": '1',
|
||||
"name": 'test-project'
|
||||
},
|
||||
"user": {
|
||||
"domain": {
|
||||
"id": '1',
|
||||
"name": 'test-domain'
|
||||
},
|
||||
"id": '1',
|
||||
"name": 'test-user'
|
||||
},
|
||||
"issued_at": "2013-05-29T16:55:21.468960Z",
|
||||
},
|
||||
})
|
||||
|
||||
CINDER_EXAMPLES = {
|
||||
"versions": [
|
||||
{
|
||||
"status": "CURRENT",
|
||||
"updated": "2012-01-04T11:33:21Z",
|
||||
"id": "v1.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "%sv1/" % BASE_URL,
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"status": "CURRENT",
|
||||
"updated": "2012-11-21T11:33:21Z",
|
||||
"id": "v2.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "%sv2/" % BASE_URL,
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
GLANCE_EXAMPLES = {
|
||||
"versions": [
|
||||
{
|
||||
"status": "CURRENT",
|
||||
"id": "v2.2",
|
||||
"links": [
|
||||
{
|
||||
"href": "%sv2/" % BASE_URL,
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"status": "SUPPORTED",
|
||||
"id": "v2.1",
|
||||
"links": [
|
||||
{
|
||||
"href": "%sv2/" % BASE_URL,
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"status": "SUPPORTED",
|
||||
"id": "v2.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "%sv2/" % BASE_URL,
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"status": "CURRENT",
|
||||
"id": "v1.1",
|
||||
"links": [
|
||||
{
|
||||
"href": "%sv1/" % BASE_URL,
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"status": "SUPPORTED",
|
||||
"id": "v1.0",
|
||||
"links": [
|
||||
{
|
||||
"href": "%sv1/" % BASE_URL,
|
||||
"rel": "self"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def _create_version_list(versions):
|
||||
return jsonutils.dumps({'versions': {'values': versions}})
|
||||
|
||||
|
||||
def _create_single_version(version):
|
||||
return jsonutils.dumps({'version': version})
|
||||
|
||||
|
||||
V3_VERSION_LIST = _create_version_list([V3_VERSION, V2_VERSION])
|
||||
V2_VERSION_LIST = _create_version_list([V2_VERSION])
|
||||
|
||||
V3_VERSION_ENTRY = _create_single_version(V3_VERSION)
|
||||
V2_VERSION_ENTRY = _create_single_version(V2_VERSION)
|
||||
|
||||
|
||||
@httpretty.activate
|
||||
class AvailableVersionsTests(utils.TestCase):
|
||||
|
||||
def test_available_versions_basics(self):
|
||||
examples = {'keystone': V3_VERSION_LIST,
|
||||
'cinder': jsonutils.dumps(CINDER_EXAMPLES),
|
||||
'glance': jsonutils.dumps(GLANCE_EXAMPLES)}
|
||||
|
||||
for path, ex in six.iteritems(examples):
|
||||
url = "%s%s" % (BASE_URL, path)
|
||||
|
||||
httpretty.register_uri(httpretty.GET, url, status=300, body=ex)
|
||||
versions = discover.available_versions(url)
|
||||
|
||||
for v in versions:
|
||||
for n in ('id', 'status', 'links'):
|
||||
msg = '%s missing from %s version data' % (n, path)
|
||||
self.assertThat(v, matchers.Annotate(msg,
|
||||
matchers.Contains(n)))
|
||||
|
||||
def test_available_versions_individual(self):
|
||||
httpretty.register_uri(httpretty.GET, V3_URL, status=200,
|
||||
body=V3_VERSION_ENTRY)
|
||||
|
||||
versions = discover.available_versions(V3_URL)
|
||||
|
||||
for v in versions:
|
||||
self.assertEqual(v['id'], 'v3.0')
|
||||
self.assertEqual(v['status'], 'stable')
|
||||
self.assertIn('media-types', v)
|
||||
self.assertIn('links', v)
|
||||
|
||||
def test_available_keystone_data(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=V3_VERSION_LIST)
|
||||
|
||||
versions = discover.available_versions(BASE_URL)
|
||||
self.assertEqual(2, len(versions))
|
||||
|
||||
for v in versions:
|
||||
self.assertIn(v['id'], ('v2.0', 'v3.0'))
|
||||
self.assertEqual(v['updated'], UPDATED)
|
||||
self.assertEqual(v['status'], 'stable')
|
||||
|
||||
if v['id'] == 'v3.0':
|
||||
self.assertEqual(v['media-types'], V3_MEDIA_TYPES)
|
||||
|
||||
def test_available_cinder_data(self):
|
||||
body = jsonutils.dumps(CINDER_EXAMPLES)
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300, body=body)
|
||||
|
||||
versions = discover.available_versions(BASE_URL)
|
||||
self.assertEqual(2, len(versions))
|
||||
|
||||
for v in versions:
|
||||
self.assertEqual(v['status'], 'CURRENT')
|
||||
if v['id'] == 'v1.0':
|
||||
self.assertEqual(v['updated'], '2012-01-04T11:33:21Z')
|
||||
elif v['id'] == 'v2.0':
|
||||
self.assertEqual(v['updated'], '2012-11-21T11:33:21Z')
|
||||
else:
|
||||
self.fail("Invalid version found")
|
||||
|
||||
def test_available_glance_data(self):
|
||||
body = jsonutils.dumps(GLANCE_EXAMPLES)
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=200, body=body)
|
||||
|
||||
versions = discover.available_versions(BASE_URL)
|
||||
self.assertEqual(5, len(versions))
|
||||
|
||||
for v in versions:
|
||||
if v['id'] in ('v2.2', 'v1.1'):
|
||||
self.assertEqual(v['status'], 'CURRENT')
|
||||
elif v['id'] in ('v2.1', 'v2.0', 'v1.0'):
|
||||
self.assertEqual(v['status'], 'SUPPORTED')
|
||||
else:
|
||||
self.fail("Invalid version found")
|
||||
|
||||
|
||||
@httpretty.activate
|
||||
class ClientDiscoveryTests(utils.TestCase):
|
||||
|
||||
def assertCreatesV3(self, **kwargs):
|
||||
httpretty.register_uri(httpretty.POST, "%s/auth/tokens" % V3_URL,
|
||||
body=V3_AUTH_RESPONSE, X_Subject_Token=V3_TOKEN)
|
||||
|
||||
kwargs.setdefault('username', 'foo')
|
||||
kwargs.setdefault('password', 'bar')
|
||||
keystone = client.Client(**kwargs)
|
||||
self.assertIsInstance(keystone, v3_client.Client)
|
||||
return keystone
|
||||
|
||||
def assertCreatesV2(self, **kwargs):
|
||||
httpretty.register_uri(httpretty.POST, "%s/tokens" % V2_URL,
|
||||
body=V2_AUTH_RESPONSE)
|
||||
|
||||
kwargs.setdefault('username', 'foo')
|
||||
kwargs.setdefault('password', 'bar')
|
||||
keystone = client.Client(**kwargs)
|
||||
self.assertIsInstance(keystone, v2_client.Client)
|
||||
return keystone
|
||||
|
||||
def assertVersionNotAvailable(self, **kwargs):
|
||||
kwargs.setdefault('username', 'foo')
|
||||
kwargs.setdefault('password', 'bar')
|
||||
|
||||
self.assertRaises(exceptions.VersionNotAvailable,
|
||||
client.Client, **kwargs)
|
||||
|
||||
def assertDiscoveryFailure(self, **kwargs):
|
||||
kwargs.setdefault('username', 'foo')
|
||||
kwargs.setdefault('password', 'bar')
|
||||
|
||||
self.assertRaises(exceptions.DiscoveryFailure,
|
||||
client.Client, **kwargs)
|
||||
|
||||
def test_discover_v3(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=V3_VERSION_LIST)
|
||||
|
||||
self.assertCreatesV3(auth_url=BASE_URL)
|
||||
|
||||
def test_discover_v2(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=V2_VERSION_LIST)
|
||||
httpretty.register_uri(httpretty.POST, "%s/tokens" % V2_URL,
|
||||
body=V2_AUTH_RESPONSE)
|
||||
|
||||
self.assertCreatesV2(auth_url=BASE_URL)
|
||||
|
||||
def test_discover_endpoint_v2(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=V2_VERSION_LIST)
|
||||
self.assertCreatesV2(endpoint=BASE_URL, token='fake-token')
|
||||
|
||||
def test_discover_endpoint_v3(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=V3_VERSION_LIST)
|
||||
self.assertCreatesV3(endpoint=BASE_URL, token='fake-token')
|
||||
|
||||
def test_discover_invalid_major_version(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=V3_VERSION_LIST)
|
||||
|
||||
self.assertVersionNotAvailable(auth_url=BASE_URL, version=5)
|
||||
|
||||
def test_discover_200_response_fails(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=200, body='ok')
|
||||
self.assertDiscoveryFailure(auth_url=BASE_URL)
|
||||
|
||||
def test_discover_minor_greater_than_available_fails(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=V3_VERSION_LIST)
|
||||
|
||||
self.assertVersionNotAvailable(endpoint=BASE_URL, version=3.4)
|
||||
|
||||
def test_discover_individual_version_v2(self):
|
||||
httpretty.register_uri(httpretty.GET, V2_URL, status=200,
|
||||
body=V2_VERSION_ENTRY)
|
||||
|
||||
self.assertCreatesV2(auth_url=V2_URL)
|
||||
|
||||
def test_discover_individual_version_v3(self):
|
||||
httpretty.register_uri(httpretty.GET, V3_URL, status=200,
|
||||
body=V3_VERSION_ENTRY)
|
||||
|
||||
self.assertCreatesV3(auth_url=V3_URL)
|
||||
|
||||
def test_discover_individual_endpoint_v2(self):
|
||||
httpretty.register_uri(httpretty.GET, V2_URL, status=200,
|
||||
body=V2_VERSION_ENTRY)
|
||||
self.assertCreatesV2(endpoint=V2_URL, token='fake-token')
|
||||
|
||||
def test_discover_individual_endpoint_v3(self):
|
||||
httpretty.register_uri(httpretty.GET, V3_URL, status=200,
|
||||
body=V3_VERSION_ENTRY)
|
||||
self.assertCreatesV3(endpoint=V3_URL, token='fake-token')
|
||||
|
||||
def test_discover_fail_to_create_bad_individual_version(self):
|
||||
httpretty.register_uri(httpretty.GET, V2_URL, status=200,
|
||||
body=V2_VERSION_ENTRY)
|
||||
httpretty.register_uri(httpretty.GET, V3_URL, status=200,
|
||||
body=V3_VERSION_ENTRY)
|
||||
|
||||
self.assertVersionNotAvailable(auth_url=V2_URL, version=3)
|
||||
self.assertVersionNotAvailable(auth_url=V3_URL, version=2)
|
||||
|
||||
def test_discover_unstable_versions(self):
|
||||
v3_unstable_version = V3_VERSION.copy()
|
||||
v3_unstable_version['status'] = 'beta'
|
||||
version_list = _create_version_list([v3_unstable_version, V2_VERSION])
|
||||
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=version_list)
|
||||
|
||||
self.assertCreatesV2(auth_url=BASE_URL)
|
||||
self.assertVersionNotAvailable(auth_url=BASE_URL, version=3)
|
||||
self.assertCreatesV3(auth_url=BASE_URL, unstable=True)
|
||||
|
||||
def test_discover_forwards_original_ip(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=V3_VERSION_LIST)
|
||||
|
||||
ip = '192.168.1.1'
|
||||
self.assertCreatesV3(auth_url=BASE_URL, original_ip=ip)
|
||||
|
||||
self.assertThat(httpretty.last_request().headers['forwarded'],
|
||||
matchers.Contains(ip))
|
||||
|
||||
def test_discover_bad_args(self):
|
||||
self.assertRaises(exceptions.DiscoveryFailure,
|
||||
client.Client)
|
||||
|
||||
def test_discover_bad_response(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=jsonutils.dumps({'FOO': 'BAR'}))
|
||||
self.assertDiscoveryFailure(auth_url=BASE_URL)
|
||||
|
||||
def test_discovery_ignore_invalid(self):
|
||||
resp = [{'id': 'v3.0',
|
||||
'links': [1, 2, 3, 4], # invalid links
|
||||
'media-types': V3_MEDIA_TYPES,
|
||||
'status': 'stable',
|
||||
'updated': UPDATED}]
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=_create_version_list(resp))
|
||||
self.assertDiscoveryFailure(auth_url=BASE_URL)
|
||||
|
||||
def test_ignore_entry_without_links(self):
|
||||
v3 = V3_VERSION.copy()
|
||||
v3['links'] = []
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=_create_version_list([v3, V2_VERSION]))
|
||||
self.assertCreatesV2(auth_url=BASE_URL)
|
||||
|
||||
def test_ignore_entry_without_status(self):
|
||||
v3 = V3_VERSION.copy()
|
||||
del v3['status']
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=_create_version_list([v3, V2_VERSION]))
|
||||
self.assertCreatesV2(auth_url=BASE_URL)
|
||||
|
||||
def test_greater_version_than_required(self):
|
||||
resp = [{'id': 'v3.6',
|
||||
'links': [{'href': V3_URL, 'rel': 'self'}],
|
||||
'media-types': V3_MEDIA_TYPES,
|
||||
'status': 'stable',
|
||||
'updated': UPDATED}]
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=200,
|
||||
body=_create_version_list(resp))
|
||||
self.assertCreatesV3(auth_url=BASE_URL, version=(3, 4))
|
||||
|
||||
def test_lesser_version_than_required(self):
|
||||
resp = [{'id': 'v3.4',
|
||||
'links': [{'href': V3_URL, 'rel': 'self'}],
|
||||
'media-types': V3_MEDIA_TYPES,
|
||||
'status': 'stable',
|
||||
'updated': UPDATED}]
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=200,
|
||||
body=_create_version_list(resp))
|
||||
self.assertVersionNotAvailable(auth_url=BASE_URL, version=(3, 6))
|
||||
|
||||
def test_bad_response(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body="Ugly Duckling")
|
||||
self.assertDiscoveryFailure(auth_url=BASE_URL)
|
||||
|
||||
def test_pass_client_arguments(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=V2_VERSION_LIST)
|
||||
kwargs = {'original_ip': '100', 'use_keyring': False,
|
||||
'stale_duration': 15}
|
||||
|
||||
cl = self.assertCreatesV2(auth_url=BASE_URL, **kwargs)
|
||||
|
||||
self.assertEqual(cl.original_ip, '100')
|
||||
self.assertEqual(cl.stale_duration, 15)
|
||||
self.assertFalse(cl.use_keyring)
|
||||
|
||||
def test_overriding_stored_kwargs(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=V3_VERSION_LIST)
|
||||
|
||||
httpretty.register_uri(httpretty.POST, "%s/auth/tokens" % V3_URL,
|
||||
body=V3_AUTH_RESPONSE, X_Subject_Token=V3_TOKEN)
|
||||
|
||||
disc = discover.Discover(auth_url=BASE_URL, debug=False,
|
||||
username='foo')
|
||||
client = disc.create_client(debug=True, password='bar')
|
||||
|
||||
self.assertIsInstance(client, v3_client.Client)
|
||||
self.assertTrue(client.debug_log)
|
||||
self.assertFalse(disc._client_kwargs['debug'])
|
||||
self.assertEqual(client.username, 'foo')
|
||||
self.assertEqual(client.password, 'bar')
|
||||
|
||||
def test_available_versions(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=V3_VERSION_ENTRY)
|
||||
disc = discover.Discover(auth_url=BASE_URL)
|
||||
|
||||
versions = disc.available_versions()
|
||||
self.assertEqual(1, len(versions))
|
||||
self.assertEqual(V3_VERSION, versions[0])
|
||||
|
||||
def test_unknown_client_version(self):
|
||||
V4_VERSION = {'id': 'v4.0',
|
||||
'links': [{'href': 'http://url', 'rel': 'self'}],
|
||||
'media-types': V3_MEDIA_TYPES,
|
||||
'status': 'stable',
|
||||
'updated': UPDATED}
|
||||
body = _create_version_list([V4_VERSION, V3_VERSION, V2_VERSION])
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300, body=body)
|
||||
|
||||
disc = discover.Discover(auth_url=BASE_URL)
|
||||
self.assertRaises(exceptions.DiscoveryFailure,
|
||||
disc.create_client, version=4)
|
||||
|
||||
|
||||
@httpretty.activate
|
||||
class DiscoverQueryTests(utils.TestCase):
|
||||
|
||||
def test_available_keystone_data(self):
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300,
|
||||
body=V3_VERSION_LIST)
|
||||
|
||||
disc = discover.Discover(auth_url=BASE_URL)
|
||||
versions = disc.version_data()
|
||||
|
||||
self.assertEqual((2, 0), versions[0]['version'])
|
||||
self.assertEqual('stable', versions[0]['raw_status'])
|
||||
self.assertEqual(V2_URL, versions[0]['url'])
|
||||
self.assertEqual((3, 0), versions[1]['version'])
|
||||
self.assertEqual('stable', versions[1]['raw_status'])
|
||||
self.assertEqual(V3_URL, versions[1]['url'])
|
||||
|
||||
version = disc.data_for('v3.0')
|
||||
self.assertEqual((3, 0), version['version'])
|
||||
self.assertEqual('stable', version['raw_status'])
|
||||
self.assertEqual(V3_URL, version['url'])
|
||||
|
||||
version = disc.data_for(2)
|
||||
self.assertEqual((2, 0), version['version'])
|
||||
self.assertEqual('stable', version['raw_status'])
|
||||
self.assertEqual(V2_URL, version['url'])
|
||||
|
||||
self.assertIsNone(disc.url_for('v4'))
|
||||
self.assertEqual(V3_URL, disc.url_for('v3'))
|
||||
self.assertEqual(V2_URL, disc.url_for('v2'))
|
||||
|
||||
def test_available_cinder_data(self):
|
||||
body = jsonutils.dumps(CINDER_EXAMPLES)
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=300, body=body)
|
||||
|
||||
v1_url = "%sv1/" % BASE_URL
|
||||
v2_url = "%sv2/" % BASE_URL
|
||||
|
||||
disc = discover.Discover(auth_url=BASE_URL)
|
||||
versions = disc.version_data()
|
||||
|
||||
self.assertEqual((1, 0), versions[0]['version'])
|
||||
self.assertEqual('CURRENT', versions[0]['raw_status'])
|
||||
self.assertEqual(v1_url, versions[0]['url'])
|
||||
self.assertEqual((2, 0), versions[1]['version'])
|
||||
self.assertEqual('CURRENT', versions[1]['raw_status'])
|
||||
self.assertEqual(v2_url, versions[1]['url'])
|
||||
|
||||
version = disc.data_for('v2.0')
|
||||
self.assertEqual((2, 0), version['version'])
|
||||
self.assertEqual('CURRENT', version['raw_status'])
|
||||
self.assertEqual(v2_url, version['url'])
|
||||
|
||||
version = disc.data_for(1)
|
||||
self.assertEqual((1, 0), version['version'])
|
||||
self.assertEqual('CURRENT', version['raw_status'])
|
||||
self.assertEqual(v1_url, version['url'])
|
||||
|
||||
self.assertIsNone(disc.url_for('v3'))
|
||||
self.assertEqual(v2_url, disc.url_for('v2'))
|
||||
self.assertEqual(v1_url, disc.url_for('v1'))
|
||||
|
||||
def test_available_glance_data(self):
|
||||
body = jsonutils.dumps(GLANCE_EXAMPLES)
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=200, body=body)
|
||||
|
||||
v1_url = "%sv1/" % BASE_URL
|
||||
v2_url = "%sv2/" % BASE_URL
|
||||
|
||||
disc = discover.Discover(auth_url=BASE_URL)
|
||||
versions = disc.version_data()
|
||||
|
||||
self.assertEqual((1, 0), versions[0]['version'])
|
||||
self.assertEqual('SUPPORTED', versions[0]['raw_status'])
|
||||
self.assertEqual(v1_url, versions[0]['url'])
|
||||
self.assertEqual((1, 1), versions[1]['version'])
|
||||
self.assertEqual('CURRENT', versions[1]['raw_status'])
|
||||
self.assertEqual(v1_url, versions[1]['url'])
|
||||
self.assertEqual((2, 0), versions[2]['version'])
|
||||
self.assertEqual('SUPPORTED', versions[2]['raw_status'])
|
||||
self.assertEqual(v2_url, versions[2]['url'])
|
||||
self.assertEqual((2, 1), versions[3]['version'])
|
||||
self.assertEqual('SUPPORTED', versions[3]['raw_status'])
|
||||
self.assertEqual(v2_url, versions[3]['url'])
|
||||
self.assertEqual((2, 2), versions[4]['version'])
|
||||
self.assertEqual('CURRENT', versions[4]['raw_status'])
|
||||
self.assertEqual(v2_url, versions[4]['url'])
|
||||
|
||||
for ver in (2, 2.1, 2.2):
|
||||
version = disc.data_for(ver)
|
||||
self.assertEqual((2, 2), version['version'])
|
||||
self.assertEqual('CURRENT', version['raw_status'])
|
||||
self.assertEqual(v2_url, version['url'])
|
||||
self.assertEqual(v2_url, disc.url_for(ver))
|
||||
|
||||
for ver in (1, 1.1):
|
||||
version = disc.data_for(ver)
|
||||
self.assertEqual((1, 1), version['version'])
|
||||
self.assertEqual('CURRENT', version['raw_status'])
|
||||
self.assertEqual(v1_url, version['url'])
|
||||
self.assertEqual(v1_url, disc.url_for(ver))
|
||||
|
||||
self.assertIsNone(disc.url_for('v3'))
|
||||
self.assertIsNone(disc.url_for('v2.3'))
|
||||
|
||||
def test_allow_deprecated(self):
|
||||
status = 'deprecated'
|
||||
version_list = [{'id': 'v3.0',
|
||||
'links': [{'href': V3_URL, 'rel': 'self'}],
|
||||
'media-types': V3_MEDIA_TYPES,
|
||||
'status': status,
|
||||
'updated': UPDATED}]
|
||||
body = jsonutils.dumps({'versions': version_list})
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=200, body=body)
|
||||
|
||||
disc = discover.Discover(auth_url=BASE_URL)
|
||||
|
||||
# deprecated is allowed by default
|
||||
versions = disc.version_data(allow_deprecated=False)
|
||||
self.assertEqual(0, len(versions))
|
||||
|
||||
versions = disc.version_data(allow_deprecated=True)
|
||||
self.assertEqual(1, len(versions))
|
||||
self.assertEqual(status, versions[0]['raw_status'])
|
||||
self.assertEqual(V3_URL, versions[0]['url'])
|
||||
self.assertEqual((3, 0), versions[0]['version'])
|
||||
|
||||
def test_allow_experimental(self):
|
||||
status = 'experimental'
|
||||
version_list = [{'id': 'v3.0',
|
||||
'links': [{'href': V3_URL, 'rel': 'self'}],
|
||||
'media-types': V3_MEDIA_TYPES,
|
||||
'status': status,
|
||||
'updated': UPDATED}]
|
||||
body = jsonutils.dumps({'versions': version_list})
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=200, body=body)
|
||||
|
||||
disc = discover.Discover(auth_url=BASE_URL)
|
||||
|
||||
versions = disc.version_data()
|
||||
self.assertEqual(0, len(versions))
|
||||
|
||||
versions = disc.version_data(allow_experimental=True)
|
||||
self.assertEqual(1, len(versions))
|
||||
self.assertEqual(status, versions[0]['raw_status'])
|
||||
self.assertEqual(V3_URL, versions[0]['url'])
|
||||
self.assertEqual((3, 0), versions[0]['version'])
|
||||
|
||||
def test_allow_unknown(self):
|
||||
status = 'abcdef'
|
||||
version_list = [{'id': 'v3.0',
|
||||
'links': [{'href': V3_URL, 'rel': 'self'}],
|
||||
'media-types': V3_MEDIA_TYPES,
|
||||
'status': status,
|
||||
'updated': UPDATED}]
|
||||
body = jsonutils.dumps({'versions': version_list})
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=200, body=body)
|
||||
|
||||
disc = discover.Discover(auth_url=BASE_URL)
|
||||
|
||||
versions = disc.version_data()
|
||||
self.assertEqual(0, len(versions))
|
||||
|
||||
versions = disc.version_data(allow_unknown=True)
|
||||
self.assertEqual(1, len(versions))
|
||||
self.assertEqual(status, versions[0]['raw_status'])
|
||||
self.assertEqual(V3_URL, versions[0]['url'])
|
||||
self.assertEqual((3, 0), versions[0]['version'])
|
||||
|
||||
def test_ignoring_invalid_lnks(self):
|
||||
version_list = [{'id': 'v3.0',
|
||||
'links': [{'href': V3_URL, 'rel': 'self'}],
|
||||
'media-types': V3_MEDIA_TYPES,
|
||||
'status': 'stable',
|
||||
'updated': UPDATED},
|
||||
{'id': 'v3.1',
|
||||
'media-types': V3_MEDIA_TYPES,
|
||||
'status': 'stable',
|
||||
'updated': UPDATED},
|
||||
{'media-types': V3_MEDIA_TYPES,
|
||||
'status': 'stable',
|
||||
'updated': UPDATED,
|
||||
'links': [{'href': V3_URL, 'rel': 'self'}],
|
||||
}]
|
||||
|
||||
body = jsonutils.dumps({'versions': version_list})
|
||||
httpretty.register_uri(httpretty.GET, BASE_URL, status=200, body=body)
|
||||
|
||||
disc = discover.Discover(auth_url=BASE_URL)
|
||||
|
||||
# raw_version_data will return all choices, even invalid ones
|
||||
versions = disc.raw_version_data()
|
||||
self.assertEqual(3, len(versions))
|
||||
|
||||
# only the version with both id and links will be actually returned
|
||||
versions = disc.version_data()
|
||||
self.assertEqual(1, len(versions))
|
||||
|
||||
|
||||
class DiscoverUtils(utils.TestCase):
|
||||
|
||||
def test_version_number(self):
|
||||
def assertVersion(inp, out):
|
||||
self.assertEqual(out, _discover.normalize_version_number(inp))
|
||||
|
||||
def versionRaises(inp):
|
||||
self.assertRaises(TypeError,
|
||||
_discover.normalize_version_number,
|
||||
inp)
|
||||
|
||||
assertVersion('v1.2', (1, 2))
|
||||
assertVersion('v11', (11, 0))
|
||||
assertVersion('1.2', (1, 2))
|
||||
assertVersion('1.5.1', (1, 5, 1))
|
||||
assertVersion('1', (1, 0))
|
||||
assertVersion(1, (1, 0))
|
||||
assertVersion(5.2, (5, 2))
|
||||
assertVersion((6, 1), (6, 1))
|
||||
assertVersion([1, 4], (1, 4))
|
||||
|
||||
versionRaises('hello')
|
||||
versionRaises('1.a')
|
||||
versionRaises('vacuum')
|
@ -1,252 +0,0 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import testtools
|
||||
|
||||
from keystoneclient.contrib.ec2 import utils
|
||||
|
||||
|
||||
class Ec2SignerTest(testtools.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(Ec2SignerTest, self).setUp()
|
||||
self.access = '966afbde20b84200ae4e62e09acf46b2'
|
||||
self.secret = '89cdf9e94e2643cab35b8b8ac5a51f83'
|
||||
self.signer = utils.Ec2Signer(self.secret)
|
||||
|
||||
def test_v4_creds_header(self):
|
||||
auth_str = 'AWS4-HMAC-SHA256 blah'
|
||||
credentials = {'host': '127.0.0.1',
|
||||
'verb': 'GET',
|
||||
'path': '/v1/',
|
||||
'params': {},
|
||||
'headers': {'Authorization': auth_str}}
|
||||
self.assertTrue(self.signer._v4_creds(credentials))
|
||||
|
||||
def test_v4_creds_param(self):
|
||||
credentials = {'host': '127.0.0.1',
|
||||
'verb': 'GET',
|
||||
'path': '/v1/',
|
||||
'params': {'X-Amz-Algorithm': 'AWS4-HMAC-SHA256'},
|
||||
'headers': {}}
|
||||
self.assertTrue(self.signer._v4_creds(credentials))
|
||||
|
||||
def test_v4_creds_false(self):
|
||||
credentials = {'host': '127.0.0.1',
|
||||
'verb': 'GET',
|
||||
'path': '/v1/',
|
||||
'params': {'SignatureVersion': '0',
|
||||
'AWSAccessKeyId': self.access,
|
||||
'Timestamp': '2012-11-27T11:47:02Z',
|
||||
'Action': 'Foo'}}
|
||||
self.assertFalse(self.signer._v4_creds(credentials))
|
||||
|
||||
def test_generate_0(self):
|
||||
"""Test generate function for v0 signature."""
|
||||
credentials = {'host': '127.0.0.1',
|
||||
'verb': 'GET',
|
||||
'path': '/v1/',
|
||||
'params': {'SignatureVersion': '0',
|
||||
'AWSAccessKeyId': self.access,
|
||||
'Timestamp': '2012-11-27T11:47:02Z',
|
||||
'Action': 'Foo'}}
|
||||
signature = self.signer.generate(credentials)
|
||||
expected = 'SmXQEZAUdQw5glv5mX8mmixBtas='
|
||||
self.assertEqual(signature, expected)
|
||||
|
||||
def test_generate_1(self):
|
||||
"""Test generate function for v1 signature."""
|
||||
credentials = {'host': '127.0.0.1',
|
||||
'verb': 'GET',
|
||||
'path': '/v1/',
|
||||
'params': {'SignatureVersion': '1',
|
||||
'AWSAccessKeyId': self.access}}
|
||||
signature = self.signer.generate(credentials)
|
||||
expected = 'VRnoQH/EhVTTLhwRLfuL7jmFW9c='
|
||||
self.assertEqual(signature, expected)
|
||||
|
||||
def test_generate_v2_SHA256(self):
|
||||
"""Test generate function for v2 signature, SHA256."""
|
||||
credentials = {'host': '127.0.0.1',
|
||||
'verb': 'GET',
|
||||
'path': '/v1/',
|
||||
'params': {'SignatureVersion': '2',
|
||||
'AWSAccessKeyId': self.access}}
|
||||
signature = self.signer.generate(credentials)
|
||||
expected = 'odsGmT811GffUO0Eu13Pq+xTzKNIjJ6NhgZU74tYX/w='
|
||||
self.assertEqual(signature, expected)
|
||||
|
||||
def test_generate_v2_SHA1(self):
|
||||
"""Test generate function for v2 signature, SHA1."""
|
||||
credentials = {'host': '127.0.0.1',
|
||||
'verb': 'GET',
|
||||
'path': '/v1/',
|
||||
'params': {'SignatureVersion': '2',
|
||||
'AWSAccessKeyId': self.access}}
|
||||
self.signer.hmac_256 = None
|
||||
signature = self.signer.generate(credentials)
|
||||
expected = 'ZqCxMI4ZtTXWI175743mJ0hy/Gc='
|
||||
self.assertEqual(signature, expected)
|
||||
|
||||
def test_generate_v4(self):
|
||||
"""Test v4 generator with data from AWS docs example.
|
||||
|
||||
see:
|
||||
http://docs.aws.amazon.com/general/latest/gr/
|
||||
sigv4-create-canonical-request.html
|
||||
and
|
||||
http://docs.aws.amazon.com/general/latest/gr/
|
||||
sigv4-signed-request-examples.html
|
||||
"""
|
||||
# Create a new signer object with the AWS example key
|
||||
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
|
||||
signer = utils.Ec2Signer(secret)
|
||||
|
||||
body_hash = ('b6359072c78d70ebee1e81adcbab4f0'
|
||||
'1bf2c23245fa365ef83fe8f1f955085e2')
|
||||
auth_str = ('AWS4-HMAC-SHA256 '
|
||||
'Credential=AKIAIOSFODNN7EXAMPLE/20110909/'
|
||||
'us-east-1/iam/aws4_request,'
|
||||
'SignedHeaders=content-type;host;x-amz-date,')
|
||||
headers = {'Content-type':
|
||||
'application/x-www-form-urlencoded; charset=utf-8',
|
||||
'X-Amz-Date': '20110909T233600Z',
|
||||
'Host': 'iam.amazonaws.com',
|
||||
'Authorization': auth_str}
|
||||
# Note the example in the AWS docs is inconsistent, previous
|
||||
# examples specify no query string, but the final POST example
|
||||
# does, apparently incorrectly since an empty parameter list
|
||||
# aligns all steps and the final signature with the examples
|
||||
params = {}
|
||||
credentials = {'host': 'iam.amazonaws.com',
|
||||
'verb': 'POST',
|
||||
'path': '/',
|
||||
'params': params,
|
||||
'headers': headers,
|
||||
'body_hash': body_hash}
|
||||
signature = signer.generate(credentials)
|
||||
expected = ('ced6826de92d2bdeed8f846f0bf508e8'
|
||||
'559e98e4b0199114b84c54174deb456c')
|
||||
self.assertEqual(signature, expected)
|
||||
|
||||
def test_generate_v4_port(self):
|
||||
"""Test v4 generator with host:port format."""
|
||||
# Create a new signer object with the AWS example key
|
||||
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
|
||||
signer = utils.Ec2Signer(secret)
|
||||
|
||||
body_hash = ('b6359072c78d70ebee1e81adcbab4f0'
|
||||
'1bf2c23245fa365ef83fe8f1f955085e2')
|
||||
auth_str = ('AWS4-HMAC-SHA256 '
|
||||
'Credential=AKIAIOSFODNN7EXAMPLE/20110909/'
|
||||
'us-east-1/iam/aws4_request,'
|
||||
'SignedHeaders=content-type;host;x-amz-date,')
|
||||
headers = {'Content-type':
|
||||
'application/x-www-form-urlencoded; charset=utf-8',
|
||||
'X-Amz-Date': '20110909T233600Z',
|
||||
'Host': 'foo:8000',
|
||||
'Authorization': auth_str}
|
||||
# Note the example in the AWS docs is inconsistent, previous
|
||||
# examples specify no query string, but the final POST example
|
||||
# does, apparently incorrectly since an empty parameter list
|
||||
# aligns all steps and the final signature with the examples
|
||||
params = {}
|
||||
credentials = {'host': 'foo:8000',
|
||||
'verb': 'POST',
|
||||
'path': '/',
|
||||
'params': params,
|
||||
'headers': headers,
|
||||
'body_hash': body_hash}
|
||||
signature = signer.generate(credentials)
|
||||
|
||||
expected = ('26dd92ea79aaa49f533d13b1055acdc'
|
||||
'd7d7321460d64621f96cc79c4f4d4ab2b')
|
||||
self.assertEqual(signature, expected)
|
||||
|
||||
def test_generate_v4_port_strip(self):
|
||||
"""Test v4 generator with host:port format, but for an old
|
||||
(<2.9.3) version of boto, where the port should be stripped
|
||||
to match boto behavior.
|
||||
"""
|
||||
# Create a new signer object with the AWS example key
|
||||
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
|
||||
signer = utils.Ec2Signer(secret)
|
||||
|
||||
body_hash = ('b6359072c78d70ebee1e81adcbab4f0'
|
||||
'1bf2c23245fa365ef83fe8f1f955085e2')
|
||||
auth_str = ('AWS4-HMAC-SHA256 '
|
||||
'Credential=AKIAIOSFODNN7EXAMPLE/20110909/'
|
||||
'us-east-1/iam/aws4_request,'
|
||||
'SignedHeaders=content-type;host;x-amz-date,')
|
||||
headers = {'Content-type':
|
||||
'application/x-www-form-urlencoded; charset=utf-8',
|
||||
'X-Amz-Date': '20110909T233600Z',
|
||||
'Host': 'foo:8000',
|
||||
'Authorization': auth_str,
|
||||
'User-Agent': 'Boto/2.9.2 (linux2)'}
|
||||
# Note the example in the AWS docs is inconsistent, previous
|
||||
# examples specify no query string, but the final POST example
|
||||
# does, apparently incorrectly since an empty parameter list
|
||||
# aligns all steps and the final signature with the examples
|
||||
params = {}
|
||||
credentials = {'host': 'foo:8000',
|
||||
'verb': 'POST',
|
||||
'path': '/',
|
||||
'params': params,
|
||||
'headers': headers,
|
||||
'body_hash': body_hash}
|
||||
signature = signer.generate(credentials)
|
||||
|
||||
expected = ('9a4b2276a5039ada3b90f72ea8ec1745'
|
||||
'14b92b909fb106b22ad910c5d75a54f4')
|
||||
self.assertEqual(expected, signature)
|
||||
|
||||
def test_generate_v4_port_nostrip(self):
|
||||
"""Test v4 generator with host:port format, but for an new
|
||||
(>=2.9.3) version of boto, where the port should not be stripped.
|
||||
"""
|
||||
# Create a new signer object with the AWS example key
|
||||
secret = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
|
||||
signer = utils.Ec2Signer(secret)
|
||||
|
||||
body_hash = ('b6359072c78d70ebee1e81adcbab4f0'
|
||||
'1bf2c23245fa365ef83fe8f1f955085e2')
|
||||
auth_str = ('AWS4-HMAC-SHA256 '
|
||||
'Credential=AKIAIOSFODNN7EXAMPLE/20110909/'
|
||||
'us-east-1/iam/aws4_request,'
|
||||
'SignedHeaders=content-type;host;x-amz-date,')
|
||||
headers = {'Content-type':
|
||||
'application/x-www-form-urlencoded; charset=utf-8',
|
||||
'X-Amz-Date': '20110909T233600Z',
|
||||
'Host': 'foo:8000',
|
||||
'Authorization': auth_str,
|
||||
'User-Agent': 'Boto/2.9.3 (linux2)'}
|
||||
# Note the example in the AWS docs is inconsistent, previous
|
||||
# examples specify no query string, but the final POST example
|
||||
# does, apparently incorrectly since an empty parameter list
|
||||
# aligns all steps and the final signature with the examples
|
||||
params = {}
|
||||
credentials = {'host': 'foo:8000',
|
||||
'verb': 'POST',
|
||||
'path': '/',
|
||||
'params': params,
|
||||
'headers': headers,
|
||||
'body_hash': body_hash}
|
||||
signature = signer.generate(credentials)
|
||||
|
||||
expected = ('26dd92ea79aaa49f533d13b1055acdc'
|
||||
'd7d7321460d64621f96cc79c4f4d4ab2b')
|
||||
self.assertEqual(expected, signature)
|
@ -1,216 +0,0 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
#
|
||||
# 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 httpretty
|
||||
import six
|
||||
from testtools import matchers
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient import httpclient
|
||||
from keystoneclient import session
|
||||
from keystoneclient.tests import utils
|
||||
|
||||
|
||||
RESPONSE_BODY = '{"hi": "there"}'
|
||||
|
||||
|
||||
def get_client():
|
||||
cl = httpclient.HTTPClient(username="username", password="password",
|
||||
tenant_id="tenant", auth_url="auth_test")
|
||||
return cl
|
||||
|
||||
|
||||
def get_authed_client():
|
||||
cl = get_client()
|
||||
cl.management_url = "http://127.0.0.1:5000"
|
||||
cl.auth_token = "token"
|
||||
return cl
|
||||
|
||||
|
||||
class FakeLog(object):
|
||||
def __init__(self):
|
||||
self.warn_log = str()
|
||||
self.debug_log = str()
|
||||
|
||||
def warn(self, msg=None, *args, **kwargs):
|
||||
self.warn_log = "%s\n%s" % (self.warn_log, (msg % args))
|
||||
|
||||
def debug(self, msg=None, *args, **kwargs):
|
||||
self.debug_log = "%s\n%s" % (self.debug_log, (msg % args))
|
||||
|
||||
|
||||
class ClientTest(utils.TestCase):
|
||||
|
||||
TEST_URL = 'http://127.0.0.1:5000/hi'
|
||||
|
||||
def test_unauthorized_client_requests(self):
|
||||
cl = get_client()
|
||||
self.assertRaises(exceptions.AuthorizationFailure, cl.get, '/hi')
|
||||
self.assertRaises(exceptions.AuthorizationFailure, cl.post, '/hi')
|
||||
self.assertRaises(exceptions.AuthorizationFailure, cl.put, '/hi')
|
||||
self.assertRaises(exceptions.AuthorizationFailure, cl.delete, '/hi')
|
||||
|
||||
@httpretty.activate
|
||||
def test_get(self):
|
||||
cl = get_authed_client()
|
||||
|
||||
self.stub_url(httpretty.GET, body=RESPONSE_BODY)
|
||||
|
||||
resp, body = cl.get("/hi")
|
||||
self.assertEqual(httpretty.last_request().method, 'GET')
|
||||
self.assertEqual(httpretty.last_request().path, '/hi')
|
||||
|
||||
self.assertRequestHeaderEqual('X-Auth-Token', 'token')
|
||||
self.assertRequestHeaderEqual('User-Agent', httpclient.USER_AGENT)
|
||||
|
||||
# Automatic JSON parsing
|
||||
self.assertEqual(body, {"hi": "there"})
|
||||
|
||||
@httpretty.activate
|
||||
def test_get_error_with_plaintext_resp(self):
|
||||
cl = get_authed_client()
|
||||
self.stub_url(httpretty.GET, status=400,
|
||||
body='Some evil plaintext string')
|
||||
|
||||
self.assertRaises(exceptions.BadRequest, cl.get, '/hi')
|
||||
|
||||
@httpretty.activate
|
||||
def test_get_error_with_json_resp(self):
|
||||
cl = get_authed_client()
|
||||
err_response = {
|
||||
"error": {
|
||||
"code": 400,
|
||||
"title": "Error title",
|
||||
"message": "Error message string"
|
||||
}
|
||||
}
|
||||
self.stub_url(httpretty.GET, status=400, json=err_response)
|
||||
exc_raised = False
|
||||
try:
|
||||
cl.get('/hi')
|
||||
except exceptions.BadRequest as exc:
|
||||
exc_raised = True
|
||||
self.assertEqual(exc.message, "Error message string")
|
||||
self.assertTrue(exc_raised, 'Exception not raised.')
|
||||
|
||||
@httpretty.activate
|
||||
def test_post(self):
|
||||
cl = get_authed_client()
|
||||
|
||||
self.stub_url(httpretty.POST)
|
||||
cl.post("/hi", body=[1, 2, 3])
|
||||
|
||||
self.assertEqual(httpretty.last_request().method, 'POST')
|
||||
self.assertEqual(httpretty.last_request().body, b'[1, 2, 3]')
|
||||
|
||||
self.assertRequestHeaderEqual('X-Auth-Token', 'token')
|
||||
self.assertRequestHeaderEqual('Content-Type', 'application/json')
|
||||
self.assertRequestHeaderEqual('User-Agent', httpclient.USER_AGENT)
|
||||
|
||||
@httpretty.activate
|
||||
def test_forwarded_for(self):
|
||||
ORIGINAL_IP = "10.100.100.1"
|
||||
cl = httpclient.HTTPClient(username="username", password="password",
|
||||
tenant_id="tenant", auth_url="auth_test",
|
||||
original_ip=ORIGINAL_IP)
|
||||
|
||||
self.stub_url(httpretty.GET)
|
||||
|
||||
cl.request(self.TEST_URL, 'GET')
|
||||
forwarded = "for=%s;by=%s" % (ORIGINAL_IP, httpclient.USER_AGENT)
|
||||
self.assertRequestHeaderEqual('Forwarded', forwarded)
|
||||
|
||||
def test_client_deprecated(self):
|
||||
# Can resolve symbols from the keystoneclient.client module.
|
||||
# keystoneclient.client was deprecated and renamed to
|
||||
# keystoneclient.httpclient. This tests that keystoneclient.client
|
||||
# can still be used.
|
||||
|
||||
from keystoneclient import client
|
||||
|
||||
# These statements will raise an AttributeError if the symbol isn't
|
||||
# defined in the module.
|
||||
|
||||
client.HTTPClient
|
||||
|
||||
|
||||
class BasicRequestTests(utils.TestCase):
|
||||
|
||||
url = 'http://keystone.test.com/'
|
||||
|
||||
def setUp(self):
|
||||
super(BasicRequestTests, self).setUp()
|
||||
self.logger_message = six.moves.cStringIO()
|
||||
handler = logging.StreamHandler(self.logger_message)
|
||||
handler.setLevel(logging.DEBUG)
|
||||
|
||||
self.logger = logging.getLogger(session.__name__)
|
||||
level = self.logger.getEffectiveLevel()
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
self.logger.addHandler(handler)
|
||||
|
||||
self.addCleanup(self.logger.removeHandler, handler)
|
||||
self.addCleanup(self.logger.setLevel, level)
|
||||
|
||||
def request(self, method='GET', response='Test Response', status=200,
|
||||
url=None, **kwargs):
|
||||
if not url:
|
||||
url = self.url
|
||||
|
||||
httpretty.register_uri(method, url, body=response, status=status)
|
||||
|
||||
return httpclient.request(url, method, **kwargs)
|
||||
|
||||
@httpretty.activate
|
||||
def test_basic_params(self):
|
||||
method = 'GET'
|
||||
response = 'Test Response'
|
||||
status = 200
|
||||
|
||||
self.request(method=method, status=status, response=response)
|
||||
|
||||
self.assertEqual(httpretty.last_request().method, method)
|
||||
|
||||
logger_message = self.logger_message.getvalue()
|
||||
|
||||
self.assertThat(logger_message, matchers.Contains('curl'))
|
||||
self.assertThat(logger_message, matchers.Contains('-X %s' %
|
||||
method))
|
||||
self.assertThat(logger_message, matchers.Contains(self.url))
|
||||
|
||||
self.assertThat(logger_message, matchers.Contains(str(status)))
|
||||
self.assertThat(logger_message, matchers.Contains(response))
|
||||
|
||||
@httpretty.activate
|
||||
def test_headers(self):
|
||||
headers = {'key': 'val', 'test': 'other'}
|
||||
|
||||
self.request(headers=headers)
|
||||
|
||||
for k, v in six.iteritems(headers):
|
||||
self.assertRequestHeaderEqual(k, v)
|
||||
|
||||
for header in six.iteritems(headers):
|
||||
self.assertThat(self.logger_message.getvalue(),
|
||||
matchers.Contains('-H "%s: %s"' % header))
|
||||
|
||||
@httpretty.activate
|
||||
def test_body(self):
|
||||
data = "BODY DATA"
|
||||
self.request(response=data)
|
||||
logger_message = self.logger_message.getvalue()
|
||||
self.assertThat(logger_message, matchers.Contains('BODY:'))
|
||||
self.assertThat(logger_message, matchers.Contains(data))
|
@ -1,107 +0,0 @@
|
||||
# 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
|
||||
import requests
|
||||
|
||||
from keystoneclient import httpclient
|
||||
from keystoneclient.tests import utils
|
||||
|
||||
|
||||
FAKE_RESPONSE = utils.TestResponse({
|
||||
"status_code": 200,
|
||||
"text": '{"hi": "there"}',
|
||||
})
|
||||
|
||||
REQUEST_URL = 'https://127.0.0.1:5000/hi'
|
||||
RESPONSE_BODY = '{"hi": "there"}'
|
||||
|
||||
|
||||
def get_client():
|
||||
cl = httpclient.HTTPClient(username="username", password="password",
|
||||
tenant_id="tenant", auth_url="auth_test",
|
||||
cacert="ca.pem", key="key.pem", cert="cert.pem")
|
||||
return cl
|
||||
|
||||
|
||||
def get_authed_client():
|
||||
cl = get_client()
|
||||
cl.management_url = "https://127.0.0.1:5000"
|
||||
cl.auth_token = "token"
|
||||
return cl
|
||||
|
||||
|
||||
class ClientTest(utils.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ClientTest, self).setUp()
|
||||
self.request_patcher = mock.patch.object(requests, 'request',
|
||||
self.mox.CreateMockAnything())
|
||||
self.request_patcher.start()
|
||||
self.addCleanup(self.request_patcher.stop)
|
||||
|
||||
@mock.patch.object(requests, 'request')
|
||||
def test_get(self, MOCK_REQUEST):
|
||||
MOCK_REQUEST.return_value = FAKE_RESPONSE
|
||||
cl = get_authed_client()
|
||||
|
||||
resp, body = cl.get("/hi")
|
||||
|
||||
# this may become too tightly couple later
|
||||
mock_args, mock_kwargs = MOCK_REQUEST.call_args
|
||||
|
||||
self.assertEqual(mock_args[0], 'GET')
|
||||
self.assertEqual(mock_args[1], REQUEST_URL)
|
||||
self.assertEqual(mock_kwargs['headers']['X-Auth-Token'], 'token')
|
||||
self.assertEqual(mock_kwargs['cert'], ('cert.pem', 'key.pem'))
|
||||
self.assertEqual(mock_kwargs['verify'], 'ca.pem')
|
||||
|
||||
# Automatic JSON parsing
|
||||
self.assertEqual(body, {"hi": "there"})
|
||||
|
||||
@mock.patch.object(requests, 'request')
|
||||
def test_post(self, MOCK_REQUEST):
|
||||
MOCK_REQUEST.return_value = FAKE_RESPONSE
|
||||
cl = get_authed_client()
|
||||
|
||||
cl.post("/hi", body=[1, 2, 3])
|
||||
|
||||
# this may become too tightly couple later
|
||||
mock_args, mock_kwargs = MOCK_REQUEST.call_args
|
||||
|
||||
self.assertEqual(mock_args[0], 'POST')
|
||||
self.assertEqual(mock_args[1], REQUEST_URL)
|
||||
self.assertEqual(mock_kwargs['data'], '[1, 2, 3]')
|
||||
self.assertEqual(mock_kwargs['headers']['X-Auth-Token'], 'token')
|
||||
self.assertEqual(mock_kwargs['cert'], ('cert.pem', 'key.pem'))
|
||||
self.assertEqual(mock_kwargs['verify'], 'ca.pem')
|
||||
|
||||
@mock.patch.object(requests, 'request')
|
||||
def test_post_auth(self, MOCK_REQUEST):
|
||||
MOCK_REQUEST.return_value = FAKE_RESPONSE
|
||||
cl = httpclient.HTTPClient(
|
||||
username="username", password="password", tenant_id="tenant",
|
||||
auth_url="auth_test", cacert="ca.pem", key="key.pem",
|
||||
cert="cert.pem")
|
||||
cl.management_url = "https://127.0.0.1:5000"
|
||||
cl.auth_token = "token"
|
||||
cl.post("/hi", body=[1, 2, 3])
|
||||
|
||||
# this may become too tightly couple later
|
||||
mock_args, mock_kwargs = MOCK_REQUEST.call_args
|
||||
|
||||
self.assertEqual(mock_args[0], 'POST')
|
||||
self.assertEqual(mock_args[1], REQUEST_URL)
|
||||
self.assertEqual(mock_kwargs['data'], '[1, 2, 3]')
|
||||
self.assertEqual(mock_kwargs['headers']['X-Auth-Token'], 'token')
|
||||
self.assertEqual(mock_kwargs['cert'], ('cert.pem', 'key.pem'))
|
||||
self.assertEqual(mock_kwargs['verify'], 'ca.pem')
|
@ -1,187 +0,0 @@
|
||||
# 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 datetime
|
||||
|
||||
import mock
|
||||
|
||||
from keystoneclient import access
|
||||
from keystoneclient import httpclient
|
||||
from keystoneclient.openstack.common import timeutils
|
||||
from keystoneclient.tests import utils
|
||||
from keystoneclient.tests.v2_0 import client_fixtures
|
||||
|
||||
try:
|
||||
import keyring # noqa
|
||||
import pickle # noqa
|
||||
except ImportError:
|
||||
keyring = None
|
||||
|
||||
|
||||
PROJECT_SCOPED_TOKEN = client_fixtures.project_scoped_token()
|
||||
|
||||
# These mirror values from PROJECT_SCOPED_TOKEN
|
||||
USERNAME = 'exampleuser'
|
||||
AUTH_URL = 'http://public.com:5000/v2.0'
|
||||
TOKEN = '04c7d5ffaeef485f9dc69c06db285bdb'
|
||||
|
||||
PASSWORD = 'password'
|
||||
TENANT = 'tenant'
|
||||
TENANT_ID = 'tenant_id'
|
||||
|
||||
|
||||
class KeyringTest(utils.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
if keyring is None:
|
||||
self.skipTest(
|
||||
'optional package keyring or pickle is not installed')
|
||||
|
||||
class MemoryKeyring(keyring.backend.KeyringBackend):
|
||||
"""A Simple testing keyring.
|
||||
|
||||
This class supports stubbing an initial password to be returned by
|
||||
setting password, and allows easy password and key retrieval. Also
|
||||
records if a password was retrieved.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.key = None
|
||||
self.password = None
|
||||
self.fetched = False
|
||||
self.get_password_called = False
|
||||
self.set_password_called = False
|
||||
|
||||
def supported(self):
|
||||
return 1
|
||||
|
||||
def get_password(self, service, username):
|
||||
self.get_password_called = True
|
||||
key = username + '@' + service
|
||||
# make sure we don't get passwords crossed if one is enforced.
|
||||
if self.key and self.key != key:
|
||||
return None
|
||||
if self.password:
|
||||
self.fetched = True
|
||||
return self.password
|
||||
|
||||
def set_password(self, service, username, password):
|
||||
self.set_password_called = True
|
||||
self.key = username + '@' + service
|
||||
self.password = password
|
||||
|
||||
super(KeyringTest, self).setUp()
|
||||
self.memory_keyring = MemoryKeyring()
|
||||
keyring.set_keyring(self.memory_keyring)
|
||||
|
||||
def test_no_keyring_key(self):
|
||||
"""Ensure that if we don't have use_keyring set in the client that
|
||||
the keyring is never accessed.
|
||||
"""
|
||||
cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD,
|
||||
tenant_id=TENANT_ID, auth_url=AUTH_URL)
|
||||
|
||||
# stub and check that a new token is received
|
||||
with mock.patch.object(cl, 'get_raw_token_from_identity_service') \
|
||||
as meth:
|
||||
meth.return_value = (True, PROJECT_SCOPED_TOKEN)
|
||||
|
||||
self.assertTrue(cl.authenticate())
|
||||
|
||||
self.assertEqual(1, meth.call_count)
|
||||
|
||||
# make sure that we never touched the keyring
|
||||
self.assertFalse(self.memory_keyring.get_password_called)
|
||||
self.assertFalse(self.memory_keyring.set_password_called)
|
||||
|
||||
def test_build_keyring_key(self):
|
||||
cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD,
|
||||
tenant_id=TENANT_ID, auth_url=AUTH_URL)
|
||||
|
||||
keyring_key = cl._build_keyring_key(auth_url=AUTH_URL,
|
||||
username=USERNAME,
|
||||
tenant_name=TENANT,
|
||||
tenant_id=TENANT_ID,
|
||||
token=TOKEN)
|
||||
|
||||
self.assertEqual(keyring_key,
|
||||
'%s/%s/%s/%s/%s' %
|
||||
(AUTH_URL, TENANT_ID, TENANT, TOKEN, USERNAME))
|
||||
|
||||
def test_set_and_get_keyring_expired(self):
|
||||
cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD,
|
||||
tenant_id=TENANT_ID, auth_url=AUTH_URL,
|
||||
use_keyring=True)
|
||||
|
||||
# set an expired token into the keyring
|
||||
auth_ref = access.AccessInfo.factory(body=PROJECT_SCOPED_TOKEN)
|
||||
expired = timeutils.utcnow() - datetime.timedelta(minutes=30)
|
||||
auth_ref['token']['expires'] = timeutils.isotime(expired)
|
||||
self.memory_keyring.password = pickle.dumps(auth_ref)
|
||||
|
||||
# stub and check that a new token is received, so not using expired
|
||||
with mock.patch.object(cl, 'get_raw_token_from_identity_service') \
|
||||
as meth:
|
||||
meth.return_value = (True, PROJECT_SCOPED_TOKEN)
|
||||
|
||||
self.assertTrue(cl.authenticate())
|
||||
|
||||
self.assertEqual(1, meth.call_count)
|
||||
|
||||
# check that a value was returned from the keyring
|
||||
self.assertTrue(self.memory_keyring.fetched)
|
||||
|
||||
# check that the new token has been loaded into the keyring
|
||||
new_auth_ref = pickle.loads(self.memory_keyring.password)
|
||||
self.assertEqual(new_auth_ref['token']['expires'],
|
||||
PROJECT_SCOPED_TOKEN['access']['token']['expires'])
|
||||
|
||||
def test_get_keyring(self):
|
||||
cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD,
|
||||
tenant_id=TENANT_ID, auth_url=AUTH_URL,
|
||||
use_keyring=True)
|
||||
|
||||
# set an token into the keyring
|
||||
auth_ref = access.AccessInfo.factory(body=PROJECT_SCOPED_TOKEN)
|
||||
future = timeutils.utcnow() + datetime.timedelta(minutes=30)
|
||||
auth_ref['token']['expires'] = timeutils.isotime(future)
|
||||
self.memory_keyring.password = pickle.dumps(auth_ref)
|
||||
|
||||
# don't stub get_raw_token so will fail if authenticate happens
|
||||
|
||||
self.assertTrue(cl.authenticate())
|
||||
self.assertTrue(self.memory_keyring.fetched)
|
||||
|
||||
def test_set_keyring(self):
|
||||
cl = httpclient.HTTPClient(username=USERNAME, password=PASSWORD,
|
||||
tenant_id=TENANT_ID, auth_url=AUTH_URL,
|
||||
use_keyring=True)
|
||||
|
||||
# stub and check that a new token is received
|
||||
with mock.patch.object(cl, 'get_raw_token_from_identity_service') \
|
||||
as meth:
|
||||
meth.return_value = (True, PROJECT_SCOPED_TOKEN)
|
||||
|
||||
self.assertTrue(cl.authenticate())
|
||||
|
||||
self.assertEqual(1, meth.call_count)
|
||||
|
||||
# we checked the keyring, but we didn't find anything
|
||||
self.assertTrue(self.memory_keyring.get_password_called)
|
||||
self.assertFalse(self.memory_keyring.fetched)
|
||||
|
||||
# check that the new token has been loaded into the keyring
|
||||
self.assertTrue(self.memory_keyring.set_password_called)
|
||||
new_auth_ref = pickle.loads(self.memory_keyring.password)
|
||||
self.assertEqual(new_auth_ref.auth_token, TOKEN)
|
||||
self.assertEqual(new_auth_ref['token'],
|
||||
PROJECT_SCOPED_TOKEN['access']['token'])
|
||||
self.assertEqual(new_auth_ref.username, USERNAME)
|
@ -1,508 +0,0 @@
|
||||
# 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 httpretty
|
||||
import mock
|
||||
import requests
|
||||
import six
|
||||
|
||||
from keystoneclient.auth import base
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient import session as client_session
|
||||
from keystoneclient.tests import utils
|
||||
|
||||
|
||||
class SessionTests(utils.TestCase):
|
||||
|
||||
TEST_URL = 'http://127.0.0.1:5000/'
|
||||
|
||||
@httpretty.activate
|
||||
def test_get(self):
|
||||
session = client_session.Session()
|
||||
self.stub_url(httpretty.GET, body='response')
|
||||
resp = session.get(self.TEST_URL)
|
||||
|
||||
self.assertEqual(httpretty.GET, httpretty.last_request().method)
|
||||
self.assertEqual(resp.text, 'response')
|
||||
self.assertTrue(resp.ok)
|
||||
|
||||
@httpretty.activate
|
||||
def test_post(self):
|
||||
session = client_session.Session()
|
||||
self.stub_url(httpretty.POST, body='response')
|
||||
resp = session.post(self.TEST_URL, json={'hello': 'world'})
|
||||
|
||||
self.assertEqual(httpretty.POST, httpretty.last_request().method)
|
||||
self.assertEqual(resp.text, 'response')
|
||||
self.assertTrue(resp.ok)
|
||||
self.assertRequestBodyIs(json={'hello': 'world'})
|
||||
|
||||
@httpretty.activate
|
||||
def test_head(self):
|
||||
session = client_session.Session()
|
||||
self.stub_url(httpretty.HEAD)
|
||||
resp = session.head(self.TEST_URL)
|
||||
|
||||
self.assertEqual(httpretty.HEAD, httpretty.last_request().method)
|
||||
self.assertTrue(resp.ok)
|
||||
self.assertRequestBodyIs('')
|
||||
|
||||
@httpretty.activate
|
||||
def test_put(self):
|
||||
session = client_session.Session()
|
||||
self.stub_url(httpretty.PUT, body='response')
|
||||
resp = session.put(self.TEST_URL, json={'hello': 'world'})
|
||||
|
||||
self.assertEqual(httpretty.PUT, httpretty.last_request().method)
|
||||
self.assertEqual(resp.text, 'response')
|
||||
self.assertTrue(resp.ok)
|
||||
self.assertRequestBodyIs(json={'hello': 'world'})
|
||||
|
||||
@httpretty.activate
|
||||
def test_delete(self):
|
||||
session = client_session.Session()
|
||||
self.stub_url(httpretty.DELETE, body='response')
|
||||
resp = session.delete(self.TEST_URL)
|
||||
|
||||
self.assertEqual(httpretty.DELETE, httpretty.last_request().method)
|
||||
self.assertTrue(resp.ok)
|
||||
self.assertEqual(resp.text, 'response')
|
||||
|
||||
@httpretty.activate
|
||||
def test_patch(self):
|
||||
session = client_session.Session()
|
||||
self.stub_url(httpretty.PATCH, body='response')
|
||||
resp = session.patch(self.TEST_URL, json={'hello': 'world'})
|
||||
|
||||
self.assertEqual(httpretty.PATCH, httpretty.last_request().method)
|
||||
self.assertTrue(resp.ok)
|
||||
self.assertEqual(resp.text, 'response')
|
||||
self.assertRequestBodyIs(json={'hello': 'world'})
|
||||
|
||||
@httpretty.activate
|
||||
def test_user_agent(self):
|
||||
session = client_session.Session(user_agent='test-agent')
|
||||
self.stub_url(httpretty.GET, body='response')
|
||||
resp = session.get(self.TEST_URL)
|
||||
|
||||
self.assertTrue(resp.ok)
|
||||
self.assertRequestHeaderEqual('User-Agent', 'test-agent')
|
||||
|
||||
resp = session.get(self.TEST_URL, headers={'User-Agent': 'new-agent'})
|
||||
self.assertTrue(resp.ok)
|
||||
self.assertRequestHeaderEqual('User-Agent', 'new-agent')
|
||||
|
||||
resp = session.get(self.TEST_URL, headers={'User-Agent': 'new-agent'},
|
||||
user_agent='overrides-agent')
|
||||
self.assertTrue(resp.ok)
|
||||
self.assertRequestHeaderEqual('User-Agent', 'overrides-agent')
|
||||
|
||||
@httpretty.activate
|
||||
def test_http_session_opts(self):
|
||||
session = client_session.Session(cert='cert.pem', timeout=5,
|
||||
verify='certs')
|
||||
|
||||
FAKE_RESP = utils.TestResponse({'status_code': 200, 'text': 'resp'})
|
||||
RESP = mock.Mock(return_value=FAKE_RESP)
|
||||
|
||||
with mock.patch.object(session.session, 'request', RESP) as mocked:
|
||||
session.post(self.TEST_URL, data='value')
|
||||
|
||||
mock_args, mock_kwargs = mocked.call_args
|
||||
|
||||
self.assertEqual(mock_args[0], 'POST')
|
||||
self.assertEqual(mock_args[1], self.TEST_URL)
|
||||
self.assertEqual(mock_kwargs['data'], 'value')
|
||||
self.assertEqual(mock_kwargs['cert'], 'cert.pem')
|
||||
self.assertEqual(mock_kwargs['verify'], 'certs')
|
||||
self.assertEqual(mock_kwargs['timeout'], 5)
|
||||
|
||||
@httpretty.activate
|
||||
def test_not_found(self):
|
||||
session = client_session.Session()
|
||||
self.stub_url(httpretty.GET, status=404)
|
||||
self.assertRaises(exceptions.NotFound, session.get, self.TEST_URL)
|
||||
|
||||
@httpretty.activate
|
||||
def test_server_error(self):
|
||||
session = client_session.Session()
|
||||
self.stub_url(httpretty.GET, status=500)
|
||||
self.assertRaises(exceptions.InternalServerError,
|
||||
session.get, self.TEST_URL)
|
||||
|
||||
@httpretty.activate
|
||||
def test_session_debug_output(self):
|
||||
session = client_session.Session(verify=False)
|
||||
headers = {'HEADERA': 'HEADERVALB'}
|
||||
body = 'BODYRESPONSE'
|
||||
data = 'BODYDATA'
|
||||
self.stub_url(httpretty.POST, body=body)
|
||||
session.post(self.TEST_URL, headers=headers, data=data)
|
||||
|
||||
self.assertIn('curl', self.logger.output)
|
||||
self.assertIn('POST', self.logger.output)
|
||||
self.assertIn('--insecure', self.logger.output)
|
||||
self.assertIn(body, self.logger.output)
|
||||
self.assertIn("'%s'" % data, self.logger.output)
|
||||
|
||||
for k, v in six.iteritems(headers):
|
||||
self.assertIn(k, self.logger.output)
|
||||
self.assertIn(v, self.logger.output)
|
||||
|
||||
|
||||
class RedirectTests(utils.TestCase):
|
||||
|
||||
REDIRECT_CHAIN = ['http://myhost:3445/',
|
||||
'http://anotherhost:6555/',
|
||||
'http://thirdhost/',
|
||||
'http://finaldestination:55/']
|
||||
|
||||
DEFAULT_REDIRECT_BODY = 'Redirect'
|
||||
DEFAULT_RESP_BODY = 'Found'
|
||||
|
||||
def setup_redirects(self, method=httpretty.GET, status=305,
|
||||
redirect_kwargs={}, final_kwargs={}):
|
||||
redirect_kwargs.setdefault('body', self.DEFAULT_REDIRECT_BODY)
|
||||
|
||||
for s, d in zip(self.REDIRECT_CHAIN, self.REDIRECT_CHAIN[1:]):
|
||||
httpretty.register_uri(method, s, status=status, location=d,
|
||||
**redirect_kwargs)
|
||||
|
||||
final_kwargs.setdefault('status', 200)
|
||||
final_kwargs.setdefault('body', self.DEFAULT_RESP_BODY)
|
||||
httpretty.register_uri(method, self.REDIRECT_CHAIN[-1], **final_kwargs)
|
||||
|
||||
def assertResponse(self, resp):
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp.text, self.DEFAULT_RESP_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_basic_get(self):
|
||||
session = client_session.Session()
|
||||
self.setup_redirects()
|
||||
resp = session.get(self.REDIRECT_CHAIN[-2])
|
||||
self.assertResponse(resp)
|
||||
|
||||
@httpretty.activate
|
||||
def test_basic_post_keeps_correct_method(self):
|
||||
session = client_session.Session()
|
||||
self.setup_redirects(method=httpretty.POST, status=301)
|
||||
resp = session.post(self.REDIRECT_CHAIN[-2])
|
||||
self.assertResponse(resp)
|
||||
|
||||
@httpretty.activate
|
||||
def test_redirect_forever(self):
|
||||
session = client_session.Session(redirect=True)
|
||||
self.setup_redirects()
|
||||
resp = session.get(self.REDIRECT_CHAIN[0])
|
||||
self.assertResponse(resp)
|
||||
self.assertTrue(len(resp.history), len(self.REDIRECT_CHAIN))
|
||||
|
||||
@httpretty.activate
|
||||
def test_no_redirect(self):
|
||||
session = client_session.Session(redirect=False)
|
||||
self.setup_redirects()
|
||||
resp = session.get(self.REDIRECT_CHAIN[0])
|
||||
self.assertEqual(resp.status_code, 305)
|
||||
self.assertEqual(resp.url, self.REDIRECT_CHAIN[0])
|
||||
|
||||
@httpretty.activate
|
||||
def test_redirect_limit(self):
|
||||
self.setup_redirects()
|
||||
for i in (1, 2):
|
||||
session = client_session.Session(redirect=i)
|
||||
resp = session.get(self.REDIRECT_CHAIN[0])
|
||||
self.assertEqual(resp.status_code, 305)
|
||||
self.assertEqual(resp.url, self.REDIRECT_CHAIN[i])
|
||||
self.assertEqual(resp.text, self.DEFAULT_REDIRECT_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_history_matches_requests(self):
|
||||
self.setup_redirects(status=301)
|
||||
session = client_session.Session(redirect=True)
|
||||
req_resp = requests.get(self.REDIRECT_CHAIN[0],
|
||||
allow_redirects=True)
|
||||
|
||||
ses_resp = session.get(self.REDIRECT_CHAIN[0])
|
||||
|
||||
self.assertEqual(len(req_resp.history), len(ses_resp.history))
|
||||
|
||||
for r, s in zip(req_resp.history, ses_resp.history):
|
||||
self.assertEqual(r.url, s.url)
|
||||
self.assertEqual(r.status_code, s.status_code)
|
||||
|
||||
|
||||
class ConstructSessionFromArgsTests(utils.TestCase):
|
||||
|
||||
KEY = 'keyfile'
|
||||
CERT = 'certfile'
|
||||
CACERT = 'cacert-path'
|
||||
|
||||
def _s(self, k=None, **kwargs):
|
||||
k = k or kwargs
|
||||
return client_session.Session.construct(k)
|
||||
|
||||
def test_verify(self):
|
||||
self.assertFalse(self._s(insecure=True).verify)
|
||||
self.assertTrue(self._s(verify=True, insecure=True).verify)
|
||||
self.assertFalse(self._s(verify=False, insecure=True).verify)
|
||||
self.assertEqual(self._s(cacert=self.CACERT).verify, self.CACERT)
|
||||
|
||||
def test_cert(self):
|
||||
tup = (self.CERT, self.KEY)
|
||||
self.assertEqual(self._s(cert=tup).cert, tup)
|
||||
self.assertEqual(self._s(cert=self.CERT, key=self.KEY).cert, tup)
|
||||
self.assertIsNone(self._s(key=self.KEY).cert)
|
||||
|
||||
def test_pass_through(self):
|
||||
value = 42 # only a number because timeout needs to be
|
||||
for key in ['timeout', 'session', 'original_ip', 'user_agent']:
|
||||
args = {key: value}
|
||||
self.assertEqual(getattr(self._s(args), key), value)
|
||||
self.assertNotIn(key, args)
|
||||
|
||||
|
||||
class AuthPlugin(base.BaseAuthPlugin):
|
||||
"""Very simple debug authentication plugin.
|
||||
|
||||
Takes Parameters such that it can throw exceptions at the right times.
|
||||
"""
|
||||
|
||||
TEST_TOKEN = 'aToken'
|
||||
|
||||
SERVICE_URLS = {
|
||||
'identity': {'public': 'http://identity-public:1111/v2.0',
|
||||
'admin': 'http://identity-admin:1111/v2.0'},
|
||||
'compute': {'public': 'http://compute-public:2222/v1.0',
|
||||
'admin': 'http://compute-admin:2222/v1.0'},
|
||||
'image': {'public': 'http://image-public:3333/v2.0',
|
||||
'admin': 'http://image-admin:3333/v2.0'}
|
||||
}
|
||||
|
||||
def __init__(self, token=TEST_TOKEN, invalidate=True):
|
||||
self.token = token
|
||||
self._invalidate = invalidate
|
||||
|
||||
def get_token(self, session):
|
||||
return self.token
|
||||
|
||||
def get_endpoint(self, session, service_type=None, interface=None,
|
||||
**kwargs):
|
||||
try:
|
||||
return self.SERVICE_URLS[service_type][interface]
|
||||
except (KeyError, AttributeError):
|
||||
return None
|
||||
|
||||
def invalidate(self):
|
||||
return self._invalidate
|
||||
|
||||
|
||||
class CalledAuthPlugin(base.BaseAuthPlugin):
|
||||
|
||||
ENDPOINT = 'http://fakeendpoint/'
|
||||
|
||||
def __init__(self, invalidate=True):
|
||||
self.get_token_called = False
|
||||
self.get_endpoint_called = False
|
||||
self.invalidate_called = False
|
||||
self._invalidate = invalidate
|
||||
|
||||
def get_token(self, session):
|
||||
self.get_token_called = True
|
||||
return 'aToken'
|
||||
|
||||
def get_endpoint(self, session, **kwargs):
|
||||
self.get_endpoint_called = True
|
||||
return self.ENDPOINT
|
||||
|
||||
def invalidate(self):
|
||||
self.invalidate_called = True
|
||||
return self._invalidate
|
||||
|
||||
|
||||
class SessionAuthTests(utils.TestCase):
|
||||
|
||||
TEST_URL = 'http://127.0.0.1:5000/'
|
||||
TEST_JSON = {'hello': 'world'}
|
||||
|
||||
def stub_service_url(self, service_type, interface, path,
|
||||
method=httpretty.GET, **kwargs):
|
||||
base_url = AuthPlugin.SERVICE_URLS[service_type][interface]
|
||||
uri = "%s/%s" % (base_url.rstrip('/'), path.lstrip('/'))
|
||||
|
||||
httpretty.register_uri(method, uri, **kwargs)
|
||||
|
||||
@httpretty.activate
|
||||
def test_auth_plugin_default_with_plugin(self):
|
||||
self.stub_url('GET', base_url=self.TEST_URL, json=self.TEST_JSON)
|
||||
|
||||
# if there is an auth_plugin then it should default to authenticated
|
||||
auth = AuthPlugin()
|
||||
sess = client_session.Session(auth=auth)
|
||||
resp = sess.get(self.TEST_URL)
|
||||
self.assertDictEqual(resp.json(), self.TEST_JSON)
|
||||
|
||||
self.assertRequestHeaderEqual('X-Auth-Token', AuthPlugin.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def test_auth_plugin_disable(self):
|
||||
self.stub_url('GET', base_url=self.TEST_URL, json=self.TEST_JSON)
|
||||
|
||||
auth = AuthPlugin()
|
||||
sess = client_session.Session(auth=auth)
|
||||
resp = sess.get(self.TEST_URL, authenticated=False)
|
||||
self.assertDictEqual(resp.json(), self.TEST_JSON)
|
||||
|
||||
self.assertRequestHeaderEqual('X-Auth-Token', None)
|
||||
|
||||
@httpretty.activate
|
||||
def test_service_type_urls(self):
|
||||
service_type = 'compute'
|
||||
interface = 'public'
|
||||
path = '/instances'
|
||||
status = 200
|
||||
body = 'SUCCESS'
|
||||
|
||||
self.stub_service_url(service_type=service_type,
|
||||
interface=interface,
|
||||
path=path,
|
||||
status=status,
|
||||
body=body)
|
||||
|
||||
sess = client_session.Session(auth=AuthPlugin())
|
||||
resp = sess.get(path,
|
||||
endpoint_filter={'service_type': service_type,
|
||||
'interface': interface})
|
||||
|
||||
self.assertEqual(httpretty.last_request().path, '/v1.0/instances')
|
||||
self.assertEqual(resp.text, body)
|
||||
self.assertEqual(resp.status_code, status)
|
||||
|
||||
def test_service_url_raises_if_no_auth_plugin(self):
|
||||
sess = client_session.Session()
|
||||
self.assertRaises(exceptions.MissingAuthPlugin,
|
||||
sess.get, '/path',
|
||||
endpoint_filter={'service_type': 'compute',
|
||||
'interface': 'public'})
|
||||
|
||||
def test_service_url_raises_if_no_url_returned(self):
|
||||
sess = client_session.Session(auth=AuthPlugin())
|
||||
self.assertRaises(exceptions.EndpointNotFound,
|
||||
sess.get, '/path',
|
||||
endpoint_filter={'service_type': 'unknown',
|
||||
'interface': 'public'})
|
||||
|
||||
@httpretty.activate
|
||||
def test_raises_exc_only_when_asked(self):
|
||||
# A request that returns a HTTP error should by default raise an
|
||||
# exception by default, if you specify raise_exc=False then it will not
|
||||
|
||||
self.stub_url(httpretty.GET, status=401)
|
||||
|
||||
sess = client_session.Session()
|
||||
self.assertRaises(exceptions.Unauthorized, sess.get, self.TEST_URL)
|
||||
|
||||
resp = sess.get(self.TEST_URL, raise_exc=False)
|
||||
self.assertEqual(401, resp.status_code)
|
||||
|
||||
@httpretty.activate
|
||||
def test_passed_auth_plugin(self):
|
||||
passed = CalledAuthPlugin()
|
||||
sess = client_session.Session()
|
||||
|
||||
httpretty.register_uri(httpretty.GET,
|
||||
CalledAuthPlugin.ENDPOINT + 'path',
|
||||
status=200)
|
||||
endpoint_filter = {'service_type': 'identity'}
|
||||
|
||||
# no plugin with authenticated won't work
|
||||
self.assertRaises(exceptions.MissingAuthPlugin, sess.get, 'path',
|
||||
authenticated=True)
|
||||
|
||||
# no plugin with an endpoint filter won't work
|
||||
self.assertRaises(exceptions.MissingAuthPlugin, sess.get, 'path',
|
||||
authenticated=False, endpoint_filter=endpoint_filter)
|
||||
|
||||
resp = sess.get('path', auth=passed, endpoint_filter=endpoint_filter)
|
||||
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertTrue(passed.get_endpoint_called)
|
||||
self.assertTrue(passed.get_token_called)
|
||||
|
||||
@httpretty.activate
|
||||
def test_passed_auth_plugin_overrides(self):
|
||||
fixed = CalledAuthPlugin()
|
||||
passed = CalledAuthPlugin()
|
||||
|
||||
sess = client_session.Session(fixed)
|
||||
|
||||
httpretty.register_uri(httpretty.GET,
|
||||
CalledAuthPlugin.ENDPOINT + 'path',
|
||||
status=200)
|
||||
|
||||
resp = sess.get('path', auth=passed,
|
||||
endpoint_filter={'service_type': 'identity'})
|
||||
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertTrue(passed.get_endpoint_called)
|
||||
self.assertTrue(passed.get_token_called)
|
||||
self.assertFalse(fixed.get_endpoint_called)
|
||||
self.assertFalse(fixed.get_token_called)
|
||||
|
||||
def test_requests_auth_plugin(self):
|
||||
sess = client_session.Session()
|
||||
|
||||
requests_auth = object()
|
||||
|
||||
FAKE_RESP = utils.TestResponse({'status_code': 200, 'text': 'resp'})
|
||||
RESP = mock.Mock(return_value=FAKE_RESP)
|
||||
|
||||
with mock.patch.object(sess.session, 'request', RESP) as mocked:
|
||||
sess.get(self.TEST_URL, requests_auth=requests_auth)
|
||||
|
||||
mocked.assert_called_once_with('GET', self.TEST_URL,
|
||||
headers=mock.ANY,
|
||||
allow_redirects=mock.ANY,
|
||||
auth=requests_auth,
|
||||
verify=mock.ANY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_reauth_called(self):
|
||||
auth = CalledAuthPlugin(invalidate=True)
|
||||
sess = client_session.Session(auth=auth)
|
||||
|
||||
responses = [httpretty.Response(body='Failed', status=401),
|
||||
httpretty.Response(body='Hello', status=200)]
|
||||
httpretty.register_uri(httpretty.GET, self.TEST_URL,
|
||||
responses=responses)
|
||||
|
||||
# allow_reauth=True is the default
|
||||
resp = sess.get(self.TEST_URL, authenticated=True)
|
||||
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual('Hello', resp.text)
|
||||
self.assertTrue(auth.invalidate_called)
|
||||
|
||||
@httpretty.activate
|
||||
def test_reauth_not_called(self):
|
||||
auth = CalledAuthPlugin(invalidate=True)
|
||||
sess = client_session.Session(auth=auth)
|
||||
|
||||
responses = [httpretty.Response(body='Failed', status=401),
|
||||
httpretty.Response(body='Hello', status=200)]
|
||||
httpretty.register_uri(httpretty.GET, self.TEST_URL,
|
||||
responses=responses)
|
||||
|
||||
self.assertRaises(exceptions.Unauthorized, sess.get, self.TEST_URL,
|
||||
authenticated=True, allow_reauth=False)
|
||||
self.assertFalse(auth.invalidate_called)
|
@ -1,517 +0,0 @@
|
||||
# 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 argparse
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
import fixtures
|
||||
import mock
|
||||
import six
|
||||
import testtools
|
||||
from testtools import matchers
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient import session
|
||||
from keystoneclient import shell as openstack_shell
|
||||
from keystoneclient.tests import utils
|
||||
from keystoneclient.v2_0 import shell as shell_v2_0
|
||||
|
||||
|
||||
DEFAULT_USERNAME = 'username'
|
||||
DEFAULT_PASSWORD = 'password'
|
||||
DEFAULT_TENANT_ID = 'tenant_id'
|
||||
DEFAULT_TENANT_NAME = 'tenant_name'
|
||||
DEFAULT_AUTH_URL = 'http://127.0.0.1:5000/v2.0/'
|
||||
|
||||
|
||||
class NoExitArgumentParser(argparse.ArgumentParser):
|
||||
def error(self, message):
|
||||
raise exceptions.CommandError(message)
|
||||
|
||||
|
||||
class ShellTest(utils.TestCase):
|
||||
|
||||
FAKE_ENV = {
|
||||
'OS_USERNAME': DEFAULT_USERNAME,
|
||||
'OS_PASSWORD': DEFAULT_PASSWORD,
|
||||
'OS_TENANT_ID': DEFAULT_TENANT_ID,
|
||||
'OS_TENANT_NAME': DEFAULT_TENANT_NAME,
|
||||
'OS_AUTH_URL': DEFAULT_AUTH_URL,
|
||||
}
|
||||
|
||||
def _tolerant_shell(self, cmd):
|
||||
t_shell = openstack_shell.OpenStackIdentityShell(NoExitArgumentParser)
|
||||
t_shell.main(cmd.split())
|
||||
|
||||
# Patch os.environ to avoid required auth info.
|
||||
def setUp(self):
|
||||
|
||||
super(ShellTest, self).setUp()
|
||||
for var in os.environ:
|
||||
if var.startswith("OS_"):
|
||||
self.useFixture(fixtures.EnvironmentVariable(var, ""))
|
||||
|
||||
for var in self.FAKE_ENV:
|
||||
self.useFixture(fixtures.EnvironmentVariable(var,
|
||||
self.FAKE_ENV[var]))
|
||||
|
||||
# Make a fake shell object, a helping wrapper to call it, and a quick
|
||||
# way of asserting that certain API calls were made.
|
||||
global shell, _shell, assert_called, assert_called_anytime
|
||||
_shell = openstack_shell.OpenStackIdentityShell()
|
||||
shell = lambda cmd: _shell.main(cmd.split())
|
||||
|
||||
def test_help_unknown_command(self):
|
||||
self.assertRaises(exceptions.CommandError, shell, 'help %s'
|
||||
% uuid.uuid4().hex)
|
||||
|
||||
def shell(self, argstr):
|
||||
orig = sys.stdout
|
||||
clean_env = {}
|
||||
_old_env, os.environ = os.environ, clean_env.copy()
|
||||
try:
|
||||
sys.stdout = six.StringIO()
|
||||
_shell = openstack_shell.OpenStackIdentityShell()
|
||||
_shell.main(argstr.split())
|
||||
except SystemExit:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
self.assertEqual(exc_value.code, 0)
|
||||
finally:
|
||||
out = sys.stdout.getvalue()
|
||||
sys.stdout.close()
|
||||
sys.stdout = orig
|
||||
os.environ = _old_env
|
||||
return out
|
||||
|
||||
def test_help_no_args(self):
|
||||
do_tenant_mock = mock.MagicMock()
|
||||
with mock.patch('keystoneclient.shell.OpenStackIdentityShell.do_help',
|
||||
do_tenant_mock):
|
||||
self.shell('')
|
||||
assert do_tenant_mock.called
|
||||
|
||||
def test_help(self):
|
||||
required = 'usage:'
|
||||
help_text = self.shell('help')
|
||||
self.assertThat(help_text,
|
||||
matchers.MatchesRegex(required))
|
||||
|
||||
def test_help_command(self):
|
||||
required = 'usage: keystone user-create'
|
||||
help_text = self.shell('help user-create')
|
||||
self.assertThat(help_text,
|
||||
matchers.MatchesRegex(required))
|
||||
|
||||
def test_auth_no_credentials(self):
|
||||
with testtools.ExpectedException(
|
||||
exceptions.CommandError, 'Expecting'):
|
||||
self.shell('user-list')
|
||||
|
||||
def test_debug(self):
|
||||
logging_mock = mock.MagicMock()
|
||||
with mock.patch('logging.basicConfig', logging_mock):
|
||||
self.assertRaises(exceptions.CommandError,
|
||||
self.shell, '--debug user-list')
|
||||
self.assertTrue(logging_mock.called)
|
||||
self.assertEqual([(), {'level': logging.DEBUG}],
|
||||
list(logging_mock.call_args))
|
||||
|
||||
def test_auth_password_authurl_no_username(self):
|
||||
with testtools.ExpectedException(
|
||||
exceptions.CommandError,
|
||||
'Expecting a username provided via either'):
|
||||
self.shell('--os-password=%s --os-auth-url=%s user-list'
|
||||
% (uuid.uuid4().hex, uuid.uuid4().hex))
|
||||
|
||||
def test_auth_username_password_no_authurl(self):
|
||||
with testtools.ExpectedException(
|
||||
exceptions.CommandError, 'Expecting an auth URL via either'):
|
||||
self.shell('--os-password=%s --os-username=%s user-list'
|
||||
% (uuid.uuid4().hex, uuid.uuid4().hex))
|
||||
|
||||
def test_token_no_endpoint(self):
|
||||
with testtools.ExpectedException(
|
||||
exceptions.CommandError, 'Expecting an endpoint provided'):
|
||||
self.shell('--os-token=%s user-list' % uuid.uuid4().hex)
|
||||
|
||||
def test_endpoint_no_token(self):
|
||||
with testtools.ExpectedException(
|
||||
exceptions.CommandError, 'Expecting a token provided'):
|
||||
self.shell('--os-endpoint=http://10.0.0.1:5000/v2.0/ user-list')
|
||||
|
||||
def test_shell_args(self):
|
||||
do_tenant_mock = mock.MagicMock()
|
||||
with mock.patch('keystoneclient.v2_0.shell.do_user_list',
|
||||
do_tenant_mock):
|
||||
shell('user-list')
|
||||
assert do_tenant_mock.called
|
||||
((a, b), c) = do_tenant_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID,
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# Old_style options
|
||||
shell('--os_auth_url http://0.0.0.0:5000/ --os_password xyzpdq '
|
||||
'--os_tenant_id 1234 --os_tenant_name fred '
|
||||
'--os_username barney '
|
||||
'--os_identity_api_version 2.0 user-list')
|
||||
assert do_tenant_mock.called
|
||||
((a, b), c) = do_tenant_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = ('http://0.0.0.0:5000/', 'xyzpdq', '1234',
|
||||
'fred', 'barney', '2.0')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# New-style options
|
||||
shell('--os-auth-url http://1.1.1.1:5000/ --os-password xyzpdq '
|
||||
'--os-tenant-id 4321 --os-tenant-name wilma '
|
||||
'--os-username betty '
|
||||
'--os-identity-api-version 2.0 user-list')
|
||||
assert do_tenant_mock.called
|
||||
((a, b), c) = do_tenant_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = ('http://1.1.1.1:5000/', 'xyzpdq', '4321',
|
||||
'wilma', 'betty', '2.0')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# Test keyring options
|
||||
shell('--os-auth-url http://1.1.1.1:5000/ --os-password xyzpdq '
|
||||
'--os-tenant-id 4321 --os-tenant-name wilma '
|
||||
'--os-username betty '
|
||||
'--os-identity-api-version 2.0 '
|
||||
'--os-cache '
|
||||
'--stale-duration 500 '
|
||||
'--force-new-token user-list')
|
||||
assert do_tenant_mock.called
|
||||
((a, b), c) = do_tenant_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version, b.os_cache,
|
||||
b.stale_duration, b.force_new_token)
|
||||
expect = ('http://1.1.1.1:5000/', 'xyzpdq', '4321',
|
||||
'wilma', 'betty', '2.0', True, '500', True)
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# Test os-identity-api-version fall back to 2.0
|
||||
shell('--os-identity-api-version 3.0 user-list')
|
||||
assert do_tenant_mock.called
|
||||
self.assertTrue(b.os_identity_api_version, '2.0')
|
||||
|
||||
def test_shell_user_create_args(self):
|
||||
"""Test user-create args."""
|
||||
do_uc_mock = mock.MagicMock()
|
||||
# grab the decorators for do_user_create
|
||||
uc_func = getattr(shell_v2_0, 'do_user_create')
|
||||
do_uc_mock.arguments = getattr(uc_func, 'arguments', [])
|
||||
with mock.patch('keystoneclient.v2_0.shell.do_user_create',
|
||||
do_uc_mock):
|
||||
|
||||
# Old_style options
|
||||
# Test case with one --tenant_id args present: ec2 creds
|
||||
shell('user-create --name=FOO '
|
||||
'--pass=secrete --tenant_id=barrr --enabled=true')
|
||||
assert do_uc_mock.called
|
||||
((a, b), c) = do_uc_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID,
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
actual = (b.tenant_id, b.name, b.passwd, b.enabled)
|
||||
expect = ('barrr', 'FOO', 'secrete', 'true')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# New-style options
|
||||
# Test case with one --tenant args present: ec2 creds
|
||||
shell('user-create --name=foo '
|
||||
'--pass=secrete --tenant=BARRR --enabled=true')
|
||||
assert do_uc_mock.called
|
||||
((a, b), c) = do_uc_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID,
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
actual = (b.tenant, b.name, b.passwd, b.enabled)
|
||||
expect = ('BARRR', 'foo', 'secrete', 'true')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# New-style options
|
||||
# Test case with one --tenant-id args present: ec2 creds
|
||||
shell('user-create --name=foo '
|
||||
'--pass=secrete --tenant-id=BARRR --enabled=true')
|
||||
assert do_uc_mock.called
|
||||
((a, b), c) = do_uc_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID,
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
actual = (b.tenant, b.name, b.passwd, b.enabled)
|
||||
expect = ('BARRR', 'foo', 'secrete', 'true')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# Old_style options
|
||||
# Test case with --os_tenant_id and --tenant_id args present
|
||||
shell('--os_tenant_id=os-tenant user-create --name=FOO '
|
||||
'--pass=secrete --tenant_id=barrr --enabled=true')
|
||||
assert do_uc_mock.called
|
||||
((a, b), c) = do_uc_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, 'os-tenant',
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
actual = (b.tenant_id, b.name, b.passwd, b.enabled)
|
||||
expect = ('barrr', 'FOO', 'secrete', 'true')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# New-style options
|
||||
# Test case with --os-tenant-id and --tenant-id args present
|
||||
shell('--os-tenant-id=ostenant user-create --name=foo '
|
||||
'--pass=secrete --tenant-id=BARRR --enabled=true')
|
||||
assert do_uc_mock.called
|
||||
((a, b), c) = do_uc_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, 'ostenant',
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
actual = (b.tenant, b.name, b.passwd, b.enabled)
|
||||
expect = ('BARRR', 'foo', 'secrete', 'true')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
def test_do_tenant_create(self):
|
||||
do_tenant_mock = mock.MagicMock()
|
||||
with mock.patch('keystoneclient.v2_0.shell.do_tenant_create',
|
||||
do_tenant_mock):
|
||||
shell('tenant-create')
|
||||
assert do_tenant_mock.called
|
||||
# FIXME(dtroyer): how do you test the decorators?
|
||||
#shell('tenant-create --tenant-name wilma '
|
||||
# '--description "fred\'s wife"')
|
||||
#assert do_tenant_mock.called
|
||||
|
||||
def test_do_tenant_list(self):
|
||||
do_tenant_mock = mock.MagicMock()
|
||||
with mock.patch('keystoneclient.v2_0.shell.do_tenant_list',
|
||||
do_tenant_mock):
|
||||
shell('tenant-list')
|
||||
assert do_tenant_mock.called
|
||||
|
||||
def test_shell_tenant_id_args(self):
|
||||
"""Test a corner case where --tenant_id appears on the
|
||||
command-line twice.
|
||||
"""
|
||||
do_ec2_mock = mock.MagicMock()
|
||||
# grab the decorators for do_ec2_create_credentials
|
||||
ec2_func = getattr(shell_v2_0, 'do_ec2_credentials_create')
|
||||
do_ec2_mock.arguments = getattr(ec2_func, 'arguments', [])
|
||||
with mock.patch('keystoneclient.v2_0.shell.do_ec2_credentials_create',
|
||||
do_ec2_mock):
|
||||
|
||||
# Old_style options
|
||||
# Test case with one --tenant_id args present: ec2 creds
|
||||
shell('ec2-credentials-create '
|
||||
'--tenant_id=ec2-tenant --user_id=ec2-user')
|
||||
assert do_ec2_mock.called
|
||||
((a, b), c) = do_ec2_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID,
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
actual = (b.tenant_id, b.user_id)
|
||||
expect = ('ec2-tenant', 'ec2-user')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# New-style options
|
||||
# Test case with one --tenant-id args present: ec2 creds
|
||||
shell('ec2-credentials-create '
|
||||
'--tenant-id=dash-tenant --user-id=dash-user')
|
||||
assert do_ec2_mock.called
|
||||
((a, b), c) = do_ec2_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID,
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
actual = (b.tenant_id, b.user_id)
|
||||
expect = ('dash-tenant', 'dash-user')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# Old_style options
|
||||
# Test case with two --tenant_id args present
|
||||
shell('--os_tenant_id=os-tenant ec2-credentials-create '
|
||||
'--tenant_id=ec2-tenant --user_id=ec2-user')
|
||||
assert do_ec2_mock.called
|
||||
((a, b), c) = do_ec2_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, 'os-tenant',
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
actual = (b.tenant_id, b.user_id)
|
||||
expect = ('ec2-tenant', 'ec2-user')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# New-style options
|
||||
# Test case with two --tenant-id args present
|
||||
shell('--os-tenant-id=ostenant ec2-credentials-create '
|
||||
'--tenant-id=dash-tenant --user-id=dash-user')
|
||||
assert do_ec2_mock.called
|
||||
((a, b), c) = do_ec2_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, 'ostenant',
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
actual = (b.tenant_id, b.user_id)
|
||||
expect = ('dash-tenant', 'dash-user')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
def test_do_ec2_get(self):
|
||||
do_shell_mock = mock.MagicMock()
|
||||
|
||||
with mock.patch('keystoneclient.v2_0.shell.do_ec2_credentials_create',
|
||||
do_shell_mock):
|
||||
shell('ec2-credentials-create')
|
||||
assert do_shell_mock.called
|
||||
|
||||
with mock.patch('keystoneclient.v2_0.shell.do_ec2_credentials_get',
|
||||
do_shell_mock):
|
||||
shell('ec2-credentials-get')
|
||||
assert do_shell_mock.called
|
||||
|
||||
with mock.patch('keystoneclient.v2_0.shell.do_ec2_credentials_list',
|
||||
do_shell_mock):
|
||||
shell('ec2-credentials-list')
|
||||
assert do_shell_mock.called
|
||||
|
||||
with mock.patch('keystoneclient.v2_0.shell.do_ec2_credentials_delete',
|
||||
do_shell_mock):
|
||||
shell('ec2-credentials-delete')
|
||||
assert do_shell_mock.called
|
||||
|
||||
def test_timeout_parse_invalid_type(self):
|
||||
for f in ['foobar', 'xyz']:
|
||||
cmd = '--timeout %s endpoint-create' % (f)
|
||||
self.assertRaises(exceptions.CommandError,
|
||||
self._tolerant_shell, cmd)
|
||||
|
||||
def test_timeout_parse_invalid_number(self):
|
||||
for f in [-1, 0]:
|
||||
cmd = '--timeout %s endpoint-create' % (f)
|
||||
self.assertRaises(exceptions.CommandError,
|
||||
self._tolerant_shell, cmd)
|
||||
|
||||
def test_do_timeout(self):
|
||||
response_mock = mock.MagicMock()
|
||||
response_mock.status_code = 200
|
||||
response_mock.text = json.dumps({
|
||||
'endpoints': [],
|
||||
})
|
||||
request_mock = mock.MagicMock(return_value=response_mock)
|
||||
with mock.patch.object(session.requests, 'request',
|
||||
request_mock):
|
||||
shell(('--timeout 2 --os-token=blah --os-endpoint=blah'
|
||||
' --os-auth-url=blah.com endpoint-list'))
|
||||
request_mock.assert_called_with(mock.ANY, mock.ANY,
|
||||
timeout=2,
|
||||
allow_redirects=False,
|
||||
headers=mock.ANY,
|
||||
verify=mock.ANY)
|
||||
|
||||
def test_do_endpoints(self):
|
||||
do_shell_mock = mock.MagicMock()
|
||||
# grab the decorators for do_endpoint_create
|
||||
shell_func = getattr(shell_v2_0, 'do_endpoint_create')
|
||||
do_shell_mock.arguments = getattr(shell_func, 'arguments', [])
|
||||
with mock.patch('keystoneclient.v2_0.shell.do_endpoint_create',
|
||||
do_shell_mock):
|
||||
|
||||
# Old_style options
|
||||
# Test create args
|
||||
shell('endpoint-create '
|
||||
'--service_id=2 --publicurl=http://example.com:1234/go '
|
||||
'--adminurl=http://example.com:9876/adm')
|
||||
assert do_shell_mock.called
|
||||
((a, b), c) = do_shell_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID,
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
actual = (b.service, b.publicurl, b.adminurl)
|
||||
expect = ('2',
|
||||
'http://example.com:1234/go',
|
||||
'http://example.com:9876/adm')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# New-style options
|
||||
# Test create args
|
||||
shell('endpoint-create '
|
||||
'--service-id=3 --publicurl=http://example.com:4321/go '
|
||||
'--adminurl=http://example.com:9876/adm')
|
||||
assert do_shell_mock.called
|
||||
((a, b), c) = do_shell_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID,
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
actual = (b.service, b.publicurl, b.adminurl)
|
||||
expect = ('3',
|
||||
'http://example.com:4321/go',
|
||||
'http://example.com:9876/adm')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
|
||||
# New-style options
|
||||
# Test create args
|
||||
shell('endpoint-create '
|
||||
'--service=3 --publicurl=http://example.com:4321/go '
|
||||
'--adminurl=http://example.com:9876/adm')
|
||||
assert do_shell_mock.called
|
||||
((a, b), c) = do_shell_mock.call_args
|
||||
actual = (b.os_auth_url, b.os_password, b.os_tenant_id,
|
||||
b.os_tenant_name, b.os_username,
|
||||
b.os_identity_api_version)
|
||||
expect = (DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID,
|
||||
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
||||
actual = (b.service, b.publicurl, b.adminurl)
|
||||
expect = ('3',
|
||||
'http://example.com:4321/go',
|
||||
'http://example.com:9876/adm')
|
||||
self.assertTrue(all([x == y for x, y in zip(actual, expect)]))
|
@ -1,240 +0,0 @@
|
||||
# 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
|
||||
|
||||
import six
|
||||
import testresources
|
||||
from testtools import matchers
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.tests import client_fixtures
|
||||
from keystoneclient.tests import utils as test_utils
|
||||
from keystoneclient import utils
|
||||
|
||||
|
||||
class FakeResource(object):
|
||||
pass
|
||||
|
||||
|
||||
class FakeManager(object):
|
||||
|
||||
resource_class = FakeResource
|
||||
|
||||
resources = {
|
||||
'1234': {'name': 'entity_one'},
|
||||
'8e8ec658-c7b0-4243-bdf8-6f7f2952c0d0': {'name': 'entity_two'},
|
||||
'\xe3\x82\xbdtest': {'name': u'\u30bdtest'},
|
||||
'5678': {'name': '9876'}
|
||||
}
|
||||
|
||||
def get(self, resource_id):
|
||||
try:
|
||||
return self.resources[str(resource_id)]
|
||||
except KeyError:
|
||||
raise exceptions.NotFound(resource_id)
|
||||
|
||||
def find(self, name=None):
|
||||
if name == '9999':
|
||||
# NOTE(morganfainberg): special case that raises NoUniqueMatch.
|
||||
raise exceptions.NoUniqueMatch()
|
||||
for resource_id, resource in self.resources.items():
|
||||
if resource['name'] == str(name):
|
||||
return resource
|
||||
raise exceptions.NotFound(name)
|
||||
|
||||
|
||||
class FindResourceTestCase(test_utils.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(FindResourceTestCase, self).setUp()
|
||||
self.manager = FakeManager()
|
||||
|
||||
def test_find_none(self):
|
||||
self.assertRaises(exceptions.CommandError,
|
||||
utils.find_resource,
|
||||
self.manager,
|
||||
'asdf')
|
||||
|
||||
def test_find_by_integer_id(self):
|
||||
output = utils.find_resource(self.manager, 1234)
|
||||
self.assertEqual(output, self.manager.resources['1234'])
|
||||
|
||||
def test_find_by_str_id(self):
|
||||
output = utils.find_resource(self.manager, '1234')
|
||||
self.assertEqual(output, self.manager.resources['1234'])
|
||||
|
||||
def test_find_by_uuid(self):
|
||||
uuid = '8e8ec658-c7b0-4243-bdf8-6f7f2952c0d0'
|
||||
output = utils.find_resource(self.manager, uuid)
|
||||
self.assertEqual(output, self.manager.resources[uuid])
|
||||
|
||||
def test_find_by_unicode(self):
|
||||
name = '\xe3\x82\xbdtest'
|
||||
output = utils.find_resource(self.manager, name)
|
||||
self.assertEqual(output, self.manager.resources[name])
|
||||
|
||||
def test_find_by_str_name(self):
|
||||
output = utils.find_resource(self.manager, 'entity_one')
|
||||
self.assertEqual(output, self.manager.resources['1234'])
|
||||
|
||||
def test_find_by_int_name(self):
|
||||
output = utils.find_resource(self.manager, 9876)
|
||||
self.assertEqual(output, self.manager.resources['5678'])
|
||||
|
||||
def test_find_no_unique_match(self):
|
||||
self.assertRaises(exceptions.CommandError,
|
||||
utils.find_resource,
|
||||
self.manager,
|
||||
9999)
|
||||
|
||||
|
||||
class FakeObject(object):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
|
||||
class PrintTestCase(test_utils.TestCase):
|
||||
def setUp(self):
|
||||
super(PrintTestCase, self).setUp()
|
||||
self.old_stdout = sys.stdout
|
||||
self.stdout = six.moves.cStringIO()
|
||||
self.addCleanup(setattr, self, 'stdout', None)
|
||||
sys.stdout = self.stdout
|
||||
self.addCleanup(setattr, sys, 'stdout', self.old_stdout)
|
||||
|
||||
def test_print_list_unicode(self):
|
||||
name = six.u('\u540d\u5b57')
|
||||
objs = [FakeObject(name)]
|
||||
# NOTE(Jeffrey4l) If the text's encode is proper, this method will not
|
||||
# raise UnicodeEncodeError exceptions
|
||||
utils.print_list(objs, ['name'])
|
||||
output = self.stdout.getvalue()
|
||||
# In Python 2, output will be bytes, while in Python 3, it will not.
|
||||
# Let's decode the value if needed.
|
||||
if isinstance(output, six.binary_type):
|
||||
output = output.decode('utf-8')
|
||||
self.assertIn(name, output)
|
||||
|
||||
def test_print_dict_unicode(self):
|
||||
name = six.u('\u540d\u5b57')
|
||||
utils.print_dict({'name': name})
|
||||
output = self.stdout.getvalue()
|
||||
# In Python 2, output will be bytes, while in Python 3, it will not.
|
||||
# Let's decode the value if needed.
|
||||
if isinstance(output, six.binary_type):
|
||||
output = output.decode('utf-8')
|
||||
self.assertIn(name, output)
|
||||
|
||||
|
||||
class TestPositional(test_utils.TestCase):
|
||||
|
||||
@utils.positional(1)
|
||||
def no_vars(self):
|
||||
# positional doesn't enforce anything here
|
||||
return True
|
||||
|
||||
@utils.positional(3, utils.positional.EXCEPT)
|
||||
def mixed_except(self, arg, kwarg1=None, kwarg2=None):
|
||||
# self, arg, and kwarg1 may be passed positionally
|
||||
return (arg, kwarg1, kwarg2)
|
||||
|
||||
@utils.positional(3, utils.positional.WARN)
|
||||
def mixed_warn(self, arg, kwarg1=None, kwarg2=None):
|
||||
# self, arg, and kwarg1 may be passed positionally, only a warning
|
||||
# is emitted
|
||||
return (arg, kwarg1, kwarg2)
|
||||
|
||||
def test_nothing(self):
|
||||
self.assertTrue(self.no_vars())
|
||||
|
||||
def test_mixed_except(self):
|
||||
self.assertEqual((1, 2, 3), self.mixed_except(1, 2, kwarg2=3))
|
||||
self.assertEqual((1, 2, 3), self.mixed_except(1, kwarg1=2, kwarg2=3))
|
||||
self.assertEqual((1, None, None), self.mixed_except(1))
|
||||
self.assertRaises(TypeError, self.mixed_except, 1, 2, 3)
|
||||
|
||||
def test_mixed_warn(self):
|
||||
logger_message = six.moves.cStringIO()
|
||||
handler = logging.StreamHandler(logger_message)
|
||||
handler.setLevel(logging.DEBUG)
|
||||
|
||||
logger = logging.getLogger(utils.__name__)
|
||||
level = logger.getEffectiveLevel()
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.addHandler(handler)
|
||||
|
||||
self.addCleanup(logger.removeHandler, handler)
|
||||
self.addCleanup(logger.setLevel, level)
|
||||
|
||||
self.mixed_warn(1, 2, 3)
|
||||
|
||||
self.assertIn('takes at most 3 positional', logger_message.getvalue())
|
||||
|
||||
@utils.positional(enforcement=utils.positional.EXCEPT)
|
||||
def inspect_func(self, arg, kwarg=None):
|
||||
return (arg, kwarg)
|
||||
|
||||
def test_inspect_positions(self):
|
||||
self.assertEqual((1, None), self.inspect_func(1))
|
||||
self.assertEqual((1, 2), self.inspect_func(1, kwarg=2))
|
||||
self.assertRaises(TypeError, self.inspect_func)
|
||||
self.assertRaises(TypeError, self.inspect_func, 1, 2)
|
||||
|
||||
@utils.positional.classmethod(1)
|
||||
def class_method(cls, a, b):
|
||||
return (cls, a, b)
|
||||
|
||||
@utils.positional.method(1)
|
||||
def normal_method(self, a, b):
|
||||
self.assertIsInstance(self, TestPositional)
|
||||
return (self, a, b)
|
||||
|
||||
def test_class_method(self):
|
||||
self.assertEqual((TestPositional, 1, 2), self.class_method(1, b=2))
|
||||
self.assertRaises(TypeError, self.class_method, 1, 2)
|
||||
|
||||
def test_normal_method(self):
|
||||
self.assertEqual((self, 1, 2), self.normal_method(1, b=2))
|
||||
self.assertRaises(TypeError, self.normal_method, 1, 2)
|
||||
|
||||
|
||||
class HashSignedTokenTestCase(test_utils.TestCase,
|
||||
testresources.ResourcedTestCase):
|
||||
"""Unit tests for utils.hash_signed_token()."""
|
||||
|
||||
resources = [('examples', client_fixtures.EXAMPLES_RESOURCE)]
|
||||
|
||||
def test_default_md5(self):
|
||||
"""The default hash method is md5."""
|
||||
token = self.examples.SIGNED_TOKEN_SCOPED
|
||||
if six.PY3:
|
||||
token = token.encode('utf-8')
|
||||
token_id_default = utils.hash_signed_token(token)
|
||||
token_id_md5 = utils.hash_signed_token(token, mode='md5')
|
||||
self.assertThat(token_id_default, matchers.Equals(token_id_md5))
|
||||
# md5 hash is 32 chars.
|
||||
self.assertThat(token_id_default, matchers.HasLength(32))
|
||||
|
||||
def test_sha256(self):
|
||||
"""Can also hash with sha256."""
|
||||
token = self.examples.SIGNED_TOKEN_SCOPED
|
||||
if six.PY3:
|
||||
token = token.encode('utf-8')
|
||||
token_id = utils.hash_signed_token(token, mode='sha256')
|
||||
# sha256 hash is 64 chars.
|
||||
self.assertThat(token_id, matchers.HasLength(64))
|
||||
|
||||
|
||||
def load_tests(loader, tests, pattern):
|
||||
return testresources.OptimisingTestSuite(tests)
|
@ -1,125 +0,0 @@
|
||||
# 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.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from keystoneclient import fixture
|
||||
|
||||
|
||||
def unscoped_token():
|
||||
return fixture.V2Token(token_id='3e2813b7ba0b4006840c3825860b86ed',
|
||||
expires='2012-10-03T16:58:01Z',
|
||||
user_id='c4da488862bd435c9e6c0275a0d0e49a',
|
||||
user_name='exampleuser')
|
||||
|
||||
|
||||
def project_scoped_token():
|
||||
_TENANT_ID = '225da22d3ce34b15877ea70b2a575f58'
|
||||
|
||||
f = fixture.V2Token(token_id='04c7d5ffaeef485f9dc69c06db285bdb',
|
||||
expires='2012-10-03T16:53:36Z',
|
||||
tenant_id='225da22d3ce34b15877ea70b2a575f58',
|
||||
tenant_name='exampleproject',
|
||||
user_id='c4da488862bd435c9e6c0275a0d0e49a',
|
||||
user_name='exampleuser')
|
||||
|
||||
f.add_role(id='edc12489faa74ee0aca0b8a0b4d74a74',
|
||||
name='Member')
|
||||
|
||||
s = f.add_service('volume', 'Volume Service')
|
||||
s.add_endpoint(public='http://public.com:8776/v1/%s' % _TENANT_ID,
|
||||
admin='http://admin:8776/v1/%s' % _TENANT_ID,
|
||||
internal='http://internal:8776/v1/%s' % _TENANT_ID,
|
||||
region='RegionOne')
|
||||
|
||||
s = f.add_service('image', 'Image Service')
|
||||
s.add_endpoint(public='http://public.com:9292/v1',
|
||||
admin='http://admin:9292/v1',
|
||||
internal='http://internal:9292/v1',
|
||||
region='RegionOne')
|
||||
|
||||
s = f.add_service('compute', 'Compute Service')
|
||||
s.add_endpoint(public='http://public.com:8774/v2/%s' % _TENANT_ID,
|
||||
admin='http://admin:8774/v2/%s' % _TENANT_ID,
|
||||
internal='http://internal:8774/v2/%s' % _TENANT_ID,
|
||||
region='RegionOne')
|
||||
|
||||
s = f.add_service('ec2', 'EC2 Service')
|
||||
s.add_endpoint(public='http://public.com:8773/services/Cloud',
|
||||
admin='http://admin:8773/services/Admin',
|
||||
internal='http://internal:8773/services/Cloud',
|
||||
region='RegionOne')
|
||||
|
||||
s = f.add_service('identity', 'Identity Service')
|
||||
s.add_endpoint(public='http://public.com:5000/v2.0',
|
||||
admin='http://admin:35357/v2.0',
|
||||
internal='http://internal:5000/v2.0',
|
||||
region='RegionOne')
|
||||
|
||||
return f
|
||||
|
||||
|
||||
def auth_response_body():
|
||||
f = fixture.V2Token(token_id='ab48a9efdfedb23ty3494',
|
||||
expires='2010-11-01T03:32:15-05:00',
|
||||
tenant_id='345',
|
||||
tenant_name='My Project',
|
||||
user_id='123',
|
||||
user_name='jqsmith')
|
||||
|
||||
f.add_role(id='234', name='compute:admin')
|
||||
role = f.add_role(id='235', name='object-store:admin')
|
||||
role['tenantId'] = '1'
|
||||
|
||||
s = f.add_service('compute', 'Cloud Servers')
|
||||
endpoint = s.add_endpoint(public='https://compute.north.host/v1/1234',
|
||||
internal='https://compute.north.host/v1/1234',
|
||||
region='North')
|
||||
endpoint['tenantId'] = '1'
|
||||
endpoint['versionId'] = '1.0'
|
||||
endpoint['versionInfo'] = 'https://compute.north.host/v1.0/'
|
||||
endpoint['versionList'] = 'https://compute.north.host/'
|
||||
|
||||
endpoint = s.add_endpoint(public='https://compute.north.host/v1.1/3456',
|
||||
internal='https://compute.north.host/v1.1/3456',
|
||||
region='North')
|
||||
endpoint['tenantId'] = '2'
|
||||
endpoint['versionId'] = '1.1'
|
||||
endpoint['versionInfo'] = 'https://compute.north.host/v1.1/'
|
||||
endpoint['versionList'] = 'https://compute.north.host/'
|
||||
|
||||
s = f.add_service('object-store', 'Cloud Files')
|
||||
endpoint = s.add_endpoint(public='https://swift.north.host/v1/blah',
|
||||
internal='https://swift.north.host/v1/blah',
|
||||
region='South')
|
||||
endpoint['tenantId'] = '11'
|
||||
endpoint['versionId'] = '1.0'
|
||||
endpoint['versionInfo'] = 'uri'
|
||||
endpoint['versionList'] = 'uri'
|
||||
|
||||
endpoint = s.add_endpoint(public='https://swift.north.host/v1.1/blah',
|
||||
internal='https://compute.north.host/v1.1/blah',
|
||||
region='South')
|
||||
endpoint['tenantId'] = '2'
|
||||
endpoint['versionId'] = '1.1'
|
||||
endpoint['versionInfo'] = 'https://swift.north.host/v1.1/'
|
||||
endpoint['versionList'] = 'https://swift.north.host/'
|
||||
|
||||
s = f.add_service('image', 'Image Servers')
|
||||
s.add_endpoint(public='https://image.north.host/v1/',
|
||||
internal='https://image-internal.north.host/v1/',
|
||||
region='North')
|
||||
s.add_endpoint(public='https://image.south.host/v1/',
|
||||
internal='https://image-internal.south.host/v1/',
|
||||
region='South')
|
||||
|
||||
return f
|
@ -1,495 +0,0 @@
|
||||
# Copyright (c) 2011 X.commerce, a business unit of eBay Inc.
|
||||
# Copyright 2011 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
|
||||
from six.moves.urllib import parse as urlparse
|
||||
|
||||
from keystoneclient.tests import fakes
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
|
||||
|
||||
class FakeHTTPClient(fakes.FakeClient):
|
||||
def __init__(self, **kwargs):
|
||||
self.username = 'username'
|
||||
self.password = 'password'
|
||||
self.auth_url = 'auth_url'
|
||||
self.callstack = []
|
||||
|
||||
def _cs_request(self, url, method, **kwargs):
|
||||
# Check that certain things are called correctly
|
||||
if method in ['GET', 'DELETE']:
|
||||
assert 'body' not in kwargs
|
||||
elif method == 'PUT':
|
||||
kwargs.setdefault('body', None)
|
||||
|
||||
# Call the method
|
||||
args = urlparse.parse_qsl(urlparse.urlparse(url)[4])
|
||||
kwargs.update(args)
|
||||
munged_url = url.rsplit('?', 1)[0]
|
||||
munged_url = munged_url.strip('/').replace('/', '_').replace('.', '_')
|
||||
munged_url = munged_url.replace('-', '_')
|
||||
|
||||
callback = "%s_%s" % (method.lower(), munged_url)
|
||||
|
||||
if not hasattr(self, callback):
|
||||
raise AssertionError('Called unknown API method: %s %s, '
|
||||
'expected fakes method name: %s' %
|
||||
(method, url, callback))
|
||||
|
||||
# Note the call
|
||||
self.callstack.append((method, url, kwargs.get('body')))
|
||||
|
||||
if not hasattr(self, callback):
|
||||
raise AssertionError('Called unknown API method: %s %s, '
|
||||
'expected fakes method name: %s' %
|
||||
(method, url, callback))
|
||||
|
||||
# Note the call
|
||||
self.callstack.append((method, url, kwargs.get('body')))
|
||||
|
||||
status, body = getattr(self, callback)(**kwargs)
|
||||
r = utils.TestResponse({
|
||||
"status_code": status,
|
||||
"text": body})
|
||||
return r, body
|
||||
|
||||
#
|
||||
# List all extensions
|
||||
#
|
||||
def post_tokens(self, **kw):
|
||||
body = [
|
||||
{"access":
|
||||
{"token":
|
||||
{"expires": "2012-02-05T00:00:00",
|
||||
"id": "887665443383838",
|
||||
"tenant":
|
||||
{"id": "1",
|
||||
"name": "customer-x"}},
|
||||
"serviceCatalog": [
|
||||
{"endpoints": [
|
||||
{"adminURL": "http://swift.admin-nets.local:8080/",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://127.0.0.1:8080/v1/AUTH_1",
|
||||
"publicURL":
|
||||
"http://swift.publicinternets.com/v1/AUTH_1"}],
|
||||
"type": "object-store",
|
||||
"name": "swift"},
|
||||
{"endpoints": [
|
||||
{"adminURL": "http://cdn.admin-nets.local/v1.1/1",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://127.0.0.1:7777/v1.1/1",
|
||||
"publicURL":
|
||||
"http://cdn.publicinternets.com/v1.1/1"}],
|
||||
"type": "object-store",
|
||||
"name": "cdn"}],
|
||||
"user":
|
||||
{"id": "1",
|
||||
"roles": [
|
||||
{"tenantId": "1",
|
||||
"id": "3",
|
||||
"name": "Member"}],
|
||||
"name": "joeuser"}}
|
||||
}
|
||||
]
|
||||
return (200, body)
|
||||
|
||||
def get_tokens_887665443383838(self, **kw):
|
||||
body = [
|
||||
{"access":
|
||||
{"token":
|
||||
{"expires": "2012-02-05T00:00:00",
|
||||
"id": "887665443383838",
|
||||
"tenant": {"id": "1",
|
||||
"name": "customer-x"}},
|
||||
"user":
|
||||
{"name": "joeuser",
|
||||
"tenantName": "customer-x",
|
||||
"id": "1",
|
||||
"roles": [{"serviceId": "1",
|
||||
"id": "3",
|
||||
"name": "Member"}],
|
||||
"tenantId": "1"}}
|
||||
}
|
||||
]
|
||||
return (200, body)
|
||||
|
||||
def get_tokens_887665443383838_endpoints(self, **kw):
|
||||
body = [
|
||||
{"endpoints_links": [
|
||||
{"href":
|
||||
"http://127.0.0.1:35357/tokens/887665443383838"
|
||||
"/endpoints?'marker=5&limit=10'",
|
||||
"rel": "next"}],
|
||||
"endpoints": [
|
||||
{"internalURL": "http://127.0.0.1:8080/v1/AUTH_1",
|
||||
"name": "swift",
|
||||
"adminURL": "http://swift.admin-nets.local:8080/",
|
||||
"region": "RegionOne",
|
||||
"tenantId": 1,
|
||||
"type": "object-store",
|
||||
"id": 1,
|
||||
"publicURL": "http://swift.publicinternets.com/v1/AUTH_1"},
|
||||
{"internalURL": "http://localhost:8774/v1.0",
|
||||
"name": "nova_compat",
|
||||
"adminURL": "http://127.0.0.1:8774/v1.0",
|
||||
"region": "RegionOne",
|
||||
"tenantId": 1,
|
||||
"type": "compute",
|
||||
"id": 2,
|
||||
"publicURL": "http://nova.publicinternets.com/v1.0/"},
|
||||
{"internalURL": "http://localhost:8774/v1.1",
|
||||
"name": "nova",
|
||||
"adminURL": "http://127.0.0.1:8774/v1.1",
|
||||
"region": "RegionOne",
|
||||
"tenantId": 1,
|
||||
"type": "compute",
|
||||
"id": 3,
|
||||
"publicURL": "http://nova.publicinternets.com/v1.1/"},
|
||||
{"internalURL": "http://127.0.0.1:9292/v1.1/",
|
||||
"name": "glance",
|
||||
"adminURL": "http://nova.admin-nets.local/v1.1/",
|
||||
"region": "RegionOne",
|
||||
"tenantId": 1,
|
||||
"type": "image",
|
||||
"id": 4,
|
||||
"publicURL": "http://glance.publicinternets.com/v1.1/"},
|
||||
{"internalURL": "http://127.0.0.1:7777/v1.1/1",
|
||||
"name": "cdn",
|
||||
"adminURL": "http://cdn.admin-nets.local/v1.1/1",
|
||||
"region": "RegionOne",
|
||||
"tenantId": 1,
|
||||
"versionId": "1.1",
|
||||
"versionList": "http://127.0.0.1:7777/",
|
||||
"versionInfo": "http://127.0.0.1:7777/v1.1",
|
||||
"type": "object-store",
|
||||
"id": 5,
|
||||
"publicURL": "http://cdn.publicinternets.com/v1.1/1"}]
|
||||
}
|
||||
]
|
||||
return (200, body)
|
||||
|
||||
def get(self, **kw):
|
||||
body = {
|
||||
"version": {
|
||||
"id": "v2.0",
|
||||
"status": "beta",
|
||||
"updated": "2011-11-19T00:00:00Z",
|
||||
"links": [
|
||||
{"rel": "self",
|
||||
"href": "http://127.0.0.1:35357/v2.0/"},
|
||||
{"rel": "describedby",
|
||||
"type": "text/html",
|
||||
"href": "http://docs.openstack.org/"
|
||||
"api/openstack-identity-service/2.0/content/"},
|
||||
{"rel": "describedby",
|
||||
"type": "application/pdf",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/2.0/"
|
||||
"identity-dev-guide-2.0.pdf"},
|
||||
{"rel": "describedby",
|
||||
"type": "application/vnd.sun.wadl+xml",
|
||||
"href":
|
||||
"http://127.0.0.1:35357/v2.0/identity-admin.wadl"}],
|
||||
"media-types": [
|
||||
{"base": "application/xml",
|
||||
"type": "application/vnd.openstack.identity-v2.0+xml"},
|
||||
{"base": "application/json",
|
||||
"type": "application/vnd.openstack.identity-v2.0+json"}]
|
||||
}
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def get_extensions(self, **kw):
|
||||
body = {
|
||||
"extensions": {"values": []}
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def post_tenants(self, **kw):
|
||||
body = {"tenant":
|
||||
{"enabled": True,
|
||||
"description": None,
|
||||
"name": "new-tenant",
|
||||
"id": "1"}}
|
||||
return (200, body)
|
||||
|
||||
def post_tenants_2(self, **kw):
|
||||
body = {"tenant":
|
||||
{"enabled": False,
|
||||
"description": "desc",
|
||||
"name": "new-tenant1",
|
||||
"id": "2"}}
|
||||
return (200, body)
|
||||
|
||||
def get_tenants(self, **kw):
|
||||
body = {
|
||||
"tenants_links": [],
|
||||
"tenants": [
|
||||
{"enabled": False,
|
||||
"description": None,
|
||||
"name": "project-y",
|
||||
"id": "1"},
|
||||
{"enabled": True,
|
||||
"description": None,
|
||||
"name": "new-tenant",
|
||||
"id": "2"},
|
||||
{"enabled": True,
|
||||
"description": None,
|
||||
"name": "customer-x",
|
||||
"id": "1"}]
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def get_tenants_1(self, **kw):
|
||||
body = {"tenant":
|
||||
{"enabled": True,
|
||||
"description": None,
|
||||
"name": "new-tenant",
|
||||
"id": "1"}}
|
||||
return (200, body)
|
||||
|
||||
def get_tenants_2(self, **kw):
|
||||
body = {"tenant":
|
||||
{"enabled": True,
|
||||
"description": None,
|
||||
"name": "new-tenant",
|
||||
"id": "2"}}
|
||||
return (200, body)
|
||||
|
||||
def delete_tenants_2(self, **kw):
|
||||
body = {}
|
||||
return (200, body)
|
||||
|
||||
def get_tenants_1_users_1_roles(self, **kw):
|
||||
body = {
|
||||
"roles": [
|
||||
{"id": "1",
|
||||
"name": "Admin"},
|
||||
{"id": "2",
|
||||
"name": "Member"},
|
||||
{"id": "3",
|
||||
"name": "new-role"}]
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def put_users_1_roles_OS_KSADM_1(self, **kw):
|
||||
body = {
|
||||
"roles":
|
||||
{"id": "1",
|
||||
"name": "Admin"}}
|
||||
return (200, body)
|
||||
|
||||
def delete_users_1_roles_OS_KSADM_1(self, **kw):
|
||||
body = {}
|
||||
return (200, body)
|
||||
|
||||
def put_tenants_1_users_1_roles_OS_KSADM_1(self, **kw):
|
||||
body = {
|
||||
"role":
|
||||
{"id": "1",
|
||||
"name": "Admin"}}
|
||||
return (200, body)
|
||||
|
||||
def get_users(self, **kw):
|
||||
body = {
|
||||
"users": [
|
||||
{"name": self.username,
|
||||
"enabled": "true",
|
||||
"email": "sdfsdf@sdfsd.sdf",
|
||||
"id": "1",
|
||||
"tenantId": "1"},
|
||||
{"name": "user2",
|
||||
"enabled": "true",
|
||||
"email": "sdfsdf@sdfsd.sdf",
|
||||
"id": "2",
|
||||
"tenantId": "1"}]
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def get_users_1(self, **kw):
|
||||
body = {
|
||||
"user": {
|
||||
"tenantId": "1",
|
||||
"enabled": "true",
|
||||
"id": "1",
|
||||
"name": self.username}
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def put_users_1(self, **kw):
|
||||
body = {
|
||||
"user": {
|
||||
"tenantId": "1",
|
||||
"enabled": "true",
|
||||
"id": "1",
|
||||
"name": "new-user1",
|
||||
"email": "user@email.com"}
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def put_users_1_OS_KSADM_password(self, **kw):
|
||||
body = {
|
||||
"user": {
|
||||
"tenantId": "1",
|
||||
"enabled": "true",
|
||||
"id": "1",
|
||||
"name": "new-user1",
|
||||
"email": "user@email.com"}
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def post_users(self, **kw):
|
||||
body = {
|
||||
"user": {
|
||||
"tenantId": "1",
|
||||
"enabled": "true",
|
||||
"id": "1",
|
||||
"name": self.username}
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def delete_users_1(self, **kw):
|
||||
body = []
|
||||
return (200, body)
|
||||
|
||||
def get_users_1_roles(self, **kw):
|
||||
body = [
|
||||
{"roles_links": [],
|
||||
"roles":[
|
||||
{"id": "2",
|
||||
"name": "KeystoneServiceAdmin"}]
|
||||
}
|
||||
]
|
||||
return (200, body)
|
||||
|
||||
def post_OS_KSADM_roles(self, **kw):
|
||||
body = {"role":
|
||||
{"name": "new-role",
|
||||
"id": "1"}}
|
||||
return (200, body)
|
||||
|
||||
def get_OS_KSADM_roles(self, **kw):
|
||||
body = {"roles": [
|
||||
{"id": "10", "name": "admin"},
|
||||
{"id": "20", "name": "member"},
|
||||
{"id": "1", "name": "new-role"}]
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def get_OS_KSADM_roles_1(self, **kw):
|
||||
body = {"role":
|
||||
{"name": "new-role",
|
||||
"id": "1"}
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def delete_OS_KSADM_roles_1(self, **kw):
|
||||
body = {}
|
||||
return (200, body)
|
||||
|
||||
def post_OS_KSADM_services(self, **kw):
|
||||
body = {"OS-KSADM:service":
|
||||
{"id": "1",
|
||||
"type": "compute",
|
||||
"name": "service1",
|
||||
"description": None}
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def get_OS_KSADM_services_1(self, **kw):
|
||||
body = {"OS-KSADM:service":
|
||||
{"description": None,
|
||||
"type": "compute",
|
||||
"id": "1",
|
||||
"name": "service1"}
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def get_OS_KSADM_services(self, **kw):
|
||||
body = {
|
||||
"OS-KSADM:services": [
|
||||
{"description": None,
|
||||
"type": "compute",
|
||||
"id": "1",
|
||||
"name": "service1"},
|
||||
{"description": None,
|
||||
"type": "identity",
|
||||
"id": "2",
|
||||
"name": "service2"}]
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def delete_OS_KSADM_services_1(self, **kw):
|
||||
body = {}
|
||||
return (200, body)
|
||||
|
||||
def post_users_1_credentials_OS_EC2(self, **kw):
|
||||
body = {"credential":
|
||||
{"access": "1",
|
||||
"tenant_id": "1",
|
||||
"secret": "1",
|
||||
"user_id": "1"}
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def get_users_1_credentials_OS_EC2(self, **kw):
|
||||
body = {"credentials": [
|
||||
{"access": "1",
|
||||
"tenant_id": "1",
|
||||
"secret": "1",
|
||||
"user_id": "1"}]
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def get_users_1_credentials_OS_EC2_2(self, **kw):
|
||||
body = {
|
||||
"credential":
|
||||
{"access": "2",
|
||||
"tenant_id": "1",
|
||||
"secret": "1",
|
||||
"user_id": "1"}
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def delete_users_1_credentials_OS_EC2_2(self, **kw):
|
||||
body = {}
|
||||
return (200, body)
|
||||
|
||||
def patch_OS_KSCRUD_users_1(self, **kw):
|
||||
body = {}
|
||||
return (200, body)
|
||||
|
||||
def get_endpoints(self, **kw):
|
||||
body = {
|
||||
'endpoints': [
|
||||
{'adminURL': 'http://cdn.admin-nets.local/v1.1/1',
|
||||
'region': 'RegionOne',
|
||||
'internalURL': 'http://127.0.0.1:7777/v1.1/1',
|
||||
'publicURL': 'http://cdn.publicinternets.com/v1.1/1'}],
|
||||
'type': 'compute',
|
||||
'name': 'nova-compute'
|
||||
}
|
||||
return (200, body)
|
||||
|
||||
def post_endpoints(self, **kw):
|
||||
body = {
|
||||
"endpoint":
|
||||
{"adminURL": "http://swift.admin-nets.local:8080/",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://127.0.0.1:8080/v1/AUTH_1",
|
||||
"publicURL": "http://swift.publicinternets.com/v1/AUTH_1"},
|
||||
"type": "compute",
|
||||
"name": "nova-compute"
|
||||
}
|
||||
return (200, body)
|
@ -1,135 +0,0 @@
|
||||
# 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 datetime
|
||||
|
||||
import testresources
|
||||
|
||||
from keystoneclient import access
|
||||
from keystoneclient.openstack.common import timeutils
|
||||
from keystoneclient.tests import client_fixtures as token_data
|
||||
from keystoneclient.tests.v2_0 import client_fixtures
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
|
||||
|
||||
class AccessInfoTest(utils.TestCase, testresources.ResourcedTestCase):
|
||||
|
||||
resources = [('examples', token_data.EXAMPLES_RESOURCE)]
|
||||
|
||||
def test_building_unscoped_accessinfo(self):
|
||||
token = client_fixtures.unscoped_token()
|
||||
auth_ref = access.AccessInfo.factory(body=token)
|
||||
|
||||
self.assertTrue(auth_ref)
|
||||
self.assertIn('token', auth_ref)
|
||||
|
||||
self.assertEqual(auth_ref.auth_token,
|
||||
'3e2813b7ba0b4006840c3825860b86ed')
|
||||
self.assertEqual(auth_ref.username, 'exampleuser')
|
||||
self.assertEqual(auth_ref.user_id, 'c4da488862bd435c9e6c0275a0d0e49a')
|
||||
|
||||
self.assertEqual(auth_ref.role_names, [])
|
||||
|
||||
self.assertIsNone(auth_ref.tenant_name)
|
||||
self.assertIsNone(auth_ref.tenant_id)
|
||||
|
||||
self.assertIsNone(auth_ref.auth_url)
|
||||
self.assertIsNone(auth_ref.management_url)
|
||||
|
||||
self.assertFalse(auth_ref.scoped)
|
||||
self.assertFalse(auth_ref.domain_scoped)
|
||||
self.assertFalse(auth_ref.project_scoped)
|
||||
self.assertFalse(auth_ref.trust_scoped)
|
||||
|
||||
self.assertIsNone(auth_ref.project_domain_id)
|
||||
self.assertIsNone(auth_ref.project_domain_name)
|
||||
self.assertEqual(auth_ref.user_domain_id, 'default')
|
||||
self.assertEqual(auth_ref.user_domain_name, 'Default')
|
||||
|
||||
self.assertEqual(auth_ref.expires, token.expires)
|
||||
|
||||
def test_will_expire_soon(self):
|
||||
token = client_fixtures.unscoped_token()
|
||||
expires = timeutils.utcnow() + datetime.timedelta(minutes=5)
|
||||
token.expires = expires
|
||||
auth_ref = access.AccessInfo.factory(body=token)
|
||||
self.assertFalse(auth_ref.will_expire_soon(stale_duration=120))
|
||||
self.assertTrue(auth_ref.will_expire_soon(stale_duration=300))
|
||||
self.assertFalse(auth_ref.will_expire_soon())
|
||||
|
||||
def test_building_scoped_accessinfo(self):
|
||||
auth_ref = access.AccessInfo.factory(
|
||||
body=client_fixtures.project_scoped_token())
|
||||
|
||||
self.assertTrue(auth_ref)
|
||||
self.assertIn('token', auth_ref)
|
||||
self.assertIn('serviceCatalog', auth_ref)
|
||||
self.assertTrue(auth_ref['serviceCatalog'])
|
||||
|
||||
self.assertEqual(auth_ref.auth_token,
|
||||
'04c7d5ffaeef485f9dc69c06db285bdb')
|
||||
self.assertEqual(auth_ref.username, 'exampleuser')
|
||||
self.assertEqual(auth_ref.user_id, 'c4da488862bd435c9e6c0275a0d0e49a')
|
||||
|
||||
self.assertEqual(auth_ref.role_names, ['Member'])
|
||||
|
||||
self.assertEqual(auth_ref.tenant_name, 'exampleproject')
|
||||
self.assertEqual(auth_ref.tenant_id,
|
||||
'225da22d3ce34b15877ea70b2a575f58')
|
||||
|
||||
self.assertEqual(auth_ref.tenant_name, auth_ref.project_name)
|
||||
self.assertEqual(auth_ref.tenant_id, auth_ref.project_id)
|
||||
|
||||
self.assertEqual(auth_ref.auth_url, ('http://public.com:5000/v2.0',))
|
||||
self.assertEqual(auth_ref.management_url, ('http://admin:35357/v2.0',))
|
||||
|
||||
self.assertEqual(auth_ref.project_domain_id, 'default')
|
||||
self.assertEqual(auth_ref.project_domain_name, 'Default')
|
||||
self.assertEqual(auth_ref.user_domain_id, 'default')
|
||||
self.assertEqual(auth_ref.user_domain_name, 'Default')
|
||||
|
||||
self.assertTrue(auth_ref.scoped)
|
||||
self.assertTrue(auth_ref.project_scoped)
|
||||
self.assertFalse(auth_ref.domain_scoped)
|
||||
|
||||
def test_diablo_token(self):
|
||||
diablo_token = self.examples.TOKEN_RESPONSES[
|
||||
self.examples.VALID_DIABLO_TOKEN]
|
||||
auth_ref = access.AccessInfo.factory(body=diablo_token)
|
||||
|
||||
self.assertTrue(auth_ref)
|
||||
self.assertEqual(auth_ref.username, 'user_name1')
|
||||
self.assertEqual(auth_ref.project_id, 'tenant_id1')
|
||||
self.assertEqual(auth_ref.project_name, 'tenant_id1')
|
||||
self.assertEqual(auth_ref.project_domain_id, 'default')
|
||||
self.assertEqual(auth_ref.project_domain_name, 'Default')
|
||||
self.assertEqual(auth_ref.user_domain_id, 'default')
|
||||
self.assertEqual(auth_ref.user_domain_name, 'Default')
|
||||
self.assertEqual(auth_ref.role_names, ['role1', 'role2'])
|
||||
self.assertFalse(auth_ref.scoped)
|
||||
|
||||
def test_grizzly_token(self):
|
||||
grizzly_token = self.examples.TOKEN_RESPONSES[
|
||||
self.examples.SIGNED_TOKEN_SCOPED_KEY]
|
||||
auth_ref = access.AccessInfo.factory(body=grizzly_token)
|
||||
|
||||
self.assertEqual(auth_ref.project_id, 'tenant_id1')
|
||||
self.assertEqual(auth_ref.project_name, 'tenant_name1')
|
||||
self.assertEqual(auth_ref.project_domain_id, 'default')
|
||||
self.assertEqual(auth_ref.project_domain_name, 'Default')
|
||||
self.assertEqual(auth_ref.user_domain_id, 'default')
|
||||
self.assertEqual(auth_ref.user_domain_name, 'Default')
|
||||
self.assertEqual(auth_ref.role_names, ['role1', 'role2'])
|
||||
|
||||
|
||||
def load_tests(loader, tests, pattern):
|
||||
return testresources.OptimisingTestSuite(tests)
|
@ -1,274 +0,0 @@
|
||||
# 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 datetime
|
||||
import json
|
||||
|
||||
import httpretty
|
||||
import six
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.openstack.common import jsonutils
|
||||
from keystoneclient.openstack.common import timeutils
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
from keystoneclient.v2_0 import client
|
||||
|
||||
|
||||
class AuthenticateAgainstKeystoneTests(utils.TestCase):
|
||||
def setUp(self):
|
||||
super(AuthenticateAgainstKeystoneTests, self).setUp()
|
||||
self.TEST_RESPONSE_DICT = {
|
||||
"access": {
|
||||
"token": {
|
||||
"expires": "2020-01-01T00:00:10.000123Z",
|
||||
"id": self.TEST_TOKEN,
|
||||
"tenant": {
|
||||
"id": self.TEST_TENANT_ID
|
||||
},
|
||||
},
|
||||
"user": {
|
||||
"id": self.TEST_USER
|
||||
},
|
||||
"serviceCatalog": self.TEST_SERVICE_CATALOG,
|
||||
},
|
||||
}
|
||||
self.TEST_REQUEST_BODY = {
|
||||
"auth": {
|
||||
"passwordCredentials": {
|
||||
"username": self.TEST_USER,
|
||||
"password": self.TEST_TOKEN,
|
||||
},
|
||||
"tenantId": self.TEST_TENANT_ID,
|
||||
},
|
||||
}
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_expired(self):
|
||||
# Build an expired token
|
||||
self.TEST_RESPONSE_DICT['access']['token']['expires'] = (
|
||||
(timeutils.utcnow() - datetime.timedelta(1)).isoformat())
|
||||
|
||||
exp_resp = httpretty.Response(body=json.dumps(self.TEST_RESPONSE_DICT),
|
||||
content_type='application/json')
|
||||
|
||||
# Build a new response
|
||||
TEST_TOKEN = "abcdef"
|
||||
self.TEST_RESPONSE_DICT['access']['token']['expires'] = (
|
||||
'2020-01-01T00:00:10.000123Z')
|
||||
self.TEST_RESPONSE_DICT['access']['token']['id'] = TEST_TOKEN
|
||||
|
||||
new_resp = httpretty.Response(body=json.dumps(self.TEST_RESPONSE_DICT),
|
||||
content_type='application/json')
|
||||
|
||||
# return expired first, and then the new response
|
||||
self.stub_auth(responses=[exp_resp, new_resp])
|
||||
|
||||
cs = client.Client(tenant_id=self.TEST_TENANT_ID,
|
||||
auth_url=self.TEST_URL,
|
||||
username=self.TEST_USER,
|
||||
password=self.TEST_TOKEN)
|
||||
|
||||
self.assertEqual(cs.management_url,
|
||||
self.TEST_RESPONSE_DICT["access"]["serviceCatalog"][3]
|
||||
['endpoints'][0]["adminURL"])
|
||||
|
||||
self.assertEqual(cs.auth_token, TEST_TOKEN)
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_failure(self):
|
||||
_auth = 'auth'
|
||||
_cred = 'passwordCredentials'
|
||||
_pass = 'password'
|
||||
self.TEST_REQUEST_BODY[_auth][_cred][_pass] = 'bad_key'
|
||||
error = {"unauthorized": {"message": "Unauthorized",
|
||||
"code": "401"}}
|
||||
|
||||
self.stub_auth(status=401, json=error)
|
||||
|
||||
# Workaround for issue with assertRaises on python2.6
|
||||
# where with assertRaises(exceptions.Unauthorized): doesn't work
|
||||
# right
|
||||
def client_create_wrapper():
|
||||
client.Client(username=self.TEST_USER,
|
||||
password="bad_key",
|
||||
tenant_id=self.TEST_TENANT_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
|
||||
self.assertRaises(exceptions.Unauthorized, client_create_wrapper)
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_auth_redirect(self):
|
||||
self.stub_auth(status=305, body='Use Proxy',
|
||||
location=self.TEST_ADMIN_URL + "/tokens")
|
||||
|
||||
self.stub_auth(base_url=self.TEST_ADMIN_URL,
|
||||
json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client(username=self.TEST_USER,
|
||||
password=self.TEST_TOKEN,
|
||||
tenant_id=self.TEST_TENANT_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
|
||||
self.assertEqual(cs.management_url,
|
||||
self.TEST_RESPONSE_DICT["access"]["serviceCatalog"][3]
|
||||
['endpoints'][0]["adminURL"])
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_DICT["access"]["token"]["id"])
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_password_scoped(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client(username=self.TEST_USER,
|
||||
password=self.TEST_TOKEN,
|
||||
tenant_id=self.TEST_TENANT_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertEqual(cs.management_url,
|
||||
self.TEST_RESPONSE_DICT["access"]["serviceCatalog"][3]
|
||||
['endpoints'][0]["adminURL"])
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_DICT["access"]["token"]["id"])
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_password_unscoped(self):
|
||||
del self.TEST_RESPONSE_DICT['access']['serviceCatalog']
|
||||
del self.TEST_REQUEST_BODY['auth']['tenantId']
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client(username=self.TEST_USER,
|
||||
password=self.TEST_TOKEN,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_DICT["access"]["token"]["id"])
|
||||
self.assertFalse('serviceCatalog' in cs.service_catalog.catalog)
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_auth_url_token_authentication(self):
|
||||
fake_token = 'fake_token'
|
||||
fake_url = '/fake-url'
|
||||
fake_resp = {'result': True}
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
self.stub_url('GET', [fake_url], json=fake_resp,
|
||||
base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT)
|
||||
|
||||
cl = client.Client(auth_url=self.TEST_URL,
|
||||
token=fake_token)
|
||||
body = httpretty.last_request().body
|
||||
if six.PY3:
|
||||
body = body.decode('utf-8')
|
||||
body = jsonutils.loads(body)
|
||||
self.assertEqual(body['auth']['token']['id'], fake_token)
|
||||
|
||||
resp, body = cl.get(fake_url)
|
||||
self.assertEqual(fake_resp, body)
|
||||
|
||||
self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
|
||||
self.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_token_scoped(self):
|
||||
del self.TEST_REQUEST_BODY['auth']['passwordCredentials']
|
||||
self.TEST_REQUEST_BODY['auth']['token'] = {'id': self.TEST_TOKEN}
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client(token=self.TEST_TOKEN,
|
||||
tenant_id=self.TEST_TENANT_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertEqual(cs.management_url,
|
||||
self.TEST_RESPONSE_DICT["access"]["serviceCatalog"][3]
|
||||
['endpoints'][0]["adminURL"])
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_DICT["access"]["token"]["id"])
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_token_scoped_trust(self):
|
||||
del self.TEST_REQUEST_BODY['auth']['passwordCredentials']
|
||||
self.TEST_REQUEST_BODY['auth']['token'] = {'id': self.TEST_TOKEN}
|
||||
self.TEST_REQUEST_BODY['auth']['trust_id'] = self.TEST_TRUST_ID
|
||||
response = self.TEST_RESPONSE_DICT.copy()
|
||||
response['access']['trust'] = {"trustee_user_id": self.TEST_USER,
|
||||
"id": self.TEST_TRUST_ID}
|
||||
self.stub_auth(json=response)
|
||||
|
||||
cs = client.Client(token=self.TEST_TOKEN,
|
||||
tenant_id=self.TEST_TENANT_ID,
|
||||
trust_id=self.TEST_TRUST_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertTrue(cs.auth_ref.trust_scoped)
|
||||
self.assertEqual(cs.auth_ref.trust_id, self.TEST_TRUST_ID)
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_token_unscoped(self):
|
||||
del self.TEST_REQUEST_BODY['auth']['passwordCredentials']
|
||||
del self.TEST_REQUEST_BODY['auth']['tenantId']
|
||||
del self.TEST_RESPONSE_DICT['access']['serviceCatalog']
|
||||
self.TEST_REQUEST_BODY['auth']['token'] = {'id': self.TEST_TOKEN}
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client(token=self.TEST_TOKEN,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_DICT["access"]["token"]["id"])
|
||||
self.assertFalse('serviceCatalog' in cs.service_catalog.catalog)
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_allow_override_of_auth_token(self):
|
||||
fake_url = '/fake-url'
|
||||
fake_token = 'fake_token'
|
||||
fake_resp = {'result': True}
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
self.stub_url('GET', [fake_url], json=fake_resp,
|
||||
base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT)
|
||||
|
||||
cl = client.Client(username='exampleuser',
|
||||
password='password',
|
||||
tenant_name='exampleproject',
|
||||
auth_url=self.TEST_URL)
|
||||
|
||||
self.assertEqual(cl.auth_token, self.TEST_TOKEN)
|
||||
|
||||
# the token returned from the authentication will be used
|
||||
resp, body = cl.get(fake_url)
|
||||
self.assertEqual(fake_resp, body)
|
||||
|
||||
self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
|
||||
self.TEST_TOKEN)
|
||||
|
||||
# then override that token and the new token shall be used
|
||||
cl.auth_token = fake_token
|
||||
|
||||
resp, body = cl.get(fake_url)
|
||||
self.assertEqual(fake_resp, body)
|
||||
|
||||
self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
|
||||
fake_token)
|
||||
|
||||
# if we clear that overridden token then we fall back to the original
|
||||
del cl.auth_token
|
||||
|
||||
resp, body = cl.get(fake_url)
|
||||
self.assertEqual(fake_resp, body)
|
||||
|
||||
self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
|
||||
self.TEST_TOKEN)
|
@ -1,162 +0,0 @@
|
||||
# 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 json
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient import fixture
|
||||
from keystoneclient.tests.v2_0 import client_fixtures
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
from keystoneclient.v2_0 import client
|
||||
|
||||
|
||||
class KeystoneClientTest(utils.TestCase):
|
||||
|
||||
@httpretty.activate
|
||||
def test_unscoped_init(self):
|
||||
self.stub_auth(json=client_fixtures.unscoped_token())
|
||||
|
||||
c = client.Client(username='exampleuser',
|
||||
password='password',
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertIsNotNone(c.auth_ref)
|
||||
self.assertFalse(c.auth_ref.scoped)
|
||||
self.assertFalse(c.auth_ref.domain_scoped)
|
||||
self.assertFalse(c.auth_ref.project_scoped)
|
||||
self.assertIsNone(c.auth_ref.trust_id)
|
||||
self.assertFalse(c.auth_ref.trust_scoped)
|
||||
|
||||
@httpretty.activate
|
||||
def test_scoped_init(self):
|
||||
self.stub_auth(json=client_fixtures.project_scoped_token())
|
||||
|
||||
c = client.Client(username='exampleuser',
|
||||
password='password',
|
||||
tenant_name='exampleproject',
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertIsNotNone(c.auth_ref)
|
||||
self.assertTrue(c.auth_ref.scoped)
|
||||
self.assertTrue(c.auth_ref.project_scoped)
|
||||
self.assertFalse(c.auth_ref.domain_scoped)
|
||||
self.assertIsNone(c.auth_ref.trust_id)
|
||||
self.assertFalse(c.auth_ref.trust_scoped)
|
||||
|
||||
@httpretty.activate
|
||||
def test_auth_ref_load(self):
|
||||
self.stub_auth(json=client_fixtures.project_scoped_token())
|
||||
|
||||
cl = client.Client(username='exampleuser',
|
||||
password='password',
|
||||
tenant_name='exampleproject',
|
||||
auth_url=self.TEST_URL)
|
||||
cache = json.dumps(cl.auth_ref)
|
||||
new_client = client.Client(auth_ref=json.loads(cache))
|
||||
self.assertIsNotNone(new_client.auth_ref)
|
||||
self.assertTrue(new_client.auth_ref.scoped)
|
||||
self.assertTrue(new_client.auth_ref.project_scoped)
|
||||
self.assertFalse(new_client.auth_ref.domain_scoped)
|
||||
self.assertIsNone(new_client.auth_ref.trust_id)
|
||||
self.assertFalse(new_client.auth_ref.trust_scoped)
|
||||
self.assertEqual(new_client.username, 'exampleuser')
|
||||
self.assertIsNone(new_client.password)
|
||||
self.assertEqual(new_client.management_url,
|
||||
'http://admin:35357/v2.0')
|
||||
|
||||
@httpretty.activate
|
||||
def test_auth_ref_load_with_overridden_arguments(self):
|
||||
self.stub_auth(json=client_fixtures.project_scoped_token())
|
||||
|
||||
cl = client.Client(username='exampleuser',
|
||||
password='password',
|
||||
tenant_name='exampleproject',
|
||||
auth_url=self.TEST_URL)
|
||||
cache = json.dumps(cl.auth_ref)
|
||||
new_auth_url = "http://new-public:5000/v2.0"
|
||||
new_client = client.Client(auth_ref=json.loads(cache),
|
||||
auth_url=new_auth_url)
|
||||
self.assertIsNotNone(new_client.auth_ref)
|
||||
self.assertTrue(new_client.auth_ref.scoped)
|
||||
self.assertTrue(new_client.auth_ref.scoped)
|
||||
self.assertTrue(new_client.auth_ref.project_scoped)
|
||||
self.assertFalse(new_client.auth_ref.domain_scoped)
|
||||
self.assertIsNone(new_client.auth_ref.trust_id)
|
||||
self.assertFalse(new_client.auth_ref.trust_scoped)
|
||||
self.assertEqual(new_client.auth_url, new_auth_url)
|
||||
self.assertEqual(new_client.username, 'exampleuser')
|
||||
self.assertIsNone(new_client.password)
|
||||
self.assertEqual(new_client.management_url,
|
||||
'http://admin:35357/v2.0')
|
||||
|
||||
def test_init_err_no_auth_url(self):
|
||||
self.assertRaises(exceptions.AuthorizationFailure,
|
||||
client.Client,
|
||||
username='exampleuser',
|
||||
password='password')
|
||||
|
||||
@httpretty.activate
|
||||
def test_management_url_is_updated(self):
|
||||
first = fixture.V2Token()
|
||||
first.set_scope()
|
||||
admin_url = 'http://admin:35357/v2.0'
|
||||
second_url = 'http://secondurl:35357/v2.0'
|
||||
|
||||
s = first.add_service('identity')
|
||||
s.add_endpoint(public='http://public.com:5000/v2.0',
|
||||
admin=admin_url)
|
||||
|
||||
second = fixture.V2Token()
|
||||
second.set_scope()
|
||||
s = second.add_service('identity')
|
||||
s.add_endpoint(public='http://secondurl:5000/v2.0',
|
||||
admin=second_url)
|
||||
|
||||
self.stub_auth(json=first)
|
||||
cl = client.Client(username='exampleuser',
|
||||
password='password',
|
||||
tenant_name='exampleproject',
|
||||
auth_url=self.TEST_URL)
|
||||
cl.authenticate()
|
||||
self.assertEqual(cl.management_url, admin_url)
|
||||
|
||||
self.stub_auth(json=second)
|
||||
cl.authenticate()
|
||||
self.assertEqual(cl.management_url, second_url)
|
||||
|
||||
@httpretty.activate
|
||||
def test_client_with_region_name_passes_to_service_catalog(self):
|
||||
# NOTE(jamielennox): this is deprecated behaviour that should be
|
||||
# removed ASAP, however must remain compatible.
|
||||
self.stub_auth(json=client_fixtures.auth_response_body())
|
||||
|
||||
cl = client.Client(username='exampleuser',
|
||||
password='password',
|
||||
tenant_name='exampleproject',
|
||||
auth_url=self.TEST_URL,
|
||||
region_name='North')
|
||||
self.assertEqual(cl.service_catalog.url_for(service_type='image'),
|
||||
'https://image.north.host/v1/')
|
||||
|
||||
cl = client.Client(username='exampleuser',
|
||||
password='password',
|
||||
tenant_name='exampleproject',
|
||||
auth_url=self.TEST_URL,
|
||||
region_name='South')
|
||||
self.assertEqual(cl.service_catalog.url_for(service_type='image'),
|
||||
'https://image.south.host/v1/')
|
||||
|
||||
def test_client_without_auth_params(self):
|
||||
self.assertRaises(exceptions.AuthorizationFailure,
|
||||
client.Client,
|
||||
tenant_name='exampleproject',
|
||||
auth_url=self.TEST_URL)
|
@ -1,83 +0,0 @@
|
||||
# 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 httpretty
|
||||
|
||||
from keystoneclient.generic import client
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
|
||||
|
||||
class DiscoverKeystoneTests(utils.UnauthenticatedTestCase):
|
||||
def setUp(self):
|
||||
super(DiscoverKeystoneTests, self).setUp()
|
||||
self.TEST_RESPONSE_DICT = {
|
||||
"versions": {
|
||||
"values": [{
|
||||
"id": "v2.0",
|
||||
"status": "beta",
|
||||
"updated": "2011-11-19T00:00:00Z",
|
||||
"links": [
|
||||
{"rel": "self",
|
||||
"href": "http://127.0.0.1:5000/v2.0/", },
|
||||
{"rel": "describedby",
|
||||
"type": "text/html",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/2.0/content/", },
|
||||
{"rel": "describedby",
|
||||
"type": "application/pdf",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/2.0/"
|
||||
"identity-dev-guide-2.0.pdf", },
|
||||
{"rel": "describedby",
|
||||
"type": "application/vnd.sun.wadl+xml",
|
||||
"href": "http://127.0.0.1:5000/v2.0/identity.wadl", }
|
||||
],
|
||||
"media-types": [{
|
||||
"base": "application/xml",
|
||||
"type": "application/vnd.openstack.identity-v2.0+xml",
|
||||
}, {
|
||||
"base": "application/json",
|
||||
"type": "application/vnd.openstack.identity-v2.0+json",
|
||||
}],
|
||||
}],
|
||||
},
|
||||
}
|
||||
|
||||
@httpretty.activate
|
||||
def test_get_versions(self):
|
||||
self.stub_url(httpretty.GET, base_url=self.TEST_ROOT_URL,
|
||||
json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client()
|
||||
versions = cs.discover(self.TEST_ROOT_URL)
|
||||
self.assertIsInstance(versions, dict)
|
||||
self.assertIn('message', versions)
|
||||
self.assertIn('v2.0', versions)
|
||||
self.assertEqual(
|
||||
versions['v2.0']['url'],
|
||||
self.TEST_RESPONSE_DICT['versions']['values'][0]['links'][0]
|
||||
['href'])
|
||||
|
||||
@httpretty.activate
|
||||
def test_get_version_local(self):
|
||||
self.stub_url(httpretty.GET, base_url="http://localhost:35357/",
|
||||
json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client()
|
||||
versions = cs.discover()
|
||||
self.assertIsInstance(versions, dict)
|
||||
self.assertIn('message', versions)
|
||||
self.assertIn('v2.0', versions)
|
||||
self.assertEqual(
|
||||
versions['v2.0']['url'],
|
||||
self.TEST_RESPONSE_DICT['versions']['values'][0]['links'][0]
|
||||
['href'])
|
@ -1,113 +0,0 @@
|
||||
# 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 httpretty
|
||||
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
from keystoneclient.v2_0 import ec2
|
||||
|
||||
|
||||
class EC2Tests(utils.TestCase):
|
||||
|
||||
@httpretty.activate
|
||||
def test_create(self):
|
||||
user_id = 'usr'
|
||||
tenant_id = 'tnt'
|
||||
req_body = {
|
||||
"tenant_id": tenant_id,
|
||||
}
|
||||
resp_body = {
|
||||
"credential": {
|
||||
"access": "access",
|
||||
"secret": "secret",
|
||||
"tenant_id": tenant_id,
|
||||
"created": "12/12/12",
|
||||
"enabled": True,
|
||||
}
|
||||
}
|
||||
self.stub_url(httpretty.POST, ['users', user_id, 'credentials',
|
||||
'OS-EC2'], json=resp_body)
|
||||
|
||||
cred = self.client.ec2.create(user_id, tenant_id)
|
||||
self.assertIsInstance(cred, ec2.EC2)
|
||||
self.assertEqual(cred.tenant_id, tenant_id)
|
||||
self.assertEqual(cred.enabled, True)
|
||||
self.assertEqual(cred.access, 'access')
|
||||
self.assertEqual(cred.secret, 'secret')
|
||||
self.assertRequestBodyIs(json=req_body)
|
||||
|
||||
@httpretty.activate
|
||||
def test_get(self):
|
||||
user_id = 'usr'
|
||||
tenant_id = 'tnt'
|
||||
resp_body = {
|
||||
"credential": {
|
||||
"access": "access",
|
||||
"secret": "secret",
|
||||
"tenant_id": tenant_id,
|
||||
"created": "12/12/12",
|
||||
"enabled": True,
|
||||
}
|
||||
}
|
||||
self.stub_url(httpretty.GET, ['users', user_id, 'credentials',
|
||||
'OS-EC2', 'access'], json=resp_body)
|
||||
|
||||
cred = self.client.ec2.get(user_id, 'access')
|
||||
self.assertIsInstance(cred, ec2.EC2)
|
||||
self.assertEqual(cred.tenant_id, tenant_id)
|
||||
self.assertEqual(cred.enabled, True)
|
||||
self.assertEqual(cred.access, 'access')
|
||||
self.assertEqual(cred.secret, 'secret')
|
||||
|
||||
@httpretty.activate
|
||||
def test_list(self):
|
||||
user_id = 'usr'
|
||||
tenant_id = 'tnt'
|
||||
resp_body = {
|
||||
"credentials": {
|
||||
"values": [
|
||||
{
|
||||
"access": "access",
|
||||
"secret": "secret",
|
||||
"tenant_id": tenant_id,
|
||||
"created": "12/12/12",
|
||||
"enabled": True,
|
||||
},
|
||||
{
|
||||
"access": "another",
|
||||
"secret": "key",
|
||||
"tenant_id": tenant_id,
|
||||
"created": "12/12/31",
|
||||
"enabled": True,
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
self.stub_url(httpretty.GET, ['users', user_id, 'credentials',
|
||||
'OS-EC2'], json=resp_body)
|
||||
|
||||
creds = self.client.ec2.list(user_id)
|
||||
self.assertEqual(len(creds), 2)
|
||||
cred = creds[0]
|
||||
self.assertIsInstance(cred, ec2.EC2)
|
||||
self.assertEqual(cred.tenant_id, tenant_id)
|
||||
self.assertEqual(cred.enabled, True)
|
||||
self.assertEqual(cred.access, 'access')
|
||||
self.assertEqual(cred.secret, 'secret')
|
||||
|
||||
@httpretty.activate
|
||||
def test_delete(self):
|
||||
user_id = 'usr'
|
||||
access = 'access'
|
||||
self.stub_url(httpretty.DELETE, ['users', user_id, 'credentials',
|
||||
'OS-EC2', access], status=204)
|
||||
self.client.ec2.delete(user_id, access)
|
@ -1,86 +0,0 @@
|
||||
# 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 httpretty
|
||||
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
from keystoneclient.v2_0 import endpoints
|
||||
|
||||
|
||||
class EndpointTests(utils.TestCase):
|
||||
def setUp(self):
|
||||
super(EndpointTests, self).setUp()
|
||||
self.TEST_ENDPOINTS = {
|
||||
'endpoints': [
|
||||
{
|
||||
'adminurl': 'http://host-1:8774/v1.1/$(tenant_id)s',
|
||||
'id': '8f9531231e044e218824b0e58688d262',
|
||||
'internalurl': 'http://host-1:8774/v1.1/$(tenant_id)s',
|
||||
'publicurl': 'http://host-1:8774/v1.1/$(tenant_id)s',
|
||||
'region': 'RegionOne',
|
||||
},
|
||||
{
|
||||
'adminurl': 'http://host-1:8774/v1.1/$(tenant_id)s',
|
||||
'id': '8f9531231e044e218824b0e58688d263',
|
||||
'internalurl': 'http://host-1:8774/v1.1/$(tenant_id)s',
|
||||
'publicurl': 'http://host-1:8774/v1.1/$(tenant_id)s',
|
||||
'region': 'RegionOne',
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@httpretty.activate
|
||||
def test_create(self):
|
||||
req_body = {
|
||||
"endpoint": {
|
||||
"region": "RegionOne",
|
||||
"publicurl": "http://host-3:8774/v1.1/$(tenant_id)s",
|
||||
"internalurl": "http://host-3:8774/v1.1/$(tenant_id)s",
|
||||
"adminurl": "http://host-3:8774/v1.1/$(tenant_id)s",
|
||||
"service_id": "e044e21",
|
||||
}
|
||||
}
|
||||
|
||||
resp_body = {
|
||||
"endpoint": {
|
||||
"adminurl": "http://host-3:8774/v1.1/$(tenant_id)s",
|
||||
"region": "RegionOne",
|
||||
"id": "1fd485b2ffd54f409a5ecd42cba11401",
|
||||
"internalurl": "http://host-3:8774/v1.1/$(tenant_id)s",
|
||||
"publicurl": "http://host-3:8774/v1.1/$(tenant_id)s",
|
||||
}
|
||||
}
|
||||
|
||||
self.stub_url(httpretty.POST, ['endpoints'], json=resp_body)
|
||||
|
||||
endpoint = self.client.endpoints.create(
|
||||
region=req_body['endpoint']['region'],
|
||||
publicurl=req_body['endpoint']['publicurl'],
|
||||
adminurl=req_body['endpoint']['adminurl'],
|
||||
internalurl=req_body['endpoint']['internalurl'],
|
||||
service_id=req_body['endpoint']['service_id']
|
||||
)
|
||||
self.assertIsInstance(endpoint, endpoints.Endpoint)
|
||||
self.assertRequestBodyIs(json=req_body)
|
||||
|
||||
@httpretty.activate
|
||||
def test_delete(self):
|
||||
self.stub_url(httpretty.DELETE, ['endpoints', '8f953'], status=204)
|
||||
self.client.endpoints.delete('8f953')
|
||||
|
||||
@httpretty.activate
|
||||
def test_list(self):
|
||||
self.stub_url(httpretty.GET, ['endpoints'], json=self.TEST_ENDPOINTS)
|
||||
|
||||
endpoint_list = self.client.endpoints.list()
|
||||
[self.assertIsInstance(r, endpoints.Endpoint)
|
||||
for r in endpoint_list]
|
@ -1,66 +0,0 @@
|
||||
# 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 httpretty
|
||||
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
from keystoneclient.v2_0 import extensions
|
||||
|
||||
|
||||
class ExtensionTests(utils.TestCase):
|
||||
def setUp(self):
|
||||
super(ExtensionTests, self).setUp()
|
||||
self.TEST_EXTENSIONS = {
|
||||
'extensions': {
|
||||
"values": [
|
||||
{
|
||||
'name': 'OpenStack Keystone User CRUD',
|
||||
'namespace': 'http://docs.openstack.org/'
|
||||
'identity/api/ext/OS-KSCRUD/v1.0',
|
||||
'updated': '2013-07-07T12:00:0-00:00',
|
||||
'alias': 'OS-KSCRUD',
|
||||
'description':
|
||||
'OpenStack extensions to Keystone v2.0 API'
|
||||
' enabling User Operations.',
|
||||
'links':
|
||||
'[{"href":'
|
||||
'"https://github.com/openstack/identity-api", "type":'
|
||||
' "text/html", "rel": "describedby"}]',
|
||||
},
|
||||
{
|
||||
'name': 'OpenStack EC2 API',
|
||||
'namespace': 'http://docs.openstack.org/'
|
||||
'identity/api/ext/OS-EC2/v1.0',
|
||||
'updated': '2013-09-07T12:00:0-00:00',
|
||||
'alias': 'OS-EC2',
|
||||
'description': 'OpenStack EC2 Credentials backend.',
|
||||
'links': '[{"href":'
|
||||
'"https://github.com/openstack/identity-api", "type":'
|
||||
' "text/html", "rel": "describedby"}]',
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@httpretty.activate
|
||||
def test_list(self):
|
||||
self.stub_url(httpretty.GET, ['extensions'], json=self.TEST_EXTENSIONS)
|
||||
extensions_list = self.client.extensions.list()
|
||||
self.assertEqual(2, len(extensions_list))
|
||||
for extension in extensions_list:
|
||||
self.assertIsInstance(extension, extensions.Extension)
|
||||
self.assertIsNotNone(extension.alias)
|
||||
self.assertIsNotNone(extension.description)
|
||||
self.assertIsNotNone(extension.links)
|
||||
self.assertIsNotNone(extension.name)
|
||||
self.assertIsNotNone(extension.namespace)
|
||||
self.assertIsNotNone(extension.updated)
|
@ -1,132 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
from keystoneclient.v2_0 import roles
|
||||
|
||||
|
||||
class RoleTests(utils.TestCase):
|
||||
def setUp(self):
|
||||
super(RoleTests, self).setUp()
|
||||
|
||||
self.ADMIN_ROLE_ID = uuid.uuid4().hex
|
||||
self.MEMBER_ROLE_ID = uuid.uuid4().hex
|
||||
|
||||
self.TEST_ROLES = {
|
||||
"roles": {
|
||||
"values": [
|
||||
{
|
||||
"name": "admin",
|
||||
"id": self.ADMIN_ROLE_ID,
|
||||
},
|
||||
{
|
||||
"name": "member",
|
||||
"id": self.MEMBER_ROLE_ID,
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
@httpretty.activate
|
||||
def test_create(self):
|
||||
req_body = {
|
||||
"role": {
|
||||
"name": "sysadmin",
|
||||
}
|
||||
}
|
||||
role_id = uuid.uuid4().hex
|
||||
resp_body = {
|
||||
"role": {
|
||||
"name": "sysadmin",
|
||||
"id": role_id,
|
||||
}
|
||||
}
|
||||
self.stub_url(httpretty.POST, ['OS-KSADM', 'roles'], json=resp_body)
|
||||
|
||||
role = self.client.roles.create(req_body['role']['name'])
|
||||
self.assertRequestBodyIs(json=req_body)
|
||||
self.assertIsInstance(role, roles.Role)
|
||||
self.assertEqual(role.id, role_id)
|
||||
self.assertEqual(role.name, req_body['role']['name'])
|
||||
|
||||
@httpretty.activate
|
||||
def test_delete(self):
|
||||
self.stub_url(httpretty.DELETE,
|
||||
['OS-KSADM', 'roles', self.ADMIN_ROLE_ID], status=204)
|
||||
self.client.roles.delete(self.ADMIN_ROLE_ID)
|
||||
|
||||
@httpretty.activate
|
||||
def test_get(self):
|
||||
self.stub_url(httpretty.GET, ['OS-KSADM', 'roles', self.ADMIN_ROLE_ID],
|
||||
json={'role': self.TEST_ROLES['roles']['values'][0]})
|
||||
|
||||
role = self.client.roles.get(self.ADMIN_ROLE_ID)
|
||||
self.assertIsInstance(role, roles.Role)
|
||||
self.assertEqual(role.id, self.ADMIN_ROLE_ID)
|
||||
self.assertEqual(role.name, 'admin')
|
||||
|
||||
@httpretty.activate
|
||||
def test_list(self):
|
||||
self.stub_url(httpretty.GET, ['OS-KSADM', 'roles'],
|
||||
json=self.TEST_ROLES)
|
||||
|
||||
role_list = self.client.roles.list()
|
||||
[self.assertIsInstance(r, roles.Role) for r in role_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_roles_for_user(self):
|
||||
self.stub_url(httpretty.GET, ['users', 'foo', 'roles'],
|
||||
json=self.TEST_ROLES)
|
||||
|
||||
role_list = self.client.roles.roles_for_user('foo')
|
||||
[self.assertIsInstance(r, roles.Role) for r in role_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_roles_for_user_tenant(self):
|
||||
self.stub_url(httpretty.GET, ['tenants', 'barrr', 'users', 'foo',
|
||||
'roles'], json=self.TEST_ROLES)
|
||||
|
||||
role_list = self.client.roles.roles_for_user('foo', 'barrr')
|
||||
[self.assertIsInstance(r, roles.Role) for r in role_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_add_user_role(self):
|
||||
self.stub_url(httpretty.PUT, ['users', 'foo', 'roles', 'OS-KSADM',
|
||||
'barrr'], status=204)
|
||||
|
||||
self.client.roles.add_user_role('foo', 'barrr')
|
||||
|
||||
@httpretty.activate
|
||||
def test_add_user_role_tenant(self):
|
||||
id_ = uuid.uuid4().hex
|
||||
self.stub_url(httpretty.PUT, ['tenants', id_, 'users', 'foo', 'roles',
|
||||
'OS-KSADM', 'barrr'], status=204)
|
||||
|
||||
self.client.roles.add_user_role('foo', 'barrr', id_)
|
||||
|
||||
@httpretty.activate
|
||||
def test_remove_user_role(self):
|
||||
self.stub_url(httpretty.DELETE, ['users', 'foo', 'roles', 'OS-KSADM',
|
||||
'barrr'], status=204)
|
||||
self.client.roles.remove_user_role('foo', 'barrr')
|
||||
|
||||
@httpretty.activate
|
||||
def test_remove_user_role_tenant(self):
|
||||
id_ = uuid.uuid4().hex
|
||||
self.stub_url(httpretty.DELETE, ['tenants', id_, 'users', 'foo',
|
||||
'roles', 'OS-KSADM', 'barrr'],
|
||||
status=204)
|
||||
self.client.roles.remove_user_role('foo', 'barrr', id_)
|
@ -1,175 +0,0 @@
|
||||
# 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.
|
||||
|
||||
from keystoneclient import access
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.tests.v2_0 import client_fixtures
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
|
||||
|
||||
class ServiceCatalogTest(utils.TestCase):
|
||||
def setUp(self):
|
||||
super(ServiceCatalogTest, self).setUp()
|
||||
self.AUTH_RESPONSE_BODY = client_fixtures.auth_response_body()
|
||||
|
||||
def test_building_a_service_catalog(self):
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
self.assertEqual(sc.url_for(service_type='compute'),
|
||||
"https://compute.north.host/v1/1234")
|
||||
self.assertEqual(sc.url_for('tenantId', '1', service_type='compute'),
|
||||
"https://compute.north.host/v1/1234")
|
||||
self.assertEqual(sc.url_for('tenantId', '2', service_type='compute'),
|
||||
"https://compute.north.host/v1.1/3456")
|
||||
|
||||
self.assertRaises(exceptions.EndpointNotFound, sc.url_for, "region",
|
||||
"South", service_type='compute')
|
||||
|
||||
def test_service_catalog_endpoints(self):
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
public_ep = sc.get_endpoints(service_type='compute',
|
||||
endpoint_type='publicURL')
|
||||
self.assertEqual(public_ep['compute'][1]['tenantId'], '2')
|
||||
self.assertEqual(public_ep['compute'][1]['versionId'], '1.1')
|
||||
self.assertEqual(public_ep['compute'][1]['internalURL'],
|
||||
"https://compute.north.host/v1.1/3456")
|
||||
|
||||
def test_service_catalog_regions(self):
|
||||
self.AUTH_RESPONSE_BODY['access']['region_name'] = "North"
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
url = sc.url_for(service_type='image', endpoint_type='publicURL')
|
||||
self.assertEqual(url, "https://image.north.host/v1/")
|
||||
|
||||
self.AUTH_RESPONSE_BODY['access']['region_name'] = "South"
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
url = sc.url_for(service_type='image', endpoint_type='internalURL')
|
||||
self.assertEqual(url, "https://image-internal.south.host/v1/")
|
||||
|
||||
def test_service_catalog_empty(self):
|
||||
self.AUTH_RESPONSE_BODY['access']['serviceCatalog'] = []
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
self.assertRaises(exceptions.EmptyCatalog,
|
||||
auth_ref.service_catalog.url_for,
|
||||
service_type='image',
|
||||
endpoint_type='internalURL')
|
||||
|
||||
def test_service_catalog_get_endpoints_region_names(self):
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='image', region_name='North')
|
||||
self.assertEqual(len(endpoints), 1)
|
||||
self.assertEqual(endpoints['image'][0]['publicURL'],
|
||||
'https://image.north.host/v1/')
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='image', region_name='South')
|
||||
self.assertEqual(len(endpoints), 1)
|
||||
self.assertEqual(endpoints['image'][0]['publicURL'],
|
||||
'https://image.south.host/v1/')
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='compute')
|
||||
self.assertEqual(len(endpoints['compute']), 2)
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='compute',
|
||||
region_name='North')
|
||||
self.assertEqual(len(endpoints['compute']), 2)
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='compute',
|
||||
region_name='West')
|
||||
self.assertEqual(len(endpoints['compute']), 0)
|
||||
|
||||
def test_service_catalog_url_for_region_names(self):
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
url = sc.url_for(service_type='image', region_name='North')
|
||||
self.assertEqual(url, 'https://image.north.host/v1/')
|
||||
|
||||
url = sc.url_for(service_type='image', region_name='South')
|
||||
self.assertEqual(url, 'https://image.south.host/v1/')
|
||||
|
||||
url = sc.url_for(service_type='compute',
|
||||
region_name='North',
|
||||
attr='versionId',
|
||||
filter_value='1.1')
|
||||
self.assertEqual(url, 'https://compute.north.host/v1.1/3456')
|
||||
|
||||
self.assertRaises(exceptions.EndpointNotFound, sc.url_for,
|
||||
service_type='image', region_name='West')
|
||||
|
||||
def test_servcie_catalog_get_url_region_names(self):
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
urls = sc.get_urls(service_type='image')
|
||||
self.assertEqual(len(urls), 2)
|
||||
|
||||
urls = sc.get_urls(service_type='image', region_name='North')
|
||||
self.assertEqual(len(urls), 1)
|
||||
self.assertEqual(urls[0], 'https://image.north.host/v1/')
|
||||
|
||||
urls = sc.get_urls(service_type='image', region_name='South')
|
||||
self.assertEqual(len(urls), 1)
|
||||
self.assertEqual(urls[0], 'https://image.south.host/v1/')
|
||||
|
||||
urls = sc.get_urls(service_type='image', region_name='West')
|
||||
self.assertIsNone(urls)
|
||||
|
||||
def test_service_catalog_param_overrides_body_region(self):
|
||||
self.AUTH_RESPONSE_BODY['access']['region_name'] = "North"
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
url = sc.url_for(service_type='image')
|
||||
self.assertEqual(url, 'https://image.north.host/v1/')
|
||||
|
||||
url = sc.url_for(service_type='image', region_name='South')
|
||||
self.assertEqual(url, 'https://image.south.host/v1/')
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='image')
|
||||
self.assertEqual(len(endpoints['image']), 1)
|
||||
self.assertEqual(endpoints['image'][0]['publicURL'],
|
||||
'https://image.north.host/v1/')
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='image', region_name='South')
|
||||
self.assertEqual(len(endpoints['image']), 1)
|
||||
self.assertEqual(endpoints['image'][0]['publicURL'],
|
||||
'https://image.south.host/v1/')
|
||||
|
||||
def test_service_catalog_service_name(self):
|
||||
auth_ref = access.AccessInfo.factory(resp=None,
|
||||
body=self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
url = sc.url_for(service_name='Image Servers', endpoint_type='public',
|
||||
service_type='image', region_name='North')
|
||||
self.assertEqual('https://image.north.host/v1/', url)
|
||||
|
||||
self.assertRaises(exceptions.EndpointNotFound, sc.url_for,
|
||||
service_name='Image Servers', service_type='compute')
|
||||
|
||||
urls = sc.get_urls(service_type='image', service_name='Image Servers',
|
||||
endpoint_type='public')
|
||||
|
||||
self.assertIn('https://image.north.host/v1/', urls)
|
||||
self.assertIn('https://image.south.host/v1/', urls)
|
||||
|
||||
urls = sc.get_urls(service_type='image', service_name='Servers',
|
||||
endpoint_type='public')
|
||||
|
||||
self.assertIsNone(urls)
|
@ -1,105 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
from keystoneclient.v2_0 import services
|
||||
|
||||
|
||||
class ServiceTests(utils.TestCase):
|
||||
def setUp(self):
|
||||
super(ServiceTests, self).setUp()
|
||||
|
||||
self.NOVA_SERVICE_ID = uuid.uuid4().hex
|
||||
self.KEYSTONE_SERVICE_ID = uuid.uuid4().hex
|
||||
|
||||
self.TEST_SERVICES = {
|
||||
"OS-KSADM:services": {
|
||||
"values": [
|
||||
{
|
||||
"name": "nova",
|
||||
"type": "compute",
|
||||
"description": "Nova-compatible service.",
|
||||
"id": self.NOVA_SERVICE_ID
|
||||
},
|
||||
{
|
||||
"name": "keystone",
|
||||
"type": "identity",
|
||||
"description": "Keystone-compatible service.",
|
||||
"id": self.KEYSTONE_SERVICE_ID
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
@httpretty.activate
|
||||
def test_create(self):
|
||||
req_body = {
|
||||
"OS-KSADM:service": {
|
||||
"name": "swift",
|
||||
"type": "object-store",
|
||||
"description": "Swift-compatible service.",
|
||||
}
|
||||
}
|
||||
service_id = uuid.uuid4().hex
|
||||
resp_body = {
|
||||
"OS-KSADM:service": {
|
||||
"name": "swift",
|
||||
"type": "object-store",
|
||||
"description": "Swift-compatible service.",
|
||||
"id": service_id,
|
||||
}
|
||||
}
|
||||
self.stub_url(httpretty.POST, ['OS-KSADM', 'services'], json=resp_body)
|
||||
|
||||
service = self.client.services.create(
|
||||
req_body['OS-KSADM:service']['name'],
|
||||
req_body['OS-KSADM:service']['type'],
|
||||
req_body['OS-KSADM:service']['description'])
|
||||
self.assertIsInstance(service, services.Service)
|
||||
self.assertEqual(service.id, service_id)
|
||||
self.assertEqual(service.name, req_body['OS-KSADM:service']['name'])
|
||||
self.assertRequestBodyIs(json=req_body)
|
||||
|
||||
@httpretty.activate
|
||||
def test_delete(self):
|
||||
self.stub_url(httpretty.DELETE,
|
||||
['OS-KSADM', 'services', self.NOVA_SERVICE_ID],
|
||||
status=204)
|
||||
|
||||
self.client.services.delete(self.NOVA_SERVICE_ID)
|
||||
|
||||
@httpretty.activate
|
||||
def test_get(self):
|
||||
test_services = self.TEST_SERVICES['OS-KSADM:services']['values'][0]
|
||||
|
||||
self.stub_url(httpretty.GET,
|
||||
['OS-KSADM', 'services', self.NOVA_SERVICE_ID],
|
||||
json={'OS-KSADM:service': test_services})
|
||||
|
||||
service = self.client.services.get(self.NOVA_SERVICE_ID)
|
||||
self.assertIsInstance(service, services.Service)
|
||||
self.assertEqual(service.id, self.NOVA_SERVICE_ID)
|
||||
self.assertEqual(service.name, 'nova')
|
||||
self.assertEqual(service.type, 'compute')
|
||||
|
||||
@httpretty.activate
|
||||
def test_list(self):
|
||||
self.stub_url(httpretty.GET, ['OS-KSADM', 'services'],
|
||||
json=self.TEST_SERVICES)
|
||||
|
||||
service_list = self.client.services.list()
|
||||
[self.assertIsInstance(r, services.Service)
|
||||
for r in service_list]
|
@ -1,361 +0,0 @@
|
||||
# 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
|
||||
import sys
|
||||
|
||||
import mock
|
||||
from mox3 import stubout
|
||||
import six
|
||||
from testtools import matchers
|
||||
|
||||
from keystoneclient import httpclient
|
||||
from keystoneclient.tests.v2_0 import fakes
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
|
||||
|
||||
DEFAULT_USERNAME = 'username'
|
||||
DEFAULT_PASSWORD = 'password'
|
||||
DEFAULT_TENANT_ID = 'tenant_id'
|
||||
DEFAULT_TENANT_NAME = 'tenant_name'
|
||||
DEFAULT_AUTH_URL = 'http://127.0.0.1:5000/v2.0/'
|
||||
|
||||
|
||||
class ShellTests(utils.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Patch os.environ to avoid required auth info."""
|
||||
|
||||
super(ShellTests, self).setUp()
|
||||
self.stubs = stubout.StubOutForTesting()
|
||||
|
||||
self.fake_client = fakes.FakeHTTPClient()
|
||||
self.stubs.Set(
|
||||
httpclient.HTTPClient, "_cs_request",
|
||||
lambda ign_self, *args, **kwargs:
|
||||
self.fake_client._cs_request(*args, **kwargs))
|
||||
self.stubs.Set(
|
||||
httpclient.HTTPClient, "authenticate",
|
||||
lambda cl_obj:
|
||||
self.fake_client.authenticate(cl_obj))
|
||||
self.old_environment = os.environ.copy()
|
||||
os.environ = {
|
||||
'OS_USERNAME': DEFAULT_USERNAME,
|
||||
'OS_PASSWORD': DEFAULT_PASSWORD,
|
||||
'OS_TENANT_ID': DEFAULT_TENANT_ID,
|
||||
'OS_TENANT_NAME': DEFAULT_TENANT_NAME,
|
||||
'OS_AUTH_URL': DEFAULT_AUTH_URL,
|
||||
}
|
||||
import keystoneclient.shell
|
||||
self.shell = keystoneclient.shell.OpenStackIdentityShell()
|
||||
|
||||
def tearDown(self):
|
||||
self.stubs.UnsetAll()
|
||||
self.stubs.SmartUnsetAll()
|
||||
os.environ = self.old_environment
|
||||
self.fake_client.clear_callstack()
|
||||
super(ShellTests, self).tearDown()
|
||||
|
||||
def run_command(self, cmd):
|
||||
orig = sys.stdout
|
||||
try:
|
||||
sys.stdout = six.StringIO()
|
||||
if isinstance(cmd, list):
|
||||
self.shell.main(cmd)
|
||||
else:
|
||||
self.shell.main(cmd.split())
|
||||
except SystemExit:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
self.assertEqual(exc_value.code, 0)
|
||||
finally:
|
||||
out = sys.stdout.getvalue()
|
||||
sys.stdout.close()
|
||||
sys.stdout = orig
|
||||
return out
|
||||
|
||||
def assert_called(self, method, url, body=None, **kwargs):
|
||||
return self.fake_client.assert_called(method, url, body, **kwargs)
|
||||
|
||||
def assert_called_anytime(self, method, url, body=None):
|
||||
return self.fake_client.assert_called_anytime(method, url, body)
|
||||
|
||||
def test_user_list(self):
|
||||
self.run_command('user-list')
|
||||
self.fake_client.assert_called_anytime('GET', '/users')
|
||||
|
||||
def test_user_create(self):
|
||||
self.run_command('user-create --name new-user')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/users',
|
||||
{'user':
|
||||
{'email': None,
|
||||
'password': None,
|
||||
'enabled': True,
|
||||
'name': 'new-user',
|
||||
'tenantId': None}})
|
||||
|
||||
@mock.patch('sys.stdin', autospec=True)
|
||||
def test_user_create_password_prompt(self, mock_stdin):
|
||||
with mock.patch('getpass.getpass') as mock_getpass:
|
||||
mock_getpass.return_value = 'newpass'
|
||||
self.run_command('user-create --name new-user --pass')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/users',
|
||||
{'user':
|
||||
{'email': None,
|
||||
'password': 'newpass',
|
||||
'enabled': True,
|
||||
'name': 'new-user',
|
||||
'tenantId': None}})
|
||||
|
||||
def test_user_get(self):
|
||||
self.run_command('user-get 1')
|
||||
self.fake_client.assert_called_anytime('GET', '/users/1')
|
||||
|
||||
def test_user_delete(self):
|
||||
self.run_command('user-delete 1')
|
||||
self.fake_client.assert_called_anytime('DELETE', '/users/1')
|
||||
|
||||
def test_user_password_update(self):
|
||||
self.run_command('user-password-update --pass newpass 1')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'PUT', '/users/1/OS-KSADM/password')
|
||||
|
||||
def test_user_update(self):
|
||||
self.run_command('user-update --name new-user1'
|
||||
' --email user@email.com --enabled true 1')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'PUT', '/users/1',
|
||||
{'user':
|
||||
{'id': '1',
|
||||
'email': 'user@email.com',
|
||||
'enabled': True,
|
||||
'name': 'new-user1'}
|
||||
})
|
||||
required = 'User not updated, no arguments present.'
|
||||
out = self.run_command('user-update 1')
|
||||
self.assertThat(out, matchers.MatchesRegex(required))
|
||||
|
||||
self.run_command(['user-update', '--email', '', '1'])
|
||||
self.fake_client.assert_called_anytime(
|
||||
'PUT', '/users/1',
|
||||
{'user':
|
||||
{'id': '1',
|
||||
'email': ''}
|
||||
})
|
||||
|
||||
def test_role_create(self):
|
||||
self.run_command('role-create --name new-role')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/OS-KSADM/roles',
|
||||
{"role": {"name": "new-role"}})
|
||||
|
||||
def test_role_get(self):
|
||||
self.run_command('role-get 1')
|
||||
self.fake_client.assert_called_anytime('GET', '/OS-KSADM/roles/1')
|
||||
|
||||
def test_role_list(self):
|
||||
self.run_command('role-list')
|
||||
self.fake_client.assert_called_anytime('GET', '/OS-KSADM/roles')
|
||||
|
||||
def test_role_delete(self):
|
||||
self.run_command('role-delete 1')
|
||||
self.fake_client.assert_called_anytime('DELETE', '/OS-KSADM/roles/1')
|
||||
|
||||
def test_user_role_add(self):
|
||||
self.run_command('user-role-add --user_id 1 --role_id 1')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'PUT', '/users/1/roles/OS-KSADM/1')
|
||||
|
||||
def test_user_role_list(self):
|
||||
self.run_command('user-role-list --user_id 1 --tenant-id 1')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'GET', '/tenants/1/users/1/roles')
|
||||
self.run_command('user-role-list --user_id 1')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'GET', '/tenants/1/users/1/roles')
|
||||
self.run_command('user-role-list')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'GET', '/tenants/1/users/1/roles')
|
||||
|
||||
def test_user_role_remove(self):
|
||||
self.run_command('user-role-remove --user_id 1 --role_id 1')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'DELETE', '/users/1/roles/OS-KSADM/1')
|
||||
|
||||
def test_tenant_create(self):
|
||||
self.run_command('tenant-create --name new-tenant')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/tenants',
|
||||
{"tenant": {"enabled": True,
|
||||
"name": "new-tenant",
|
||||
"description": None}})
|
||||
|
||||
def test_tenant_get(self):
|
||||
self.run_command('tenant-get 2')
|
||||
self.fake_client.assert_called_anytime('GET', '/tenants/2')
|
||||
|
||||
def test_tenant_list(self):
|
||||
self.run_command('tenant-list')
|
||||
self.fake_client.assert_called_anytime('GET', '/tenants')
|
||||
|
||||
def test_tenant_update(self):
|
||||
self.run_command('tenant-update'
|
||||
' --name new-tenant1 --enabled false'
|
||||
' --description desc 2')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/tenants/2',
|
||||
{"tenant":
|
||||
{"enabled": False,
|
||||
"id": "2",
|
||||
"description": "desc",
|
||||
"name": "new-tenant1"}})
|
||||
|
||||
required = 'Tenant not updated, no arguments present.'
|
||||
out = self.run_command('tenant-update 1')
|
||||
self.assertThat(out, matchers.MatchesRegex(required))
|
||||
|
||||
def test_tenant_delete(self):
|
||||
self.run_command('tenant-delete 2')
|
||||
self.fake_client.assert_called_anytime('DELETE', '/tenants/2')
|
||||
|
||||
def test_service_create(self):
|
||||
self.run_command('service-create --name service1 --type compute')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/OS-KSADM/services',
|
||||
{"OS-KSADM:service":
|
||||
{"type": "compute",
|
||||
"name": "service1",
|
||||
"description": None}})
|
||||
|
||||
def test_service_get(self):
|
||||
self.run_command('service-get 1')
|
||||
self.fake_client.assert_called_anytime('GET', '/OS-KSADM/services/1')
|
||||
|
||||
def test_service_list(self):
|
||||
self.run_command('service-list')
|
||||
self.fake_client.assert_called_anytime('GET', '/OS-KSADM/services')
|
||||
|
||||
def test_service_delete(self):
|
||||
self.run_command('service-delete 1')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'DELETE', '/OS-KSADM/services/1')
|
||||
|
||||
def test_catalog(self):
|
||||
self.run_command('catalog')
|
||||
self.run_command('catalog --service compute')
|
||||
|
||||
def test_ec2_credentials_create(self):
|
||||
self.run_command('ec2-credentials-create'
|
||||
' --tenant-id 1 --user-id 1')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/users/1/credentials/OS-EC2',
|
||||
{'tenant_id': '1'})
|
||||
|
||||
self.run_command('ec2-credentials-create --tenant-id 1')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/users/1/credentials/OS-EC2',
|
||||
{'tenant_id': '1'})
|
||||
|
||||
self.run_command('ec2-credentials-create')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/users/1/credentials/OS-EC2',
|
||||
{'tenant_id': '1'})
|
||||
|
||||
def test_ec2_credentials_delete(self):
|
||||
self.run_command('ec2-credentials-delete --access 2 --user-id 1')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'DELETE', '/users/1/credentials/OS-EC2/2')
|
||||
|
||||
self.run_command('ec2-credentials-delete --access 2')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'DELETE', '/users/1/credentials/OS-EC2/2')
|
||||
|
||||
def test_ec2_credentials_list(self):
|
||||
self.run_command('ec2-credentials-list --user-id 1')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'GET', '/users/1/credentials/OS-EC2')
|
||||
|
||||
self.run_command('ec2-credentials-list')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'GET', '/users/1/credentials/OS-EC2')
|
||||
|
||||
def test_ec2_credentials_get(self):
|
||||
self.run_command('ec2-credentials-get --access 2 --user-id 1')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'GET', '/users/1/credentials/OS-EC2/2')
|
||||
|
||||
def test_bootstrap(self):
|
||||
self.run_command('bootstrap --user-name new-user'
|
||||
' --pass 1 --role-name admin'
|
||||
' --tenant-name new-tenant')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/users',
|
||||
{'user':
|
||||
{'email': None,
|
||||
'password': '1',
|
||||
'enabled': True,
|
||||
'name': 'new-user',
|
||||
'tenantId': None}})
|
||||
self.run_command('bootstrap --user-name new-user'
|
||||
' --pass 1 --role-name admin'
|
||||
' --tenant-name new-tenant')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/tenants',
|
||||
{"tenant": {"enabled": True,
|
||||
"name": "new-tenant",
|
||||
"description": None}})
|
||||
self.run_command('bootstrap --user-name new-user'
|
||||
' --pass 1 --role-name new-role'
|
||||
' --tenant-name new-tenant')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/OS-KSADM/roles',
|
||||
{"role": {"name": "new-role"}})
|
||||
|
||||
self.run_command('bootstrap --user-name'
|
||||
' new-user --pass 1 --role-name admin'
|
||||
' --tenant-name new-tenant')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'PUT', '/tenants/1/users/1/roles/OS-KSADM/1')
|
||||
|
||||
def test_bash_completion(self):
|
||||
self.run_command('bash-completion')
|
||||
|
||||
def test_help(self):
|
||||
out = self.run_command('help')
|
||||
required = 'usage: keystone'
|
||||
self.assertThat(out, matchers.MatchesRegex(required))
|
||||
|
||||
def test_password_update(self):
|
||||
self.run_command('password-update --current-password oldpass'
|
||||
' --new-password newpass')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'PATCH', '/OS-KSCRUD/users/1',
|
||||
{'user':
|
||||
{'original_password': 'oldpass',
|
||||
'password': 'newpass'}})
|
||||
|
||||
def test_endpoint_create(self):
|
||||
self.run_command('endpoint-create --service-id 1 '
|
||||
'--publicurl=http://example.com:1234/go')
|
||||
self.fake_client.assert_called_anytime(
|
||||
'POST', '/endpoints',
|
||||
{'endpoint':
|
||||
{'adminurl': None,
|
||||
'service_id': '1',
|
||||
'region': 'regionOne',
|
||||
'internalurl': None,
|
||||
'publicurl': "http://example.com:1234/go"}})
|
||||
|
||||
def test_endpoint_list(self):
|
||||
self.run_command('endpoint-list')
|
||||
self.fake_client.assert_called_anytime('GET', '/endpoints')
|
@ -1,298 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
from keystoneclient.v2_0 import tenants
|
||||
|
||||
|
||||
class TenantTests(utils.TestCase):
|
||||
def setUp(self):
|
||||
super(TenantTests, self).setUp()
|
||||
|
||||
self.INVIS_ID = uuid.uuid4().hex
|
||||
self.DEMO_ID = uuid.uuid4().hex
|
||||
self.ADMIN_ID = uuid.uuid4().hex
|
||||
self.EXTRAS_ID = uuid.uuid4().hex
|
||||
|
||||
self.TEST_TENANTS = {
|
||||
"tenants": {
|
||||
"values": [
|
||||
{
|
||||
"enabled": True,
|
||||
"description": "A description change!",
|
||||
"name": "invisible_to_admin",
|
||||
"id": self.INVIS_ID,
|
||||
},
|
||||
{
|
||||
"enabled": True,
|
||||
"description": "None",
|
||||
"name": "demo",
|
||||
"id": self.DEMO_ID,
|
||||
},
|
||||
{
|
||||
"enabled": True,
|
||||
"description": "None",
|
||||
"name": "admin",
|
||||
"id": self.ADMIN_ID,
|
||||
},
|
||||
{
|
||||
"extravalue01": "metadata01",
|
||||
"enabled": True,
|
||||
"description": "For testing extras",
|
||||
"name": "test_extras",
|
||||
"id": self.EXTRAS_ID,
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
},
|
||||
}
|
||||
|
||||
@httpretty.activate
|
||||
def test_create(self):
|
||||
req_body = {
|
||||
"tenant": {
|
||||
"name": "tenantX",
|
||||
"description": "Like tenant 9, but better.",
|
||||
"enabled": True,
|
||||
"extravalue01": "metadata01",
|
||||
},
|
||||
}
|
||||
id_ = uuid.uuid4().hex
|
||||
resp_body = {
|
||||
"tenant": {
|
||||
"name": "tenantX",
|
||||
"enabled": True,
|
||||
"id": id_,
|
||||
"description": "Like tenant 9, but better.",
|
||||
"extravalue01": "metadata01",
|
||||
}
|
||||
}
|
||||
self.stub_url(httpretty.POST, ['tenants'], json=resp_body)
|
||||
|
||||
tenant = self.client.tenants.create(
|
||||
req_body['tenant']['name'],
|
||||
req_body['tenant']['description'],
|
||||
req_body['tenant']['enabled'],
|
||||
extravalue01=req_body['tenant']['extravalue01'],
|
||||
name="don't overwrite priors")
|
||||
self.assertIsInstance(tenant, tenants.Tenant)
|
||||
self.assertEqual(tenant.id, id_)
|
||||
self.assertEqual(tenant.name, "tenantX")
|
||||
self.assertEqual(tenant.description, "Like tenant 9, but better.")
|
||||
self.assertEqual(tenant.extravalue01, "metadata01")
|
||||
self.assertRequestBodyIs(json=req_body)
|
||||
|
||||
@httpretty.activate
|
||||
def test_duplicate_create(self):
|
||||
req_body = {
|
||||
"tenant": {
|
||||
"name": "tenantX",
|
||||
"description": "The duplicate tenant.",
|
||||
"enabled": True
|
||||
},
|
||||
}
|
||||
resp_body = {
|
||||
"error": {
|
||||
"message": "Conflict occurred attempting to store project.",
|
||||
"code": 409,
|
||||
"title": "Conflict",
|
||||
}
|
||||
}
|
||||
self.stub_url(httpretty.POST, ['tenants'], status=409, json=resp_body)
|
||||
|
||||
def create_duplicate_tenant():
|
||||
self.client.tenants.create(req_body['tenant']['name'],
|
||||
req_body['tenant']['description'],
|
||||
req_body['tenant']['enabled'])
|
||||
|
||||
self.assertRaises(exceptions.Conflict, create_duplicate_tenant)
|
||||
|
||||
@httpretty.activate
|
||||
def test_delete(self):
|
||||
self.stub_url(httpretty.DELETE, ['tenants', self.ADMIN_ID], status=204)
|
||||
self.client.tenants.delete(self.ADMIN_ID)
|
||||
|
||||
@httpretty.activate
|
||||
def test_get(self):
|
||||
resp = {'tenant': self.TEST_TENANTS['tenants']['values'][2]}
|
||||
self.stub_url(httpretty.GET, ['tenants', self.ADMIN_ID], json=resp)
|
||||
|
||||
t = self.client.tenants.get(self.ADMIN_ID)
|
||||
self.assertIsInstance(t, tenants.Tenant)
|
||||
self.assertEqual(t.id, self.ADMIN_ID)
|
||||
self.assertEqual(t.name, 'admin')
|
||||
|
||||
@httpretty.activate
|
||||
def test_list(self):
|
||||
self.stub_url(httpretty.GET, ['tenants'], json=self.TEST_TENANTS)
|
||||
|
||||
tenant_list = self.client.tenants.list()
|
||||
[self.assertIsInstance(t, tenants.Tenant) for t in tenant_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_limit(self):
|
||||
self.stub_url(httpretty.GET, ['tenants'], json=self.TEST_TENANTS)
|
||||
|
||||
tenant_list = self.client.tenants.list(limit=1)
|
||||
self.assertQueryStringIs('limit=1')
|
||||
[self.assertIsInstance(t, tenants.Tenant) for t in tenant_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_marker(self):
|
||||
self.stub_url(httpretty.GET, ['tenants'], json=self.TEST_TENANTS)
|
||||
|
||||
tenant_list = self.client.tenants.list(marker=1)
|
||||
self.assertQueryStringIs('marker=1')
|
||||
[self.assertIsInstance(t, tenants.Tenant) for t in tenant_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_limit_marker(self):
|
||||
self.stub_url(httpretty.GET, ['tenants'], json=self.TEST_TENANTS)
|
||||
|
||||
tenant_list = self.client.tenants.list(limit=1, marker=1)
|
||||
self.assertQueryStringIs('marker=1&limit=1')
|
||||
[self.assertIsInstance(t, tenants.Tenant) for t in tenant_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_update(self):
|
||||
req_body = {
|
||||
"tenant": {
|
||||
"id": self.EXTRAS_ID,
|
||||
"name": "tenantX",
|
||||
"description": "I changed you!",
|
||||
"enabled": False,
|
||||
"extravalue01": "metadataChanged",
|
||||
#"extraname": "dontoverwrite!",
|
||||
},
|
||||
}
|
||||
resp_body = {
|
||||
"tenant": {
|
||||
"name": "tenantX",
|
||||
"enabled": False,
|
||||
"id": self.EXTRAS_ID,
|
||||
"description": "I changed you!",
|
||||
"extravalue01": "metadataChanged",
|
||||
},
|
||||
}
|
||||
|
||||
self.stub_url(httpretty.POST, ['tenants', self.EXTRAS_ID],
|
||||
json=resp_body)
|
||||
|
||||
tenant = self.client.tenants.update(
|
||||
req_body['tenant']['id'],
|
||||
req_body['tenant']['name'],
|
||||
req_body['tenant']['description'],
|
||||
req_body['tenant']['enabled'],
|
||||
extravalue01=req_body['tenant']['extravalue01'],
|
||||
name="don't overwrite priors")
|
||||
self.assertIsInstance(tenant, tenants.Tenant)
|
||||
self.assertRequestBodyIs(json=req_body)
|
||||
self.assertEqual(tenant.id, self.EXTRAS_ID)
|
||||
self.assertEqual(tenant.name, "tenantX")
|
||||
self.assertEqual(tenant.description, "I changed you!")
|
||||
self.assertFalse(tenant.enabled)
|
||||
self.assertEqual(tenant.extravalue01, "metadataChanged")
|
||||
|
||||
@httpretty.activate
|
||||
def test_update_empty_description(self):
|
||||
req_body = {
|
||||
"tenant": {
|
||||
"id": self.EXTRAS_ID,
|
||||
"name": "tenantX",
|
||||
"description": "",
|
||||
"enabled": False,
|
||||
},
|
||||
}
|
||||
resp_body = {
|
||||
"tenant": {
|
||||
"name": "tenantX",
|
||||
"enabled": False,
|
||||
"id": self.EXTRAS_ID,
|
||||
"description": "",
|
||||
},
|
||||
}
|
||||
self.stub_url(httpretty.POST, ['tenants', self.EXTRAS_ID],
|
||||
json=resp_body)
|
||||
|
||||
tenant = self.client.tenants.update(req_body['tenant']['id'],
|
||||
req_body['tenant']['name'],
|
||||
req_body['tenant']['description'],
|
||||
req_body['tenant']['enabled'])
|
||||
self.assertIsInstance(tenant, tenants.Tenant)
|
||||
self.assertRequestBodyIs(json=req_body)
|
||||
self.assertEqual(tenant.id, self.EXTRAS_ID)
|
||||
self.assertEqual(tenant.name, "tenantX")
|
||||
self.assertEqual(tenant.description, "")
|
||||
self.assertFalse(tenant.enabled)
|
||||
|
||||
@httpretty.activate
|
||||
def test_add_user(self):
|
||||
self.stub_url(httpretty.PUT,
|
||||
['tenants', self.EXTRAS_ID, 'users', 'foo', 'roles',
|
||||
'OS-KSADM', 'barrr'],
|
||||
status=204)
|
||||
|
||||
self.client.tenants.add_user(self.EXTRAS_ID, 'foo', 'barrr')
|
||||
|
||||
@httpretty.activate
|
||||
def test_remove_user(self):
|
||||
self.stub_url(httpretty.DELETE, ['tenants', self.EXTRAS_ID, 'users',
|
||||
'foo', 'roles', 'OS-KSADM', 'barrr'],
|
||||
status=204)
|
||||
|
||||
self.client.tenants.remove_user(self.EXTRAS_ID, 'foo', 'barrr')
|
||||
|
||||
@httpretty.activate
|
||||
def test_tenant_add_user(self):
|
||||
self.stub_url(httpretty.PUT, ['tenants', self.EXTRAS_ID, 'users',
|
||||
'foo', 'roles', 'OS-KSADM', 'barrr'],
|
||||
status=204)
|
||||
|
||||
req_body = {
|
||||
"tenant": {
|
||||
"id": self.EXTRAS_ID,
|
||||
"name": "tenantX",
|
||||
"description": "I changed you!",
|
||||
"enabled": False,
|
||||
},
|
||||
}
|
||||
# make tenant object with manager
|
||||
tenant = self.client.tenants.resource_class(self.client.tenants,
|
||||
req_body['tenant'])
|
||||
tenant.add_user('foo', 'barrr')
|
||||
self.assertIsInstance(tenant, tenants.Tenant)
|
||||
|
||||
@httpretty.activate
|
||||
def test_tenant_remove_user(self):
|
||||
self.stub_url(httpretty.DELETE, ['tenants', self.EXTRAS_ID, 'users',
|
||||
'foo', 'roles', 'OS-KSADM', 'barrr'],
|
||||
status=204)
|
||||
|
||||
req_body = {
|
||||
"tenant": {
|
||||
"id": self.EXTRAS_ID,
|
||||
"name": "tenantX",
|
||||
"description": "I changed you!",
|
||||
"enabled": False,
|
||||
},
|
||||
}
|
||||
|
||||
# make tenant object with manager
|
||||
tenant = self.client.tenants.resource_class(self.client.tenants,
|
||||
req_body['tenant'])
|
||||
tenant.remove_user('foo', 'barrr')
|
||||
self.assertIsInstance(tenant, tenants.Tenant)
|
@ -1,25 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
|
||||
|
||||
class TokenTests(utils.TestCase):
|
||||
@httpretty.activate
|
||||
def test_delete(self):
|
||||
id_ = uuid.uuid4().hex
|
||||
self.stub_url(httpretty.DELETE, ['tokens', id_], status=204)
|
||||
self.client.tokens.delete(id_)
|
@ -1,237 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient.tests.v2_0 import utils
|
||||
from keystoneclient.v2_0 import users
|
||||
|
||||
|
||||
class UserTests(utils.TestCase):
|
||||
def setUp(self):
|
||||
super(UserTests, self).setUp()
|
||||
self.ADMIN_USER_ID = uuid.uuid4().hex
|
||||
self.DEMO_USER_ID = uuid.uuid4().hex
|
||||
self.TEST_USERS = {
|
||||
"users": {
|
||||
"values": [
|
||||
{
|
||||
"email": "None",
|
||||
"enabled": True,
|
||||
"id": self.ADMIN_USER_ID,
|
||||
"name": "admin",
|
||||
},
|
||||
{
|
||||
"email": "None",
|
||||
"enabled": True,
|
||||
"id": self.DEMO_USER_ID,
|
||||
"name": "demo",
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@httpretty.activate
|
||||
def test_create(self):
|
||||
tenant_id = uuid.uuid4().hex
|
||||
user_id = uuid.uuid4().hex
|
||||
req_body = {
|
||||
"user": {
|
||||
"name": "gabriel",
|
||||
"password": "test",
|
||||
"tenantId": tenant_id,
|
||||
"email": "test@example.com",
|
||||
"enabled": True,
|
||||
}
|
||||
}
|
||||
|
||||
resp_body = {
|
||||
"user": {
|
||||
"name": "gabriel",
|
||||
"enabled": True,
|
||||
"tenantId": tenant_id,
|
||||
"id": user_id,
|
||||
"password": "test",
|
||||
"email": "test@example.com",
|
||||
}
|
||||
}
|
||||
|
||||
self.stub_url(httpretty.POST, ['users'], json=resp_body)
|
||||
|
||||
user = self.client.users.create(req_body['user']['name'],
|
||||
req_body['user']['password'],
|
||||
req_body['user']['email'],
|
||||
tenant_id=req_body['user']['tenantId'],
|
||||
enabled=req_body['user']['enabled'])
|
||||
self.assertIsInstance(user, users.User)
|
||||
self.assertEqual(user.id, user_id)
|
||||
self.assertEqual(user.name, "gabriel")
|
||||
self.assertEqual(user.email, "test@example.com")
|
||||
self.assertRequestBodyIs(json=req_body)
|
||||
|
||||
@httpretty.activate
|
||||
def test_create_user_without_email(self):
|
||||
tenant_id = uuid.uuid4().hex
|
||||
req_body = {
|
||||
"user": {
|
||||
"name": "gabriel",
|
||||
"password": "test",
|
||||
"tenantId": tenant_id,
|
||||
"enabled": True,
|
||||
"email": None,
|
||||
}
|
||||
}
|
||||
|
||||
user_id = uuid.uuid4().hex
|
||||
resp_body = {
|
||||
"user": {
|
||||
"name": "gabriel",
|
||||
"enabled": True,
|
||||
"tenantId": tenant_id,
|
||||
"id": user_id,
|
||||
"password": "test",
|
||||
}
|
||||
}
|
||||
|
||||
self.stub_url(httpretty.POST, ['users'], json=resp_body)
|
||||
|
||||
user = self.client.users.create(
|
||||
req_body['user']['name'],
|
||||
req_body['user']['password'],
|
||||
tenant_id=req_body['user']['tenantId'],
|
||||
enabled=req_body['user']['enabled'])
|
||||
self.assertIsInstance(user, users.User)
|
||||
self.assertEqual(user.id, user_id)
|
||||
self.assertEqual(user.name, "gabriel")
|
||||
self.assertRequestBodyIs(json=req_body)
|
||||
|
||||
@httpretty.activate
|
||||
def test_delete(self):
|
||||
self.stub_url(httpretty.DELETE, ['users', self.ADMIN_USER_ID],
|
||||
status=204)
|
||||
self.client.users.delete(self.ADMIN_USER_ID)
|
||||
|
||||
@httpretty.activate
|
||||
def test_get(self):
|
||||
self.stub_url(httpretty.GET, ['users', self.ADMIN_USER_ID],
|
||||
json={'user': self.TEST_USERS['users']['values'][0]})
|
||||
|
||||
u = self.client.users.get(self.ADMIN_USER_ID)
|
||||
self.assertIsInstance(u, users.User)
|
||||
self.assertEqual(u.id, self.ADMIN_USER_ID)
|
||||
self.assertEqual(u.name, 'admin')
|
||||
|
||||
@httpretty.activate
|
||||
def test_list(self):
|
||||
self.stub_url(httpretty.GET, ['users'], json=self.TEST_USERS)
|
||||
|
||||
user_list = self.client.users.list()
|
||||
[self.assertIsInstance(u, users.User) for u in user_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_limit(self):
|
||||
self.stub_url(httpretty.GET, ['users'], json=self.TEST_USERS)
|
||||
|
||||
user_list = self.client.users.list(limit=1)
|
||||
self.assertEqual(httpretty.last_request().querystring,
|
||||
{'limit': ['1']})
|
||||
[self.assertIsInstance(u, users.User) for u in user_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_marker(self):
|
||||
self.stub_url(httpretty.GET, ['users'], json=self.TEST_USERS)
|
||||
|
||||
user_list = self.client.users.list(marker='foo')
|
||||
self.assertDictEqual(httpretty.last_request().querystring,
|
||||
{'marker': ['foo']})
|
||||
[self.assertIsInstance(u, users.User) for u in user_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_limit_marker(self):
|
||||
self.stub_url(httpretty.GET, ['users'], json=self.TEST_USERS)
|
||||
|
||||
user_list = self.client.users.list(limit=1, marker='foo')
|
||||
|
||||
self.assertDictEqual(httpretty.last_request().querystring,
|
||||
{'marker': ['foo'], 'limit': ['1']})
|
||||
[self.assertIsInstance(u, users.User) for u in user_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_update(self):
|
||||
req_1 = {
|
||||
"user": {
|
||||
"id": self.DEMO_USER_ID,
|
||||
"email": "gabriel@example.com",
|
||||
"name": "gabriel",
|
||||
}
|
||||
}
|
||||
req_2 = {
|
||||
"user": {
|
||||
"id": self.DEMO_USER_ID,
|
||||
"password": "swordfish",
|
||||
}
|
||||
}
|
||||
tenant_id = uuid.uuid4().hex
|
||||
req_3 = {
|
||||
"user": {
|
||||
"id": self.DEMO_USER_ID,
|
||||
"tenantId": tenant_id,
|
||||
}
|
||||
}
|
||||
req_4 = {
|
||||
"user": {
|
||||
"id": self.DEMO_USER_ID,
|
||||
"enabled": False,
|
||||
}
|
||||
}
|
||||
|
||||
self.stub_url(httpretty.PUT, ['users', self.DEMO_USER_ID], json=req_1)
|
||||
self.stub_url(httpretty.PUT,
|
||||
['users', self.DEMO_USER_ID, 'OS-KSADM', 'password'],
|
||||
json=req_2)
|
||||
self.stub_url(httpretty.PUT,
|
||||
['users', self.DEMO_USER_ID, 'OS-KSADM', 'tenant'],
|
||||
json=req_3)
|
||||
self.stub_url(httpretty.PUT,
|
||||
['users', self.DEMO_USER_ID, 'OS-KSADM', 'enabled'],
|
||||
json=req_4)
|
||||
|
||||
self.client.users.update(self.DEMO_USER_ID,
|
||||
name='gabriel',
|
||||
email='gabriel@example.com')
|
||||
self.assertRequestBodyIs(json=req_1)
|
||||
self.client.users.update_password(self.DEMO_USER_ID, 'swordfish')
|
||||
self.assertRequestBodyIs(json=req_2)
|
||||
self.client.users.update_tenant(self.DEMO_USER_ID, tenant_id)
|
||||
self.assertRequestBodyIs(json=req_3)
|
||||
self.client.users.update_enabled(self.DEMO_USER_ID, False)
|
||||
self.assertRequestBodyIs(json=req_4)
|
||||
|
||||
@httpretty.activate
|
||||
def test_update_own_password(self):
|
||||
req_body = {
|
||||
'user': {
|
||||
'password': 'ABCD', 'original_password': 'DCBA'
|
||||
}
|
||||
}
|
||||
resp_body = {
|
||||
'access': {}
|
||||
}
|
||||
user_id = uuid.uuid4().hex
|
||||
self.stub_url(httpretty.PATCH, ['OS-KSCRUD', 'users', user_id],
|
||||
json=resp_body)
|
||||
|
||||
self.client.user_id = user_id
|
||||
self.client.users.update_own_password('DCBA', 'ABCD')
|
||||
self.assertRequestBodyIs(json=req_body)
|
@ -1,91 +0,0 @@
|
||||
# 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 httpretty
|
||||
|
||||
from keystoneclient.tests import utils
|
||||
from keystoneclient.v2_0 import client
|
||||
|
||||
|
||||
TestResponse = utils.TestResponse
|
||||
|
||||
|
||||
class UnauthenticatedTestCase(utils.TestCase):
|
||||
"""Class used as base for unauthenticated calls."""
|
||||
|
||||
TEST_ROOT_URL = 'http://127.0.0.1:5000/'
|
||||
TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v2.0')
|
||||
TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/'
|
||||
TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v2.0')
|
||||
|
||||
|
||||
class TestCase(UnauthenticatedTestCase):
|
||||
|
||||
TEST_ADMIN_IDENTITY_ENDPOINT = "http://127.0.0.1:35357/v2.0"
|
||||
|
||||
TEST_SERVICE_CATALOG = [{
|
||||
"endpoints": [{
|
||||
"adminURL": "http://cdn.admin-nets.local:8774/v1.0",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://127.0.0.1:8774/v1.0",
|
||||
"publicURL": "http://cdn.admin-nets.local:8774/v1.0/"
|
||||
}],
|
||||
"type": "nova_compat",
|
||||
"name": "nova_compat"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": "http://nova/novapi/admin",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://nova/novapi/internal",
|
||||
"publicURL": "http://nova/novapi/public"
|
||||
}],
|
||||
"type": "compute",
|
||||
"name": "nova"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": "http://glance/glanceapi/admin",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://glance/glanceapi/internal",
|
||||
"publicURL": "http://glance/glanceapi/public"
|
||||
}],
|
||||
"type": "image",
|
||||
"name": "glance"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": TEST_ADMIN_IDENTITY_ENDPOINT,
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://127.0.0.1:5000/v2.0",
|
||||
"publicURL": "http://127.0.0.1:5000/v2.0"
|
||||
}],
|
||||
"type": "identity",
|
||||
"name": "keystone"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"adminURL": "http://swift/swiftapi/admin",
|
||||
"region": "RegionOne",
|
||||
"internalURL": "http://swift/swiftapi/internal",
|
||||
"publicURL": "http://swift/swiftapi/public"
|
||||
}],
|
||||
"type": "object-store",
|
||||
"name": "swift"
|
||||
}]
|
||||
|
||||
def setUp(self):
|
||||
super(TestCase, self).setUp()
|
||||
self.client = client.Client(username=self.TEST_USER,
|
||||
token=self.TEST_TOKEN,
|
||||
tenant_name=self.TEST_TENANT_NAME,
|
||||
auth_url=self.TEST_URL,
|
||||
endpoint=self.TEST_URL)
|
||||
|
||||
def stub_auth(self, **kwargs):
|
||||
self.stub_url(httpretty.POST, ['tokens'], **kwargs)
|
@ -1,182 +0,0 @@
|
||||
# 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.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from keystoneclient import fixture
|
||||
|
||||
|
||||
def unscoped_token():
|
||||
return fixture.V3Token(user_id='c4da488862bd435c9e6c0275a0d0e49a',
|
||||
user_name='exampleuser',
|
||||
user_domain_id='4e6893b7ba0b4006840c3845660b86ed',
|
||||
user_domain_name='exampledomain',
|
||||
expires='2010-11-01T03:32:15-05:00')
|
||||
|
||||
|
||||
def domain_scoped_token():
|
||||
f = fixture.V3Token(user_id='c4da488862bd435c9e6c0275a0d0e49a',
|
||||
user_name='exampleuser',
|
||||
user_domain_id='4e6893b7ba0b4006840c3845660b86ed',
|
||||
user_domain_name='exampledomain',
|
||||
expires='2010-11-01T03:32:15-05:00',
|
||||
domain_id='8e9283b7ba0b1038840c3842058b86ab',
|
||||
domain_name='anotherdomain')
|
||||
|
||||
f.add_role(id='76e72a', name='admin')
|
||||
f.add_role(id='f4f392', name='member')
|
||||
region = 'RegionOne'
|
||||
|
||||
s = f.add_service('volume')
|
||||
s.add_standard_endpoints(public='http://public.com:8776/v1/None',
|
||||
internal='http://internal.com:8776/v1/None',
|
||||
admin='http://admin.com:8776/v1/None',
|
||||
region=region)
|
||||
|
||||
s = f.add_service('image')
|
||||
s.add_standard_endpoints(public='http://public.com:9292/v1',
|
||||
internal='http://internal:9292/v1',
|
||||
admin='http://admin:9292/v1',
|
||||
region=region)
|
||||
|
||||
s = f.add_service('compute')
|
||||
s.add_standard_endpoints(public='http://public.com:8774/v1.1/None',
|
||||
internal='http://internal:8774/v1.1/None',
|
||||
admin='http://admin:8774/v1.1/None',
|
||||
region=region)
|
||||
|
||||
s = f.add_service('ec2')
|
||||
s.add_standard_endpoints(public='http://public.com:8773/services/Cloud',
|
||||
internal='http://internal:8773/services/Cloud',
|
||||
admin='http://admin:8773/services/Admin',
|
||||
region=region)
|
||||
|
||||
s = f.add_service('identity')
|
||||
s.add_standard_endpoints(public='http://public.com:5000/v3',
|
||||
internal='http://internal:5000/v3',
|
||||
admin='http://admin:35357/v3',
|
||||
region=region)
|
||||
|
||||
return f
|
||||
|
||||
|
||||
def project_scoped_token():
|
||||
f = fixture.V3Token(user_id='c4da488862bd435c9e6c0275a0d0e49a',
|
||||
user_name='exampleuser',
|
||||
user_domain_id='4e6893b7ba0b4006840c3845660b86ed',
|
||||
user_domain_name='exampledomain',
|
||||
expires='2010-11-01T03:32:15-05:00',
|
||||
project_id='225da22d3ce34b15877ea70b2a575f58',
|
||||
project_name='exampleproject',
|
||||
project_domain_id='4e6893b7ba0b4006840c3845660b86ed',
|
||||
project_domain_name='exampledomain')
|
||||
|
||||
f.add_role(id='76e72a', name='admin')
|
||||
f.add_role(id='f4f392', name='member')
|
||||
|
||||
region = 'RegionOne'
|
||||
tenant = '225da22d3ce34b15877ea70b2a575f58'
|
||||
|
||||
s = f.add_service('volume')
|
||||
s.add_standard_endpoints(public='http://public.com:8776/v1/%s' % tenant,
|
||||
internal='http://internal:8776/v1/%s' % tenant,
|
||||
admin='http://admin:8776/v1/%s' % tenant,
|
||||
region=region)
|
||||
|
||||
s = f.add_service('image')
|
||||
s.add_standard_endpoints(public='http://public.com:9292/v1',
|
||||
internal='http://internal:9292/v1',
|
||||
admin='http://admin:9292/v1',
|
||||
region=region)
|
||||
|
||||
s = f.add_service('compute')
|
||||
s.add_standard_endpoints(public='http://public.com:8774/v2/%s' % tenant,
|
||||
internal='http://internal:8774/v2/%s' % tenant,
|
||||
admin='http://admin:8774/v2/%s' % tenant,
|
||||
region=region)
|
||||
|
||||
s = f.add_service('ec2')
|
||||
s.add_standard_endpoints(public='http://public.com:8773/services/Cloud',
|
||||
internal='http://internal:8773/services/Cloud',
|
||||
admin='http://admin:8773/services/Admin',
|
||||
region=region)
|
||||
|
||||
s = f.add_service('identity')
|
||||
s.add_standard_endpoints(public='http://public.com:5000/v3',
|
||||
internal='http://internal:5000/v3',
|
||||
admin='http://admin:35357/v3',
|
||||
region=region)
|
||||
|
||||
return f
|
||||
|
||||
|
||||
AUTH_SUBJECT_TOKEN = '3e2813b7ba0b4006840c3825860b86ed'
|
||||
|
||||
AUTH_RESPONSE_HEADERS = {
|
||||
'X-Subject-Token': AUTH_SUBJECT_TOKEN
|
||||
}
|
||||
|
||||
|
||||
def auth_response_body():
|
||||
f = fixture.V3Token(user_id='567',
|
||||
user_name='test',
|
||||
user_domain_id='1',
|
||||
user_domain_name='aDomain',
|
||||
expires='2010-11-01T03:32:15-05:00',
|
||||
project_domain_id='123',
|
||||
project_domain_name='aDomain',
|
||||
project_id='345',
|
||||
project_name='aTenant')
|
||||
|
||||
f.add_role(id='76e72a', name='admin')
|
||||
f.add_role(id='f4f392', name='member')
|
||||
|
||||
s = f.add_service('compute', name='nova')
|
||||
s.add_standard_endpoints(
|
||||
public='https://compute.north.host/novapi/public',
|
||||
internal='https://compute.north.host/novapi/internal',
|
||||
admin='https://compute.north.host/novapi/admin',
|
||||
region='North')
|
||||
|
||||
s = f.add_service('object-store', name='swift')
|
||||
s.add_standard_endpoints(
|
||||
public='http://swift.north.host/swiftapi/public',
|
||||
internal='http://swift.north.host/swiftapi/internal',
|
||||
admin='http://swift.north.host/swiftapi/admin',
|
||||
region='South')
|
||||
|
||||
s = f.add_service('image', name='glance')
|
||||
s.add_standard_endpoints(
|
||||
public='http://glance.north.host/glanceapi/public',
|
||||
internal='http://glance.north.host/glanceapi/internal',
|
||||
admin='http://glance.north.host/glanceapi/admin',
|
||||
region='North')
|
||||
|
||||
s.add_standard_endpoints(
|
||||
public='http://glance.south.host/glanceapi/public',
|
||||
internal='http://glance.south.host/glanceapi/internal',
|
||||
admin='http://glance.south.host/glanceapi/admin',
|
||||
region='South')
|
||||
|
||||
return f
|
||||
|
||||
|
||||
def trust_token():
|
||||
return fixture.V3Token(user_id='0ca8f6',
|
||||
user_name='exampleuser',
|
||||
user_domain_id='4e6893b7ba0b4006840c3845660b86ed',
|
||||
user_domain_name='exampledomain',
|
||||
expires='2010-11-01T03:32:15-05:00',
|
||||
trust_id='fe0aef',
|
||||
trust_impersonation=False,
|
||||
trustee_user_id='0ca8f6',
|
||||
trustor_user_id='bd263c')
|
@ -1,146 +0,0 @@
|
||||
# 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 datetime
|
||||
|
||||
from keystoneclient import access
|
||||
from keystoneclient.openstack.common import timeutils
|
||||
from keystoneclient.tests.v3 import client_fixtures
|
||||
from keystoneclient.tests.v3 import utils
|
||||
|
||||
|
||||
TOKEN_RESPONSE = utils.TestResponse({
|
||||
"headers": client_fixtures.AUTH_RESPONSE_HEADERS
|
||||
})
|
||||
UNSCOPED_TOKEN = client_fixtures.unscoped_token()
|
||||
DOMAIN_SCOPED_TOKEN = client_fixtures.domain_scoped_token()
|
||||
PROJECT_SCOPED_TOKEN = client_fixtures.project_scoped_token()
|
||||
|
||||
|
||||
class AccessInfoTest(utils.TestCase):
|
||||
def test_building_unscoped_accessinfo(self):
|
||||
auth_ref = access.AccessInfo.factory(resp=TOKEN_RESPONSE,
|
||||
body=UNSCOPED_TOKEN)
|
||||
|
||||
self.assertTrue(auth_ref)
|
||||
self.assertIn('methods', auth_ref)
|
||||
self.assertNotIn('catalog', auth_ref)
|
||||
|
||||
self.assertEqual(auth_ref.auth_token,
|
||||
'3e2813b7ba0b4006840c3825860b86ed')
|
||||
self.assertEqual(auth_ref.username, 'exampleuser')
|
||||
self.assertEqual(auth_ref.user_id, 'c4da488862bd435c9e6c0275a0d0e49a')
|
||||
|
||||
self.assertEqual(auth_ref.role_names, [])
|
||||
|
||||
self.assertIsNone(auth_ref.project_name)
|
||||
self.assertIsNone(auth_ref.project_id)
|
||||
|
||||
self.assertIsNone(auth_ref.auth_url)
|
||||
self.assertIsNone(auth_ref.management_url)
|
||||
|
||||
self.assertFalse(auth_ref.domain_scoped)
|
||||
self.assertFalse(auth_ref.project_scoped)
|
||||
|
||||
self.assertEqual(auth_ref.user_domain_id,
|
||||
'4e6893b7ba0b4006840c3845660b86ed')
|
||||
self.assertEqual(auth_ref.user_domain_name, 'exampledomain')
|
||||
|
||||
self.assertIsNone(auth_ref.project_domain_id)
|
||||
self.assertIsNone(auth_ref.project_domain_name)
|
||||
|
||||
self.assertEqual(auth_ref.expires, timeutils.parse_isotime(
|
||||
UNSCOPED_TOKEN['token']['expires_at']))
|
||||
|
||||
def test_will_expire_soon(self):
|
||||
expires = timeutils.utcnow() + datetime.timedelta(minutes=5)
|
||||
UNSCOPED_TOKEN['token']['expires_at'] = expires.isoformat()
|
||||
auth_ref = access.AccessInfo.factory(resp=TOKEN_RESPONSE,
|
||||
body=UNSCOPED_TOKEN)
|
||||
self.assertFalse(auth_ref.will_expire_soon(stale_duration=120))
|
||||
self.assertTrue(auth_ref.will_expire_soon(stale_duration=300))
|
||||
self.assertFalse(auth_ref.will_expire_soon())
|
||||
|
||||
def test_building_domain_scoped_accessinfo(self):
|
||||
auth_ref = access.AccessInfo.factory(resp=TOKEN_RESPONSE,
|
||||
body=DOMAIN_SCOPED_TOKEN)
|
||||
|
||||
self.assertTrue(auth_ref)
|
||||
self.assertIn('methods', auth_ref)
|
||||
self.assertIn('catalog', auth_ref)
|
||||
self.assertTrue(auth_ref['catalog'])
|
||||
|
||||
self.assertEqual(auth_ref.auth_token,
|
||||
'3e2813b7ba0b4006840c3825860b86ed')
|
||||
self.assertEqual(auth_ref.username, 'exampleuser')
|
||||
self.assertEqual(auth_ref.user_id, 'c4da488862bd435c9e6c0275a0d0e49a')
|
||||
|
||||
self.assertEqual(auth_ref.role_names, ['admin', 'member'])
|
||||
|
||||
self.assertEqual(auth_ref.domain_name, 'anotherdomain')
|
||||
self.assertEqual(auth_ref.domain_id,
|
||||
'8e9283b7ba0b1038840c3842058b86ab')
|
||||
|
||||
self.assertIsNone(auth_ref.project_name)
|
||||
self.assertIsNone(auth_ref.project_id)
|
||||
|
||||
self.assertEqual(auth_ref.user_domain_id,
|
||||
'4e6893b7ba0b4006840c3845660b86ed')
|
||||
self.assertEqual(auth_ref.user_domain_name, 'exampledomain')
|
||||
|
||||
self.assertIsNone(auth_ref.project_domain_id)
|
||||
self.assertIsNone(auth_ref.project_domain_name)
|
||||
|
||||
self.assertTrue(auth_ref.domain_scoped)
|
||||
self.assertFalse(auth_ref.project_scoped)
|
||||
|
||||
def test_building_project_scoped_accessinfo(self):
|
||||
auth_ref = access.AccessInfo.factory(resp=TOKEN_RESPONSE,
|
||||
body=PROJECT_SCOPED_TOKEN)
|
||||
|
||||
self.assertTrue(auth_ref)
|
||||
self.assertIn('methods', auth_ref)
|
||||
self.assertIn('catalog', auth_ref)
|
||||
self.assertTrue(auth_ref['catalog'])
|
||||
|
||||
self.assertEqual(auth_ref.auth_token,
|
||||
'3e2813b7ba0b4006840c3825860b86ed')
|
||||
self.assertEqual(auth_ref.username, 'exampleuser')
|
||||
self.assertEqual(auth_ref.user_id, 'c4da488862bd435c9e6c0275a0d0e49a')
|
||||
|
||||
self.assertEqual(auth_ref.role_names, ['admin', 'member'])
|
||||
|
||||
self.assertIsNone(auth_ref.domain_name)
|
||||
self.assertIsNone(auth_ref.domain_id)
|
||||
|
||||
self.assertEqual(auth_ref.project_name, 'exampleproject')
|
||||
self.assertEqual(auth_ref.project_id,
|
||||
'225da22d3ce34b15877ea70b2a575f58')
|
||||
|
||||
self.assertEqual(auth_ref.tenant_name, auth_ref.project_name)
|
||||
self.assertEqual(auth_ref.tenant_id, auth_ref.project_id)
|
||||
|
||||
self.assertEqual(auth_ref.auth_url,
|
||||
('http://public.com:5000/v3',))
|
||||
self.assertEqual(auth_ref.management_url,
|
||||
('http://admin:35357/v3',))
|
||||
|
||||
self.assertEqual(auth_ref.project_domain_id,
|
||||
'4e6893b7ba0b4006840c3845660b86ed')
|
||||
self.assertEqual(auth_ref.project_domain_name, 'exampledomain')
|
||||
|
||||
self.assertEqual(auth_ref.user_domain_id,
|
||||
'4e6893b7ba0b4006840c3845660b86ed')
|
||||
self.assertEqual(auth_ref.user_domain_name, 'exampledomain')
|
||||
|
||||
self.assertFalse(auth_ref.domain_scoped)
|
||||
self.assertTrue(auth_ref.project_scoped)
|
@ -1,369 +0,0 @@
|
||||
# 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 httpretty
|
||||
import six
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.openstack.common import jsonutils
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import client
|
||||
|
||||
|
||||
class AuthenticateAgainstKeystoneTests(utils.TestCase):
|
||||
def setUp(self):
|
||||
super(AuthenticateAgainstKeystoneTests, self).setUp()
|
||||
self.TEST_RESPONSE_DICT = {
|
||||
"token": {
|
||||
"methods": [
|
||||
"token",
|
||||
"password"
|
||||
],
|
||||
|
||||
"expires_at": "2020-01-01T00:00:10.000123Z",
|
||||
"project": {
|
||||
"domain": {
|
||||
"id": self.TEST_DOMAIN_ID,
|
||||
"name": self.TEST_DOMAIN_NAME
|
||||
},
|
||||
"id": self.TEST_TENANT_ID,
|
||||
"name": self.TEST_TENANT_NAME
|
||||
},
|
||||
"user": {
|
||||
"domain": {
|
||||
"id": self.TEST_DOMAIN_ID,
|
||||
"name": self.TEST_DOMAIN_NAME
|
||||
},
|
||||
"id": self.TEST_USER,
|
||||
"name": self.TEST_USER
|
||||
},
|
||||
"issued_at": "2013-05-29T16:55:21.468960Z",
|
||||
"catalog": self.TEST_SERVICE_CATALOG
|
||||
},
|
||||
}
|
||||
self.TEST_REQUEST_BODY = {
|
||||
"auth": {
|
||||
"identity": {
|
||||
"methods": ["password"],
|
||||
"password": {
|
||||
"user": {
|
||||
"domain": {
|
||||
"name": self.TEST_DOMAIN_NAME
|
||||
},
|
||||
"name": self.TEST_USER,
|
||||
"password": self.TEST_TOKEN
|
||||
}
|
||||
}
|
||||
},
|
||||
"scope": {
|
||||
"project": {
|
||||
"id": self.TEST_TENANT_ID
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
self.TEST_REQUEST_HEADERS = {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': 'python-keystoneclient'
|
||||
}
|
||||
self.TEST_RESPONSE_HEADERS = {
|
||||
'X-Subject-Token': self.TEST_TOKEN
|
||||
}
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success(self):
|
||||
TEST_TOKEN = "abcdef"
|
||||
ident = self.TEST_REQUEST_BODY['auth']['identity']
|
||||
del ident['password']['user']['domain']
|
||||
del ident['password']['user']['name']
|
||||
ident['password']['user']['id'] = self.TEST_USER
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT, subject_token=TEST_TOKEN)
|
||||
|
||||
cs = client.Client(user_id=self.TEST_USER,
|
||||
password=self.TEST_TOKEN,
|
||||
project_id=self.TEST_TENANT_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertEqual(cs.auth_token, TEST_TOKEN)
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_failure(self):
|
||||
ident = self.TEST_REQUEST_BODY['auth']['identity']
|
||||
ident['password']['user']['password'] = 'bad_key'
|
||||
error = {"unauthorized": {"message": "Unauthorized",
|
||||
"code": "401"}}
|
||||
|
||||
self.stub_auth(status=401, json=error)
|
||||
|
||||
# Workaround for issue with assertRaises on python2.6
|
||||
# where with assertRaises(exceptions.Unauthorized): doesn't work
|
||||
# right
|
||||
def client_create_wrapper():
|
||||
client.Client(user_domain_name=self.TEST_DOMAIN_NAME,
|
||||
username=self.TEST_USER,
|
||||
password="bad_key",
|
||||
project_id=self.TEST_TENANT_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
|
||||
self.assertRaises(exceptions.Unauthorized, client_create_wrapper)
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_auth_redirect(self):
|
||||
self.stub_auth(status=305, body='Use proxy',
|
||||
location=self.TEST_ADMIN_URL + '/auth/tokens')
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT,
|
||||
base_url=self.TEST_ADMIN_URL)
|
||||
|
||||
cs = client.Client(user_domain_name=self.TEST_DOMAIN_NAME,
|
||||
username=self.TEST_USER,
|
||||
password=self.TEST_TOKEN,
|
||||
project_id=self.TEST_TENANT_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
|
||||
self.assertEqual(cs.management_url,
|
||||
self.TEST_RESPONSE_DICT["token"]["catalog"][3]
|
||||
['endpoints'][2]["url"])
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_HEADERS["X-Subject-Token"])
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_domain_username_password_scoped(self):
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client(user_domain_name=self.TEST_DOMAIN_NAME,
|
||||
username=self.TEST_USER,
|
||||
password=self.TEST_TOKEN,
|
||||
project_id=self.TEST_TENANT_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertEqual(cs.management_url,
|
||||
self.TEST_RESPONSE_DICT["token"]["catalog"][3]
|
||||
['endpoints'][2]["url"])
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_HEADERS["X-Subject-Token"])
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_userid_password_domain_scoped(self):
|
||||
ident = self.TEST_REQUEST_BODY['auth']['identity']
|
||||
del ident['password']['user']['domain']
|
||||
del ident['password']['user']['name']
|
||||
ident['password']['user']['id'] = self.TEST_USER
|
||||
|
||||
scope = self.TEST_REQUEST_BODY['auth']['scope']
|
||||
del scope['project']
|
||||
scope['domain'] = {}
|
||||
scope['domain']['id'] = self.TEST_DOMAIN_ID
|
||||
|
||||
token = self.TEST_RESPONSE_DICT['token']
|
||||
del token['project']
|
||||
token['domain'] = {}
|
||||
token['domain']['id'] = self.TEST_DOMAIN_ID
|
||||
token['domain']['name'] = self.TEST_DOMAIN_NAME
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client(user_id=self.TEST_USER,
|
||||
password=self.TEST_TOKEN,
|
||||
domain_id=self.TEST_DOMAIN_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertEqual(cs.auth_domain_id,
|
||||
self.TEST_DOMAIN_ID)
|
||||
self.assertEqual(cs.management_url,
|
||||
self.TEST_RESPONSE_DICT["token"]["catalog"][3]
|
||||
['endpoints'][2]["url"])
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_HEADERS["X-Subject-Token"])
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_userid_password_project_scoped(self):
|
||||
ident = self.TEST_REQUEST_BODY['auth']['identity']
|
||||
del ident['password']['user']['domain']
|
||||
del ident['password']['user']['name']
|
||||
ident['password']['user']['id'] = self.TEST_USER
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client(user_id=self.TEST_USER,
|
||||
password=self.TEST_TOKEN,
|
||||
project_id=self.TEST_TENANT_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertEqual(cs.auth_tenant_id,
|
||||
self.TEST_TENANT_ID)
|
||||
self.assertEqual(cs.management_url,
|
||||
self.TEST_RESPONSE_DICT["token"]["catalog"][3]
|
||||
['endpoints'][2]["url"])
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_HEADERS["X-Subject-Token"])
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_password_unscoped(self):
|
||||
del self.TEST_RESPONSE_DICT['token']['catalog']
|
||||
del self.TEST_REQUEST_BODY['auth']['scope']
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client(user_domain_name=self.TEST_DOMAIN_NAME,
|
||||
username=self.TEST_USER,
|
||||
password=self.TEST_TOKEN,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_HEADERS["X-Subject-Token"])
|
||||
self.assertFalse('catalog' in cs.service_catalog.catalog)
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_auth_url_token_authentication(self):
|
||||
fake_token = 'fake_token'
|
||||
fake_url = '/fake-url'
|
||||
fake_resp = {'result': True}
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
self.stub_url('GET', [fake_url], json=fake_resp,
|
||||
base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT)
|
||||
|
||||
cl = client.Client(auth_url=self.TEST_URL,
|
||||
token=fake_token)
|
||||
body = httpretty.last_request().body
|
||||
if six.PY3:
|
||||
body = body.decode('utf-8')
|
||||
body = jsonutils.loads(body)
|
||||
self.assertEqual(body['auth']['identity']['token']['id'], fake_token)
|
||||
|
||||
resp, body = cl.get(fake_url)
|
||||
self.assertEqual(fake_resp, body)
|
||||
|
||||
self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
|
||||
self.TEST_TOKEN)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_token_domain_scoped(self):
|
||||
ident = self.TEST_REQUEST_BODY['auth']['identity']
|
||||
del ident['password']
|
||||
ident['methods'] = ['token']
|
||||
ident['token'] = {}
|
||||
ident['token']['id'] = self.TEST_TOKEN
|
||||
|
||||
scope = self.TEST_REQUEST_BODY['auth']['scope']
|
||||
del scope['project']
|
||||
scope['domain'] = {}
|
||||
scope['domain']['id'] = self.TEST_DOMAIN_ID
|
||||
|
||||
token = self.TEST_RESPONSE_DICT['token']
|
||||
del token['project']
|
||||
token['domain'] = {}
|
||||
token['domain']['id'] = self.TEST_DOMAIN_ID
|
||||
token['domain']['name'] = self.TEST_DOMAIN_NAME
|
||||
|
||||
self.TEST_REQUEST_HEADERS['X-Auth-Token'] = self.TEST_TOKEN
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client(token=self.TEST_TOKEN,
|
||||
domain_id=self.TEST_DOMAIN_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertEqual(cs.auth_domain_id,
|
||||
self.TEST_DOMAIN_ID)
|
||||
self.assertEqual(cs.management_url,
|
||||
self.TEST_RESPONSE_DICT["token"]["catalog"][3]
|
||||
['endpoints'][2]["url"])
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_HEADERS["X-Subject-Token"])
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_token_project_scoped(self):
|
||||
ident = self.TEST_REQUEST_BODY['auth']['identity']
|
||||
del ident['password']
|
||||
ident['methods'] = ['token']
|
||||
ident['token'] = {}
|
||||
ident['token']['id'] = self.TEST_TOKEN
|
||||
self.TEST_REQUEST_HEADERS['X-Auth-Token'] = self.TEST_TOKEN
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client(token=self.TEST_TOKEN,
|
||||
project_id=self.TEST_TENANT_ID,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertEqual(cs.auth_tenant_id,
|
||||
self.TEST_TENANT_ID)
|
||||
self.assertEqual(cs.management_url,
|
||||
self.TEST_RESPONSE_DICT["token"]["catalog"][3]
|
||||
['endpoints'][2]["url"])
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_HEADERS["X-Subject-Token"])
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_authenticate_success_token_unscoped(self):
|
||||
ident = self.TEST_REQUEST_BODY['auth']['identity']
|
||||
del ident['password']
|
||||
ident['methods'] = ['token']
|
||||
ident['token'] = {}
|
||||
ident['token']['id'] = self.TEST_TOKEN
|
||||
del self.TEST_REQUEST_BODY['auth']['scope']
|
||||
del self.TEST_RESPONSE_DICT['token']['catalog']
|
||||
self.TEST_REQUEST_HEADERS['X-Auth-Token'] = self.TEST_TOKEN
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
|
||||
cs = client.Client(token=self.TEST_TOKEN,
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertEqual(cs.auth_token,
|
||||
self.TEST_RESPONSE_HEADERS["X-Subject-Token"])
|
||||
self.assertFalse('catalog' in cs.service_catalog.catalog)
|
||||
self.assertRequestBodyIs(json=self.TEST_REQUEST_BODY)
|
||||
|
||||
@httpretty.activate
|
||||
def test_allow_override_of_auth_token(self):
|
||||
fake_url = '/fake-url'
|
||||
fake_token = 'fake_token'
|
||||
fake_resp = {'result': True}
|
||||
|
||||
self.stub_auth(json=self.TEST_RESPONSE_DICT)
|
||||
self.stub_url('GET', [fake_url], json=fake_resp,
|
||||
base_url=self.TEST_ADMIN_IDENTITY_ENDPOINT)
|
||||
|
||||
cl = client.Client(username='exampleuser',
|
||||
password='password',
|
||||
tenant_name='exampleproject',
|
||||
auth_url=self.TEST_URL)
|
||||
|
||||
self.assertEqual(cl.auth_token, self.TEST_TOKEN)
|
||||
|
||||
# the token returned from the authentication will be used
|
||||
resp, body = cl.get(fake_url)
|
||||
self.assertEqual(fake_resp, body)
|
||||
|
||||
self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
|
||||
self.TEST_TOKEN)
|
||||
|
||||
# then override that token and the new token shall be used
|
||||
cl.auth_token = fake_token
|
||||
|
||||
resp, body = cl.get(fake_url)
|
||||
self.assertEqual(fake_resp, body)
|
||||
|
||||
self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
|
||||
fake_token)
|
||||
|
||||
# if we clear that overridden token then we fall back to the original
|
||||
del cl.auth_token
|
||||
|
||||
resp, body = cl.get(fake_url)
|
||||
self.assertEqual(fake_resp, body)
|
||||
|
||||
self.assertEqual(httpretty.last_request().headers.get('X-Auth-Token'),
|
||||
self.TEST_TOKEN)
|
@ -1,207 +0,0 @@
|
||||
# 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 copy
|
||||
import json
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.tests.v3 import client_fixtures
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import client
|
||||
|
||||
|
||||
class KeystoneClientTest(utils.TestCase):
|
||||
|
||||
@httpretty.activate
|
||||
def test_unscoped_init(self):
|
||||
self.stub_auth(json=client_fixtures.unscoped_token())
|
||||
|
||||
c = client.Client(user_domain_name='exampledomain',
|
||||
username='exampleuser',
|
||||
password='password',
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertIsNotNone(c.auth_ref)
|
||||
self.assertFalse(c.auth_ref.domain_scoped)
|
||||
self.assertFalse(c.auth_ref.project_scoped)
|
||||
self.assertEqual(c.auth_user_id,
|
||||
'c4da488862bd435c9e6c0275a0d0e49a')
|
||||
|
||||
@httpretty.activate
|
||||
def test_domain_scoped_init(self):
|
||||
self.stub_auth(json=client_fixtures.domain_scoped_token())
|
||||
|
||||
c = client.Client(user_id='c4da488862bd435c9e6c0275a0d0e49a',
|
||||
password='password',
|
||||
domain_name='exampledomain',
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertIsNotNone(c.auth_ref)
|
||||
self.assertTrue(c.auth_ref.domain_scoped)
|
||||
self.assertFalse(c.auth_ref.project_scoped)
|
||||
self.assertEqual(c.auth_user_id,
|
||||
'c4da488862bd435c9e6c0275a0d0e49a')
|
||||
self.assertEqual(c.auth_domain_id,
|
||||
'8e9283b7ba0b1038840c3842058b86ab')
|
||||
|
||||
@httpretty.activate
|
||||
def test_project_scoped_init(self):
|
||||
self.stub_auth(json=client_fixtures.project_scoped_token()),
|
||||
|
||||
c = client.Client(user_id='c4da488862bd435c9e6c0275a0d0e49a',
|
||||
password='password',
|
||||
user_domain_name='exampledomain',
|
||||
project_name='exampleproject',
|
||||
auth_url=self.TEST_URL)
|
||||
self.assertIsNotNone(c.auth_ref)
|
||||
self.assertFalse(c.auth_ref.domain_scoped)
|
||||
self.assertTrue(c.auth_ref.project_scoped)
|
||||
self.assertEqual(c.auth_user_id,
|
||||
'c4da488862bd435c9e6c0275a0d0e49a')
|
||||
self.assertEqual(c.auth_tenant_id,
|
||||
'225da22d3ce34b15877ea70b2a575f58')
|
||||
|
||||
@httpretty.activate
|
||||
def test_auth_ref_load(self):
|
||||
self.stub_auth(json=client_fixtures.project_scoped_token())
|
||||
|
||||
c = client.Client(user_id='c4da488862bd435c9e6c0275a0d0e49a',
|
||||
password='password',
|
||||
project_id='225da22d3ce34b15877ea70b2a575f58',
|
||||
auth_url=self.TEST_URL)
|
||||
cache = json.dumps(c.auth_ref)
|
||||
new_client = client.Client(auth_ref=json.loads(cache))
|
||||
self.assertIsNotNone(new_client.auth_ref)
|
||||
self.assertFalse(new_client.auth_ref.domain_scoped)
|
||||
self.assertTrue(new_client.auth_ref.project_scoped)
|
||||
self.assertEqual(new_client.username, 'exampleuser')
|
||||
self.assertIsNone(new_client.password)
|
||||
self.assertEqual(new_client.management_url,
|
||||
'http://admin:35357/v3')
|
||||
|
||||
@httpretty.activate
|
||||
def test_auth_ref_load_with_overridden_arguments(self):
|
||||
new_auth_url = 'https://newkeystone.com/v3'
|
||||
|
||||
self.stub_auth(json=client_fixtures.project_scoped_token())
|
||||
self.stub_auth(json=client_fixtures.project_scoped_token(),
|
||||
base_url=new_auth_url)
|
||||
|
||||
c = client.Client(user_id='c4da488862bd435c9e6c0275a0d0e49a',
|
||||
password='password',
|
||||
project_id='225da22d3ce34b15877ea70b2a575f58',
|
||||
auth_url=self.TEST_URL)
|
||||
cache = json.dumps(c.auth_ref)
|
||||
new_client = client.Client(auth_ref=json.loads(cache),
|
||||
auth_url=new_auth_url)
|
||||
self.assertIsNotNone(new_client.auth_ref)
|
||||
self.assertFalse(new_client.auth_ref.domain_scoped)
|
||||
self.assertTrue(new_client.auth_ref.project_scoped)
|
||||
self.assertEqual(new_client.auth_url, new_auth_url)
|
||||
self.assertEqual(new_client.username, 'exampleuser')
|
||||
self.assertIsNone(new_client.password)
|
||||
self.assertEqual(new_client.management_url,
|
||||
'http://admin:35357/v3')
|
||||
|
||||
@httpretty.activate
|
||||
def test_trust_init(self):
|
||||
self.stub_auth(json=client_fixtures.trust_token())
|
||||
|
||||
c = client.Client(user_domain_name='exampledomain',
|
||||
username='exampleuser',
|
||||
password='password',
|
||||
auth_url=self.TEST_URL,
|
||||
trust_id='fe0aef')
|
||||
self.assertIsNotNone(c.auth_ref)
|
||||
self.assertFalse(c.auth_ref.domain_scoped)
|
||||
self.assertFalse(c.auth_ref.project_scoped)
|
||||
self.assertEqual(c.auth_ref.trust_id, 'fe0aef')
|
||||
self.assertTrue(c.auth_ref.trust_scoped)
|
||||
self.assertEqual(c.auth_user_id, '0ca8f6')
|
||||
|
||||
def test_init_err_no_auth_url(self):
|
||||
self.assertRaises(exceptions.AuthorizationFailure,
|
||||
client.Client,
|
||||
username='exampleuser',
|
||||
password='password')
|
||||
|
||||
def _management_url_is_updated(self, fixture, **kwargs):
|
||||
second = copy.deepcopy(fixture)
|
||||
first_url = 'http://admin:35357/v3'
|
||||
second_url = "http://secondurl:%d/v3'"
|
||||
|
||||
for entry in second['token']['catalog']:
|
||||
if entry['type'] == 'identity':
|
||||
entry['endpoints'] = [{
|
||||
'url': second_url % 5000,
|
||||
'region': 'RegionOne',
|
||||
'interface': 'public'
|
||||
}, {
|
||||
'url': second_url % 5000,
|
||||
'region': 'RegionOne',
|
||||
'interface': 'internal'
|
||||
}, {
|
||||
'url': second_url % 35357,
|
||||
'region': 'RegionOne',
|
||||
'interface': 'admin'
|
||||
}]
|
||||
|
||||
self.stub_auth(json=fixture)
|
||||
cl = client.Client(username='exampleuser',
|
||||
password='password',
|
||||
auth_url=self.TEST_URL,
|
||||
**kwargs)
|
||||
|
||||
self.assertEqual(cl.management_url, first_url)
|
||||
|
||||
self.stub_auth(json=second)
|
||||
cl.authenticate()
|
||||
self.assertEqual(cl.management_url, second_url % 35357)
|
||||
|
||||
@httpretty.activate
|
||||
def test_management_url_is_updated_with_project(self):
|
||||
self._management_url_is_updated(client_fixtures.project_scoped_token(),
|
||||
project_name='exampleproject')
|
||||
|
||||
@httpretty.activate
|
||||
def test_management_url_is_updated_with_domain(self):
|
||||
self._management_url_is_updated(client_fixtures.domain_scoped_token(),
|
||||
domain_name='exampledomain')
|
||||
|
||||
@httpretty.activate
|
||||
def test_client_with_region_name_passes_to_service_catalog(self):
|
||||
# NOTE(jamielennox): this is deprecated behaviour that should be
|
||||
# removed ASAP, however must remain compatible.
|
||||
|
||||
self.stub_auth(json=client_fixtures.auth_response_body())
|
||||
|
||||
cl = client.Client(username='exampleuser',
|
||||
password='password',
|
||||
tenant_name='exampleproject',
|
||||
auth_url=self.TEST_URL,
|
||||
region_name='North')
|
||||
self.assertEqual(cl.service_catalog.url_for(service_type='image'),
|
||||
'http://glance.north.host/glanceapi/public')
|
||||
|
||||
cl = client.Client(username='exampleuser',
|
||||
password='password',
|
||||
tenant_name='exampleproject',
|
||||
auth_url=self.TEST_URL,
|
||||
region_name='South')
|
||||
self.assertEqual(cl.service_catalog.url_for(service_type='image'),
|
||||
'http://glance.south.host/glanceapi/public')
|
||||
|
||||
def test_client_without_auth_params(self):
|
||||
self.assertRaises(exceptions.AuthorizationFailure,
|
||||
client.Client,
|
||||
project_name='exampleproject',
|
||||
auth_url=self.TEST_URL)
|
@ -1,53 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import credentials
|
||||
|
||||
|
||||
class CredentialTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(CredentialTests, self).setUp()
|
||||
self.key = 'credential'
|
||||
self.collection_key = 'credentials'
|
||||
self.model = credentials.Credential
|
||||
self.manager = self.client.credentials
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs = super(CredentialTests, self).new_ref(**kwargs)
|
||||
kwargs.setdefault('blob', uuid.uuid4().hex)
|
||||
kwargs.setdefault('project_id', uuid.uuid4().hex)
|
||||
kwargs.setdefault('type', uuid.uuid4().hex)
|
||||
kwargs.setdefault('user_id', uuid.uuid4().hex)
|
||||
return kwargs
|
||||
|
||||
@staticmethod
|
||||
def _ref_data_not_blob(ref):
|
||||
ret_ref = ref.copy()
|
||||
ret_ref['data'] = ref['blob']
|
||||
del ret_ref['blob']
|
||||
return ret_ref
|
||||
|
||||
def test_create_data_not_blob(self):
|
||||
# Test create operation with previous, deprecated "data" argument,
|
||||
# which should be translated into "blob" at the API call level
|
||||
req_ref = self.new_ref()
|
||||
api_ref = self._ref_data_not_blob(req_ref)
|
||||
self.test_create(api_ref, req_ref)
|
||||
|
||||
def test_update_data_not_blob(self):
|
||||
# Likewise test update operation with data instead of blob argument
|
||||
req_ref = self.new_ref()
|
||||
api_ref = self._ref_data_not_blob(req_ref)
|
||||
self.test_update(api_ref, req_ref)
|
@ -1,85 +0,0 @@
|
||||
# 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 json
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient.generic import client
|
||||
from keystoneclient.tests.v3 import utils
|
||||
|
||||
|
||||
class DiscoverKeystoneTests(utils.UnauthenticatedTestCase):
|
||||
def setUp(self):
|
||||
super(DiscoverKeystoneTests, self).setUp()
|
||||
self.TEST_RESPONSE_DICT = {
|
||||
"versions": {
|
||||
"values": [{"id": "v3.0",
|
||||
"status": "beta",
|
||||
"updated": "2013-03-06T00:00:00Z",
|
||||
"links": [
|
||||
{"rel": "self",
|
||||
"href": "http://127.0.0.1:5000/v3.0/", },
|
||||
{"rel": "describedby",
|
||||
"type": "text/html",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/3/"
|
||||
"content/", },
|
||||
{"rel": "describedby",
|
||||
"type": "application/pdf",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/3/"
|
||||
"identity-dev-guide-3.pdf", },
|
||||
]},
|
||||
{"id": "v2.0",
|
||||
"status": "beta",
|
||||
"updated": "2013-03-06T00:00:00Z",
|
||||
"links": [
|
||||
{"rel": "self",
|
||||
"href": "http://127.0.0.1:5000/v2.0/", },
|
||||
{"rel": "describedby",
|
||||
"type": "text/html",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/2.0/"
|
||||
"content/", },
|
||||
{"rel": "describedby",
|
||||
"type": "application/pdf",
|
||||
"href": "http://docs.openstack.org/api/"
|
||||
"openstack-identity-service/2.0/"
|
||||
"identity-dev-guide-2.0.pdf", }
|
||||
]}],
|
||||
},
|
||||
}
|
||||
self.TEST_REQUEST_HEADERS = {
|
||||
'User-Agent': 'python-keystoneclient',
|
||||
'Accept': 'application/json',
|
||||
}
|
||||
|
||||
@httpretty.activate
|
||||
def test_get_version_local(self):
|
||||
httpretty.register_uri(httpretty.GET, "http://localhost:35357/",
|
||||
status=300,
|
||||
body=json.dumps(self.TEST_RESPONSE_DICT))
|
||||
|
||||
cs = client.Client()
|
||||
versions = cs.discover()
|
||||
self.assertIsInstance(versions, dict)
|
||||
self.assertIn('message', versions)
|
||||
self.assertIn('v3.0', versions)
|
||||
self.assertEqual(
|
||||
versions['v3.0']['url'],
|
||||
self.TEST_RESPONSE_DICT['versions']['values'][0]['links'][0]
|
||||
['href'])
|
||||
self.assertEqual(
|
||||
versions['v2.0']['url'],
|
||||
self.TEST_RESPONSE_DICT['versions']['values'][1]['links'][0]
|
||||
['href'])
|
@ -1,43 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import domains
|
||||
|
||||
|
||||
class DomainTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(DomainTests, self).setUp()
|
||||
self.key = 'domain'
|
||||
self.collection_key = 'domains'
|
||||
self.model = domains.Domain
|
||||
self.manager = self.client.domains
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs = super(DomainTests, self).new_ref(**kwargs)
|
||||
kwargs.setdefault('enabled', True)
|
||||
kwargs.setdefault('name', uuid.uuid4().hex)
|
||||
return kwargs
|
||||
|
||||
def test_list_filter_name(self):
|
||||
super(DomainTests, self).test_list(name='adomain123')
|
||||
|
||||
def test_list_filter_enabled(self):
|
||||
super(DomainTests, self).test_list(enabled=True)
|
||||
|
||||
def test_list_filter_disabled(self):
|
||||
# False is converted to '0' ref bug #1267530
|
||||
expected_query = {'enabled': '0'}
|
||||
super(DomainTests, self).test_list(expected_query=expected_query,
|
||||
enabled=False)
|
@ -1,153 +0,0 @@
|
||||
# Copyright 2014 OpenStack Foundation
|
||||
#
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient.tests.v3 import utils
|
||||
|
||||
|
||||
class EndpointFilterTests(utils.TestCase):
|
||||
"""Test project-endpoint associations (a.k.a. EndpointFilter Extension).
|
||||
|
||||
Endpoint filter provides associations between service endpoints and
|
||||
projects. These assciations are then used to create ad-hoc catalogs for
|
||||
each project-scoped token request.
|
||||
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(EndpointFilterTests, self).setUp()
|
||||
self.manager = self.client.endpoint_filter
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
# copied from CrudTests as we need to create endpoint and project
|
||||
# refs for our tests. EndpointFilter is not exactly CRUD API.
|
||||
kwargs.setdefault('id', uuid.uuid4().hex)
|
||||
kwargs.setdefault('enabled', True)
|
||||
return kwargs
|
||||
|
||||
def new_endpoint_ref(self, **kwargs):
|
||||
# copied from EndpointTests as we need endpoint refs for our tests
|
||||
kwargs = self.new_ref(**kwargs)
|
||||
kwargs.setdefault('interface', 'public')
|
||||
kwargs.setdefault('region', uuid.uuid4().hex)
|
||||
kwargs.setdefault('service_id', uuid.uuid4().hex)
|
||||
kwargs.setdefault('url', uuid.uuid4().hex)
|
||||
return kwargs
|
||||
|
||||
def new_project_ref(self, **kwargs):
|
||||
# copied from ProjectTests as we need project refs for our tests
|
||||
kwargs = self.new_ref(**kwargs)
|
||||
kwargs.setdefault('domain_id', uuid.uuid4().hex)
|
||||
kwargs.setdefault('name', uuid.uuid4().hex)
|
||||
return kwargs
|
||||
|
||||
@httpretty.activate
|
||||
def test_add_endpoint_to_project_via_id(self):
|
||||
endpoint_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
|
||||
self.stub_url(httpretty.PUT,
|
||||
[self.manager.OS_EP_FILTER_EXT, 'projects', project_id,
|
||||
'endpoints', endpoint_id],
|
||||
status=201)
|
||||
|
||||
self.manager.add_endpoint_to_project(project=project_id,
|
||||
endpoint=endpoint_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_add_endpoint_to_project_via_obj(self):
|
||||
project_ref = self.new_project_ref()
|
||||
endpoint_ref = self.new_endpoint_ref()
|
||||
project = self.client.projects.resource_class(self.client.projects,
|
||||
project_ref,
|
||||
loaded=True)
|
||||
endpoint = self.client.endpoints.resource_class(self.client.endpoints,
|
||||
endpoint_ref,
|
||||
loaded=True)
|
||||
|
||||
self.stub_url(httpretty.PUT,
|
||||
[self.manager.OS_EP_FILTER_EXT,
|
||||
'projects', project_ref['id'],
|
||||
'endpoints', endpoint_ref['id']],
|
||||
status=201)
|
||||
|
||||
self.manager.add_endpoint_to_project(project=project,
|
||||
endpoint=endpoint)
|
||||
|
||||
@httpretty.activate
|
||||
def test_delete_endpoint_from_project(self):
|
||||
endpoint_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
|
||||
self.stub_url(httpretty.DELETE,
|
||||
[self.manager.OS_EP_FILTER_EXT, 'projects', project_id,
|
||||
'endpoints', endpoint_id],
|
||||
status=201)
|
||||
|
||||
self.manager.delete_endpoint_from_project(project=project_id,
|
||||
endpoint=endpoint_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_check_endpoint_in_project(self):
|
||||
endpoint_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
|
||||
self.stub_url(httpretty.HEAD,
|
||||
[self.manager.OS_EP_FILTER_EXT, 'projects', project_id,
|
||||
'endpoints', endpoint_id],
|
||||
status=201)
|
||||
|
||||
self.manager.check_endpoint_in_project(project=project_id,
|
||||
endpoint=endpoint_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_endpoints_for_project(self):
|
||||
project_id = uuid.uuid4().hex
|
||||
endpoints = {'endpoints': [self.new_endpoint_ref(),
|
||||
self.new_endpoint_ref()]}
|
||||
self.stub_url(httpretty.GET,
|
||||
[self.manager.OS_EP_FILTER_EXT, 'projects', project_id,
|
||||
'endpoints'],
|
||||
json=endpoints,
|
||||
status=200)
|
||||
|
||||
endpoints_resp = self.manager.list_endpoints_for_project(
|
||||
project=project_id)
|
||||
|
||||
expected_endpoint_ids = [
|
||||
endpoint['id'] for endpoint in endpoints['endpoints']]
|
||||
actual_endpoint_ids = [endpoint.id for endpoint in endpoints_resp]
|
||||
self.assertEqual(expected_endpoint_ids, actual_endpoint_ids)
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_projects_for_endpoint(self):
|
||||
endpoint_id = uuid.uuid4().hex
|
||||
projects = {'projects': [self.new_project_ref(),
|
||||
self.new_project_ref()]}
|
||||
self.stub_url(httpretty.GET,
|
||||
[self.manager.OS_EP_FILTER_EXT, 'endpoints', endpoint_id,
|
||||
'projects'],
|
||||
json=projects,
|
||||
status=200)
|
||||
|
||||
projects_resp = self.manager.list_projects_for_endpoint(
|
||||
endpoint=endpoint_id)
|
||||
|
||||
expected_project_ids = [
|
||||
project['id'] for project in projects['projects']]
|
||||
actual_project_ids = [project.id for project in projects_resp]
|
||||
self.assertEqual(expected_project_ids, actual_project_ids)
|
@ -1,91 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import endpoints
|
||||
|
||||
|
||||
class EndpointTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(EndpointTests, self).setUp()
|
||||
self.key = 'endpoint'
|
||||
self.collection_key = 'endpoints'
|
||||
self.model = endpoints.Endpoint
|
||||
self.manager = self.client.endpoints
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs = super(EndpointTests, self).new_ref(**kwargs)
|
||||
kwargs.setdefault('interface', 'public')
|
||||
kwargs.setdefault('region', uuid.uuid4().hex)
|
||||
kwargs.setdefault('service_id', uuid.uuid4().hex)
|
||||
kwargs.setdefault('url', uuid.uuid4().hex)
|
||||
kwargs.setdefault('enabled', True)
|
||||
return kwargs
|
||||
|
||||
def test_create_public_interface(self):
|
||||
ref = self.new_ref(interface='public')
|
||||
self.test_create(ref)
|
||||
|
||||
def test_create_admin_interface(self):
|
||||
ref = self.new_ref(interface='admin')
|
||||
self.test_create(ref)
|
||||
|
||||
def test_create_internal_interface(self):
|
||||
ref = self.new_ref(interface='internal')
|
||||
self.test_create(ref)
|
||||
|
||||
def test_create_invalid_interface(self):
|
||||
ref = self.new_ref(interface=uuid.uuid4().hex)
|
||||
self.assertRaises(exceptions.ValidationError, self.manager.create,
|
||||
**utils.parameterize(ref))
|
||||
|
||||
def test_update_public_interface(self):
|
||||
ref = self.new_ref(interface='public')
|
||||
self.test_update(ref)
|
||||
|
||||
def test_update_admin_interface(self):
|
||||
ref = self.new_ref(interface='admin')
|
||||
self.test_update(ref)
|
||||
|
||||
def test_update_internal_interface(self):
|
||||
ref = self.new_ref(interface='internal')
|
||||
self.test_update(ref)
|
||||
|
||||
def test_update_invalid_interface(self):
|
||||
ref = self.new_ref(interface=uuid.uuid4().hex)
|
||||
ref['endpoint'] = "fake_endpoint"
|
||||
self.assertRaises(exceptions.ValidationError, self.manager.update,
|
||||
**utils.parameterize(ref))
|
||||
|
||||
def test_list_public_interface(self):
|
||||
interface = 'public'
|
||||
expected_path = 'v3/%s?interface=%s' % (self.collection_key, interface)
|
||||
self.test_list(expected_path=expected_path, interface=interface)
|
||||
|
||||
def test_list_admin_interface(self):
|
||||
interface = 'admin'
|
||||
expected_path = 'v3/%s?interface=%s' % (self.collection_key, interface)
|
||||
self.test_list(expected_path=expected_path, interface=interface)
|
||||
|
||||
def test_list_internal_interface(self):
|
||||
interface = 'admin'
|
||||
expected_path = 'v3/%s?interface=%s' % (self.collection_key, interface)
|
||||
self.test_list(expected_path=expected_path, interface=interface)
|
||||
|
||||
def test_list_invalid_interface(self):
|
||||
interface = uuid.uuid4().hex
|
||||
expected_path = 'v3/%s?interface=%s' % (self.collection_key, interface)
|
||||
self.assertRaises(exceptions.ValidationError, self.manager.list,
|
||||
expected_path=expected_path, interface=interface)
|
@ -1,127 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3.contrib.federation import identity_providers
|
||||
from keystoneclient.v3.contrib.federation import mappings
|
||||
|
||||
|
||||
class IdentityProviderTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(IdentityProviderTests, self).setUp()
|
||||
self.key = 'identity_provider'
|
||||
self.collection_key = 'identity_providers'
|
||||
self.model = identity_providers.IdentityProvider
|
||||
self.manager = self.client.federation.identity_providers
|
||||
self.path_prefix = 'OS-FEDERATION'
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs.setdefault('id', uuid.uuid4().hex)
|
||||
kwargs.setdefault('description', uuid.uuid4().hex)
|
||||
kwargs.setdefault('enabled', True)
|
||||
return kwargs
|
||||
|
||||
def test_positional_parameters_expect_fail(self):
|
||||
"""Ensure CrudManager raises TypeError exceptions.
|
||||
|
||||
After passing wrong number of positional arguments
|
||||
an exception should be raised.
|
||||
|
||||
Operations to be tested:
|
||||
* create()
|
||||
* get()
|
||||
* list()
|
||||
* delete()
|
||||
* update()
|
||||
|
||||
"""
|
||||
POS_PARAM_1 = uuid.uuid4().hex
|
||||
POS_PARAM_2 = uuid.uuid4().hex
|
||||
POS_PARAM_3 = uuid.uuid4().hex
|
||||
|
||||
PARAMETERS = {
|
||||
'create': (POS_PARAM_1, POS_PARAM_2),
|
||||
'get': (POS_PARAM_1, POS_PARAM_2),
|
||||
'list': (POS_PARAM_1, POS_PARAM_2),
|
||||
'update': (POS_PARAM_1, POS_PARAM_2, POS_PARAM_3),
|
||||
'delete': (POS_PARAM_1, POS_PARAM_2)
|
||||
}
|
||||
|
||||
for f_name, args in PARAMETERS.items():
|
||||
self.assertRaises(TypeError, getattr(self.manager, f_name),
|
||||
*args)
|
||||
|
||||
@httpretty.activate
|
||||
def test_create(self, ref=None, req_ref=None):
|
||||
ref = ref or self.new_ref()
|
||||
|
||||
# req_ref argument allows you to specify a different
|
||||
# signature for the request when the manager does some
|
||||
# conversion before doing the request (e.g. converting
|
||||
# from datetime object to timestamp string)
|
||||
req_ref = (req_ref or ref).copy()
|
||||
req_ref.pop('id')
|
||||
|
||||
self.stub_entity(httpretty.PUT, entity=ref, id=ref['id'], status=201)
|
||||
|
||||
returned = self.manager.create(**ref)
|
||||
self.assertIsInstance(returned, self.model)
|
||||
for attr in req_ref:
|
||||
self.assertEqual(
|
||||
getattr(returned, attr),
|
||||
req_ref[attr],
|
||||
'Expected different %s' % attr)
|
||||
self.assertEntityRequestBodyIs(req_ref)
|
||||
|
||||
|
||||
class MappingTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(MappingTests, self).setUp()
|
||||
self.key = 'mapping'
|
||||
self.collection_key = 'mappings'
|
||||
self.model = mappings.Mapping
|
||||
self.manager = self.client.federation.mappings
|
||||
self.path_prefix = 'OS-FEDERATION'
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs.setdefault('id', uuid.uuid4().hex)
|
||||
kwargs.setdefault('rules', [uuid.uuid4().hex,
|
||||
uuid.uuid4().hex])
|
||||
return kwargs
|
||||
|
||||
@httpretty.activate
|
||||
def test_create(self, ref=None, req_ref=None):
|
||||
ref = ref or self.new_ref()
|
||||
manager_ref = ref.copy()
|
||||
mapping_id = manager_ref.pop('id')
|
||||
|
||||
# req_ref argument allows you to specify a different
|
||||
# signature for the request when the manager does some
|
||||
# conversion before doing the request (e.g. converting
|
||||
# from datetime object to timestamp string)
|
||||
req_ref = (req_ref or ref).copy()
|
||||
|
||||
self.stub_entity(httpretty.PUT, entity=req_ref, id=mapping_id,
|
||||
status=201)
|
||||
|
||||
returned = self.manager.create(mapping_id=mapping_id, **manager_ref)
|
||||
self.assertIsInstance(returned, self.model)
|
||||
for attr in req_ref:
|
||||
self.assertEqual(
|
||||
getattr(returned, attr),
|
||||
req_ref[attr],
|
||||
'Expected different %s' % attr)
|
||||
self.assertEntityRequestBodyIs(manager_ref)
|
@ -1,63 +0,0 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
#
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import groups
|
||||
|
||||
|
||||
class GroupTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(GroupTests, self).setUp()
|
||||
self.key = 'group'
|
||||
self.collection_key = 'groups'
|
||||
self.model = groups.Group
|
||||
self.manager = self.client.groups
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs = super(GroupTests, self).new_ref(**kwargs)
|
||||
kwargs.setdefault('name', uuid.uuid4().hex)
|
||||
return kwargs
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_groups_for_user(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
ref_list = [self.new_ref(), self.new_ref()]
|
||||
|
||||
self.stub_entity(httpretty.GET,
|
||||
['users', user_id, self.collection_key],
|
||||
status=200, entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list(user=user_id)
|
||||
self.assertEqual(len(ref_list), len(returned_list))
|
||||
[self.assertIsInstance(r, self.model) for r in returned_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_groups_for_domain(self):
|
||||
ref_list = [self.new_ref(), self.new_ref()]
|
||||
domain_id = uuid.uuid4().hex
|
||||
|
||||
self.stub_entity(httpretty.GET,
|
||||
[self.collection_key],
|
||||
status=200, entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list(domain=domain_id)
|
||||
self.assertTrue(len(ref_list), len(returned_list))
|
||||
[self.assertIsInstance(r, self.model) for r in returned_list]
|
||||
|
||||
self.assertEqual(httpretty.last_request().querystring,
|
||||
{'domain_id': [domain_id]})
|
@ -1,305 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
import mock
|
||||
import six
|
||||
from testtools import matchers
|
||||
|
||||
from keystoneclient.openstack.common import jsonutils
|
||||
from keystoneclient.openstack.common import timeutils
|
||||
from keystoneclient import session
|
||||
from keystoneclient.tests.v3 import client_fixtures
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3.contrib.oauth1 import access_tokens
|
||||
from keystoneclient.v3.contrib.oauth1 import auth
|
||||
from keystoneclient.v3.contrib.oauth1 import consumers
|
||||
from keystoneclient.v3.contrib.oauth1 import request_tokens
|
||||
|
||||
try:
|
||||
import oauthlib
|
||||
from oauthlib import oauth1
|
||||
except ImportError:
|
||||
oauth1 = None
|
||||
|
||||
|
||||
class BaseTest(utils.TestCase):
|
||||
def setUp(self):
|
||||
super(BaseTest, self).setUp()
|
||||
if oauth1 is None:
|
||||
self.skipTest('oauthlib package not available')
|
||||
|
||||
|
||||
class ConsumerTests(BaseTest, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(ConsumerTests, self).setUp()
|
||||
self.key = 'consumer'
|
||||
self.collection_key = 'consumers'
|
||||
self.model = consumers.Consumer
|
||||
self.manager = self.client.oauth1.consumers
|
||||
self.path_prefix = 'OS-OAUTH1'
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs = super(ConsumerTests, self).new_ref(**kwargs)
|
||||
kwargs.setdefault('description', uuid.uuid4().hex)
|
||||
return kwargs
|
||||
|
||||
@httpretty.activate
|
||||
def test_description_is_optional(self):
|
||||
consumer_id = uuid.uuid4().hex
|
||||
resp_ref = {'consumer': {'description': None,
|
||||
'id': consumer_id}}
|
||||
|
||||
self.stub_url(httpretty.POST,
|
||||
[self.path_prefix, self.collection_key],
|
||||
status=201, json=resp_ref)
|
||||
|
||||
consumer = self.manager.create()
|
||||
self.assertEqual(consumer_id, consumer.id)
|
||||
self.assertIsNone(consumer.description)
|
||||
|
||||
@httpretty.activate
|
||||
def test_description_not_included(self):
|
||||
consumer_id = uuid.uuid4().hex
|
||||
resp_ref = {'consumer': {'id': consumer_id}}
|
||||
|
||||
self.stub_url(httpretty.POST,
|
||||
[self.path_prefix, self.collection_key],
|
||||
status=201, json=resp_ref)
|
||||
|
||||
consumer = self.manager.create()
|
||||
self.assertEqual(consumer_id, consumer.id)
|
||||
|
||||
|
||||
class TokenTests(BaseTest):
|
||||
def _new_oauth_token(self):
|
||||
key = uuid.uuid4().hex
|
||||
secret = uuid.uuid4().hex
|
||||
token = 'oauth_token=%s&oauth_token_secret=%s' % (key, secret)
|
||||
return (key, secret, token)
|
||||
|
||||
def _new_oauth_token_with_expires_at(self):
|
||||
key, secret, token = self._new_oauth_token()
|
||||
expires_at = timeutils.strtime()
|
||||
token += '&oauth_expires_at=%s' % expires_at
|
||||
return (key, secret, expires_at, token)
|
||||
|
||||
def _validate_oauth_headers(self, auth_header, oauth_client):
|
||||
"""Assert that the data in the headers matches the data
|
||||
that is produced from oauthlib.
|
||||
"""
|
||||
|
||||
self.assertThat(auth_header, matchers.StartsWith('OAuth '))
|
||||
auth_header = auth_header[len('OAuth '):]
|
||||
# NOTE(stevemar): In newer versions of oauthlib there is
|
||||
# an additional argument for getting oauth parameters.
|
||||
# Adding a conditional here to revert back to no arguments
|
||||
# if an earlier version is detected.
|
||||
if tuple(oauthlib.__version__.split('.')) > ('0', '6', '1'):
|
||||
header_params = oauth_client.get_oauth_params(None)
|
||||
else:
|
||||
header_params = oauth_client.get_oauth_params()
|
||||
parameters = dict(header_params)
|
||||
|
||||
self.assertEqual('HMAC-SHA1', parameters['oauth_signature_method'])
|
||||
self.assertEqual('1.0', parameters['oauth_version'])
|
||||
self.assertIsInstance(parameters['oauth_nonce'], six.string_types)
|
||||
self.assertEqual(oauth_client.client_key,
|
||||
parameters['oauth_consumer_key'])
|
||||
if oauth_client.resource_owner_key:
|
||||
self.assertEqual(oauth_client.resource_owner_key,
|
||||
parameters['oauth_token'],)
|
||||
if oauth_client.verifier:
|
||||
self.assertEqual(oauth_client.verifier,
|
||||
parameters['oauth_verifier'])
|
||||
if oauth_client.callback_uri:
|
||||
self.assertEqual(oauth_client.callback_uri,
|
||||
parameters['oauth_callback'])
|
||||
if oauth_client.timestamp:
|
||||
self.assertEqual(oauth_client.timestamp,
|
||||
parameters['oauth_timestamp'])
|
||||
return parameters
|
||||
|
||||
|
||||
class RequestTokenTests(TokenTests):
|
||||
def setUp(self):
|
||||
super(RequestTokenTests, self).setUp()
|
||||
self.model = request_tokens.RequestToken
|
||||
self.manager = self.client.oauth1.request_tokens
|
||||
self.path_prefix = 'OS-OAUTH1'
|
||||
|
||||
@httpretty.activate
|
||||
def test_authorize_request_token(self):
|
||||
request_key = uuid.uuid4().hex
|
||||
info = {'id': request_key,
|
||||
'key': request_key,
|
||||
'secret': uuid.uuid4().hex}
|
||||
request_token = request_tokens.RequestToken(self.manager, info)
|
||||
|
||||
verifier = uuid.uuid4().hex
|
||||
resp_ref = {'token': {'oauth_verifier': verifier}}
|
||||
self.stub_url(httpretty.PUT,
|
||||
[self.path_prefix, 'authorize', request_key],
|
||||
status=200, json=resp_ref)
|
||||
|
||||
# Assert the manager is returning the expected data
|
||||
role_id = uuid.uuid4().hex
|
||||
token = request_token.authorize([role_id])
|
||||
self.assertEqual(verifier, token.oauth_verifier)
|
||||
|
||||
# Assert that the request was sent in the expected structure
|
||||
exp_body = {'roles': [{'id': role_id}]}
|
||||
self.assertRequestBodyIs(json=exp_body)
|
||||
|
||||
@httpretty.activate
|
||||
def test_create_request_token(self):
|
||||
project_id = uuid.uuid4().hex
|
||||
consumer_key = uuid.uuid4().hex
|
||||
consumer_secret = uuid.uuid4().hex
|
||||
|
||||
request_key, request_secret, resp_ref = self._new_oauth_token()
|
||||
|
||||
# NOTE(stevemar) The server expects the body to be JSON. Even though
|
||||
# the resp_ref is a string it is not a JSON string.
|
||||
self.stub_url(httpretty.POST, [self.path_prefix, 'request_token'],
|
||||
status=201, body=jsonutils.dumps(resp_ref),
|
||||
content_type='application/x-www-form-urlencoded')
|
||||
|
||||
# Assert the manager is returning request token object
|
||||
request_token = self.manager.create(consumer_key, consumer_secret,
|
||||
project_id)
|
||||
self.assertIsInstance(request_token, self.model)
|
||||
self.assertEqual(request_key, request_token.key)
|
||||
self.assertEqual(request_secret, request_token.secret)
|
||||
|
||||
# Assert that the project id is in the header
|
||||
self.assertRequestHeaderEqual('requested_project_id', project_id)
|
||||
req_headers = httpretty.last_request().headers
|
||||
|
||||
oauth_client = oauth1.Client(consumer_key,
|
||||
client_secret=consumer_secret,
|
||||
signature_method=oauth1.SIGNATURE_HMAC,
|
||||
callback_uri="oob")
|
||||
self._validate_oauth_headers(req_headers['Authorization'],
|
||||
oauth_client)
|
||||
|
||||
|
||||
class AccessTokenTests(TokenTests):
|
||||
def setUp(self):
|
||||
super(AccessTokenTests, self).setUp()
|
||||
self.manager = self.client.oauth1.access_tokens
|
||||
self.model = access_tokens.AccessToken
|
||||
self.path_prefix = 'OS-OAUTH1'
|
||||
|
||||
@httpretty.activate
|
||||
def test_create_access_token_expires_at(self):
|
||||
verifier = uuid.uuid4().hex
|
||||
consumer_key = uuid.uuid4().hex
|
||||
consumer_secret = uuid.uuid4().hex
|
||||
request_key = uuid.uuid4().hex
|
||||
request_secret = uuid.uuid4().hex
|
||||
|
||||
t = self._new_oauth_token_with_expires_at()
|
||||
access_key, access_secret, expires_at, resp_ref = t
|
||||
|
||||
# NOTE(stevemar) The server expects the body to be JSON. Even though
|
||||
# the resp_ref is a string it is not a JSON string.
|
||||
self.stub_url(httpretty.POST, [self.path_prefix, 'access_token'],
|
||||
status=201, body=jsonutils.dumps(resp_ref),
|
||||
content_type='application/x-www-form-urlencoded')
|
||||
|
||||
# Assert that the manager creates an access token object
|
||||
access_token = self.manager.create(consumer_key, consumer_secret,
|
||||
request_key, request_secret,
|
||||
verifier)
|
||||
self.assertIsInstance(access_token, self.model)
|
||||
self.assertEqual(access_key, access_token.key)
|
||||
self.assertEqual(access_secret, access_token.secret)
|
||||
self.assertEqual(expires_at, access_token.expires)
|
||||
|
||||
req_headers = httpretty.last_request().headers
|
||||
oauth_client = oauth1.Client(consumer_key,
|
||||
client_secret=consumer_secret,
|
||||
resource_owner_key=request_key,
|
||||
resource_owner_secret=request_secret,
|
||||
signature_method=oauth1.SIGNATURE_HMAC,
|
||||
verifier=verifier,
|
||||
timestamp=expires_at)
|
||||
self._validate_oauth_headers(req_headers['Authorization'],
|
||||
oauth_client)
|
||||
|
||||
|
||||
class AuthenticateWithOAuthTests(TokenTests):
|
||||
def setUp(self):
|
||||
super(AuthenticateWithOAuthTests, self).setUp()
|
||||
if oauth1 is None:
|
||||
self.skipTest('optional package oauthlib is not installed')
|
||||
|
||||
@httpretty.activate
|
||||
def test_oauth_authenticate_success(self):
|
||||
consumer_key = uuid.uuid4().hex
|
||||
consumer_secret = uuid.uuid4().hex
|
||||
access_key = uuid.uuid4().hex
|
||||
access_secret = uuid.uuid4().hex
|
||||
|
||||
# Just use an existing project scoped token and change
|
||||
# the methods to oauth1, and add an OS-OAUTH1 section.
|
||||
oauth_token = client_fixtures.project_scoped_token()
|
||||
oauth_token['methods'] = ["oauth1"]
|
||||
oauth_token['OS-OAUTH1'] = {"consumer_id": consumer_key,
|
||||
"access_token_id": access_key}
|
||||
self.stub_auth(json=oauth_token)
|
||||
|
||||
a = auth.OAuth(self.TEST_URL, consumer_key=consumer_key,
|
||||
consumer_secret=consumer_secret,
|
||||
access_key=access_key,
|
||||
access_secret=access_secret)
|
||||
s = session.Session(auth=a)
|
||||
t = s.get_token()
|
||||
self.assertEqual(self.TEST_TOKEN, t)
|
||||
|
||||
OAUTH_REQUEST_BODY = {
|
||||
"auth": {
|
||||
"identity": {
|
||||
"methods": ["oauth1"],
|
||||
"oauth1": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.assertRequestBodyIs(json=OAUTH_REQUEST_BODY)
|
||||
|
||||
# Assert that the headers have the same oauthlib data
|
||||
req_headers = httpretty.last_request().headers
|
||||
oauth_client = oauth1.Client(consumer_key,
|
||||
client_secret=consumer_secret,
|
||||
resource_owner_key=access_key,
|
||||
resource_owner_secret=access_secret,
|
||||
signature_method=oauth1.SIGNATURE_HMAC)
|
||||
self._validate_oauth_headers(req_headers['Authorization'],
|
||||
oauth_client)
|
||||
|
||||
|
||||
class TestOAuthLibModule(utils.TestCase):
|
||||
|
||||
def test_no_oauthlib_installed(self):
|
||||
with mock.patch.object(auth, 'oauth1', None):
|
||||
self.assertRaises(NotImplementedError,
|
||||
auth.OAuth,
|
||||
self.TEST_URL,
|
||||
consumer_key=uuid.uuid4().hex,
|
||||
consumer_secret=uuid.uuid4().hex,
|
||||
access_key=uuid.uuid4().hex,
|
||||
access_secret=uuid.uuid4().hex)
|
@ -1,31 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import policies
|
||||
|
||||
|
||||
class PolicyTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(PolicyTests, self).setUp()
|
||||
self.key = 'policy'
|
||||
self.collection_key = 'policies'
|
||||
self.model = policies.Policy
|
||||
self.manager = self.client.policies
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs = super(PolicyTests, self).new_ref(**kwargs)
|
||||
kwargs.setdefault('type', uuid.uuid4().hex)
|
||||
kwargs.setdefault('blob', uuid.uuid4().hex)
|
||||
return kwargs
|
@ -1,62 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import projects
|
||||
|
||||
|
||||
class ProjectTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(ProjectTests, self).setUp()
|
||||
self.key = 'project'
|
||||
self.collection_key = 'projects'
|
||||
self.model = projects.Project
|
||||
self.manager = self.client.projects
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs = super(ProjectTests, self).new_ref(**kwargs)
|
||||
kwargs.setdefault('domain_id', uuid.uuid4().hex)
|
||||
kwargs.setdefault('enabled', True)
|
||||
kwargs.setdefault('name', uuid.uuid4().hex)
|
||||
return kwargs
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_projects_for_user(self):
|
||||
ref_list = [self.new_ref(), self.new_ref()]
|
||||
user_id = uuid.uuid4().hex
|
||||
|
||||
self.stub_entity(httpretty.GET,
|
||||
['users', user_id, self.collection_key],
|
||||
entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list(user=user_id)
|
||||
self.assertEqual(len(ref_list), len(returned_list))
|
||||
[self.assertIsInstance(r, self.model) for r in returned_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_projects_for_domain(self):
|
||||
ref_list = [self.new_ref(), self.new_ref()]
|
||||
domain_id = uuid.uuid4().hex
|
||||
|
||||
self.stub_entity(httpretty.GET, [self.collection_key],
|
||||
entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list(domain=domain_id)
|
||||
self.assertEqual(len(ref_list), len(returned_list))
|
||||
[self.assertIsInstance(r, self.model) for r in returned_list]
|
||||
|
||||
self.assertEqual(httpretty.last_request().querystring,
|
||||
{'domain_id': [domain_id]})
|
@ -1,33 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import regions
|
||||
|
||||
|
||||
class RegionTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(RegionTests, self).setUp()
|
||||
self.key = 'region'
|
||||
self.collection_key = 'regions'
|
||||
self.model = regions.Region
|
||||
self.manager = self.client.regions
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs = super(RegionTests, self).new_ref(**kwargs)
|
||||
kwargs.setdefault('enabled', True)
|
||||
kwargs.setdefault('id', uuid.uuid4().hex)
|
||||
return kwargs
|
@ -1,220 +0,0 @@
|
||||
# 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 httpretty
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import role_assignments
|
||||
|
||||
|
||||
class RoleAssignmentsTests(utils.TestCase, utils.CrudTests):
|
||||
|
||||
def setUp(self):
|
||||
super(RoleAssignmentsTests, self).setUp()
|
||||
self.key = 'role_assignment'
|
||||
self.collection_key = 'role_assignments'
|
||||
self.model = role_assignments.RoleAssignment
|
||||
self.manager = self.client.role_assignments
|
||||
self.TEST_USER_DOMAIN_LIST = [{
|
||||
'role': {
|
||||
'id': self.TEST_ROLE_ID
|
||||
},
|
||||
'scope': {
|
||||
'domain': {
|
||||
'id': self.TEST_DOMAIN_ID
|
||||
}
|
||||
},
|
||||
'user': {
|
||||
'id': self.TEST_USER_ID
|
||||
}
|
||||
}]
|
||||
self.TEST_GROUP_PROJECT_LIST = [{
|
||||
'group': {
|
||||
'id': self.TEST_GROUP_ID
|
||||
},
|
||||
'role': {
|
||||
'id': self.TEST_ROLE_ID
|
||||
},
|
||||
'scope': {
|
||||
'project': {
|
||||
'id': self.TEST_TENANT_ID
|
||||
}
|
||||
}
|
||||
}]
|
||||
self.TEST_USER_PROJECT_LIST = [{
|
||||
'user': {
|
||||
'id': self.TEST_USER_ID
|
||||
},
|
||||
'role': {
|
||||
'id': self.TEST_ROLE_ID
|
||||
},
|
||||
'scope': {
|
||||
'project': {
|
||||
'id': self.TEST_TENANT_ID
|
||||
}
|
||||
}
|
||||
}]
|
||||
|
||||
self.TEST_ALL_RESPONSE_LIST = (self.TEST_USER_PROJECT_LIST +
|
||||
self.TEST_GROUP_PROJECT_LIST +
|
||||
self.TEST_USER_DOMAIN_LIST)
|
||||
|
||||
def _assert_returned_list(self, ref_list, returned_list):
|
||||
self.assertEqual(len(ref_list), len(returned_list))
|
||||
[self.assertIsInstance(r, self.model) for r in returned_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_params(self):
|
||||
ref_list = self.TEST_USER_PROJECT_LIST
|
||||
self.stub_entity(httpretty.GET,
|
||||
[self.collection_key,
|
||||
'?scope.project.id=%s&user.id=%s' %
|
||||
(self.TEST_TENANT_ID, self.TEST_USER_ID)],
|
||||
entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list(user=self.TEST_USER_ID,
|
||||
project=self.TEST_TENANT_ID)
|
||||
self._assert_returned_list(ref_list, returned_list)
|
||||
|
||||
kwargs = {'scope.project.id': self.TEST_TENANT_ID,
|
||||
'user.id': self.TEST_USER_ID}
|
||||
self.assertQueryStringContains(**kwargs)
|
||||
|
||||
@httpretty.activate
|
||||
def test_all_assignments_list(self):
|
||||
ref_list = self.TEST_ALL_RESPONSE_LIST
|
||||
self.stub_entity(httpretty.GET,
|
||||
[self.collection_key],
|
||||
entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list()
|
||||
self._assert_returned_list(ref_list, returned_list)
|
||||
|
||||
kwargs = {}
|
||||
self.assertQueryStringContains(**kwargs)
|
||||
|
||||
@httpretty.activate
|
||||
def test_project_assignments_list(self):
|
||||
ref_list = self.TEST_GROUP_PROJECT_LIST + self.TEST_USER_PROJECT_LIST
|
||||
self.stub_entity(httpretty.GET,
|
||||
[self.collection_key,
|
||||
'?scope.project.id=%s' % self.TEST_TENANT_ID],
|
||||
entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list(project=self.TEST_TENANT_ID)
|
||||
self._assert_returned_list(ref_list, returned_list)
|
||||
|
||||
kwargs = {'scope.project.id': self.TEST_TENANT_ID}
|
||||
self.assertQueryStringContains(**kwargs)
|
||||
|
||||
@httpretty.activate
|
||||
def test_domain_assignments_list(self):
|
||||
ref_list = self.TEST_USER_DOMAIN_LIST
|
||||
self.stub_entity(httpretty.GET,
|
||||
[self.collection_key,
|
||||
'?scope.domain.id=%s' % self.TEST_DOMAIN_ID],
|
||||
entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list(domain=self.TEST_DOMAIN_ID)
|
||||
self._assert_returned_list(ref_list, returned_list)
|
||||
|
||||
kwargs = {'scope.domain.id': self.TEST_DOMAIN_ID}
|
||||
self.assertQueryStringContains(**kwargs)
|
||||
|
||||
@httpretty.activate
|
||||
def test_group_assignments_list(self):
|
||||
ref_list = self.TEST_GROUP_PROJECT_LIST
|
||||
self.stub_entity(httpretty.GET,
|
||||
[self.collection_key,
|
||||
'?group.id=%s' % self.TEST_GROUP_ID],
|
||||
entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list(group=self.TEST_GROUP_ID)
|
||||
self._assert_returned_list(ref_list, returned_list)
|
||||
|
||||
kwargs = {'group.id': self.TEST_GROUP_ID}
|
||||
self.assertQueryStringContains(**kwargs)
|
||||
|
||||
@httpretty.activate
|
||||
def test_user_assignments_list(self):
|
||||
ref_list = self.TEST_USER_DOMAIN_LIST + self.TEST_USER_PROJECT_LIST
|
||||
self.stub_entity(httpretty.GET,
|
||||
[self.collection_key,
|
||||
'?user.id=%s' % self.TEST_USER_ID],
|
||||
entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list(user=self.TEST_USER_ID)
|
||||
self._assert_returned_list(ref_list, returned_list)
|
||||
|
||||
kwargs = {'user.id': self.TEST_USER_ID}
|
||||
self.assertQueryStringContains(**kwargs)
|
||||
|
||||
@httpretty.activate
|
||||
def test_effective_assignments_list(self):
|
||||
ref_list = self.TEST_USER_PROJECT_LIST + self.TEST_USER_DOMAIN_LIST
|
||||
self.stub_entity(httpretty.GET,
|
||||
[self.collection_key,
|
||||
'?effective=True'],
|
||||
entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list(effective=True)
|
||||
self._assert_returned_list(ref_list, returned_list)
|
||||
|
||||
kwargs = {'effective': 'True'}
|
||||
self.assertQueryStringContains(**kwargs)
|
||||
|
||||
@httpretty.activate
|
||||
def test_role_assignments_list(self):
|
||||
ref_list = self.TEST_ALL_RESPONSE_LIST
|
||||
self.stub_entity(httpretty.GET,
|
||||
[self.collection_key,
|
||||
'?role.id=' + self.TEST_ROLE_ID],
|
||||
entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list(role=self.TEST_ROLE_ID)
|
||||
self._assert_returned_list(ref_list, returned_list)
|
||||
|
||||
kwargs = {'role.id': self.TEST_ROLE_ID}
|
||||
self.assertQueryStringContains(**kwargs)
|
||||
|
||||
def test_domain_and_project_list(self):
|
||||
# Should only accept either domain or project, never both
|
||||
self.assertRaises(exceptions.ValidationError,
|
||||
self.manager.list,
|
||||
domain=self.TEST_DOMAIN_ID,
|
||||
project=self.TEST_TENANT_ID)
|
||||
|
||||
def test_user_and_group_list(self):
|
||||
# Should only accept either user or group, never both
|
||||
self.assertRaises(exceptions.ValidationError, self.manager.list,
|
||||
user=self.TEST_USER_ID, group=self.TEST_GROUP_ID)
|
||||
|
||||
def test_create(self):
|
||||
# Create not supported for role assignments
|
||||
self.assertRaises(exceptions.MethodNotImplemented, self.manager.create)
|
||||
|
||||
def test_update(self):
|
||||
# Update not supported for role assignments
|
||||
self.assertRaises(exceptions.MethodNotImplemented, self.manager.update)
|
||||
|
||||
def test_delete(self):
|
||||
# Delete not supported for role assignments
|
||||
self.assertRaises(exceptions.MethodNotImplemented, self.manager.delete)
|
||||
|
||||
def test_get(self):
|
||||
# Get not supported for role assignments
|
||||
self.assertRaises(exceptions.MethodNotImplemented, self.manager.get)
|
||||
|
||||
def test_find(self):
|
||||
# Find not supported for role assignments
|
||||
self.assertRaises(exceptions.MethodNotImplemented, self.manager.find)
|
@ -1,350 +0,0 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
#
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import roles
|
||||
|
||||
|
||||
class RoleTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(RoleTests, self).setUp()
|
||||
self.key = 'role'
|
||||
self.collection_key = 'roles'
|
||||
self.model = roles.Role
|
||||
self.manager = self.client.roles
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs = super(RoleTests, self).new_ref(**kwargs)
|
||||
kwargs.setdefault('name', uuid.uuid4().hex)
|
||||
return kwargs
|
||||
|
||||
@httpretty.activate
|
||||
def test_domain_role_grant(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
domain_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.PUT,
|
||||
['domains', domain_id, 'users', user_id,
|
||||
self.collection_key, ref['id']],
|
||||
status=201)
|
||||
|
||||
self.manager.grant(role=ref['id'], domain=domain_id, user=user_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_domain_group_role_grant(self):
|
||||
group_id = uuid.uuid4().hex
|
||||
domain_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.PUT,
|
||||
['domains', domain_id, 'groups', group_id,
|
||||
self.collection_key, ref['id']],
|
||||
status=201)
|
||||
|
||||
self.manager.grant(role=ref['id'], domain=domain_id, group=group_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_domain_role_list(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
domain_id = uuid.uuid4().hex
|
||||
ref_list = [self.new_ref(), self.new_ref()]
|
||||
|
||||
self.stub_entity(httpretty.GET,
|
||||
['domains', domain_id, 'users', user_id,
|
||||
self.collection_key], entity=ref_list)
|
||||
|
||||
self.manager.list(domain=domain_id, user=user_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_domain_group_role_list(self):
|
||||
group_id = uuid.uuid4().hex
|
||||
domain_id = uuid.uuid4().hex
|
||||
ref_list = [self.new_ref(), self.new_ref()]
|
||||
|
||||
self.stub_entity(httpretty.GET,
|
||||
['domains', domain_id, 'groups', group_id,
|
||||
self.collection_key], entity=ref_list)
|
||||
|
||||
self.manager.list(domain=domain_id, group=group_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_domain_role_check(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
domain_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.HEAD,
|
||||
['domains', domain_id, 'users', user_id,
|
||||
self.collection_key, ref['id']],
|
||||
status=204)
|
||||
|
||||
self.manager.check(role=ref['id'], domain=domain_id,
|
||||
user=user_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_domain_group_role_check(self):
|
||||
return
|
||||
group_id = uuid.uuid4().hex
|
||||
domain_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.HEAD,
|
||||
['domains', domain_id, 'groups', group_id,
|
||||
self.collection_key, ref['id']],
|
||||
status=204)
|
||||
|
||||
self.manager.check(role=ref['id'], domain=domain_id, group=group_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_domain_role_revoke(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
domain_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.DELETE,
|
||||
['domains', domain_id, 'users', user_id,
|
||||
self.collection_key, ref['id']],
|
||||
status=204)
|
||||
|
||||
self.manager.revoke(role=ref['id'], domain=domain_id, user=user_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_domain_group_role_revoke(self):
|
||||
group_id = uuid.uuid4().hex
|
||||
domain_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.DELETE,
|
||||
['domains', domain_id, 'groups', group_id,
|
||||
self.collection_key, ref['id']],
|
||||
status=204)
|
||||
|
||||
self.manager.revoke(role=ref['id'], domain=domain_id, group=group_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_project_role_grant(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.PUT,
|
||||
['projects', project_id, 'users', user_id,
|
||||
self.collection_key, ref['id']],
|
||||
status=201)
|
||||
|
||||
self.manager.grant(role=ref['id'], project=project_id, user=user_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_project_group_role_grant(self):
|
||||
group_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.PUT,
|
||||
['projects', project_id, 'groups', group_id,
|
||||
self.collection_key, ref['id']],
|
||||
status=201)
|
||||
|
||||
self.manager.grant(role=ref['id'], project=project_id, group=group_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_project_role_list(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
ref_list = [self.new_ref(), self.new_ref()]
|
||||
|
||||
self.stub_entity(httpretty.GET,
|
||||
['projects', project_id, 'users', user_id,
|
||||
self.collection_key], entity=ref_list)
|
||||
|
||||
self.manager.list(project=project_id, user=user_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_project_group_role_list(self):
|
||||
group_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
ref_list = [self.new_ref(), self.new_ref()]
|
||||
|
||||
self.stub_entity(httpretty.GET,
|
||||
['projects', project_id, 'groups', group_id,
|
||||
self.collection_key], entity=ref_list)
|
||||
|
||||
self.manager.list(project=project_id, group=group_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_project_role_check(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.HEAD,
|
||||
['projects', project_id, 'users', user_id,
|
||||
self.collection_key, ref['id']],
|
||||
status=200)
|
||||
|
||||
self.manager.check(role=ref['id'], project=project_id, user=user_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_project_group_role_check(self):
|
||||
group_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.HEAD,
|
||||
['projects', project_id, 'groups', group_id,
|
||||
self.collection_key, ref['id']],
|
||||
status=200)
|
||||
|
||||
self.manager.check(role=ref['id'], project=project_id, group=group_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_project_role_revoke(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.DELETE,
|
||||
['projects', project_id, 'users', user_id,
|
||||
self.collection_key, ref['id']],
|
||||
status=204)
|
||||
|
||||
self.manager.revoke(role=ref['id'], project=project_id, user=user_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_project_group_role_revoke(self):
|
||||
group_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.DELETE,
|
||||
['projects', project_id, 'groups', group_id,
|
||||
self.collection_key, ref['id']],
|
||||
status=204)
|
||||
|
||||
self.manager.revoke(role=ref['id'], project=project_id, group=group_id)
|
||||
|
||||
@httpretty.activate
|
||||
def test_domain_project_role_grant_fails(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
domain_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ValidationError,
|
||||
self.manager.grant,
|
||||
role=ref['id'],
|
||||
domain=domain_id,
|
||||
project=project_id,
|
||||
user=user_id)
|
||||
|
||||
def test_domain_project_role_list_fails(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
domain_id = uuid.uuid4().hex
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ValidationError,
|
||||
self.manager.list,
|
||||
domain=domain_id,
|
||||
project=project_id,
|
||||
user=user_id)
|
||||
|
||||
def test_domain_project_role_check_fails(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
domain_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ValidationError,
|
||||
self.manager.check,
|
||||
role=ref['id'],
|
||||
domain=domain_id,
|
||||
project=project_id,
|
||||
user=user_id)
|
||||
|
||||
def test_domain_project_role_revoke_fails(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
domain_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ValidationError,
|
||||
self.manager.revoke,
|
||||
role=ref['id'],
|
||||
domain=domain_id,
|
||||
project=project_id,
|
||||
user=user_id)
|
||||
|
||||
def test_user_group_role_grant_fails(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
group_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ValidationError,
|
||||
self.manager.grant,
|
||||
role=ref['id'],
|
||||
project=project_id,
|
||||
group=group_id,
|
||||
user=user_id)
|
||||
|
||||
def test_user_group_role_list_fails(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
group_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ValidationError,
|
||||
self.manager.list,
|
||||
project=project_id,
|
||||
group=group_id,
|
||||
user=user_id)
|
||||
|
||||
def test_user_group_role_check_fails(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
group_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ValidationError,
|
||||
self.manager.check,
|
||||
role=ref['id'],
|
||||
project=project_id,
|
||||
group=group_id,
|
||||
user=user_id)
|
||||
|
||||
def test_user_group_role_revoke_fails(self):
|
||||
user_id = uuid.uuid4().hex
|
||||
group_id = uuid.uuid4().hex
|
||||
project_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ValidationError,
|
||||
self.manager.revoke,
|
||||
role=ref['id'],
|
||||
project=project_id,
|
||||
group=group_id,
|
||||
user=user_id)
|
@ -1,218 +0,0 @@
|
||||
# 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.
|
||||
|
||||
from keystoneclient import access
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.tests.v3 import client_fixtures
|
||||
from keystoneclient.tests.v3 import utils
|
||||
|
||||
|
||||
class ServiceCatalogTest(utils.TestCase):
|
||||
def setUp(self):
|
||||
super(ServiceCatalogTest, self).setUp()
|
||||
self.AUTH_RESPONSE_BODY = client_fixtures.auth_response_body()
|
||||
self.RESPONSE = utils.TestResponse({
|
||||
"headers": client_fixtures.AUTH_RESPONSE_HEADERS
|
||||
})
|
||||
|
||||
self.north_endpoints = {'public':
|
||||
'http://glance.north.host/glanceapi/public',
|
||||
'internal':
|
||||
'http://glance.north.host/glanceapi/internal',
|
||||
'admin':
|
||||
'http://glance.north.host/glanceapi/admin'}
|
||||
|
||||
self.south_endpoints = {'public':
|
||||
'http://glance.south.host/glanceapi/public',
|
||||
'internal':
|
||||
'http://glance.south.host/glanceapi/internal',
|
||||
'admin':
|
||||
'http://glance.south.host/glanceapi/admin'}
|
||||
|
||||
def test_building_a_service_catalog(self):
|
||||
auth_ref = access.AccessInfo.factory(self.RESPONSE,
|
||||
self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
self.assertEqual(sc.url_for(service_type='compute'),
|
||||
"https://compute.north.host/novapi/public")
|
||||
self.assertEqual(sc.url_for(service_type='compute',
|
||||
endpoint_type='internal'),
|
||||
"https://compute.north.host/novapi/internal")
|
||||
|
||||
self.assertRaises(exceptions.EndpointNotFound, sc.url_for, "region",
|
||||
"South", service_type='compute')
|
||||
|
||||
def test_service_catalog_endpoints(self):
|
||||
auth_ref = access.AccessInfo.factory(self.RESPONSE,
|
||||
self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
public_ep = sc.get_endpoints(service_type='compute',
|
||||
endpoint_type='public')
|
||||
self.assertEqual(public_ep['compute'][0]['region'], 'North')
|
||||
self.assertEqual(public_ep['compute'][0]['url'],
|
||||
"https://compute.north.host/novapi/public")
|
||||
|
||||
def test_service_catalog_regions(self):
|
||||
self.AUTH_RESPONSE_BODY['token']['region_name'] = "North"
|
||||
auth_ref = access.AccessInfo.factory(self.RESPONSE,
|
||||
self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
url = sc.url_for(service_type='image', endpoint_type='public')
|
||||
self.assertEqual(url, "http://glance.north.host/glanceapi/public")
|
||||
|
||||
self.AUTH_RESPONSE_BODY['token']['region_name'] = "South"
|
||||
auth_ref = access.AccessInfo.factory(self.RESPONSE,
|
||||
self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
url = sc.url_for(service_type='image', endpoint_type='internal')
|
||||
self.assertEqual(url, "http://glance.south.host/glanceapi/internal")
|
||||
|
||||
def test_service_catalog_empty(self):
|
||||
self.AUTH_RESPONSE_BODY['token']['catalog'] = []
|
||||
auth_ref = access.AccessInfo.factory(self.RESPONSE,
|
||||
self.AUTH_RESPONSE_BODY)
|
||||
self.assertRaises(exceptions.EmptyCatalog,
|
||||
auth_ref.service_catalog.url_for,
|
||||
service_type='image',
|
||||
endpoint_type='internalURL')
|
||||
|
||||
def test_service_catalog_get_endpoints_region_names(self):
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='image', region_name='North')
|
||||
self.assertEqual(len(endpoints), 1)
|
||||
for endpoint in endpoints['image']:
|
||||
self.assertEqual(endpoint['url'],
|
||||
self.north_endpoints[endpoint['interface']])
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='image', region_name='South')
|
||||
self.assertEqual(len(endpoints), 1)
|
||||
for endpoint in endpoints['image']:
|
||||
self.assertEqual(endpoint['url'],
|
||||
self.south_endpoints[endpoint['interface']])
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='compute')
|
||||
self.assertEqual(len(endpoints['compute']), 3)
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='compute',
|
||||
region_name='North')
|
||||
self.assertEqual(len(endpoints['compute']), 3)
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='compute',
|
||||
region_name='West')
|
||||
self.assertEqual(len(endpoints['compute']), 0)
|
||||
|
||||
def test_service_catalog_url_for_region_names(self):
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
url = sc.url_for(service_type='image', region_name='North')
|
||||
self.assertEqual(url, self.north_endpoints['public'])
|
||||
|
||||
url = sc.url_for(service_type='image', region_name='South')
|
||||
self.assertEqual(url, self.south_endpoints['public'])
|
||||
|
||||
self.assertRaises(exceptions.EndpointNotFound, sc.url_for,
|
||||
service_type='image', region_name='West')
|
||||
|
||||
def test_servcie_catalog_get_url_region_names(self):
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
urls = sc.get_urls(service_type='image')
|
||||
self.assertEqual(len(urls), 2)
|
||||
|
||||
urls = sc.get_urls(service_type='image', region_name='North')
|
||||
self.assertEqual(len(urls), 1)
|
||||
self.assertEqual(urls[0], self.north_endpoints['public'])
|
||||
|
||||
urls = sc.get_urls(service_type='image', region_name='South')
|
||||
self.assertEqual(len(urls), 1)
|
||||
self.assertEqual(urls[0], self.south_endpoints['public'])
|
||||
|
||||
urls = sc.get_urls(service_type='image', region_name='West')
|
||||
self.assertIsNone(urls)
|
||||
|
||||
def test_service_catalog_param_overrides_body_region(self):
|
||||
self.AUTH_RESPONSE_BODY['token']['region_name'] = "North"
|
||||
auth_ref = access.AccessInfo.factory(None, self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
url = sc.url_for(service_type='image')
|
||||
self.assertEqual(url, self.north_endpoints['public'])
|
||||
|
||||
url = sc.url_for(service_type='image', region_name='South')
|
||||
self.assertEqual(url, self.south_endpoints['public'])
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='image')
|
||||
self.assertEqual(len(endpoints['image']), 3)
|
||||
for endpoint in endpoints['image']:
|
||||
self.assertEqual(endpoint['url'],
|
||||
self.north_endpoints[endpoint['interface']])
|
||||
|
||||
endpoints = sc.get_endpoints(service_type='image', region_name='South')
|
||||
self.assertEqual(len(endpoints['image']), 3)
|
||||
for endpoint in endpoints['image']:
|
||||
self.assertEqual(endpoint['url'],
|
||||
self.south_endpoints[endpoint['interface']])
|
||||
|
||||
def test_service_catalog_service_name(self):
|
||||
auth_ref = access.AccessInfo.factory(resp=None,
|
||||
body=self.AUTH_RESPONSE_BODY)
|
||||
sc = auth_ref.service_catalog
|
||||
|
||||
url = sc.url_for(service_name='glance', endpoint_type='public',
|
||||
service_type='image', region_name='North')
|
||||
self.assertEqual('http://glance.north.host/glanceapi/public', url)
|
||||
|
||||
url = sc.url_for(service_name='glance', endpoint_type='public',
|
||||
service_type='image', region_name='South')
|
||||
self.assertEqual('http://glance.south.host/glanceapi/public', url)
|
||||
|
||||
self.assertRaises(exceptions.EndpointNotFound, sc.url_for,
|
||||
service_name='glance', service_type='compute')
|
||||
|
||||
urls = sc.get_urls(service_type='image', service_name='glance',
|
||||
endpoint_type='public')
|
||||
|
||||
self.assertIn('http://glance.north.host/glanceapi/public', urls)
|
||||
self.assertIn('http://glance.south.host/glanceapi/public', urls)
|
||||
|
||||
urls = sc.get_urls(service_type='image', service_name='Servers',
|
||||
endpoint_type='public')
|
||||
|
||||
self.assertIsNone(urls)
|
||||
|
||||
def test_service_catalog_without_name(self):
|
||||
pr_auth_ref = access.AccessInfo.factory(
|
||||
resp=None,
|
||||
body=client_fixtures.project_scoped_token())
|
||||
pr_sc = pr_auth_ref.service_catalog
|
||||
|
||||
# this will work because there are no service names on that token
|
||||
url_ref = 'http://public.com:8774/v2/225da22d3ce34b15877ea70b2a575f58'
|
||||
url = pr_sc.url_for(service_type='compute', service_name='NotExist',
|
||||
endpoint_type='public')
|
||||
self.assertEqual(url_ref, url)
|
||||
|
||||
ab_auth_ref = access.AccessInfo.factory(resp=None,
|
||||
body=self.AUTH_RESPONSE_BODY)
|
||||
ab_sc = ab_auth_ref.service_catalog
|
||||
|
||||
# this won't work because there is a name and it's not this one
|
||||
self.assertRaises(exceptions.EndpointNotFound, ab_sc.url_for,
|
||||
service_type='compute', service_name='NotExist',
|
||||
endpoint_type='public')
|
@ -1,32 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import services
|
||||
|
||||
|
||||
class ServiceTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(ServiceTests, self).setUp()
|
||||
self.key = 'service'
|
||||
self.collection_key = 'services'
|
||||
self.model = services.Service
|
||||
self.manager = self.client.services
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs = super(ServiceTests, self).new_ref(**kwargs)
|
||||
kwargs.setdefault('name', uuid.uuid4().hex)
|
||||
kwargs.setdefault('type', uuid.uuid4().hex)
|
||||
kwargs.setdefault('enabled', True)
|
||||
return kwargs
|
@ -1,108 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.openstack.common import timeutils
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3.contrib import trusts
|
||||
|
||||
|
||||
class TrustTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(TrustTests, self).setUp()
|
||||
self.key = 'trust'
|
||||
self.collection_key = 'trusts'
|
||||
self.model = trusts.Trust
|
||||
self.manager = self.client.trusts
|
||||
self.path_prefix = 'OS-TRUST'
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs = super(TrustTests, self).new_ref(**kwargs)
|
||||
kwargs.setdefault('project_id', uuid.uuid4().hex)
|
||||
return kwargs
|
||||
|
||||
def test_create(self):
|
||||
ref = self.new_ref()
|
||||
ref['trustor_user_id'] = uuid.uuid4().hex
|
||||
ref['trustee_user_id'] = uuid.uuid4().hex
|
||||
ref['impersonation'] = False
|
||||
super(TrustTests, self).test_create(ref=ref)
|
||||
|
||||
def test_create_limited_uses(self):
|
||||
ref = self.new_ref()
|
||||
ref['trustor_user_id'] = uuid.uuid4().hex
|
||||
ref['trustee_user_id'] = uuid.uuid4().hex
|
||||
ref['impersonation'] = False
|
||||
ref['remaining_uses'] = 5
|
||||
super(TrustTests, self).test_create(ref=ref)
|
||||
|
||||
def test_create_roles(self):
|
||||
ref = self.new_ref()
|
||||
ref['trustor_user_id'] = uuid.uuid4().hex
|
||||
ref['trustee_user_id'] = uuid.uuid4().hex
|
||||
ref['impersonation'] = False
|
||||
req_ref = ref.copy()
|
||||
|
||||
# Note the TrustManager takes a list of role_names, and converts
|
||||
# internally to the slightly odd list-of-dict API format, so we
|
||||
# have to pass the expected request data to allow correct stubbing
|
||||
ref['role_names'] = ['atestrole']
|
||||
req_ref['roles'] = [{'name': 'atestrole'}]
|
||||
super(TrustTests, self).test_create(ref=ref, req_ref=req_ref)
|
||||
|
||||
def test_create_expires(self):
|
||||
ref = self.new_ref()
|
||||
ref['trustor_user_id'] = uuid.uuid4().hex
|
||||
ref['trustee_user_id'] = uuid.uuid4().hex
|
||||
ref['impersonation'] = False
|
||||
ref['expires_at'] = timeutils.parse_isotime(
|
||||
'2013-03-04T12:00:01.000000Z')
|
||||
req_ref = ref.copy()
|
||||
|
||||
# Note the TrustManager takes a datetime.datetime object for
|
||||
# expires_at, and converts it internally into an iso format datestamp
|
||||
req_ref['expires_at'] = '2013-03-04T12:00:01.000000Z'
|
||||
super(TrustTests, self).test_create(ref=ref, req_ref=req_ref)
|
||||
|
||||
def test_create_imp(self):
|
||||
ref = self.new_ref()
|
||||
ref['trustor_user_id'] = uuid.uuid4().hex
|
||||
ref['trustee_user_id'] = uuid.uuid4().hex
|
||||
ref['impersonation'] = True
|
||||
super(TrustTests, self).test_create(ref=ref)
|
||||
|
||||
def test_create_roles_imp(self):
|
||||
ref = self.new_ref()
|
||||
ref['trustor_user_id'] = uuid.uuid4().hex
|
||||
ref['trustee_user_id'] = uuid.uuid4().hex
|
||||
ref['impersonation'] = True
|
||||
req_ref = ref.copy()
|
||||
ref['role_names'] = ['atestrole']
|
||||
req_ref['roles'] = [{'name': 'atestrole'}]
|
||||
super(TrustTests, self).test_create(ref=ref, req_ref=req_ref)
|
||||
|
||||
def test_list_filter_trustor(self):
|
||||
expected_query = {'trustor_user_id': '12345'}
|
||||
super(TrustTests, self).test_list(expected_query=expected_query,
|
||||
trustor_user='12345')
|
||||
|
||||
def test_list_filter_trustee(self):
|
||||
expected_query = {'trustee_user_id': '12345'}
|
||||
super(TrustTests, self).test_list(expected_query=expected_query,
|
||||
trustee_user='12345')
|
||||
|
||||
def test_update(self):
|
||||
# Update not supported for the OS-TRUST API
|
||||
self.assertRaises(exceptions.MethodNotImplemented, self.manager.update)
|
@ -1,251 +0,0 @@
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
#
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3 import users
|
||||
|
||||
|
||||
class UserTests(utils.TestCase, utils.CrudTests):
|
||||
def setUp(self):
|
||||
super(UserTests, self).setUp()
|
||||
self.key = 'user'
|
||||
self.collection_key = 'users'
|
||||
self.model = users.User
|
||||
self.manager = self.client.users
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs = super(UserTests, self).new_ref(**kwargs)
|
||||
kwargs.setdefault('description', uuid.uuid4().hex)
|
||||
kwargs.setdefault('domain_id', uuid.uuid4().hex)
|
||||
kwargs.setdefault('enabled', True)
|
||||
kwargs.setdefault('name', uuid.uuid4().hex)
|
||||
kwargs.setdefault('default_project_id', uuid.uuid4().hex)
|
||||
return kwargs
|
||||
|
||||
@httpretty.activate
|
||||
def test_add_user_to_group(self):
|
||||
group_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
self.stub_url(httpretty.PUT,
|
||||
['groups', group_id, self.collection_key, ref['id']],
|
||||
status=204)
|
||||
|
||||
self.manager.add_to_group(user=ref['id'], group=group_id)
|
||||
self.assertRaises(exceptions.ValidationError,
|
||||
self.manager.remove_from_group,
|
||||
user=ref['id'],
|
||||
group=None)
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_users_in_group(self):
|
||||
group_id = uuid.uuid4().hex
|
||||
ref_list = [self.new_ref(), self.new_ref()]
|
||||
|
||||
self.stub_entity(httpretty.GET,
|
||||
['groups', group_id, self.collection_key],
|
||||
entity=ref_list)
|
||||
|
||||
returned_list = self.manager.list(group=group_id)
|
||||
self.assertEqual(len(ref_list), len(returned_list))
|
||||
[self.assertIsInstance(r, self.model) for r in returned_list]
|
||||
|
||||
@httpretty.activate
|
||||
def test_check_user_in_group(self):
|
||||
group_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.HEAD,
|
||||
['groups', group_id, self.collection_key, ref['id']],
|
||||
status=204)
|
||||
|
||||
self.manager.check_in_group(user=ref['id'], group=group_id)
|
||||
|
||||
self.assertRaises(exceptions.ValidationError,
|
||||
self.manager.check_in_group,
|
||||
user=ref['id'],
|
||||
group=None)
|
||||
|
||||
@httpretty.activate
|
||||
def test_remove_user_from_group(self):
|
||||
group_id = uuid.uuid4().hex
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_url(httpretty.DELETE,
|
||||
['groups', group_id, self.collection_key, ref['id']],
|
||||
status=204)
|
||||
|
||||
self.manager.remove_from_group(user=ref['id'], group=group_id)
|
||||
self.assertRaises(exceptions.ValidationError,
|
||||
self.manager.remove_from_group,
|
||||
user=ref['id'],
|
||||
group=None)
|
||||
|
||||
@httpretty.activate
|
||||
def test_create_with_project(self):
|
||||
# Can create a user with the deprecated project option rather than
|
||||
# default_project_id.
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_entity(httpretty.POST, [self.collection_key],
|
||||
status=201, entity=ref)
|
||||
|
||||
req_ref = ref.copy()
|
||||
req_ref.pop('id')
|
||||
param_ref = req_ref.copy()
|
||||
# Use deprecated project_id rather than new default_project_id.
|
||||
param_ref['project_id'] = param_ref.pop('default_project_id')
|
||||
params = utils.parameterize(param_ref)
|
||||
|
||||
returned = self.manager.create(**params)
|
||||
self.assertIsInstance(returned, self.model)
|
||||
for attr in ref:
|
||||
self.assertEqual(
|
||||
getattr(returned, attr),
|
||||
ref[attr],
|
||||
'Expected different %s' % attr)
|
||||
self.assertEntityRequestBodyIs(req_ref)
|
||||
|
||||
@httpretty.activate
|
||||
def test_create_with_project_and_default_project(self):
|
||||
# Can create a user with the deprecated project and default_project_id.
|
||||
# The backend call should only pass the default_project_id.
|
||||
ref = self.new_ref()
|
||||
|
||||
self.stub_entity(httpretty.POST,
|
||||
[self.collection_key],
|
||||
status=201, entity=ref)
|
||||
|
||||
req_ref = ref.copy()
|
||||
req_ref.pop('id')
|
||||
param_ref = req_ref.copy()
|
||||
|
||||
# Add the deprecated project_id in the call, the value will be ignored.
|
||||
param_ref['project_id'] = 'project'
|
||||
params = utils.parameterize(param_ref)
|
||||
|
||||
returned = self.manager.create(**params)
|
||||
self.assertIsInstance(returned, self.model)
|
||||
for attr in ref:
|
||||
self.assertEqual(
|
||||
getattr(returned, attr),
|
||||
ref[attr],
|
||||
'Expected different %s' % attr)
|
||||
self.assertEntityRequestBodyIs(req_ref)
|
||||
|
||||
@httpretty.activate
|
||||
def test_update_with_project(self):
|
||||
# Can update a user with the deprecated project option rather than
|
||||
# default_project_id.
|
||||
ref = self.new_ref()
|
||||
req_ref = ref.copy()
|
||||
req_ref.pop('id')
|
||||
param_ref = req_ref.copy()
|
||||
|
||||
self.stub_entity(httpretty.PATCH,
|
||||
[self.collection_key, ref['id']],
|
||||
status=200, entity=ref)
|
||||
|
||||
# Use deprecated project_id rather than new default_project_id.
|
||||
param_ref['project_id'] = param_ref.pop('default_project_id')
|
||||
params = utils.parameterize(param_ref)
|
||||
|
||||
returned = self.manager.update(ref['id'], **params)
|
||||
self.assertIsInstance(returned, self.model)
|
||||
for attr in ref:
|
||||
self.assertEqual(
|
||||
getattr(returned, attr),
|
||||
ref[attr],
|
||||
'Expected different %s' % attr)
|
||||
self.assertEntityRequestBodyIs(req_ref)
|
||||
|
||||
@httpretty.activate
|
||||
def test_update_with_project_and_default_project(self, ref=None):
|
||||
ref = self.new_ref()
|
||||
req_ref = ref.copy()
|
||||
req_ref.pop('id')
|
||||
param_ref = req_ref.copy()
|
||||
|
||||
self.stub_entity(httpretty.PATCH,
|
||||
[self.collection_key, ref['id']],
|
||||
status=200, entity=ref)
|
||||
|
||||
# Add the deprecated project_id in the call, the value will be ignored.
|
||||
param_ref['project_id'] = 'project'
|
||||
params = utils.parameterize(param_ref)
|
||||
|
||||
returned = self.manager.update(ref['id'], **params)
|
||||
self.assertIsInstance(returned, self.model)
|
||||
for attr in ref:
|
||||
self.assertEqual(
|
||||
getattr(returned, attr),
|
||||
ref[attr],
|
||||
'Expected different %s' % attr)
|
||||
self.assertEntityRequestBodyIs(req_ref)
|
||||
|
||||
@httpretty.activate
|
||||
def test_update_password(self):
|
||||
old_password = uuid.uuid4().hex
|
||||
new_password = uuid.uuid4().hex
|
||||
|
||||
self.stub_url(httpretty.POST,
|
||||
[self.collection_key, self.TEST_USER, 'password'])
|
||||
self.client.user_id = self.TEST_USER
|
||||
self.manager.update_password(old_password, new_password)
|
||||
|
||||
exp_req_body = {
|
||||
'user': {
|
||||
'password': new_password, 'original_password': old_password
|
||||
}
|
||||
}
|
||||
|
||||
self.assertEqual('/v3/users/test/password',
|
||||
httpretty.last_request().path)
|
||||
self.assertRequestBodyIs(json=exp_req_body)
|
||||
|
||||
def test_update_password_with_bad_inputs(self):
|
||||
old_password = uuid.uuid4().hex
|
||||
new_password = uuid.uuid4().hex
|
||||
|
||||
# users can't unset their password
|
||||
self.assertRaises(exceptions.ValidationError,
|
||||
self.manager.update_password,
|
||||
old_password, None)
|
||||
self.assertRaises(exceptions.ValidationError,
|
||||
self.manager.update_password,
|
||||
old_password, '')
|
||||
|
||||
# users can't start with empty passwords
|
||||
self.assertRaises(exceptions.ValidationError,
|
||||
self.manager.update_password,
|
||||
None, new_password)
|
||||
self.assertRaises(exceptions.ValidationError,
|
||||
self.manager.update_password,
|
||||
'', new_password)
|
||||
|
||||
# this wouldn't result in any change anyway
|
||||
self.assertRaises(exceptions.ValidationError,
|
||||
self.manager.update_password,
|
||||
None, None)
|
||||
self.assertRaises(exceptions.ValidationError,
|
||||
self.manager.update_password,
|
||||
'', '')
|
||||
password = uuid.uuid4().hex
|
||||
self.assertRaises(exceptions.ValidationError,
|
||||
self.manager.update_password,
|
||||
password, password)
|
@ -1,327 +0,0 @@
|
||||
# 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 uuid
|
||||
|
||||
import httpretty
|
||||
import six
|
||||
from six.moves.urllib import parse as urlparse
|
||||
|
||||
from keystoneclient.openstack.common import jsonutils
|
||||
from keystoneclient.tests import utils
|
||||
from keystoneclient.v3 import client
|
||||
|
||||
|
||||
TestResponse = utils.TestResponse
|
||||
|
||||
|
||||
def parameterize(ref):
|
||||
"""Rewrites attributes to match the kwarg naming convention in client.
|
||||
|
||||
>>> parameterize({'project_id': 0})
|
||||
{'project': 0}
|
||||
|
||||
"""
|
||||
params = ref.copy()
|
||||
for key in ref:
|
||||
if key[-3:] == '_id':
|
||||
params.setdefault(key[:-3], params.pop(key))
|
||||
return params
|
||||
|
||||
|
||||
class UnauthenticatedTestCase(utils.TestCase):
|
||||
"""Class used as base for unauthenticated calls."""
|
||||
|
||||
TEST_ROOT_URL = 'http://127.0.0.1:5000/'
|
||||
TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3')
|
||||
TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/'
|
||||
TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v3')
|
||||
|
||||
|
||||
class TestCase(UnauthenticatedTestCase):
|
||||
|
||||
TEST_ADMIN_IDENTITY_ENDPOINT = "http://127.0.0.1:35357/v3"
|
||||
|
||||
TEST_SERVICE_CATALOG = [{
|
||||
"endpoints": [{
|
||||
"url": "http://cdn.admin-nets.local:8774/v1.0/",
|
||||
"region": "RegionOne",
|
||||
"interface": "public"
|
||||
}, {
|
||||
"url": "http://127.0.0.1:8774/v1.0",
|
||||
"region": "RegionOne",
|
||||
"interface": "internal"
|
||||
}, {
|
||||
"url": "http://cdn.admin-nets.local:8774/v1.0",
|
||||
"region": "RegionOne",
|
||||
"interface": "admin"
|
||||
}],
|
||||
"type": "nova_compat"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"url": "http://nova/novapi/public",
|
||||
"region": "RegionOne",
|
||||
"interface": "public"
|
||||
}, {
|
||||
"url": "http://nova/novapi/internal",
|
||||
"region": "RegionOne",
|
||||
"interface": "internal"
|
||||
}, {
|
||||
"url": "http://nova/novapi/admin",
|
||||
"region": "RegionOne",
|
||||
"interface": "admin"
|
||||
}],
|
||||
"type": "compute"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"url": "http://glance/glanceapi/public",
|
||||
"region": "RegionOne",
|
||||
"interface": "public"
|
||||
}, {
|
||||
"url": "http://glance/glanceapi/internal",
|
||||
"region": "RegionOne",
|
||||
"interface": "internal"
|
||||
}, {
|
||||
"url": "http://glance/glanceapi/admin",
|
||||
"region": "RegionOne",
|
||||
"interface": "admin"
|
||||
}],
|
||||
"type": "image",
|
||||
"name": "glance"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"url": "http://127.0.0.1:5000/v3",
|
||||
"region": "RegionOne",
|
||||
"interface": "public"
|
||||
}, {
|
||||
"url": "http://127.0.0.1:5000/v3",
|
||||
"region": "RegionOne",
|
||||
"interface": "internal"
|
||||
}, {
|
||||
"url": TEST_ADMIN_IDENTITY_ENDPOINT,
|
||||
"region": "RegionOne",
|
||||
"interface": "admin"
|
||||
}],
|
||||
"type": "identity"
|
||||
}, {
|
||||
"endpoints": [{
|
||||
"url": "http://swift/swiftapi/public",
|
||||
"region": "RegionOne",
|
||||
"interface": "public"
|
||||
}, {
|
||||
"url": "http://swift/swiftapi/internal",
|
||||
"region": "RegionOne",
|
||||
"interface": "internal"
|
||||
}, {
|
||||
"url": "http://swift/swiftapi/admin",
|
||||
"region": "RegionOne",
|
||||
"interface": "admin"
|
||||
}],
|
||||
"type": "object-store"
|
||||
}]
|
||||
|
||||
def setUp(self):
|
||||
super(TestCase, self).setUp()
|
||||
self.client = client.Client(username=self.TEST_USER,
|
||||
token=self.TEST_TOKEN,
|
||||
tenant_name=self.TEST_TENANT_NAME,
|
||||
auth_url=self.TEST_URL,
|
||||
endpoint=self.TEST_URL)
|
||||
|
||||
def stub_auth(self, subject_token=None, **kwargs):
|
||||
if not subject_token:
|
||||
subject_token = self.TEST_TOKEN
|
||||
|
||||
self.stub_url(httpretty.POST, ['auth', 'tokens'],
|
||||
X_Subject_Token=subject_token, **kwargs)
|
||||
|
||||
|
||||
class CrudTests(object):
|
||||
key = None
|
||||
collection_key = None
|
||||
model = None
|
||||
manager = None
|
||||
path_prefix = None
|
||||
|
||||
def new_ref(self, **kwargs):
|
||||
kwargs.setdefault('id', uuid.uuid4().hex)
|
||||
kwargs.setdefault(uuid.uuid4().hex, uuid.uuid4().hex)
|
||||
return kwargs
|
||||
|
||||
def encode(self, entity):
|
||||
if isinstance(entity, dict):
|
||||
return {self.key: entity}
|
||||
if isinstance(entity, list):
|
||||
return {self.collection_key: entity}
|
||||
raise NotImplementedError('Are you sure you want to encode that?')
|
||||
|
||||
def stub_entity(self, method, parts=None, entity=None, id=None, **kwargs):
|
||||
if entity:
|
||||
entity = self.encode(entity)
|
||||
kwargs['json'] = entity
|
||||
|
||||
if not parts:
|
||||
parts = [self.collection_key]
|
||||
|
||||
if self.path_prefix:
|
||||
parts.insert(0, self.path_prefix)
|
||||
|
||||
if id:
|
||||
if not parts:
|
||||
parts = []
|
||||
|
||||
parts.append(id)
|
||||
|
||||
self.stub_url(method, parts=parts, **kwargs)
|
||||
|
||||
def assertEntityRequestBodyIs(self, entity):
|
||||
self.assertRequestBodyIs(json=self.encode(entity))
|
||||
|
||||
@httpretty.activate
|
||||
def test_create(self, ref=None, req_ref=None):
|
||||
ref = ref or self.new_ref()
|
||||
manager_ref = ref.copy()
|
||||
manager_ref.pop('id')
|
||||
|
||||
# req_ref argument allows you to specify a different
|
||||
# signature for the request when the manager does some
|
||||
# conversion before doing the request (e.g. converting
|
||||
# from datetime object to timestamp string)
|
||||
req_ref = (req_ref or ref).copy()
|
||||
req_ref.pop('id')
|
||||
|
||||
self.stub_entity(httpretty.POST, entity=req_ref, status=201)
|
||||
|
||||
returned = self.manager.create(**parameterize(manager_ref))
|
||||
self.assertIsInstance(returned, self.model)
|
||||
for attr in req_ref:
|
||||
self.assertEqual(
|
||||
getattr(returned, attr),
|
||||
req_ref[attr],
|
||||
'Expected different %s' % attr)
|
||||
self.assertEntityRequestBodyIs(req_ref)
|
||||
|
||||
@httpretty.activate
|
||||
def test_get(self, ref=None):
|
||||
ref = ref or self.new_ref()
|
||||
|
||||
self.stub_entity(httpretty.GET, id=ref['id'], entity=ref)
|
||||
|
||||
returned = self.manager.get(ref['id'])
|
||||
self.assertIsInstance(returned, self.model)
|
||||
for attr in ref:
|
||||
self.assertEqual(
|
||||
getattr(returned, attr),
|
||||
ref[attr],
|
||||
'Expected different %s' % attr)
|
||||
|
||||
def _get_expected_path(self, expected_path=None):
|
||||
if not expected_path:
|
||||
if self.path_prefix:
|
||||
expected_path = 'v3/%s/%s' % (self.path_prefix,
|
||||
self.collection_key)
|
||||
else:
|
||||
expected_path = 'v3/%s' % self.collection_key
|
||||
|
||||
return expected_path
|
||||
|
||||
@httpretty.activate
|
||||
def test_list(self, ref_list=None, expected_path=None,
|
||||
expected_query=None, **filter_kwargs):
|
||||
ref_list = ref_list or [self.new_ref(), self.new_ref()]
|
||||
expected_path = self._get_expected_path(expected_path)
|
||||
|
||||
httpretty.register_uri(httpretty.GET,
|
||||
urlparse.urljoin(self.TEST_URL, expected_path),
|
||||
body=jsonutils.dumps(self.encode(ref_list)))
|
||||
|
||||
returned_list = self.manager.list(**filter_kwargs)
|
||||
self.assertEqual(len(ref_list), len(returned_list))
|
||||
[self.assertIsInstance(r, self.model) for r in returned_list]
|
||||
|
||||
# register_uri doesn't match the querystring component, so we have to
|
||||
# explicitly test the querystring component passed by the manager
|
||||
qs_args = httpretty.last_request().querystring
|
||||
qs_args_expected = expected_query or filter_kwargs
|
||||
for key, value in six.iteritems(qs_args_expected):
|
||||
self.assertIn(key, qs_args)
|
||||
# The httppretty.querystring value is a list
|
||||
# Note we convert the value to a string, as the query string
|
||||
# is always a string and the filter_kwargs may contain non-string
|
||||
# values, for example a boolean, causing the comaprison to fail.
|
||||
self.assertIn(str(value), qs_args[key])
|
||||
|
||||
# Also check that no query string args exist which are not expected
|
||||
for key in qs_args:
|
||||
self.assertIn(key, qs_args_expected)
|
||||
|
||||
@httpretty.activate
|
||||
def test_list_params(self):
|
||||
ref_list = [self.new_ref()]
|
||||
filter_kwargs = {uuid.uuid4().hex: uuid.uuid4().hex}
|
||||
expected_path = self._get_expected_path()
|
||||
|
||||
httpretty.register_uri(httpretty.GET,
|
||||
urlparse.urljoin(self.TEST_URL, expected_path),
|
||||
body=jsonutils.dumps(self.encode(ref_list)))
|
||||
|
||||
self.manager.list(**filter_kwargs)
|
||||
self.assertQueryStringContains(**filter_kwargs)
|
||||
|
||||
@httpretty.activate
|
||||
def test_find(self, ref=None):
|
||||
ref = ref or self.new_ref()
|
||||
ref_list = [ref]
|
||||
|
||||
self.stub_entity(httpretty.GET, entity=ref_list)
|
||||
|
||||
returned = self.manager.find(name=getattr(ref, 'name', None))
|
||||
self.assertIsInstance(returned, self.model)
|
||||
for attr in ref:
|
||||
self.assertEqual(
|
||||
getattr(returned, attr),
|
||||
ref[attr],
|
||||
'Expected different %s' % attr)
|
||||
|
||||
if hasattr(ref, 'name'):
|
||||
self.assertQueryStringIs('name=%s' % ref['name'])
|
||||
else:
|
||||
self.assertQueryStringIs('')
|
||||
|
||||
@httpretty.activate
|
||||
def test_update(self, ref=None, req_ref=None):
|
||||
ref = ref or self.new_ref()
|
||||
|
||||
self.stub_entity(httpretty.PATCH, id=ref['id'], entity=ref)
|
||||
|
||||
# req_ref argument allows you to specify a different
|
||||
# signature for the request when the manager does some
|
||||
# conversion before doing the request (e.g. converting
|
||||
# from datetime object to timestamp string)
|
||||
req_ref = (req_ref or ref).copy()
|
||||
req_ref.pop('id')
|
||||
|
||||
returned = self.manager.update(ref['id'], **parameterize(req_ref))
|
||||
self.assertIsInstance(returned, self.model)
|
||||
for attr in ref:
|
||||
self.assertEqual(
|
||||
getattr(returned, attr),
|
||||
ref[attr],
|
||||
'Expected different %s' % attr)
|
||||
self.assertEntityRequestBodyIs(req_ref)
|
||||
|
||||
@httpretty.activate
|
||||
def test_delete(self, ref=None):
|
||||
ref = ref or self.new_ref()
|
||||
|
||||
self.stub_entity(httpretty.DELETE, id=ref['id'], status=204)
|
||||
self.manager.delete(ref['id'])
|
Loading…
Reference in New Issue
Block a user