summaryrefslogtreecommitdiff
path: root/openstackclient/tests
diff options
context:
space:
mode:
authorMatthieu Huin <mhu@enovance.com>2014-07-18 19:18:25 +0200
committerMatthieu Huin <mhu@enovance.com>2014-10-09 12:34:47 +0200
commit0c77a9fe8baa4df9ea2d0055db9c700af3cae310 (patch)
tree5ad4edc96382e322774af1bcadf90064612b1b78 /openstackclient/tests
parent866965f0111db09cda0a7d983eb60b0287fe8727 (diff)
downloadpython-openstackclient-0c77a9fe8baa4df9ea2d0055db9c700af3cae310.tar.gz
Support for keystone auth plugins
This patch allows the user to choose which authentication plugin to use with the CLI. The arguments needed by the auth plugins are automatically added to the argument parser. Some examples with the currently available authentication plugins:: OS_USERNAME=admin OS_PROJECT_NAME=admin OS_AUTH_URL=http://keystone:5000/v2.0 \ OS_PASSWORD=admin openstack user list OS_USERNAME=admin OS_PROJECT_DOMAIN_NAME=default OS_USER_DOMAIN_NAME=default \ OS_PROJECT_NAME=admin OS_AUTH_URL=http://keystone:5000/v3 OS_PASSWORD=admin \ OS_IDENTITY_API_VERSION=3 OS_AUTH_PLUGIN=v3password openstack project list OS_TOKEN=1234 OS_URL=http://service_url:35357/v2.0 \ OS_IDENTITY_API_VERSION=2.0 openstack user list The --os-auth-plugin option can be omitted; if so the CLI will attempt to guess which plugin to use from the other options. Change-Id: I330c20ddb8d96b3a4287c68b57c36c4a0f869669 Co-Authored-By: Florent Flament <florent.flament-ext@cloudwatt.com>
Diffstat (limited to 'openstackclient/tests')
-rw-r--r--openstackclient/tests/common/test_clientmanager.py172
-rw-r--r--openstackclient/tests/fakes.py136
-rw-r--r--openstackclient/tests/test_shell.py86
3 files changed, 306 insertions, 88 deletions
diff --git a/openstackclient/tests/common/test_clientmanager.py b/openstackclient/tests/common/test_clientmanager.py
index 0bb657ad..18461fb7 100644
--- a/openstackclient/tests/common/test_clientmanager.py
+++ b/openstackclient/tests/common/test_clientmanager.py
@@ -12,34 +12,25 @@
# License for the specific language governing permissions and limitations
# under the License.
#
-
import mock
+from requests_mock.contrib import fixture
from keystoneclient.auth.identity import v2 as auth_v2
+from keystoneclient.openstack.common import jsonutils
+from keystoneclient import service_catalog
+
+from openstackclient.api import auth
from openstackclient.common import clientmanager
+from openstackclient.common import exceptions as exc
+from openstackclient.tests import fakes
from openstackclient.tests import utils
-AUTH_REF = {'a': 1}
-AUTH_TOKEN = "foobar"
-AUTH_URL = "http://0.0.0.0"
-USERNAME = "itchy"
-PASSWORD = "scratchy"
-SERVICE_CATALOG = {'sc': '123'}
-
-API_VERSION = {
- 'identity': '2.0',
-}
-
+API_VERSION = {"identity": "2.0"}
-def FakeMakeClient(instance):
- return FakeClient()
-
-
-class FakeClient(object):
- auth_ref = AUTH_REF
- auth_token = AUTH_TOKEN
- service_catalog = SERVICE_CATALOG
+AUTH_REF = {'version': 'v2.0'}
+AUTH_REF.update(fakes.TEST_RESPONSE_DICT['access'])
+SERVICE_CATALOG = service_catalog.ServiceCatalogV2(AUTH_REF)
class Container(object):
@@ -49,6 +40,18 @@ class Container(object):
pass
+class FakeOptions(object):
+ def __init__(self, **kwargs):
+ for option in auth.OPTIONS_LIST:
+ setattr(self, 'os_' + option.replace('-', '_'), None)
+ self.os_auth_plugin = None
+ self.os_identity_api_version = '2.0'
+ self.timing = None
+ self.os_region_name = None
+ self.os_url = None
+ self.__dict__.update(kwargs)
+
+
class TestClientCache(utils.TestCase):
def test_singleton(self):
@@ -58,30 +61,38 @@ class TestClientCache(utils.TestCase):
self.assertEqual(c.attr, c.attr)
-@mock.patch('keystoneclient.session.Session')
class TestClientManager(utils.TestCase):
def setUp(self):
super(TestClientManager, self).setUp()
-
- clientmanager.ClientManager.identity = \
- clientmanager.ClientCache(FakeMakeClient)
-
- def test_client_manager_token(self, mock):
+ self.mock = mock.Mock()
+ self.requests = self.useFixture(fixture.Fixture())
+ # fake v2password token retrieval
+ self.stub_auth(json=fakes.TEST_RESPONSE_DICT)
+ # fake v3password token retrieval
+ self.stub_auth(json=fakes.TEST_RESPONSE_DICT_V3,
+ url='/'.join([fakes.AUTH_URL, 'auth/tokens']))
+ # fake password version endpoint discovery
+ self.stub_auth(json=fakes.TEST_VERSIONS,
+ url=fakes.AUTH_URL,
+ verb='GET')
+
+ def test_client_manager_token(self):
client_manager = clientmanager.ClientManager(
- token=AUTH_TOKEN,
- url=AUTH_URL,
- verify=True,
+ auth_options=FakeOptions(os_token=fakes.AUTH_TOKEN,
+ os_auth_url=fakes.AUTH_URL,
+ os_auth_plugin='v2token'),
api_version=API_VERSION,
+ verify=True
)
self.assertEqual(
- AUTH_TOKEN,
+ fakes.AUTH_TOKEN,
client_manager._token,
)
self.assertEqual(
- AUTH_URL,
- client_manager._url,
+ fakes.AUTH_URL,
+ client_manager._auth_url,
)
self.assertIsInstance(
client_manager.auth,
@@ -90,26 +101,26 @@ class TestClientManager(utils.TestCase):
self.assertFalse(client_manager._insecure)
self.assertTrue(client_manager._verify)
- def test_client_manager_password(self, mock):
+ def test_client_manager_password(self):
client_manager = clientmanager.ClientManager(
- auth_url=AUTH_URL,
- username=USERNAME,
- password=PASSWORD,
- verify=False,
+ auth_options=FakeOptions(os_auth_url=fakes.AUTH_URL,
+ os_username=fakes.USERNAME,
+ os_password=fakes.PASSWORD),
api_version=API_VERSION,
+ verify=False,
)
self.assertEqual(
- AUTH_URL,
+ fakes.AUTH_URL,
client_manager._auth_url,
)
self.assertEqual(
- USERNAME,
+ fakes.USERNAME,
client_manager._username,
)
self.assertEqual(
- PASSWORD,
+ fakes.PASSWORD,
client_manager._password,
)
self.assertIsInstance(
@@ -119,16 +130,87 @@ class TestClientManager(utils.TestCase):
self.assertTrue(client_manager._insecure)
self.assertFalse(client_manager._verify)
- def test_client_manager_password_verify_ca(self, mock):
+ # These need to stick around until the old-style clients are gone
+ self.assertEqual(
+ AUTH_REF,
+ client_manager.auth_ref,
+ )
+ self.assertEqual(
+ fakes.AUTH_TOKEN,
+ client_manager._token,
+ )
+ self.assertEqual(
+ dir(SERVICE_CATALOG),
+ dir(client_manager._service_catalog),
+ )
+
+ def stub_auth(self, json=None, url=None, verb=None, **kwargs):
+ subject_token = fakes.AUTH_TOKEN
+ base_url = fakes.AUTH_URL
+ if json:
+ text = jsonutils.dumps(json)
+ headers = {'X-Subject-Token': subject_token,
+ 'Content-Type': 'application/json'}
+ if not url:
+ url = '/'.join([base_url, 'tokens'])
+ url = url.replace("/?", "?")
+ if not verb:
+ verb = 'POST'
+ self.requests.register_uri(verb,
+ url,
+ headers=headers,
+ text=text)
+
+ def test_client_manager_password_verify_ca(self):
client_manager = clientmanager.ClientManager(
- auth_url=AUTH_URL,
- username=USERNAME,
- password=PASSWORD,
- verify='cafile',
+ auth_options=FakeOptions(os_auth_url=fakes.AUTH_URL,
+ os_username=fakes.USERNAME,
+ os_password=fakes.PASSWORD,
+ os_auth_plugin='v2password'),
api_version=API_VERSION,
+ verify='cafile',
)
self.assertFalse(client_manager._insecure)
self.assertTrue(client_manager._verify)
self.assertEqual('cafile', client_manager._cacert)
+
+ def _client_manager_guess_auth_plugin(self, auth_params,
+ api_version, auth_plugin):
+ auth_params['os_auth_plugin'] = auth_plugin
+ auth_params['os_identity_api_version'] = api_version
+ client_manager = clientmanager.ClientManager(
+ auth_options=FakeOptions(**auth_params),
+ api_version=API_VERSION,
+ verify=True
+ )
+ self.assertEqual(
+ auth_plugin,
+ client_manager._auth_plugin,
+ )
+
+ def test_client_manager_guess_auth_plugin(self):
+ # test token auth
+ params = dict(os_token=fakes.AUTH_TOKEN,
+ os_auth_url=fakes.AUTH_URL)
+ self._client_manager_guess_auth_plugin(params, '2.0', 'v2token')
+ self._client_manager_guess_auth_plugin(params, '3', 'v3token')
+ self._client_manager_guess_auth_plugin(params, 'XXX', 'token')
+ # test service auth
+ params = dict(os_token=fakes.AUTH_TOKEN, os_url='test')
+ self._client_manager_guess_auth_plugin(params, 'XXX', '')
+ # test password auth
+ params = dict(os_auth_url=fakes.AUTH_URL,
+ os_username=fakes.USERNAME,
+ os_password=fakes.PASSWORD)
+ self._client_manager_guess_auth_plugin(params, '2.0', 'v2password')
+ self._client_manager_guess_auth_plugin(params, '3', 'v3password')
+ self._client_manager_guess_auth_plugin(params, 'XXX', 'password')
+
+ def test_client_manager_guess_auth_plugin_failure(self):
+ self.assertRaises(exc.CommandError,
+ clientmanager.ClientManager,
+ auth_options=FakeOptions(os_auth_plugin=''),
+ api_version=API_VERSION,
+ verify=True)
diff --git a/openstackclient/tests/fakes.py b/openstackclient/tests/fakes.py
index 5a1fc005..f8b7bb6f 100644
--- a/openstackclient/tests/fakes.py
+++ b/openstackclient/tests/fakes.py
@@ -22,6 +22,142 @@ import requests
AUTH_TOKEN = "foobar"
AUTH_URL = "http://0.0.0.0"
+USERNAME = "itchy"
+PASSWORD = "scratchy"
+TEST_RESPONSE_DICT = {
+ "access": {
+ "metadata": {
+ "is_admin": 0,
+ "roles": [
+ "1234",
+ ]
+ },
+ "serviceCatalog": [
+ {
+ "endpoints": [
+ {
+ "adminURL": AUTH_URL + "/v2.0",
+ "id": "1234",
+ "internalURL": AUTH_URL + "/v2.0",
+ "publicURL": AUTH_URL + "/v2.0",
+ "region": "RegionOne"
+ }
+ ],
+ "endpoints_links": [],
+ "name": "keystone",
+ "type": "identity"
+ }
+ ],
+ "token": {
+ "expires": "2035-01-01T00:00:01Z",
+ "id": AUTH_TOKEN,
+ "issued_at": "2013-01-01T00:00:01.692048",
+ "tenant": {
+ "description": None,
+ "enabled": True,
+ "id": "1234",
+ "name": "testtenant"
+ }
+ },
+ "user": {
+ "id": "5678",
+ "name": USERNAME,
+ "roles": [
+ {
+ "name": "testrole"
+ },
+ ],
+ "roles_links": [],
+ "username": USERNAME
+ }
+ }
+}
+TEST_RESPONSE_DICT_V3 = {
+ "token": {
+ "audit_ids": [
+ "a"
+ ],
+ "catalog": [
+ ],
+ "expires_at": "2034-09-29T18:27:15.978064Z",
+ "extras": {},
+ "issued_at": "2014-09-29T17:27:15.978097Z",
+ "methods": [
+ "password"
+ ],
+ "project": {
+ "domain": {
+ "id": "default",
+ "name": "Default"
+ },
+ "id": "bbb",
+ "name": "project"
+ },
+ "roles": [
+ ],
+ "user": {
+ "domain": {
+ "id": "default",
+ "name": "Default"
+ },
+ "id": "aaa",
+ "name": USERNAME
+ }
+ }
+}
+TEST_VERSIONS = {
+ "versions": {
+ "values": [
+ {
+ "id": "v3.0",
+ "links": [
+ {
+ "href": AUTH_URL,
+ "rel": "self"
+ }
+ ],
+ "media-types": [
+ {
+ "base": "application/json",
+ "type": "application/vnd.openstack.identity-v3+json"
+ },
+ {
+ "base": "application/xml",
+ "type": "application/vnd.openstack.identity-v3+xml"
+ }
+ ],
+ "status": "stable",
+ "updated": "2013-03-06T00:00:00Z"
+ },
+ {
+ "id": "v2.0",
+ "links": [
+ {
+ "href": AUTH_URL,
+ "rel": "self"
+ },
+ {
+ "href": "http://docs.openstack.org/",
+ "rel": "describedby",
+ "type": "text/html"
+ }
+ ],
+ "media-types": [
+ {
+ "base": "application/json",
+ "type": "application/vnd.openstack.identity-v2.0+json"
+ },
+ {
+ "base": "application/xml",
+ "type": "application/vnd.openstack.identity-v2.0+xml"
+ }
+ ],
+ "status": "stable",
+ "updated": "2014-04-17T00:00:00Z"
+ }
+ ]
+ }
+}
class FakeStdout:
diff --git a/openstackclient/tests/test_shell.py b/openstackclient/tests/test_shell.py
index c180289e..b0c1452e 100644
--- a/openstackclient/tests/test_shell.py
+++ b/openstackclient/tests/test_shell.py
@@ -34,6 +34,8 @@ DEFAULT_PASSWORD = "password"
DEFAULT_REGION_NAME = "ZZ9_Plural_Z_Alpha"
DEFAULT_TOKEN = "token"
DEFAULT_SERVICE_URL = "http://127.0.0.1:8771/v3.0/"
+DEFAULT_AUTH_PLUGIN = "v2password"
+
DEFAULT_COMPUTE_API_VERSION = "2"
DEFAULT_IDENTITY_API_VERSION = "2.0"
@@ -106,6 +108,8 @@ class TestShell(utils.TestCase):
default_args["region_name"])
self.assertEqual(_shell.options.os_trust_id,
default_args["trust_id"])
+ self.assertEqual(_shell.options.os_auth_plugin,
+ default_args['auth_plugin'])
def _assert_token_auth(self, cmd_options, default_args):
with mock.patch("openstackclient.shell.OpenStackShell.initialize_app",
@@ -115,7 +119,8 @@ class TestShell(utils.TestCase):
self.app.assert_called_with(["list", "role"])
self.assertEqual(_shell.options.os_token, default_args["os_token"])
- self.assertEqual(_shell.options.os_url, default_args["os_url"])
+ self.assertEqual(_shell.options.os_auth_url,
+ default_args["os_auth_url"])
def _assert_cli(self, cmd_options, default_args):
with mock.patch("openstackclient.shell.OpenStackShell.initialize_app",
@@ -175,9 +180,9 @@ class TestShellPasswordAuth(TestShell):
"auth_url": DEFAULT_AUTH_URL,
"project_id": "",
"project_name": "",
+ "user_domain_id": "",
"domain_id": "",
"domain_name": "",
- "user_domain_id": "",
"user_domain_name": "",
"project_domain_id": "",
"project_domain_name": "",
@@ -185,6 +190,7 @@ class TestShellPasswordAuth(TestShell):
"password": "",
"region_name": "",
"trust_id": "",
+ "auth_plugin": "",
}
self._assert_password_auth(flag, kwargs)
@@ -204,6 +210,7 @@ class TestShellPasswordAuth(TestShell):
"password": "",
"region_name": "",
"trust_id": "",
+ "auth_plugin": "",
}
self._assert_password_auth(flag, kwargs)
@@ -223,44 +230,7 @@ class TestShellPasswordAuth(TestShell):
"password": "",
"region_name": "",
"trust_id": "",
- }
- self._assert_password_auth(flag, kwargs)
-
- def test_only_tenant_id_flow(self):
- flag = "--os-tenant-id " + DEFAULT_PROJECT_ID
- kwargs = {
- "auth_url": "",
- "project_id": DEFAULT_PROJECT_ID,
- "project_name": "",
- "domain_id": "",
- "domain_name": "",
- "user_domain_id": "",
- "user_domain_name": "",
- "project_domain_id": "",
- "project_domain_name": "",
- "username": "",
- "password": "",
- "region_name": "",
- "trust_id": "",
- }
- self._assert_password_auth(flag, kwargs)
-
- def test_only_tenant_name_flow(self):
- flag = "--os-tenant-name " + DEFAULT_PROJECT_NAME
- kwargs = {
- "auth_url": "",
- "project_id": "",
- "project_name": DEFAULT_PROJECT_NAME,
- "domain_id": "",
- "domain_name": "",
- "user_domain_id": "",
- "user_domain_name": "",
- "project_domain_id": "",
- "project_domain_name": "",
- "username": "",
- "password": "",
- "region_name": "",
- "trust_id": "",
+ "auth_plugin": "",
}
self._assert_password_auth(flag, kwargs)
@@ -280,6 +250,7 @@ class TestShellPasswordAuth(TestShell):
"password": "",
"region_name": "",
"trust_id": "",
+ "auth_plugin": "",
}
self._assert_password_auth(flag, kwargs)
@@ -299,6 +270,7 @@ class TestShellPasswordAuth(TestShell):
"password": "",
"region_name": "",
"trust_id": "",
+ "auth_plugin": "",
}
self._assert_password_auth(flag, kwargs)
@@ -318,6 +290,7 @@ class TestShellPasswordAuth(TestShell):
"password": "",
"region_name": "",
"trust_id": "",
+ "auth_plugin": "",
}
self._assert_password_auth(flag, kwargs)
@@ -337,6 +310,7 @@ class TestShellPasswordAuth(TestShell):
"password": "",
"region_name": "",
"trust_id": "",
+ "auth_plugin": "",
}
self._assert_password_auth(flag, kwargs)
@@ -356,6 +330,7 @@ class TestShellPasswordAuth(TestShell):
"password": "",
"region_name": "",
"trust_id": "",
+ "auth_plugin": "",
}
self._assert_password_auth(flag, kwargs)
@@ -375,6 +350,7 @@ class TestShellPasswordAuth(TestShell):
"password": "",
"region_name": "",
"trust_id": "",
+ "auth_plugin": "",
}
self._assert_password_auth(flag, kwargs)
@@ -394,6 +370,7 @@ class TestShellPasswordAuth(TestShell):
"password": "",
"region_name": "",
"trust_id": "",
+ "auth_plugin": "",
}
self._assert_password_auth(flag, kwargs)
@@ -413,6 +390,7 @@ class TestShellPasswordAuth(TestShell):
"password": DEFAULT_PASSWORD,
"region_name": "",
"trust_id": "",
+ "auth_plugin": "",
}
self._assert_password_auth(flag, kwargs)
@@ -432,6 +410,7 @@ class TestShellPasswordAuth(TestShell):
"password": "",
"region_name": DEFAULT_REGION_NAME,
"trust_id": "",
+ "auth_plugin": "",
}
self._assert_password_auth(flag, kwargs)
@@ -451,6 +430,27 @@ class TestShellPasswordAuth(TestShell):
"password": "",
"region_name": "",
"trust_id": "1234",
+ "auth_plugin": "",
+ }
+ self._assert_password_auth(flag, kwargs)
+
+ def test_only_auth_plugin_flow(self):
+ flag = "--os-auth-plugin " + "v2password"
+ kwargs = {
+ "auth_url": "",
+ "project_id": "",
+ "project_name": "",
+ "domain_id": "",
+ "domain_name": "",
+ "user_domain_id": "",
+ "user_domain_name": "",
+ "project_domain_id": "",
+ "project_domain_name": "",
+ "username": "",
+ "password": "",
+ "region_name": "",
+ "trust_id": "",
+ "auth_plugin": DEFAULT_AUTH_PLUGIN
}
self._assert_password_auth(flag, kwargs)
@@ -460,7 +460,7 @@ class TestShellTokenAuth(TestShell):
super(TestShellTokenAuth, self).setUp()
env = {
"OS_TOKEN": DEFAULT_TOKEN,
- "OS_URL": DEFAULT_SERVICE_URL,
+ "OS_AUTH_URL": DEFAULT_SERVICE_URL,
}
self.orig_env, os.environ = os.environ, env.copy()
@@ -472,7 +472,7 @@ class TestShellTokenAuth(TestShell):
flag = ""
kwargs = {
"os_token": DEFAULT_TOKEN,
- "os_url": DEFAULT_SERVICE_URL
+ "os_auth_url": DEFAULT_SERVICE_URL
}
self._assert_token_auth(flag, kwargs)
@@ -481,7 +481,7 @@ class TestShellTokenAuth(TestShell):
flag = ""
kwargs = {
"os_token": "",
- "os_url": ""
+ "os_auth_url": ""
}
self._assert_token_auth(flag, kwargs)