Merge "Fix V3 credential behavior, documentation"
diff --git a/etc/accounts.yaml.sample b/etc/accounts.yaml.sample
index decc659..3dbed79 100644
--- a/etc/accounts.yaml.sample
+++ b/etc/accounts.yaml.sample
@@ -3,7 +3,25 @@
# This is required to provide isolation between test for running in parallel
#
# Valid fields for credentials are defined in the descendants of
-# auth.Credentials - see KeystoneV[2|3]Credentials.CONF_ATTRIBUTES
+# lib.auth.Credentials - see KeystoneV[2|3]Credentials.ATTRIBUTES
+#
+# The fields in KeystoneV3Credentials behave as follows:
+#
+# tenant_[id|name] also sets project_[id|name].
+#
+# project_[id|name] also sets tenant_[id|name].
+#
+# Providing distinct values for both tenant_[id|name] and project_[id|name]
+# will result in an InvalidCredentials exception.
+#
+# The value of project_domain_[id|name] is used for user_domain_[id|name] if
+# the latter is not specified.
+#
+# The value of user_domain_[id|name] is used for project_domain_[id|name] if
+# the latter is not specified.
+#
+# The value of domain_[id|name] is used for project_domain_[id|name] if not
+# specified and user_domain_[id|name] if not specified.
- username: 'user_1'
tenant_name: 'test_tenant_1'
diff --git a/tempest/lib/auth.py b/tempest/lib/auth.py
index 2d20a0b..71c4f4f 100644
--- a/tempest/lib/auth.py
+++ b/tempest/lib/auth.py
@@ -622,6 +622,9 @@
return None not in (self.username, self.password)
+COLLISIONS = [('project_name', 'tenant_name'), ('project_id', 'tenant_id')]
+
+
class KeystoneV3Credentials(Credentials):
"""Credentials suitable for the Keystone Identity V3 API"""
@@ -630,6 +633,16 @@
'project_name', 'tenant_id', 'tenant_name', 'user_domain_id',
'user_domain_name', 'user_id']
+ def _apply_credentials(self, attr):
+ for (key1, key2) in COLLISIONS:
+ val1 = attr.get(key1)
+ val2 = attr.get(key2)
+ if val1 and val2 and val1 != val2:
+ msg = ('Cannot have conflicting values for %s and %s' %
+ (key1, key2))
+ raise exceptions.InvalidCredentials(msg)
+ super(KeystoneV3Credentials, self)._apply_credentials(attr)
+
def __setattr__(self, key, value):
parent = super(KeystoneV3Credentials, self)
# for tenant_* set both project and tenant
@@ -657,8 +670,10 @@
parent.__setattr__('user_domain_name', value)
# support domain_name coming from config
if key == 'domain_name':
- parent.__setattr__('user_domain_name', value)
- parent.__setattr__('project_domain_name', value)
+ if self.user_domain_name is None:
+ parent.__setattr__('user_domain_name', value)
+ if self.project_domain_name is None:
+ parent.__setattr__('project_domain_name', value)
# finally trigger default behaviour for all attributes
parent.__setattr__(key, value)
diff --git a/tempest/tests/lib/test_auth.py b/tempest/tests/lib/test_auth.py
index ebcfe82..6a01490 100644
--- a/tempest/tests/lib/test_auth.py
+++ b/tempest/tests/lib/test_auth.py
@@ -530,3 +530,43 @@
expected = 'http://fake_url/v3'
self._test_base_url_helper(expected, filters, ('token', auth_data))
+
+
+class TestKeystoneV3Credentials(base.TestCase):
+ def testSetAttrUserDomain(self):
+ creds = auth.KeystoneV3Credentials()
+ creds.user_domain_name = 'user_domain'
+ creds.domain_name = 'domain'
+ self.assertEqual('user_domain', creds.user_domain_name)
+ creds = auth.KeystoneV3Credentials()
+ creds.domain_name = 'domain'
+ creds.user_domain_name = 'user_domain'
+ self.assertEqual('user_domain', creds.user_domain_name)
+
+ def testSetAttrProjectDomain(self):
+ creds = auth.KeystoneV3Credentials()
+ creds.project_domain_name = 'project_domain'
+ creds.domain_name = 'domain'
+ self.assertEqual('project_domain', creds.user_domain_name)
+ creds = auth.KeystoneV3Credentials()
+ creds.domain_name = 'domain'
+ creds.project_domain_name = 'project_domain'
+ self.assertEqual('project_domain', creds.project_domain_name)
+
+ def testProjectTenantNoCollision(self):
+ creds = auth.KeystoneV3Credentials(tenant_id='tenant')
+ self.assertEqual('tenant', creds.project_id)
+ creds = auth.KeystoneV3Credentials(project_id='project')
+ self.assertEqual('project', creds.tenant_id)
+ creds = auth.KeystoneV3Credentials(tenant_name='tenant')
+ self.assertEqual('tenant', creds.project_name)
+ creds = auth.KeystoneV3Credentials(project_name='project')
+ self.assertEqual('project', creds.tenant_name)
+
+ def testProjectTenantCollision(self):
+ attrs = {'tenant_id': 'tenant', 'project_id': 'project'}
+ self.assertRaises(
+ exceptions.InvalidCredentials, auth.KeystoneV3Credentials, **attrs)
+ attrs = {'tenant_name': 'tenant', 'project_name': 'project'}
+ self.assertRaises(
+ exceptions.InvalidCredentials, auth.KeystoneV3Credentials, **attrs)