3aaeadf895
Keystone role names are case-insensistive and Horizon should handle role names in a case-insensitive manner. For example, when keystone bootstraps default roles, it creates “admin”, “member”, and “reader”. If another role, “Member” (note the upper case ‘M’) is created, keystone will return a 409 Conflict since it considers the name “Member” equivalent to “member”. Note that case is preserved in this event. https://docs.openstack.org/keystone/latest/admin/case-insensitive.html#roles Also whatever is written in defaults can be overridden in settings by the operator - especially these days when actually the default should be 'member' (one of the default roles created by Keystone during the bootstrap), not _member_ which is there for legacy reasons I presume. Change-Id: Ibfb80a47a8aaed8f33e4e1dcfb428e70c829f0dd
167 lines
7.6 KiB
Python
167 lines
7.6 KiB
Python
# Copyright 2012 United States Government as represented by the
|
|
# Administrator of the National Aeronautics and Space Administration.
|
|
# All Rights Reserved.
|
|
#
|
|
# Copyright 2012 Nebula, 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 random import choice
|
|
from unittest import mock
|
|
|
|
|
|
from django.test.utils import override_settings
|
|
from openstack_dashboard import api
|
|
from openstack_dashboard.test import helpers as test
|
|
|
|
|
|
class RoleAPITests(test.APIMockTestCase):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.role = self.roles.member
|
|
self.roles = self.roles.list()
|
|
|
|
@mock.patch.object(api.keystone, 'keystoneclient')
|
|
def test_remove_tenant_user(self, mock_keystoneclient):
|
|
"""Tests api.keystone.remove_tenant_user
|
|
|
|
Verifies that remove_tenant_user is called with the right arguments
|
|
after iterating the user's roles.
|
|
"""
|
|
keystoneclient = mock_keystoneclient.return_value
|
|
tenant = self.tenants.first()
|
|
|
|
keystoneclient.roles.roles_for_user.return_value = self.roles
|
|
keystoneclient.roles.revoke.side_effect = [None for role in self.roles]
|
|
|
|
api.keystone.remove_tenant_user(self.request, tenant.id, self.user.id)
|
|
|
|
keystoneclient.roles.roles_for_user.assert_called_once_with(
|
|
self.user.id, tenant.id)
|
|
keystoneclient.roles.revoke.assert_has_calls(
|
|
[mock.call(role.id,
|
|
domain=None,
|
|
group=None,
|
|
project=tenant.id,
|
|
user=self.user.id)
|
|
for role in self.roles]
|
|
)
|
|
|
|
@mock.patch.object(api.keystone, 'keystoneclient')
|
|
def test_get_default_role(self, mock_keystoneclient):
|
|
keystoneclient = mock_keystoneclient.return_value
|
|
keystoneclient.roles.list.return_value = self.roles
|
|
|
|
role = api.keystone.get_default_role(self.request)
|
|
self.assertEqual(self.role, role)
|
|
|
|
# Verify that a second call doesn't hit the API again,
|
|
# so we use assert_called_once_with() here.
|
|
role = api.keystone.get_default_role(self.request)
|
|
keystoneclient.roles.list.assert_called_once_with()
|
|
|
|
@mock.patch.object(api.keystone, 'keystoneclient')
|
|
@mock.patch.object(api.keystone, 'DEFAULT_ROLE', new=None)
|
|
def test_get_case_insensitive_default_role(self, mock_keystoneclient):
|
|
def convert_to_random_case(role_):
|
|
new_name = list()
|
|
for char in list(role_.name):
|
|
new_name.append(getattr(char, choice(["lower", "upper"]))())
|
|
role_.name = role_._info["name"] = "".join(new_name)
|
|
return role_
|
|
keystoneclient = mock_keystoneclient.return_value
|
|
keystoneclient.roles.list.return_value = list()
|
|
for role in self.roles:
|
|
role = convert_to_random_case(role)
|
|
keystoneclient.roles.list.return_value.append(role)
|
|
role = api.keystone.get_default_role(self.request)
|
|
self.assertEqual(self.role.name.lower(), role.name.lower())
|
|
# Verify that a second call doesn't hit the API again,
|
|
# so we use assert_called_once_with() here.
|
|
api.keystone.get_default_role(self.request)
|
|
keystoneclient.roles.list.assert_called_once_with()
|
|
|
|
|
|
class ServiceAPITests(test.APIMockTestCase):
|
|
@override_settings(OPENSTACK_ENDPOINT_TYPE='internalURL')
|
|
def test_service_wrapper_for_internal_endpoint_type(self):
|
|
catalog = self.service_catalog
|
|
identity_data = api.base.get_service_from_catalog(catalog, "identity")
|
|
# 'Service' class below requires 'id', so populate it here.
|
|
identity_data['id'] = 1
|
|
service = api.keystone.Service(identity_data, "RegionOne")
|
|
self.assertEqual(u"identity (native backend)", str(service))
|
|
self.assertEqual("RegionOne", service.region)
|
|
self.assertEqual("http://int.keystone.example.com/identity/v3",
|
|
service.url)
|
|
self.assertEqual("http://public.keystone.example.com/identity/v3",
|
|
service.public_url)
|
|
self.assertEqual("int.keystone.example.com", service.host)
|
|
|
|
@override_settings(OPENSTACK_ENDPOINT_TYPE='publicURL')
|
|
def test_service_wrapper_for_public_endpoint_type(self):
|
|
catalog = self.service_catalog
|
|
identity_data = api.base.get_service_from_catalog(catalog, "identity")
|
|
# 'Service' class below requires 'id', so populate it here.
|
|
identity_data['id'] = 1
|
|
service = api.keystone.Service(identity_data, "RegionOne")
|
|
self.assertEqual(u"identity (native backend)", str(service))
|
|
self.assertEqual("RegionOne", service.region)
|
|
self.assertEqual("http://public.keystone.example.com/identity/v3",
|
|
service.url)
|
|
self.assertEqual("http://public.keystone.example.com/identity/v3",
|
|
service.public_url)
|
|
self.assertEqual("public.keystone.example.com", service.host)
|
|
|
|
@override_settings(OPENSTACK_ENDPOINT_TYPE='internalURL')
|
|
def test_service_wrapper_in_region_for_internal_endpoint_type(self):
|
|
catalog = self.service_catalog
|
|
compute_data = api.base.get_service_from_catalog(catalog, "compute")
|
|
# 'Service' class below requires 'id', so populate it here.
|
|
compute_data['id'] = 1
|
|
service = api.keystone.Service(compute_data, 'RegionTwo')
|
|
self.assertEqual(u"compute", str(service))
|
|
self.assertEqual("RegionTwo", service.region)
|
|
self.assertEqual("http://int.nova2.example.com:8774/v2",
|
|
service.url)
|
|
self.assertEqual("http://public.nova2.example.com:8774/v2",
|
|
service.public_url)
|
|
self.assertEqual("int.nova2.example.com", service.host)
|
|
|
|
@override_settings(OPENSTACK_ENDPOINT_TYPE='publicURL')
|
|
def test_service_wrapper_service_in_region_for_public_endpoint_type(self):
|
|
catalog = self.service_catalog
|
|
compute_data = api.base.get_service_from_catalog(catalog, "compute")
|
|
# 'Service' class below requires 'id', so populate it here.
|
|
compute_data['id'] = 1
|
|
service = api.keystone.Service(compute_data, 'RegionTwo')
|
|
self.assertEqual(u"compute", str(service))
|
|
self.assertEqual("RegionTwo", service.region)
|
|
self.assertEqual("http://public.nova2.example.com:8774/v2",
|
|
service.url)
|
|
self.assertEqual("http://public.nova2.example.com:8774/v2",
|
|
service.public_url)
|
|
self.assertEqual("public.nova2.example.com", service.host)
|
|
|
|
|
|
class APIVersionTests(test.APIMockTestCase):
|
|
@mock.patch.object(api.keystone, 'keystoneclient')
|
|
def test_get_identity_api_version(self, mock_keystoneclient):
|
|
keystoneclient = mock_keystoneclient.return_value
|
|
endpoint_data = mock.Mock()
|
|
endpoint_data.api_version = (3, 10)
|
|
keystoneclient.session.get_endpoint_data.return_value = endpoint_data
|
|
api_version = api.keystone.get_identity_api_version(self.request)
|
|
keystoneclient.session.get_endpoint_data.assert_called_once_with(
|
|
service_type='identity')
|
|
self.assertEqual((3, 10), api_version)
|