Add identity providers integration tests

This patch adds a first set of tests in the keystone tempest plugin.
These tests are for the Identity Provider API (part of the Federated
Identity API).

To run the tests install keystone and run (in tempest):

    $ tox -e all-plugin -- keystone

Change-Id: I64ebba2e57aa952a2262f9e0ad143cea7de259c0
This commit is contained in:
Rodrigo Duarte 2016-04-06 11:52:19 -03:00
parent bfc93c8980
commit 4666c64163
10 changed files with 323 additions and 0 deletions

View File

@ -0,0 +1,28 @@
# Copyright 2016 Red Hat, Inc.
#
# 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 keystone_tempest_plugin.services.identity.v3 import (
identity_providers_client)
from tempest import clients
class Manager(clients.Manager):
def __init__(self, credentials, service=None):
super(Manager, self).__init__(credentials, service)
self.identity_providers_client = (
identity_providers_client.IdentityProvidersClient(
self.auth_provider))

View File

@ -0,0 +1,36 @@
# Copyright 2016 Red Hat, Inc.
#
# 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 tempest import config
from tempest.lib.common import rest_client
CONF = config.CONF
# We only use the identity catalog type
SERVICE_TYPE = 'identity'
class Identity(rest_client.RestClient):
"""Tempest REST client for keystone."""
# Used by the superclass to build the correct URL paths
api_version = 'v3'
def __init__(self, auth_provider):
super(Identity, self).__init__(
auth_provider,
SERVICE_TYPE,
CONF.identity.region,
endpoint_type='adminURL')

View File

@ -0,0 +1,79 @@
# Copyright 2016 Red Hat, Inc.
#
# 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
from tempest.lib.common import rest_client
from keystone_tempest_plugin.services.identity import clients
class IdentityProvidersClient(clients.Identity):
subpath = 'OS-FEDERATION/identity_providers'
def _build_path(self, idp_id=None):
return '%s/%s' % (self.subpath, idp_id) if idp_id else self.subpath
def create_identity_provider(self, idp_id, **kwargs):
"""Create an identity provider.
:param str idp_id: The ID to be used to create the Identity Provider.
:param kwargs: All optional attributes: description (str), enabled
(boolean) and remote_ids (list).
"""
put_body = json.dumps({'identity_provider': kwargs})
url = self._build_path(idp_id)
resp, body = self.put(url, put_body)
self.expected_success(201, resp.status)
body = json.loads(body)
idp = rest_client.ResponseBody(resp, body)
return idp
def list_identity_providers(self):
"""List the identity providers."""
url = self._build_path()
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def show_identity_provider(self, idp_id):
"""Get an identity provider."""
url = self._build_path(idp_id)
resp, body = self.get(url)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
def delete_identity_provider(self, idp_id):
"""Delete an identity provider."""
url = self._build_path(idp_id)
resp, body = self.delete(url)
self.expected_success(204, resp.status)
return rest_client.ResponseBody(resp, body)
def update_identity_provider(self, idp_id, **kwargs):
"""Update an identity provider.
:param str idp_id: The ID from the Identity Provider to be updated.
:param kwargs: All optional attributes to update: description (str),
enabled (boolean) and remote_ids (list).
"""
patch_body = json.dumps({'identity_provider': kwargs})
url = self._build_path(idp_id)
resp, body = self.patch(url, patch_body)
self.expected_success(200, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)

View File

@ -0,0 +1,36 @@
# Copyright 2016 Red Hat, Inc.
#
# 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 tempest.common import credentials_factory as common_creds
from tempest import test
from keystone_tempest_plugin import clients
class BaseIdentityTest(test.BaseTestCase):
# The version of the identity that will be used in the tests.
identity_version = 'v3'
# NOTE(rodrigods): for now, all tests are in the admin scope, if
# necessary, another class can be created to handle non-admin tests.
credential_type = 'identity_admin'
@classmethod
def setup_clients(cls):
super(BaseIdentityTest, cls).setup_clients()
credentials = common_creds.get_configured_credentials(
cls.credential_type, identity_version=cls.identity_version)
cls.keystone_manager = clients.Manager(credentials=credentials)
cls.idps_client = cls.keystone_manager.identity_providers_client

View File

