From 00ef277fa1dbbb5e8084e702f3eb836e5713b53f Mon Sep 17 00:00:00 2001 From: Terry Howe Date: Fri, 4 Jul 2014 12:56:36 -0600 Subject: [PATCH] Add some factories Add some factories for transport, authenticate, and session. Change-Id: I355b07b2e644358295ba4543cfce3418235ba4ff --- examples/authenticate.py | 40 +++------ examples/session.py | 19 +++-- examples/transport.py | 11 ++- openstack/auth/identity/authenticator.py | 53 ++++++++++++ openstack/session.py | 25 ++++++ .../tests/auth/identity/test_authenticator.py | 81 +++++++++++++++++++ openstack/tests/test_session.py | 21 +++++ openstack/tests/test_transport.py | 29 +++++++ openstack/transport.py | 9 +++ 9 files changed, 244 insertions(+), 44 deletions(-) create mode 100644 openstack/auth/identity/authenticator.py create mode 100644 openstack/tests/auth/identity/test_authenticator.py diff --git a/examples/authenticate.py b/examples/authenticate.py index de0e150a..3e70f6cb 100644 --- a/examples/authenticate.py +++ b/examples/authenticate.py @@ -30,8 +30,7 @@ import sys from examples import common from examples import transport from openstack.auth import base -from openstack.auth.identity import v2 -from openstack.auth.identity import v3 +from openstack.auth.identity import authenticator class TestAuthenticator(base.BaseAuthenticator): @@ -48,35 +47,14 @@ class TestAuthenticator(base.BaseAuthenticator): def make_authenticate(opts): - """Create authenticator of some sort.""" - token = opts.os_token - username = opts.os_username - password = opts.os_password - auth_url = opts.os_auth_url - project_name = opts.os_project_name - version = opts.os_identity_api_version - if version is None: - version = '3' - else: - version = version.lower().replace('v', '') - version = version.split('.')[0] - if version == '3': - if not token: - args = {'username': username, 'password': password} - if project_name: - args['project_name'] = project_name - return v3.Password(auth_url, **args) - else: - return v3.Token(auth_url, token=token) - elif version == '2': - if not token: - args = {} - if project_name: - args['tenant_name'] = project_name - return v2.Password(auth_url, username, password, **args) - else: - return v2.Token(auth_url, token) - raise Exception("No support for version: %s" % version) + return authenticator.Authenticator.create( + username=opts.os_username, + password=opts.os_password, + token=opts.os_token, + auth_url=opts.os_auth_url, + version=opts.os_identity_api_version, + project_name=opts.os_project_name, + ) def run_authenticate(opts): diff --git a/examples/session.py b/examples/session.py index 93862de9..d314b19d 100644 --- a/examples/session.py +++ b/examples/session.py @@ -22,19 +22,24 @@ For example: import sys -from examples import authenticate from examples import common -from examples import transport from openstack.auth import service_filter from openstack import session def make_session(opts): - region = opts.os_region - preference = service_filter.ServiceFilter(region=region) - xport = transport.make_transport(opts) - auth = authenticate.make_authenticate(opts) - return session.Session(xport, auth, preference=preference) + return session.Session.create( + username=opts.os_username, + password=opts.os_password, + token=opts.os_token, + auth_url=opts.os_auth_url, + version=opts.os_identity_api_version, + project_name=opts.os_project_name, + cacert=opts.os_cacert, + insecure=opts.insecure, + user_agent='SDKExample', + region=opts.os_region, + ) def run_session(opts): diff --git a/examples/transport.py b/examples/transport.py index 70c9b8be..d7ac3f83 100755 --- a/examples/transport.py +++ b/examples/transport.py @@ -30,12 +30,11 @@ USER_AGENT = 'SDKExample' def make_transport(opts): - # Certificate verification - defaults to True - if opts.os_cacert: - verify = opts.os_cacert - else: - verify = not opts.insecure - return transport.Transport(verify=verify, user_agent=USER_AGENT) + return transport.Transport.create( + cacert=opts.os_cacert, + insecure=opts.insecure, + user_agent=USER_AGENT + ) def run_transport(opts): diff --git a/openstack/auth/identity/authenticator.py b/openstack/auth/identity/authenticator.py new file mode 100644 index 00000000..00535782 --- /dev/null +++ b/openstack/auth/identity/authenticator.py @@ -0,0 +1,53 @@ +# 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 openstack.auth.identity import v2 +from openstack.auth.identity import v3 +from openstack import exceptions + + +def create(username=None, password=None, token=None, auth_url=None, + version='3', project_name=None): + """Temporary code for creating an authenticator + + This is temporary code to create an authenticator. This code will be + removed in the future. + + :param string username: User name for authentication. + :param string password: Password associated with the user. + :param string token: Authentication token to use if available. + :param string auth_url: The URL to use for authentication. + :param string version: Version of authentication to use. + :param string project_name: Project name to athenticate. + + :returns string: An authenticator. + """ + version = version.lower().replace('v', '') + version = version.split('.')[0] + if version == '3': + if not token: + args = {'username': username, 'password': password} + if project_name: + args['project_name'] = project_name + return v3.Password(auth_url, **args) + else: + return v3.Token(auth_url, token=token) + elif version == '2': + if not token: + args = {} + if project_name: + args['tenant_name'] = project_name + return v2.Password(auth_url, username, password, **args) + else: + return v2.Token(auth_url, token) + msg = ("No support for identity version: %s" % version) + raise exceptions.NoMatchingPlugin(msg) diff --git a/openstack/session.py b/openstack/session.py index 268155b2..f99f94b9 100644 --- a/openstack/session.py +++ b/openstack/session.py @@ -12,6 +12,9 @@ import logging +from openstack.auth.identity import authenticator +from openstack.auth import service_filter +from openstack import transport from openstack import utils @@ -35,6 +38,28 @@ class Session(object): self.authenticator = authenticator self.preference = preference + @classmethod + def create(cls, username=None, password=None, token=None, auth_url=None, + version=None, project_name=None, cacert=None, insecure=False, + user_agent=None, region=None): + xport = transport.Transport.create( + cacert=cacert, + insecure=insecure, + user_agent=user_agent, + ) + args = { + 'username': username, + 'password': password, + 'token': token, + 'auth_url': auth_url, + 'project_name': project_name + } + if version: + args['version'] = version + auth = authenticator.create(**args) + preference = service_filter.ServiceFilter(region=region) + return cls(xport, auth, preference=preference) + def _request(self, path, method, service=None, authenticate=True, **kwargs): """Send an HTTP request with the specified characteristics. diff --git a/openstack/tests/auth/identity/test_authenticator.py b/openstack/tests/auth/identity/test_authenticator.py new file mode 100644 index 00000000..86fc4060 --- /dev/null +++ b/openstack/tests/auth/identity/test_authenticator.py @@ -0,0 +1,81 @@ +# 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 openstack.auth.identity import authenticator +from openstack import exceptions +from openstack.tests import base + + +class TestAuthenticatorCreate(base.TestCase): + def test_create_3_password(self): + auth = authenticator.create( + username='1', + password='2', + token=None, + auth_url='4', + version='3', + project_name='6', + ) + self.assertEqual('1', auth.auth_methods[0].username) + self.assertEqual('2', auth.auth_methods[0].password) + self.assertEqual('4', auth.auth_url) + self.assertEqual('6', auth.project_name) + + def test_create_3_token(self): + auth = authenticator.create( + username='1', + password='2', + token='3', + auth_url='4', + version='3', + project_name='6', + ) + self.assertEqual('3', auth.auth_methods[0].token) + self.assertEqual('4', auth.auth_url) + + def test_create_2_password(self): + auth = authenticator.create( + username='1', + password='2', + token=None, + auth_url='4', + version='2', + project_name='6', + ) + self.assertEqual('1', auth.username) + self.assertEqual('2', auth.password) + self.assertEqual('4', auth.auth_url) + self.assertEqual('6', auth.tenant_name) + + def test_create_2_token(self): + auth = authenticator.create( + username='1', + password='2', + token='3', + auth_url='4', + version='2', + project_name='6', + ) + self.assertEqual('3', auth.token) + self.assertEqual('4', auth.auth_url) + + def test_create_bogus(self): + self.assertRaises( + exceptions.NoMatchingPlugin, + authenticator.create, + username='1', + password='2', + token='3', + auth_url='4', + version='99', + project_name='6', + ) diff --git a/openstack/tests/test_session.py b/openstack/tests/test_session.py index aeeb15e8..5fdbdc6a 100644 --- a/openstack/tests/test_session.py +++ b/openstack/tests/test_session.py @@ -81,3 +81,24 @@ class TestSession(base.TestCase): self.auth.get_endpoint.assert_called_with(self.xport, self.serv) url = self.auth.ENDPOINT + self.TEST_PATH self.xport.request.assert_called_with('PATCH', url, **self.expected) + + +class TestSessionCreate(base.TestCase): + def test_create(self): + sess = session.Session.create( + username='1', + password='2', + token=None, + auth_url='4', + version='3', + project_name='6', + cacert='7', + insecure='8', + user_agent='9', + region='10', + ) + self.assertEqual('1', sess.authenticator.auth_methods[0].username) + self.assertEqual('2', sess.authenticator.auth_methods[0].password) + self.assertEqual('7', sess.transport.verify) + self.assertEqual('9', sess.transport._user_agent) + self.assertEqual('10', sess.preference.region) diff --git a/openstack/tests/test_transport.py b/openstack/tests/test_transport.py index 207f4566..b8ab7f17 100644 --- a/openstack/tests/test_transport.py +++ b/openstack/tests/test_transport.py @@ -638,3 +638,32 @@ class TestTransportRedirects(base.TestTransportBase): for r, s in zip(req_resp.history, resp.history): self.assertEqual(s.url, r.url) self.assertEqual(s.status_code, r.status_code) + + +class TestTransporCreate(base.TestCase): + def test_create(self): + xport = transport.Transport.create( + cacert='1', + insecure=False, + user_agent='2', + ) + self.assertEqual('1', xport.verify) + self.assertEqual('2', xport._user_agent) + + def test_create_no_cert(self): + xport = transport.Transport.create( + cacert=None, + insecure=False, + user_agent='3', + ) + self.assertEqual(True, xport.verify) + self.assertEqual('3', xport._user_agent) + + def test_create_verify(self): + xport = transport.Transport.create( + cacert=None, + insecure=True, + user_agent='4', + ) + self.assertEqual(False, xport.verify) + self.assertEqual('4', xport._user_agent) diff --git a/openstack/transport.py b/openstack/transport.py index 2ac884b7..6e24963d 100644 --- a/openstack/transport.py +++ b/openstack/transport.py @@ -82,6 +82,15 @@ class Transport(requests.Session): self._redirect = redirect self._accept = accept + @classmethod + def create(cls, cacert=None, insecure=False, user_agent=None): + # Certificate verification - defaults to True + if cacert: + verify = cacert + else: + verify = not insecure + return cls(verify=verify, user_agent=user_agent) + def request(self, method, url, redirect=None, **kwargs): """Send a request