Important changes for service filtering
Some important changes for service filtering to support resources: * Support the notion of ANY service_type in the service filter for user preferences. * Create a join method in ServiceFilter to join a resource filter with a user preference. * Support service filter preference in session. For example if a user wanted to use region='East' they would create a service filter preference in their session with that region and use that session with any resource. Change-Id: I13fc2838b66ec85bdd0191c78b27b3cd685a8322
This commit is contained in:
@@ -106,6 +106,11 @@ def option_parser():
|
|||||||
default=env('OS_PASSWORD'),
|
default=env('OS_PASSWORD'),
|
||||||
help='Authentication password (Env: OS_PASSWORD)',
|
help='Authentication password (Env: OS_PASSWORD)',
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--os-region',
|
||||||
|
metavar='<region>',
|
||||||
|
default=env('OS_REGION'),
|
||||||
|
help='Service region (Env: OS_REGION)')
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--os-cacert',
|
'--os-cacert',
|
||||||
metavar='<ca-bundle-file>',
|
metavar='<ca-bundle-file>',
|
||||||
|
@@ -20,9 +20,11 @@ from openstack import session
|
|||||||
|
|
||||||
|
|
||||||
def make_session(opts):
|
def make_session(opts):
|
||||||
|
region = opts.os_region
|
||||||
|
preference = service_filter.ServiceFilter(region=region)
|
||||||
xport = transport.make_transport(opts)
|
xport = transport.make_transport(opts)
|
||||||
auth = authenticate.make_authenticate(opts)
|
auth = authenticate.make_authenticate(opts)
|
||||||
return session.Session(xport, auth)
|
return session.Session(xport, auth, preference=preference)
|
||||||
|
|
||||||
|
|
||||||
def run_session(opts):
|
def run_session(opts):
|
||||||
@@ -30,7 +32,7 @@ def run_session(opts):
|
|||||||
if argument is None:
|
if argument is None:
|
||||||
raise Exception("A path argument must be specified")
|
raise Exception("A path argument must be specified")
|
||||||
sess = make_session(opts)
|
sess = make_session(opts)
|
||||||
filtration = service_filter.ServiceFilter('Identity')
|
filtration = service_filter.ServiceFilter(service_type='Identity')
|
||||||
print("Session: %s" % sess)
|
print("Session: %s" % sess)
|
||||||
print(sess.get(argument, service=filtration).text)
|
print(sess.get(argument, service=filtration).text)
|
||||||
return
|
return
|
||||||
|
@@ -16,12 +16,13 @@ from openstack import exceptions
|
|||||||
class ServiceFilter(object):
|
class ServiceFilter(object):
|
||||||
"""The basic structure of an authentication plugin."""
|
"""The basic structure of an authentication plugin."""
|
||||||
|
|
||||||
|
ANY = 'any'
|
||||||
PUBLIC = 'public'
|
PUBLIC = 'public'
|
||||||
INTERNAL = 'internal'
|
INTERNAL = 'internal'
|
||||||
ADMIN = 'admin'
|
ADMIN = 'admin'
|
||||||
VISIBILITY = [PUBLIC, INTERNAL, ADMIN]
|
VISIBILITY = [PUBLIC, INTERNAL, ADMIN]
|
||||||
|
|
||||||
def __init__(self, service_type, visibility=PUBLIC, region=None,
|
def __init__(self, service_type=ANY, visibility=PUBLIC, region=None,
|
||||||
service_name=None):
|
service_name=None):
|
||||||
"""" Create a service identifier.
|
"""" Create a service identifier.
|
||||||
|
|
||||||
@@ -31,9 +32,6 @@ class ServiceFilter(object):
|
|||||||
:param string region: The desired region (optional).
|
:param string region: The desired region (optional).
|
||||||
:param string service_name: Name of the service
|
:param string service_name: Name of the service
|
||||||
"""
|
"""
|
||||||
if not service_type:
|
|
||||||
msg = "Service type must be specified to locate service"
|
|
||||||
raise exceptions.SDKException(msg)
|
|
||||||
self.service_type = service_type.lower()
|
self.service_type = service_type.lower()
|
||||||
if not visibility:
|
if not visibility:
|
||||||
msg = "Visibility must be specified to locate service"
|
msg = "Visibility must be specified to locate service"
|
||||||
@@ -55,7 +53,15 @@ class ServiceFilter(object):
|
|||||||
ret += ",service_name=%s" % self.service_name
|
ret += ",service_name=%s" % self.service_name
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def join(self, default):
|
||||||
|
return ServiceFilter(service_type=default.service_type,
|
||||||
|
visibility=default.visibility,
|
||||||
|
region=self.region,
|
||||||
|
service_name=self.service_name)
|
||||||
|
|
||||||
def match_service_type(self, service_type):
|
def match_service_type(self, service_type):
|
||||||
|
if self.service_type == self.ANY:
|
||||||
|
return True
|
||||||
return self.service_type == service_type
|
return self.service_type == service_type
|
||||||
|
|
||||||
def match_service_name(self, service_name):
|
def match_service_name(self, service_name):
|
||||||
|
@@ -20,7 +20,7 @@ _logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class Session(object):
|
class Session(object):
|
||||||
|
|
||||||
def __init__(self, transport, authenticator):
|
def __init__(self, transport, authenticator, preference=None):
|
||||||
"""Maintains client communication session.
|
"""Maintains client communication session.
|
||||||
|
|
||||||
Session layer which uses the transport for communication. The
|
Session layer which uses the transport for communication. The
|
||||||
@@ -28,9 +28,12 @@ class Session(object):
|
|||||||
|
|
||||||
:param transport: A transport layer for the session.
|
:param transport: A transport layer for the session.
|
||||||
:param authenticator: An authenticator to authenticate the session.
|
:param authenticator: An authenticator to authenticate the session.
|
||||||
|
:param ServiceFilter preference: Service filter preference.
|
||||||
|
:type preference: :class:`openstack.auth.service_filter.ServiceFilter`
|
||||||
"""
|
"""
|
||||||
self.transport = transport
|
self.transport = transport
|
||||||
self.authenticator = authenticator
|
self.authenticator = authenticator
|
||||||
|
self.preference = preference
|
||||||
|
|
||||||
def _request(self, path, method, service=None, authenticate=True,
|
def _request(self, path, method, service=None, authenticate=True,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
@@ -55,6 +58,8 @@ class Session(object):
|
|||||||
token = self.authenticator.get_token(self.transport)
|
token = self.authenticator.get_token(self.transport)
|
||||||
if token:
|
if token:
|
||||||
headers['X-Auth-Token'] = token
|
headers['X-Auth-Token'] = token
|
||||||
|
if service and self.preference:
|
||||||
|
service = self.preference.join(service)
|
||||||
|
|
||||||
endpoint = self.authenticator.get_endpoint(self.transport, service)
|
endpoint = self.authenticator.get_endpoint(self.transport, service)
|
||||||
url = utils.urljoin(endpoint, path)
|
url = utils.urljoin(endpoint, path)
|
||||||
|
@@ -20,37 +20,44 @@ from openstack.tests.auth import common
|
|||||||
|
|
||||||
class TestServiceCatalog(testtools.TestCase):
|
class TestServiceCatalog(testtools.TestCase):
|
||||||
def get_urls(self, sot):
|
def get_urls(self, sot):
|
||||||
sf = service_filter.ServiceFilter('compute')
|
sf = service_filter.ServiceFilter(service_type='compute')
|
||||||
exp = ["http://compute.region2.public/",
|
exp = ["http://compute.region2.public/",
|
||||||
"http://compute.region1.public/"]
|
"http://compute.region1.public/"]
|
||||||
self.assertEqual(exp, sot.get_urls(sf))
|
self.assertEqual(exp, sot.get_urls(sf))
|
||||||
sf = service_filter.ServiceFilter('image')
|
sf = service_filter.ServiceFilter(service_type='image')
|
||||||
self.assertEqual(["http://image.region1.public/"], sot.get_urls(sf))
|
self.assertEqual(["http://image.region1.public/"], sot.get_urls(sf))
|
||||||
sf = service_filter.ServiceFilter('identity')
|
sf = service_filter.ServiceFilter(service_type='identity')
|
||||||
self.assertEqual(["http://identity.region1.public/"], sot.get_urls(sf))
|
self.assertEqual(["http://identity.region1.public/"], sot.get_urls(sf))
|
||||||
sf = service_filter.ServiceFilter('object-store')
|
sf = service_filter.ServiceFilter(service_type='object-store')
|
||||||
self.assertEqual(["http://object-store.region1.public/"],
|
self.assertEqual(["http://object-store.region1.public/"],
|
||||||
sot.get_urls(sf))
|
sot.get_urls(sf))
|
||||||
|
|
||||||
def get_urls_name(self, sot):
|
def get_urls_name(self, sot):
|
||||||
sf = service_filter.ServiceFilter('compute', service_name='nova')
|
sf = service_filter.ServiceFilter(service_type='compute',
|
||||||
|
service_name='nova')
|
||||||
self.assertEqual(["http://compute.region1.public/"], sot.get_urls(sf))
|
self.assertEqual(["http://compute.region1.public/"], sot.get_urls(sf))
|
||||||
sf = service_filter.ServiceFilter('compute', service_name='nova2')
|
sf = service_filter.ServiceFilter(service_type='compute',
|
||||||
|
service_name='nova2')
|
||||||
self.assertEqual(["http://compute.region2.public/"], sot.get_urls(sf))
|
self.assertEqual(["http://compute.region2.public/"], sot.get_urls(sf))
|
||||||
|
|
||||||
def get_urls_region(self, sot):
|
def get_urls_region(self, sot):
|
||||||
sf = service_filter.ServiceFilter('compute', region='RegionTwo')
|
sf = service_filter.ServiceFilter(service_type='compute',
|
||||||
|
region='RegionTwo')
|
||||||
self.assertEqual(["http://compute.region2.public/"], sot.get_urls(sf))
|
self.assertEqual(["http://compute.region2.public/"], sot.get_urls(sf))
|
||||||
sf = service_filter.ServiceFilter('compute', region='RegionOne')
|
sf = service_filter.ServiceFilter(service_type='compute',
|
||||||
|
region='RegionOne')
|
||||||
self.assertEqual(["http://compute.region1.public/"], sot.get_urls(sf))
|
self.assertEqual(["http://compute.region1.public/"], sot.get_urls(sf))
|
||||||
|
|
||||||
def get_urls_visibility(self, sot):
|
def get_urls_visibility(self, sot):
|
||||||
sf = service_filter.ServiceFilter('identity', visibility='admin')
|
sf = service_filter.ServiceFilter(service_type='identity',
|
||||||
|
visibility='admin')
|
||||||
self.assertEqual(["http://identity.region1.admin/"], sot.get_urls(sf))
|
self.assertEqual(["http://identity.region1.admin/"], sot.get_urls(sf))
|
||||||
sf = service_filter.ServiceFilter('identity', visibility='internal')
|
sf = service_filter.ServiceFilter(service_type='identity',
|
||||||
|
visibility='internal')
|
||||||
self.assertEqual(["http://identity.region1.internal/"],
|
self.assertEqual(["http://identity.region1.internal/"],
|
||||||
sot.get_urls(sf))
|
sot.get_urls(sf))
|
||||||
sf = service_filter.ServiceFilter('identity', visibility='public')
|
sf = service_filter.ServiceFilter(service_type='identity',
|
||||||
|
visibility='public')
|
||||||
self.assertEqual(["http://identity.region1.public/"], sot.get_urls(sf))
|
self.assertEqual(["http://identity.region1.public/"], sot.get_urls(sf))
|
||||||
|
|
||||||
|
|
||||||
|
@@ -19,69 +19,89 @@ from openstack import exceptions
|
|||||||
|
|
||||||
class TestServiceFilter(testtools.TestCase):
|
class TestServiceFilter(testtools.TestCase):
|
||||||
def test_minimum(self):
|
def test_minimum(self):
|
||||||
sot = filt.ServiceFilter('identity')
|
sot = filt.ServiceFilter()
|
||||||
self.assertEqual("service_type=identity,visibility=public",
|
self.assertEqual("service_type=any,visibility=public",
|
||||||
six.text_type(sot))
|
six.text_type(sot))
|
||||||
|
|
||||||
def test_maximum(self):
|
def test_maximum(self):
|
||||||
sot = filt.ServiceFilter('compute', visibility='admin', region='b',
|
sot = filt.ServiceFilter(service_type='compute', visibility='admin',
|
||||||
service_name='c')
|
region='b', service_name='c')
|
||||||
exp = "service_type=compute,visibility=admin,region=b,service_name=c"
|
exp = "service_type=compute,visibility=admin,region=b,service_name=c"
|
||||||
self.assertEqual(exp, six.text_type(sot))
|
self.assertEqual(exp, six.text_type(sot))
|
||||||
|
|
||||||
def test_visibility(self):
|
def test_visibility(self):
|
||||||
sot = filt.ServiceFilter('identity', visibility='public')
|
sot = filt.ServiceFilter(service_type='identity', visibility='public')
|
||||||
self.assertEqual("service_type=identity,visibility=public",
|
self.assertEqual("service_type=identity,visibility=public",
|
||||||
six.text_type(sot))
|
six.text_type(sot))
|
||||||
sot = filt.ServiceFilter('identity', visibility='internal')
|
sot = filt.ServiceFilter(service_type='identity',
|
||||||
|
visibility='internal')
|
||||||
self.assertEqual("service_type=identity,visibility=internal",
|
self.assertEqual("service_type=identity,visibility=internal",
|
||||||
six.text_type(sot))
|
six.text_type(sot))
|
||||||
sot = filt.ServiceFilter('identity', visibility='admin')
|
sot = filt.ServiceFilter(service_type='identity', visibility='admin')
|
||||||
self.assertEqual("service_type=identity,visibility=admin",
|
self.assertEqual("service_type=identity,visibility=admin",
|
||||||
six.text_type(sot))
|
six.text_type(sot))
|
||||||
sot = filt.ServiceFilter('identity', visibility='publicURL')
|
sot = filt.ServiceFilter(service_type='identity',
|
||||||
|
visibility='publicURL')
|
||||||
self.assertEqual("service_type=identity,visibility=public",
|
self.assertEqual("service_type=identity,visibility=public",
|
||||||
six.text_type(sot))
|
six.text_type(sot))
|
||||||
sot = filt.ServiceFilter('identity', visibility='internalURL')
|
sot = filt.ServiceFilter(service_type='identity',
|
||||||
|
visibility='internalURL')
|
||||||
self.assertEqual("service_type=identity,visibility=internal",
|
self.assertEqual("service_type=identity,visibility=internal",
|
||||||
six.text_type(sot))
|
six.text_type(sot))
|
||||||
sot = filt.ServiceFilter('identity', visibility='adminURL')
|
sot = filt.ServiceFilter(service_type='identity',
|
||||||
|
visibility='adminURL')
|
||||||
self.assertEqual("service_type=identity,visibility=admin",
|
self.assertEqual("service_type=identity,visibility=admin",
|
||||||
six.text_type(sot))
|
six.text_type(sot))
|
||||||
self.assertRaises(exceptions.SDKException,
|
|
||||||
filt.ServiceFilter, 'identity', visibility='b')
|
|
||||||
self.assertRaises(exceptions.SDKException, filt.ServiceFilter,
|
self.assertRaises(exceptions.SDKException, filt.ServiceFilter,
|
||||||
'identity', visibility=None)
|
service_type='identity', visibility='b')
|
||||||
self.assertRaises(exceptions.SDKException, filt.ServiceFilter, None)
|
self.assertRaises(exceptions.SDKException, filt.ServiceFilter,
|
||||||
self.assertRaises(exceptions.SDKException, filt.ServiceFilter, None)
|
service_type='identity', visibility=None)
|
||||||
|
|
||||||
def test_match_service_type(self):
|
def test_match_service_type(self):
|
||||||
sot = filt.ServiceFilter('identity')
|
sot = filt.ServiceFilter(service_type='identity')
|
||||||
self.assertTrue(sot.match_service_type('identity'))
|
self.assertTrue(sot.match_service_type('identity'))
|
||||||
self.assertFalse(sot.match_service_type('compute'))
|
self.assertFalse(sot.match_service_type('compute'))
|
||||||
|
|
||||||
|
def test_match_service_type_any(self):
|
||||||
|
sot = filt.ServiceFilter()
|
||||||
|
self.assertTrue(sot.match_service_type('identity'))
|
||||||
|
self.assertTrue(sot.match_service_type('compute'))
|
||||||
|
|
||||||
def test_match_service_name(self):
|
def test_match_service_name(self):
|
||||||
sot = filt.ServiceFilter('identity')
|
sot = filt.ServiceFilter(service_type='identity')
|
||||||
self.assertTrue(sot.match_service_name('keystone'))
|
self.assertTrue(sot.match_service_name('keystone'))
|
||||||
self.assertTrue(sot.match_service_name('ldap'))
|
self.assertTrue(sot.match_service_name('ldap'))
|
||||||
self.assertTrue(sot.match_service_name(None))
|
self.assertTrue(sot.match_service_name(None))
|
||||||
sot = filt.ServiceFilter('identity', service_name='keystone')
|
sot = filt.ServiceFilter(service_type='identity',
|
||||||
|
service_name='keystone')
|
||||||
self.assertTrue(sot.match_service_name('keystone'))
|
self.assertTrue(sot.match_service_name('keystone'))
|
||||||
self.assertFalse(sot.match_service_name('ldap'))
|
self.assertFalse(sot.match_service_name('ldap'))
|
||||||
self.assertFalse(sot.match_service_name(None))
|
self.assertFalse(sot.match_service_name(None))
|
||||||
|
|
||||||
def test_match_region(self):
|
def test_match_region(self):
|
||||||
sot = filt.ServiceFilter('identity')
|
sot = filt.ServiceFilter(service_type='identity')
|
||||||
self.assertTrue(sot.match_region('East'))
|
self.assertTrue(sot.match_region('East'))
|
||||||
self.assertTrue(sot.match_region('West'))
|
self.assertTrue(sot.match_region('West'))
|
||||||
self.assertTrue(sot.match_region(None))
|
self.assertTrue(sot.match_region(None))
|
||||||
sot = filt.ServiceFilter('identity', region='East')
|
sot = filt.ServiceFilter(service_type='identity', region='East')
|
||||||
self.assertTrue(sot.match_region('East'))
|
self.assertTrue(sot.match_region('East'))
|
||||||
self.assertFalse(sot.match_region('West'))
|
self.assertFalse(sot.match_region('West'))
|
||||||
self.assertFalse(sot.match_region(None))
|
self.assertFalse(sot.match_region(None))
|
||||||
|
|
||||||
def test_match_visibility(self):
|
def test_match_visibility(self):
|
||||||
sot = filt.ServiceFilter('identity', visibility='internal')
|
sot = filt.ServiceFilter(service_type='identity',
|
||||||
|
visibility='internal')
|
||||||
self.assertFalse(sot.match_visibility('admin'))
|
self.assertFalse(sot.match_visibility('admin'))
|
||||||
self.assertTrue(sot.match_visibility('internal'))
|
self.assertTrue(sot.match_visibility('internal'))
|
||||||
self.assertFalse(sot.match_visibility('public'))
|
self.assertFalse(sot.match_visibility('public'))
|
||||||
|
|
||||||
|
def test_join(self):
|
||||||
|
a = filt.ServiceFilter(region='east')
|
||||||
|
b = filt.ServiceFilter(service_type='identity')
|
||||||
|
result = a.join(b)
|
||||||
|
self.assertEqual("service_type=identity,visibility=public,region=east",
|
||||||
|
six.text_type(result))
|
||||||
|
self.assertEqual("service_type=any,visibility=public,region=east",
|
||||||
|
six.text_type(a))
|
||||||
|
self.assertEqual("service_type=identity,visibility=public",
|
||||||
|
six.text_type(b))
|
||||||
|
@@ -24,7 +24,7 @@ class TestSession(base.TestCase):
|
|||||||
super(TestSession, self).setUp()
|
super(TestSession, self).setUp()
|
||||||
self.xport = fakes.FakeTransport()
|
self.xport = fakes.FakeTransport()
|
||||||
self.auth = fakes.FakeAuthenticator()
|
self.auth = fakes.FakeAuthenticator()
|
||||||
self.serv = service_filter.ServiceFilter('identity')
|
self.serv = service_filter.ServiceFilter(service_type='identity')
|
||||||
self.sess = session.Session(self.xport, self.auth)
|
self.sess = session.Session(self.xport, self.auth)
|
||||||
self.expected = {'headers': {'X-Auth-Token': self.auth.TOKEN}}
|
self.expected = {'headers': {'X-Auth-Token': self.auth.TOKEN}}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user