@ -0,0 +1,28 @@
# Copyright 2016 Red Hat, Inc.
#
# 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 tempest.lib.common.utils import data_utils
def idp_ref(enabled=None, remote_ids=None):
ref = {
'description': data_utils.rand_uuid_hex(),
}
if enabled is not None:
ref['enabled'] = enabled
if remote_ids:
ref['remote_ids'] = remote_ids
return ref

View File

@ -0,0 +1,116 @@
# Copyright 2016 Red Hat, Inc.
#
# 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 tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from keystone_tempest_plugin.tests.api.identity import base
from keystone_tempest_plugin.tests.api.identity.v3 import fixtures
class IndentityProvidersTest(base.BaseIdentityTest):
def _assert_identity_provider_attributes(self, idp, idp_id, idp_ref=None):
self.assertIn('id', idp)
self.assertEqual(idp_id, idp['id'])
# Check the optional attributes have been set
self.assertIn('description', idp)
self.assertIn('enabled', idp)
self.assertIn('remote_ids', idp)
if idp_ref:
self.assertEqual(idp_ref['description'], idp['description'])
if 'enabled' in idp_ref:
self.assertEqual(idp_ref['enabled'], idp['enabled'])
if 'remote_ids' in idp_ref:
self.assertItemsEqual(idp_ref['remote_ids'], idp['remote_ids'])
def _create_idp(self, idp_id, idp_ref):
idp = self.idps_client.create_identity_provider(
idp_id, **idp_ref)['identity_provider']
self.addCleanup(
self.idps_client.delete_identity_provider, idp_id)
return idp
@decorators.idempotent_id('09450910-b816-4150-8513-a2fd4628a0c3')
def test_identity_provider_create(self):
idp_id = data_utils.rand_uuid_hex()
idp_ref = fixtures.idp_ref()
idp = self._create_idp(idp_id, idp_ref)
# The identity provider is disabled by default
idp_ref['enabled'] = False
# The remote_ids attribute should be set to an empty list by default
idp_ref['remote_ids'] = []
self._assert_identity_provider_attributes(idp, idp_id, idp_ref)
@decorators.idempotent_id('f430a337-545d-455e-bb6c-cb0fdf4be5c1')
def test_identity_provider_create_with_enabled_true(self):
idp_id = data_utils.rand_uuid_hex()
idp_ref = fixtures.idp_ref(enabled=True)
idp = self._create_idp(idp_id, idp_ref)
self._assert_identity_provider_attributes(idp, idp_id, idp_ref)
@decorators.idempotent_id('238e6163-d600-4f59-9982-c621f057221d')
def test_identity_provider_create_with_remote_ids(self):
idp_id = data_utils.rand_uuid_hex()
remote_ids = [data_utils.rand_uuid_hex(), data_utils.rand_uuid_hex()]
idp_ref = fixtures.idp_ref(remote_ids=remote_ids)
idp = self._create_idp(idp_id, idp_ref)
self._assert_identity_provider_attributes(idp, idp_id, idp_ref)
@decorators.idempotent_id('8a7817ad-27f8-436b-9cbe-46aa20989beb')
def test_identity_provider_get(self):
idp_id = data_utils.rand_uuid_hex()
idp_create = self._create_idp(idp_id, fixtures.idp_ref())
idp_get = self.idps_client.show_identity_provider(
idp_id)['identity_provider']
self._assert_identity_provider_attributes(idp_get, idp_id, idp_create)
@decorators.idempotent_id('cbfe5de9-c58a-4810-950c-2acdf985879d')
def test_identity_provider_list(self):
idp_ids = []
for _ in range(3):
idp_id = data_utils.rand_uuid_hex()
self._create_idp(idp_id, fixtures.idp_ref())
idp_ids.append(idp_id)
idp_list = self.idps_client.list_identity_providers()[
'identity_providers']
fetched_ids = [fetched_idp['id'] for fetched_idp in idp_list]
for idp_id in idp_ids:
self.assertIn(idp_id, fetched_ids)
@decorators.idempotent_id('36a0d9f0-9517-4139-85d0-f78d905aece5')
def test_identity_provider_update(self):
idp_id = data_utils.rand_uuid_hex()
idp = self._create_idp(idp_id, fixtures.idp_ref(enabled=True))
# The identity provider should be enabled
self.assertTrue(idp['enabled'])
idp = self.idps_client.update_identity_provider(
idp_id, enabled=False)['identity_provider']
# The identity provider should be disabled
self.assertFalse(idp['enabled'])