aboutsummaryrefslogtreecommitdiffstats
path: root/keystone-moon
diff options
context:
space:
mode:
Diffstat (limited to 'keystone-moon')
-rw-r--r--keystone-moon/doc/source/configuration.rst12
-rw-r--r--keystone-moon/etc/keystone.conf.sample12
-rw-r--r--keystone-moon/keystone/assignment/controllers.py6
-rw-r--r--keystone-moon/keystone/catalog/controllers.py77
-rw-r--r--keystone-moon/keystone/common/config.py10
-rw-r--r--keystone-moon/keystone/common/ldap/core.py31
-rw-r--r--keystone-moon/keystone/contrib/federation/migrate_repo/versions/007_add_remote_id_table.py4
-rw-r--r--keystone-moon/keystone/identity/controllers.py9
-rw-r--r--keystone-moon/keystone/locale/de/LC_MESSAGES/keystone-log-critical.po13
-rw-r--r--keystone-moon/keystone/locale/de/LC_MESSAGES/keystone.po10
-rw-r--r--keystone-moon/keystone/locale/el/LC_MESSAGES/keystone-log-critical.po13
-rw-r--r--keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone-log-critical.po9
-rw-r--r--keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone-log-error.po9
-rw-r--r--keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone.po13
-rw-r--r--keystone-moon/keystone/locale/es/LC_MESSAGES/keystone-log-critical.po13
-rw-r--r--keystone-moon/keystone/locale/es/LC_MESSAGES/keystone.po10
-rw-r--r--keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-critical.po13
-rw-r--r--keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-error.po9
-rw-r--r--keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-info.po11
-rw-r--r--keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-warning.po11
-rw-r--r--keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone.po10
-rw-r--r--keystone-moon/keystone/locale/hu/LC_MESSAGES/keystone-log-critical.po13
-rw-r--r--keystone-moon/keystone/locale/it/LC_MESSAGES/keystone-log-critical.po13
-rw-r--r--keystone-moon/keystone/locale/it/LC_MESSAGES/keystone.po10
-rw-r--r--keystone-moon/keystone/locale/ja/LC_MESSAGES/keystone-log-critical.po13
-rw-r--r--keystone-moon/keystone/locale/ja/LC_MESSAGES/keystone.po483
-rw-r--r--keystone-moon/keystone/locale/keystone-log-warning.pot6
-rw-r--r--keystone-moon/keystone/locale/keystone.pot6
-rw-r--r--keystone-moon/keystone/locale/ko_KR/LC_MESSAGES/keystone-log-critical.po9
-rw-r--r--keystone-moon/keystone/locale/ko_KR/LC_MESSAGES/keystone.po10
-rw-r--r--keystone-moon/keystone/locale/pl_PL/LC_MESSAGES/keystone-log-critical.po9
-rw-r--r--keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone-log-critical.po9
-rw-r--r--keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone-log-error.po9
-rw-r--r--keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone.po10
-rw-r--r--keystone-moon/keystone/locale/ru/LC_MESSAGES/keystone-log-critical.po13
-rw-r--r--keystone-moon/keystone/locale/ru/LC_MESSAGES/keystone.po10
-rw-r--r--keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-critical.po9
-rw-r--r--keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-error.po9
-rw-r--r--keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-info.po9
-rw-r--r--keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-warning.po9
-rw-r--r--keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone.po10
-rw-r--r--keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-critical.po9
-rw-r--r--keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-error.po9
-rw-r--r--keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-info.po9
-rw-r--r--keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone.po10
-rw-r--r--keystone-moon/keystone/locale/zh_TW/LC_MESSAGES/keystone-log-critical.po9
-rw-r--r--keystone-moon/keystone/locale/zh_TW/LC_MESSAGES/keystone.po10
-rw-r--r--keystone-moon/keystone/resource/controllers.py10
-rw-r--r--keystone-moon/keystone/resource/core.py1
-rw-r--r--keystone-moon/keystone/tests/unit/common/test_notifications.py163
-rw-r--r--keystone-moon/keystone/tests/unit/rest.py2
-rw-r--r--keystone-moon/keystone/tests/unit/test_associate_project_endpoint_extension.py60
-rw-r--r--keystone-moon/keystone/tests/unit/test_backend.py2
-rw-r--r--keystone-moon/keystone/tests/unit/test_backend_ldap.py47
-rw-r--r--keystone-moon/keystone/tests/unit/test_catalog.py89
-rw-r--r--keystone-moon/keystone/tests/unit/test_cert_setup.py11
-rw-r--r--keystone-moon/keystone/tests/unit/test_contrib_simple_cert.py6
-rw-r--r--keystone-moon/keystone/tests/unit/test_policy.py24
-rw-r--r--keystone-moon/keystone/tests/unit/test_sql_migrate_extensions.py63
-rw-r--r--keystone-moon/keystone/tests/unit/test_v2.py70
-rw-r--r--keystone-moon/keystone/tests/unit/test_v2_keystoneclient.py4
-rw-r--r--keystone-moon/keystone/tests/unit/test_v3.py50
-rw-r--r--keystone-moon/keystone/tests/unit/test_v3_assignment.py17
-rw-r--r--keystone-moon/keystone/tests/unit/test_v3_auth.py253
-rw-r--r--keystone-moon/keystone/tests/unit/test_v3_catalog.py54
-rw-r--r--keystone-moon/keystone/tests/unit/test_v3_credential.py2
-rw-r--r--keystone-moon/keystone/tests/unit/test_v3_domain_config.py12
-rw-r--r--keystone-moon/keystone/tests/unit/test_v3_endpoint_policy.py42
-rw-r--r--keystone-moon/keystone/tests/unit/test_v3_federation.py73
-rw-r--r--keystone-moon/keystone/tests/unit/test_v3_identity.py28
-rw-r--r--keystone-moon/keystone/tests/unit/test_v3_oauth1.py21
-rw-r--r--keystone-moon/keystone/tests/unit/test_v3_protection.py23
-rw-r--r--keystone-moon/keystone/tests/unit/test_versions.py16
-rw-r--r--keystone-moon/keystone/tests/unit/test_wsgi.py11
-rw-r--r--keystone-moon/keystone/tests/unit/token/test_fernet_provider.py276
-rw-r--r--keystone-moon/keystone/token/providers/fernet/core.py4
-rw-r--r--keystone-moon/keystone/token/providers/fernet/token_formatters.py71
-rw-r--r--keystone-moon/releasenotes/notes/.placeholder0
-rw-r--r--keystone-moon/releasenotes/notes/deprecations-c4afc19dc5324b9c.yaml19
-rw-r--r--keystone-moon/releasenotes/notes/new_features-e33d793d8a5ca76a.yaml21
-rw-r--r--keystone-moon/releasenotes/notes/upgrade_notes-ca81f5d531ab3522.yaml31
-rw-r--r--keystone-moon/releasenotes/source/_static/.placeholder0
-rw-r--r--keystone-moon/releasenotes/source/_templates/.placeholder0
-rw-r--r--keystone-moon/releasenotes/source/conf.py275
-rw-r--r--keystone-moon/releasenotes/source/index.rst9
-rw-r--r--keystone-moon/releasenotes/source/liberty.rst6
-rw-r--r--keystone-moon/releasenotes/source/unreleased.rst5
-rw-r--r--keystone-moon/requirements.txt8
-rw-r--r--keystone-moon/setup.cfg14
-rw-r--r--keystone-moon/test-requirements.txt3
-rw-r--r--keystone-moon/tox.ini5
91 files changed, 1980 insertions, 951 deletions
diff --git a/keystone-moon/doc/source/configuration.rst b/keystone-moon/doc/source/configuration.rst
index 96491660..574b26be 100644
--- a/keystone-moon/doc/source/configuration.rst
+++ b/keystone-moon/doc/source/configuration.rst
@@ -1637,9 +1637,9 @@ have been created. They are enabled by setting their respective flags to True.
Then the attributes ``user_enabled_emulation_dn`` and
``project_enabled_emulation_dn`` may be set to specify how the enabled users
and projects (tenants) are selected. These attributes work by using a
-``groupOfNames`` and adding whichever users or projects (tenants) that you want
-enabled to the respective group. For example, this will mark any user who is a
-member of ``enabled_users`` as enabled:
+``groupOfNames`` entry and adding whichever users or projects (tenants) that
+you want enabled to the respective group with the ``member`` attribute. For
+example, this will mark any user who is a member of ``enabled_users`` as enabled:
.. code-block:: ini
@@ -1651,6 +1651,12 @@ The default values for user and project (tenant) enabled emulation DN is
``cn=enabled_users,$user_tree_dn`` and ``cn=enabled_tenants,$project_tree_dn``
respectively.
+If a different LDAP schema is used for group membership, it is possible to use
+the ``group_objectclass`` and ``group_member_attribute`` attributes to
+determine membership in the enabled emulation group by setting the
+``user_enabled_emulation_use_group_config`` and
+``project_enabled_emulation_use_group_config`` attributes to True.
+
Secure Connection
-----------------
diff --git a/keystone-moon/etc/keystone.conf.sample b/keystone-moon/etc/keystone.conf.sample
index 9c76fc0d..8e5ea13b 100644
--- a/keystone-moon/etc/keystone.conf.sample
+++ b/keystone-moon/etc/keystone.conf.sample
@@ -760,8 +760,8 @@
# A list of trusted dashboard hosts. Before accepting a Single Sign-On request
# to return a token, the origin host must be a member of the trusted_dashboard
# list. This configuration option may be repeated for multiple values. For
-# example: trusted_dashboard=http://acme.com/auth/websso
-# trusted_dashboard=http://beta.com/auth/websso (multi valued)
+# example: trusted_dashboard=http://acme.com trusted_dashboard=http://beta.com
+# (multi valued)
#trusted_dashboard =
# Location of Single Sign-On callback handler, will return a token to a trusted
@@ -1019,6 +1019,10 @@
# (string value)
#user_enabled_emulation_dn = <None>
+# Use the "group_member_attribute" and "group_objectclass" settings to
+# determine membership in the emulated enabled group. (boolean value)
+#user_enabled_emulation_use_group_config = false
+
# List of additional LDAP attributes used for mapping additional attribute
# mappings for users. Attribute mapping format is <ldap_attr>:<user_attr>,
# where ldap_attr is the attribute in the LDAP entry and user_attr is the
@@ -1118,6 +1122,10 @@
# Its value may be silently ignored in the future.
#project_enabled_emulation_dn = <None>
+# Use the "group_member_attribute" and "group_objectclass" settings to
+# determine membership in the emulated enabled group. (boolean value)
+#project_enabled_emulation_use_group_config = false
+
# Additional attribute mappings for projects. Attribute mapping format is
# <ldap_attr>:<user_attr>, where ldap_attr is the attribute in the LDAP entry
# and user_attr is the Identity API attribute. (list value)
diff --git a/keystone-moon/keystone/assignment/controllers.py b/keystone-moon/keystone/assignment/controllers.py
index d33dce70..bbaf9437 100644
--- a/keystone-moon/keystone/assignment/controllers.py
+++ b/keystone-moon/keystone/assignment/controllers.py
@@ -108,13 +108,15 @@ class Role(controller.V2Controller):
role_id = uuid.uuid4().hex
role['id'] = role_id
- role_ref = self.role_api.create_role(role_id, role)
+ initiator = notifications._get_request_audit_info(context)
+ role_ref = self.role_api.create_role(role_id, role, initiator)
return {'role': role_ref}
@controller.v2_deprecated
def delete_role(self, context, role_id):
self.assert_admin(context)
- self.role_api.delete_role(role_id)
+ initiator = notifications._get_request_audit_info(context)
+ self.role_api.delete_role(role_id, initiator)
@controller.v2_deprecated
def get_roles(self, context):
diff --git a/keystone-moon/keystone/catalog/controllers.py b/keystone-moon/keystone/catalog/controllers.py
index 92046e8a..e14b268a 100644
--- a/keystone-moon/keystone/catalog/controllers.py
+++ b/keystone-moon/keystone/catalog/controllers.py
@@ -47,7 +47,8 @@ class Service(controller.V2Controller):
@controller.v2_deprecated
def delete_service(self, context, service_id):
self.assert_admin(context)
- self.catalog_api.delete_service(service_id)
+ initiator = notifications._get_request_audit_info(context)
+ self.catalog_api.delete_service(service_id, initiator)
@controller.v2_deprecated
def create_service(self, context, OS_KSADM_service):
@@ -55,8 +56,9 @@ class Service(controller.V2Controller):
service_id = uuid.uuid4().hex
service_ref = OS_KSADM_service.copy()
service_ref['id'] = service_id
+ initiator = notifications._get_request_audit_info(context)
new_service_ref = self.catalog_api.create_service(
- service_id, service_ref)
+ service_id, service_ref, initiator)
return {'OS-KSADM:service': new_service_ref}
@@ -68,25 +70,59 @@ class Endpoint(controller.V2Controller):
"""Merge matching v3 endpoint refs into legacy refs."""
self.assert_admin(context)
legacy_endpoints = {}
+ v3_endpoints = {}
for endpoint in self.catalog_api.list_endpoints():
- if not endpoint.get('legacy_endpoint_id'):
- # endpoints created in v3 should not appear on the v2 API
+ if not endpoint.get('legacy_endpoint_id'): # pure v3 endpoint
+ # tell endpoints apart by the combination of
+ # service_id and region_id.
+ # NOTE(muyu): in theory, it's possible that there are more than
+ # one endpoint of one service, one region and one interface,
+ # but in practice, it makes no sense because only one will be
+ # used.
+ key = (endpoint['service_id'], endpoint['region_id'])
+ v3_endpoints.setdefault(key, []).append(endpoint)
+ else: # legacy endpoint
+ if endpoint['legacy_endpoint_id'] not in legacy_endpoints:
+ legacy_ep = endpoint.copy()
+ legacy_ep['id'] = legacy_ep.pop('legacy_endpoint_id')
+ legacy_ep.pop('interface')
+ legacy_ep.pop('url')
+ legacy_ep['region'] = legacy_ep.pop('region_id')
+
+ legacy_endpoints[endpoint['legacy_endpoint_id']] = (
+ legacy_ep)
+ else:
+ legacy_ep = (
+ legacy_endpoints[endpoint['legacy_endpoint_id']])
+
+ # add the legacy endpoint with an interface url
+ legacy_ep['%surl' % endpoint['interface']] = endpoint['url']
+
+ # convert collected v3 endpoints into v2 endpoints
+ for endpoints in v3_endpoints.values():
+ legacy_ep = {}
+ # For v3 endpoints in the same group, contents of extra attributes
+ # can be different, which may cause confusion if a random one is
+ # used. So only necessary attributes are used here.
+ # It's different for legacy v2 endpoints, which are created
+ # with the same "extra" value when being migrated.
+ for key in ('service_id', 'enabled'):
+ legacy_ep[key] = endpoints[0][key]
+ legacy_ep['region'] = endpoints[0]['region_id']
+ for endpoint in endpoints:
+ # Public URL is required for v2 endpoints, so the generated v2
+ # endpoint uses public endpoint's id as its id, which can also
+ # be an indicator whether a public v3 endpoint is present.
+ # It's safe to do so is also because that there is no v2 API to
+ # get an endpoint by endpoint ID.
+ if endpoint['interface'] == 'public':
+ legacy_ep['id'] = endpoint['id']
+ legacy_ep['%surl' % endpoint['interface']] = endpoint['url']
+
+ # this means there is no public URL of this group of v3 endpoints
+ if 'id' not in legacy_ep:
continue
-
- # is this is a legacy endpoint we haven't indexed yet?
- if endpoint['legacy_endpoint_id'] not in legacy_endpoints:
- legacy_ep = endpoint.copy()
- legacy_ep['id'] = legacy_ep.pop('legacy_endpoint_id')
- legacy_ep.pop('interface')
- legacy_ep.pop('url')
- legacy_ep['region'] = legacy_ep.pop('region_id')
-
- legacy_endpoints[endpoint['legacy_endpoint_id']] = legacy_ep
- else:
- legacy_ep = legacy_endpoints[endpoint['legacy_endpoint_id']]
-
- # add the legacy endpoint with an interface url
- legacy_ep['%surl' % endpoint['interface']] = endpoint['url']
+ legacy_endpoints[legacy_ep['id']] = legacy_ep
return {'endpoints': list(legacy_endpoints.values())}
@controller.v2_deprecated
@@ -148,11 +184,12 @@ class Endpoint(controller.V2Controller):
def delete_endpoint(self, context, endpoint_id):
"""Delete up to three v3 endpoint refs based on a legacy ref ID."""
self.assert_admin(context)
+ initiator = notifications._get_request_audit_info(context)
deleted_at_least_one = False
for endpoint in self.catalog_api.list_endpoints():
if endpoint['legacy_endpoint_id'] == endpoint_id:
- self.catalog_api.delete_endpoint(endpoint['id'])
+ self.catalog_api.delete_endpoint(endpoint['id'], initiator)
deleted_at_least_one = True
if not deleted_at_least_one:
diff --git a/keystone-moon/keystone/common/config.py b/keystone-moon/keystone/common/config.py
index fcf05abe..4ba740fe 100644
--- a/keystone-moon/keystone/common/config.py
+++ b/keystone-moon/keystone/common/config.py
@@ -668,6 +668,10 @@ FILE_OPTIONS = {
cfg.StrOpt('user_enabled_emulation_dn',
help='DN of the group entry to hold enabled users when '
'using enabled emulation.'),
+ cfg.BoolOpt('user_enabled_emulation_use_group_config', default=False,
+ help='Use the "group_member_attribute" and '
+ '"group_objectclass" settings to determine '
+ 'membership in the emulated enabled group.'),
cfg.ListOpt('user_additional_attribute_mapping',
default=[],
help='List of additional LDAP attributes used for mapping '
@@ -759,6 +763,11 @@ FILE_OPTIONS = {
deprecated_for_removal=True,
help='DN of the group entry to hold enabled projects when '
'using enabled emulation.'),
+ cfg.BoolOpt('project_enabled_emulation_use_group_config',
+ default=False,
+ help='Use the "group_member_attribute" and '
+ '"group_objectclass" settings to determine '
+ 'membership in the emulated enabled group.'),
cfg.ListOpt('project_additional_attribute_mapping',
deprecated_opts=[cfg.DeprecatedOpt(
'tenant_additional_attribute_mapping', group='ldap')],
@@ -1191,6 +1200,7 @@ FILE_OPTIONS = {
default='policy_root',
help='Local directory where Root IntraExtension configuration is stored.'),
]
+
}
diff --git a/keystone-moon/keystone/common/ldap/core.py b/keystone-moon/keystone/common/ldap/core.py
index 0bb3830c..6386ae2a 100644
--- a/keystone-moon/keystone/common/ldap/core.py
+++ b/keystone-moon/keystone/common/ldap/core.py
@@ -1771,19 +1771,23 @@ class BaseLdap(object):
class EnabledEmuMixIn(BaseLdap):
"""Emulates boolean 'enabled' attribute if turned on.
- Creates groupOfNames holding all enabled objects of this class, all missing
+ Creates a group holding all enabled objects of this class, all missing
objects are considered disabled.
Options:
* $name_enabled_emulation - boolean, on/off
- * $name_enabled_emulation_dn - DN of that groupOfNames, default is
+ * $name_enabled_emulation_dn - DN of that group, default is
cn=enabled_${name}s,${tree_dn}
+ * $name_enabled_emulation_use_group_config - boolean, on/off
Where ${name}s is the plural of self.options_name ('users' or 'tenants'),
${tree_dn} is self.tree_dn.
"""
+ DEFAULT_GROUP_OBJECTCLASS = 'groupOfNames'
+ DEFAULT_MEMBER_ATTRIBUTE = 'member'
+
def __init__(self, conf):
super(EnabledEmuMixIn, self).__init__(conf)
enabled_emulation = '%s_enabled_emulation' % self.options_name
@@ -1791,6 +1795,18 @@ class EnabledEmuMixIn(BaseLdap):
enabled_emulation_dn = '%s_enabled_emulation_dn' % self.options_name
self.enabled_emulation_dn = getattr(conf.ldap, enabled_emulation_dn)
+
+ use_group_config = ('%s_enabled_emulation_use_group_config' %
+ self.options_name)
+ self.use_group_config = getattr(conf.ldap, use_group_config)
+
+ if not self.use_group_config:
+ self.member_attribute = self.DEFAULT_MEMBER_ATTRIBUTE
+ self.group_objectclass = self.DEFAULT_GROUP_OBJECTCLASS
+ else:
+ self.member_attribute = conf.ldap.group_member_attribute
+ self.group_objectclass = conf.ldap.group_objectclass
+
if not self.enabled_emulation_dn:
naming_attr_name = 'cn'
naming_attr_value = 'enabled_%ss' % self.options_name
@@ -1807,7 +1823,7 @@ class EnabledEmuMixIn(BaseLdap):
def _get_enabled(self, object_id, conn):
dn = self._id_to_dn(object_id)
- query = '(member=%s)' % dn
+ query = '(%s=%s)' % (self.member_attribute, dn)
try:
enabled_value = conn.search_s(self.enabled_emulation_dn,
ldap.SCOPE_BASE,
@@ -1821,13 +1837,14 @@ class EnabledEmuMixIn(BaseLdap):
with self.get_connection() as conn:
if not self._get_enabled(object_id, conn):
modlist = [(ldap.MOD_ADD,
- 'member',
+ self.member_attribute,
[self._id_to_dn(object_id)])]
try:
conn.modify_s(self.enabled_emulation_dn, modlist)
except ldap.NO_SUCH_OBJECT:
- attr_list = [('objectClass', ['groupOfNames']),
- ('member', [self._id_to_dn(object_id)]),
+ attr_list = [('objectClass', [self.group_objectclass]),
+ (self.member_attribute,
+ [self._id_to_dn(object_id)]),
self.enabled_emulation_naming_attr]
if self.use_dumb_member:
attr_list[1][1].append(self.dumb_member)
@@ -1835,7 +1852,7 @@ class EnabledEmuMixIn(BaseLdap):
def _remove_enabled(self, object_id):
modlist = [(ldap.MOD_DELETE,
- 'member',
+ self.member_attribute,
[self._id_to_dn(object_id)])]
with self.get_connection() as conn:
try:
diff --git a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/007_add_remote_id_table.py b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/007_add_remote_id_table.py
index cd571245..77012aad 100644
--- a/keystone-moon/keystone/contrib/federation/migrate_repo/versions/007_add_remote_id_table.py
+++ b/keystone-moon/keystone/contrib/federation/migrate_repo/versions/007_add_remote_id_table.py
@@ -32,7 +32,9 @@ def upgrade(migrate_engine):
remote_id_table.create(migrate_engine, checkfirst=True)
- select = orm.sql.select([idp_table.c.id, idp_table.c.remote_id])
+ select = orm.sql.select([idp_table.c.id, idp_table.c.remote_id]).where(
+ idp_table.c.remote_id.isnot(None))
+
for identity in migrate_engine.execute(select):
remote_idp_entry = {'idp_id': identity.id,
'remote_id': identity.remote_id}
diff --git a/keystone-moon/keystone/identity/controllers.py b/keystone-moon/keystone/identity/controllers.py
index 7a6a642a..0ec38190 100644
--- a/keystone-moon/keystone/identity/controllers.py
+++ b/keystone-moon/keystone/identity/controllers.py
@@ -82,8 +82,9 @@ class User(controller.V2Controller):
# The manager layer will generate the unique ID for users
user_ref = self._normalize_domain_id(context, user.copy())
+ initiator = notifications._get_request_audit_info(context)
new_user_ref = self.v3_to_v2_user(
- self.identity_api.create_user(user_ref))
+ self.identity_api.create_user(user_ref, initiator))
if default_project_id is not None:
self.assignment_api.add_user_to_project(default_project_id,
@@ -120,8 +121,9 @@ class User(controller.V2Controller):
# user update.
self.resource_api.get_project(default_project_id)
+ initiator = notifications._get_request_audit_info(context)
user_ref = self.v3_to_v2_user(
- self.identity_api.update_user(user_id, user))
+ self.identity_api.update_user(user_id, user, initiator))
# If 'tenantId' is in either ref, we might need to add or remove the
# user from a project.
@@ -166,7 +168,8 @@ class User(controller.V2Controller):
@controller.v2_deprecated
def delete_user(self, context, user_id):
self.assert_admin(context)
- self.identity_api.delete_user(user_id)
+ initiator = notifications._get_request_audit_info(context)
+ self.identity_api.delete_user(user_id, initiator)
@controller.v2_deprecated
def set_user_enabled(self, context, user_id, user):
diff --git a/keystone-moon/keystone/locale/de/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/de/LC_MESSAGES/keystone-log-critical.po
index 0403952d..a9cfc70a 100644
--- a/keystone-moon/keystone/locale/de/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/de/LC_MESSAGES/keystone-log-critical.po
@@ -3,21 +3,22 @@
# This file is distributed under the same license as the keystone project.
#
# Translators:
+# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: Keystone\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-08-06 06:28+0000\n"
-"PO-Revision-Date: 2014-08-31 15:19+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
+"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: German (http://www.transifex.com/openstack/keystone/language/"
-"de/)\n"
+"Language-Team: German\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Generated-By: Babel 2.0\n"
+"X-Generator: Zanata 3.7.1\n"
#, python-format
msgid "Unable to open template file %s"
diff --git a/keystone-moon/keystone/locale/de/LC_MESSAGES/keystone.po b/keystone-moon/keystone/locale/de/LC_MESSAGES/keystone.po
index 1b2f1094..6f860754 100644
--- a/keystone-moon/keystone/locale/de/LC_MESSAGES/keystone.po
+++ b/keystone-moon/keystone/locale/de/LC_MESSAGES/keystone.po
@@ -10,18 +10,18 @@
# Tom Cocozzello <tjcocozz@us.ibm.com>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-09-03 12:54+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: German (http://www.transifex.com/openstack/keystone/language/"
-"de/)\n"
+"Language: de\n"
+"Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#, python-format
msgid "%(detail)s"
diff --git a/keystone-moon/keystone/locale/el/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/el/LC_MESSAGES/keystone-log-critical.po
index 1dffb340..90f983b2 100644
--- a/keystone-moon/keystone/locale/el/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/el/LC_MESSAGES/keystone-log-critical.po
@@ -4,21 +4,22 @@
#
# Translators:
# Efstathios Iosifidis <iefstathios@gmail.com>, 2015
+# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: Keystone\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-08 06:08+0000\n"
-"PO-Revision-Date: 2015-09-05 13:09+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
+"PO-Revision-Date: 2015-09-05 01:09+0000\n"
"Last-Translator: Efstathios Iosifidis <iefstathios@gmail.com>\n"
-"Language-Team: Greek (http://www.transifex.com/openstack/keystone/language/"
-"el/)\n"
+"Language-Team: Greek\n"
"Language: el\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Generated-By: Babel 2.0\n"
+"X-Generator: Zanata 3.7.1\n"
#, python-format
msgid "Unable to open template file %s"
diff --git a/keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone-log-critical.po
index 99590953..5576d065 100644
--- a/keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone-log-critical.po
@@ -6,19 +6,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: English (Australia) (http://www.transifex.com/openstack/"
-"keystone/language/en_AU/)\n"
+"Language-Team: English (Australia)\n"
"Language: en-AU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
#, python-format
diff --git a/keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone-log-error.po b/keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone-log-error.po
index 7fd91ea1..141e7ec1 100644
--- a/keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone-log-error.po
+++ b/keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone-log-error.po
@@ -6,19 +6,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-06-26 05:13+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: English (Australia) (http://www.transifex.com/openstack/"
-"keystone/language/en_AU/)\n"
+"Language-Team: English (Australia)\n"
"Language: en-AU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
msgid ""
diff --git a/keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone.po b/keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone.po
index dca5aa9b..f290a110 100644
--- a/keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone.po
+++ b/keystone-moon/keystone/locale/en_AU/LC_MESSAGES/keystone.po
@@ -4,20 +4,21 @@
#
# Translators:
# Tom Fifield <tom@openstack.org>, 2013
+# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: Keystone\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-08-06 06:28+0000\n"
-"PO-Revision-Date: 2015-08-04 18:01+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
+"PO-Revision-Date: 2015-09-03 12:54+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: English (Australia) (http://www.transifex.com/openstack/"
-"keystone/language/en_AU/)\n"
+"Language: en_AU\n"
+"Language-Team: English (Australia)\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#, python-format
msgid "%(property_name)s cannot be less than %(min_length)s characters."
diff --git a/keystone-moon/keystone/locale/es/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/es/LC_MESSAGES/keystone-log-critical.po
index 336c5d33..9b93b5ed 100644
--- a/keystone-moon/keystone/locale/es/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/es/LC_MESSAGES/keystone-log-critical.po
@@ -3,21 +3,22 @@
# This file is distributed under the same license as the keystone project.
#
# Translators:
+# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: Keystone\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-08-06 06:28+0000\n"
-"PO-Revision-Date: 2014-08-31 15:19+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
+"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Spanish (http://www.transifex.com/openstack/keystone/language/"
-"es/)\n"
+"Language-Team: Spanish\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Generated-By: Babel 2.0\n"
+"X-Generator: Zanata 3.7.1\n"
#, python-format
msgid "Unable to open template file %s"
diff --git a/keystone-moon/keystone/locale/es/LC_MESSAGES/keystone.po b/keystone-moon/keystone/locale/es/LC_MESSAGES/keystone.po
index 70752350..46520ca7 100644
--- a/keystone-moon/keystone/locale/es/LC_MESSAGES/keystone.po
+++ b/keystone-moon/keystone/locale/es/LC_MESSAGES/keystone.po
@@ -13,18 +13,18 @@
# Tom Cocozzello <tjcocozz@us.ibm.com>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-09-03 12:54+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Spanish (http://www.transifex.com/openstack/keystone/language/"
-"es/)\n"
+"Language: es\n"
+"Language-Team: Spanish\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#, python-format
msgid "%(detail)s"
diff --git a/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-critical.po
index 8657e66a..5967192b 100644
--- a/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-critical.po
@@ -3,21 +3,22 @@
# This file is distributed under the same license as the keystone project.
#
# Translators:
+# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: Keystone\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-08-06 06:28+0000\n"
-"PO-Revision-Date: 2014-08-31 15:19+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
+"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: French (http://www.transifex.com/openstack/keystone/language/"
-"fr/)\n"
+"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"Generated-By: Babel 2.0\n"
+"X-Generator: Zanata 3.7.1\n"
#, python-format
msgid "Unable to open template file %s"
diff --git a/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-error.po b/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-error.po
index 5ddd639a..0339cacd 100644
--- a/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-error.po
+++ b/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-error.po
@@ -8,19 +8,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-06-26 05:13+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: French (http://www.transifex.com/openstack/keystone/language/"
-"fr/)\n"
+"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
#, python-format
diff --git a/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-info.po b/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-info.po
index 08cee0e0..37ef89ea 100644
--- a/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-info.po
+++ b/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-info.po
@@ -6,21 +6,22 @@
# Bruno Cornec <bruno.cornec@hp.com>, 2014
# Maxime COQUEREL <max.coquerel@gmail.com>, 2014
# Andrew Melim <nokostya.translation@gmail.com>, 2014
+# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: Keystone\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-08-06 06:28+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-08-01 06:26+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: French (http://www.transifex.com/openstack/keystone/language/"
-"fr/)\n"
+"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"Generated-By: Babel 2.0\n"
+"X-Generator: Zanata 3.7.1\n"
#, python-format
msgid ""
diff --git a/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-warning.po b/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-warning.po
index d2fddf29..6eb07830 100644
--- a/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-warning.po
+++ b/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone-log-warning.po
@@ -5,21 +5,22 @@
# Translators:
# Bruno Cornec <bruno.cornec@hp.com>, 2014
# Maxime COQUEREL <max.coquerel@gmail.com>, 2014
+# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: Keystone\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-08-06 06:28+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-07-29 06:04+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: French (http://www.transifex.com/openstack/keystone/language/"
-"fr/)\n"
+"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"Generated-By: Babel 2.0\n"
+"X-Generator: Zanata 3.7.1\n"
#, python-format
msgid "%s is not a dogpile.proxy.ProxyBackend"
diff --git a/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone.po b/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone.po
index b2aff55b..9fb2b2ec 100644
--- a/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone.po
+++ b/keystone-moon/keystone/locale/fr/LC_MESSAGES/keystone.po
@@ -12,18 +12,18 @@
# Tom Cocozzello <tjcocozz@us.ibm.com>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-09-03 12:54+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: French (http://www.transifex.com/openstack/keystone/language/"
-"fr/)\n"
+"Language: fr\n"
+"Language-Team: French\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#, python-format
msgid "%(detail)s"
diff --git a/keystone-moon/keystone/locale/hu/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/hu/LC_MESSAGES/keystone-log-critical.po
index 102329f6..b45fc0d3 100644
--- a/keystone-moon/keystone/locale/hu/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/hu/LC_MESSAGES/keystone-log-critical.po
@@ -3,21 +3,22 @@
# This file is distributed under the same license as the keystone project.
#
# Translators:
+# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: Keystone\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-08-06 06:28+0000\n"
-"PO-Revision-Date: 2014-08-31 15:19+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
+"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Hungarian (http://www.transifex.com/openstack/keystone/"
-"language/hu/)\n"
+"Language-Team: Hungarian\n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Generated-By: Babel 2.0\n"
+"X-Generator: Zanata 3.7.1\n"
#, python-format
msgid "Unable to open template file %s"
diff --git a/keystone-moon/keystone/locale/it/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/it/LC_MESSAGES/keystone-log-critical.po
index db15042f..317cdc85 100644
--- a/keystone-moon/keystone/locale/it/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/it/LC_MESSAGES/keystone-log-critical.po
@@ -3,21 +3,22 @@
# This file is distributed under the same license as the keystone project.
#
# Translators:
+# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: Keystone\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-08-06 06:28+0000\n"
-"PO-Revision-Date: 2014-08-31 15:19+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
+"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Italian (http://www.transifex.com/openstack/keystone/language/"
-"it/)\n"
+"Language-Team: Italian\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Generated-By: Babel 2.0\n"
+"X-Generator: Zanata 3.7.1\n"
#, python-format
msgid "Unable to open template file %s"
diff --git a/keystone-moon/keystone/locale/it/LC_MESSAGES/keystone.po b/keystone-moon/keystone/locale/it/LC_MESSAGES/keystone.po
index 085f3b34..e60a6d8c 100644
--- a/keystone-moon/keystone/locale/it/LC_MESSAGES/keystone.po
+++ b/keystone-moon/keystone/locale/it/LC_MESSAGES/keystone.po
@@ -7,18 +7,18 @@
# Tom Cocozzello <tjcocozz@us.ibm.com>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-09-03 12:54+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Italian (http://www.transifex.com/openstack/keystone/language/"
-"it/)\n"
+"Language: it\n"
+"Language-Team: Italian\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#, python-format
msgid "%(detail)s"
diff --git a/keystone-moon/keystone/locale/ja/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/ja/LC_MESSAGES/keystone-log-critical.po
index e5ec3075..9337f92f 100644
--- a/keystone-moon/keystone/locale/ja/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/ja/LC_MESSAGES/keystone-log-critical.po
@@ -3,21 +3,22 @@
# This file is distributed under the same license as the keystone project.
#
# Translators:
+# Akihiro Motoki <amotoki@gmail.com>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: Keystone\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-08-06 06:28+0000\n"
-"PO-Revision-Date: 2014-08-31 15:19+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
+"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Japanese (http://www.transifex.com/openstack/keystone/"
-"language/ja/)\n"
+"Language-Team: Japanese\n"
"Language: ja\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+"Generated-By: Babel 2.0\n"
+"X-Generator: Zanata 3.7.1\n"
#, python-format
msgid "Unable to open template file %s"
diff --git a/keystone-moon/keystone/locale/ja/LC_MESSAGES/keystone.po b/keystone-moon/keystone/locale/ja/LC_MESSAGES/keystone.po
index 639a2438..541eda96 100644
--- a/keystone-moon/keystone/locale/ja/LC_MESSAGES/keystone.po
+++ b/keystone-moon/keystone/locale/ja/LC_MESSAGES/keystone.po
@@ -4,22 +4,21 @@
#
# Translators:
# Tomoyuki KATO <tomo@dream.daynight.jp>, 2012-2013
-# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
-# Tom Cocozzello <tjcocozz@us.ibm.com>, 2015. #zanata
+# Akihiro Motoki <amotoki@gmail.com>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
-"PO-Revision-Date: 2015-09-03 12:54+0000\n"
-"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Japanese (http://www.transifex.com/openstack/keystone/"
-"language/ja/)\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
+"PO-Revision-Date: 2015-09-27 10:27+0000\n"
+"Last-Translator: Akihiro Motoki <amotoki@gmail.com>\n"
+"Language: ja\n"
+"Language-Team: Japanese\n"
"Plural-Forms: nplurals=1; plural=0\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#, python-format
msgid "%(detail)s"
@@ -34,7 +33,7 @@ msgstr ""
#, python-format
msgid "%(host)s is not a trusted dashboard host"
-msgstr "%(host)s はトラステッド・ダッシュボード・ホストではありません"
+msgstr "%(host)s は信頼されたダッシュボードホストではありません"
#, python-format
msgid "%(message)s %(amendment)s"
@@ -45,13 +44,13 @@ msgid ""
"%(mod_name)s doesn't provide database migrations. The migration repository "
"path at %(path)s doesn't exist or isn't a directory."
msgstr ""
-"%(mod_name)s はデータベース・マイグレーションを提供していません。%(path)s の"
-"マイグレーション・リポジトリー・パスは存在しないか、またはディレクトリーでは"
-"ありません。"
+"%(mod_name)s はデータベースマイグレーションを提供していません。%(path)s のマ"
+"イグレーションリポジトリーのパスが存在しないか、ディレクトリーではないかのい"
+"ずれかです。"
#, python-format
msgid "%(property_name)s cannot be less than %(min_length)s characters."
-msgstr "%(property_name)s は %(min_length)s 文字より小さくできません。"
+msgstr "%(property_name)s は %(min_length)s 文字より短くできません。"
#, python-format
msgid "%(property_name)s is not a %(display_expected_type)s"
@@ -59,11 +58,11 @@ msgstr "%(property_name)s が %(display_expected_type)s ではありません。
#, python-format
msgid "%(property_name)s should not be greater than %(max_length)s characters."
-msgstr "%(property_name)s は %(max_length)s 文字より大きくできません。"
+msgstr "%(property_name)s は %(max_length)s 文字より長くできません。"
#, python-format
msgid "%s cannot be empty."
-msgstr "%s は空にできません。"
+msgstr "%s は空にはできません。"
#, python-format
msgid "%s extension does not exist."
@@ -71,55 +70,55 @@ msgstr "%s 拡張が存在しません。"
#, python-format
msgid "%s field is required and cannot be empty"
-msgstr "%s フィールドは必須フィールドであるため、空にできません"
+msgstr "フィールド %s は必須フィールドであるため、空にできません"
#, python-format
msgid "%s field(s) cannot be empty"
-msgstr "%s フィールドを空にすることはできません"
+msgstr "フィールド %s を空にすることはできません"
msgid "(Disable debug mode to suppress these details.)"
-msgstr "(これらの詳細を抑制するには、デバッグ・モードを無効にします。)"
+msgstr "(これらの詳細出力を抑制するには、デバッグモードを無効にします。)"
msgid "--all option cannot be mixed with other options"
msgstr "--all オプションを他のオプションと組み合わせて使用することはできません"
msgid "A project-scoped token is required to produce a service catalog."
msgstr ""
-"サービス・カタログを生成するには、プロジェクトにスコープ宣言されたトークンが"
+"サービスカタログを生成するには、プロジェクトにスコープが設定されたトークンが"
"必要です。"
msgid "Access token is expired"
-msgstr "アクセス・トークンの有効期限が切れています"
+msgstr "アクセストークンの有効期限が切れています"
msgid "Access token not found"
-msgstr "アクセス・トークンが見つかりません"
+msgstr "アクセストークンが見つかりません"
msgid "Additional authentications steps required."
msgstr "追加認証手順が必要です。"
msgid "An unexpected error occurred when retrieving domain configs"
-msgstr "ドメイン構成の取得中に予期しないエラーが発生しました"
+msgstr "ドメイン設定の取得中に予期しないエラーが発生しました"
#, python-format
msgid "An unexpected error occurred when trying to store %s"
-msgstr "%s を保管しようと試みているときに、予期しないエラーが発生しました"
+msgstr "%s の保存中に予期しないエラーが発生しました"
msgid "An unexpected error prevented the server from fulfilling your request."
-msgstr "予期しないエラーが発生したため、サーバーは要求を満たすことが"
+msgstr "予期しないエラーが発生したため、サーバーが要求を完了できませんでした。"
#, python-format
msgid ""
"An unexpected error prevented the server from fulfilling your request: "
"%(exception)s"
msgstr ""
-"予期しないエラーが発生したため、サーバーは要求を満たすことができませんでし"
-"た: %(exception)s"
+"予期しないエラーが発生したため、サーバーが要求を完了できませんでした: "
+"%(exception)s"
msgid "An unhandled exception has occurred: Could not find metadata."
-msgstr "未処理例外が発生しました。メタデータが見つかりませんでした。"
+msgstr "処理できない例外が発生しました。メタデータが見つかりませんでした。"
msgid "At least one option must be provided"
-msgstr "オプションを少なくとも 1 つは指定する必要があります"
+msgstr "少なくとも 1 つはオプションを指定する必要があります"
msgid "At least one option must be provided, use either --all or --domain-name"
msgstr ""
@@ -127,7 +126,7 @@ msgstr ""
"name を使用してください"
msgid "At least one role should be specified."
-msgstr "少なくとも 1 つの役割を指定する必要があります。"
+msgstr "少なくとも 1 つのロールを指定する必要があります。"
msgid "Attempted to authenticate with an unsupported method."
msgstr "サポートされていないメソッドを使用して認証を行おうとしました。"
@@ -140,7 +139,7 @@ msgstr ""
"証を使用してください"
msgid "Authentication plugin error."
-msgstr "認証プラグイン・エラー。"
+msgstr "認証プラグインエラー。"
msgid "Cannot authorize a request token with a token issued via delegation."
msgstr ""
@@ -154,6 +153,7 @@ msgstr "%(option_name)s %(attr)s を変更できません"
msgid "Cannot change Domain ID"
msgstr "ドメイン ID を変更できません"
+#, fuzzy
msgid "Cannot change consumer secret"
msgstr "コンシューマーの秘密を変更できません"
@@ -163,7 +163,7 @@ msgstr "ユーザー ID を変更できません"
msgid "Cannot change user name"
msgstr "ユーザー名を変更できません"
-#, python-format
+#, fuzzy, python-format
msgid "Cannot create project with parent: %(project_id)s"
msgstr "親を持つプロジェクトを作成できません: %(project_id)s"
@@ -184,44 +184,48 @@ msgstr "証明書 %(cert_file)s を開くことができません。理由: %(re
msgid "Cannot remove role that has not been granted, %s"
msgstr "許可されていないロールを削除できません、%s"
+#, fuzzy
msgid ""
"Cannot truncate a driver call without hints list as first parameter after "
"self "
msgstr ""
-"セルフの後に最初のパラメーターとしてヒント・リストなしでドライバー呼び出しを"
-"切り捨てることはできません"
+"セルフの後に最初のパラメーターとしてヒントリストなしでドライバー呼び出しを切"
+"り捨てることはできません"
msgid ""
"Cannot use parents_as_list and parents_as_ids query params at the same time."
msgstr ""
-"照会パラメーター parents_as_list と parents_as_ids を併用することはできませ"
-"ん。"
+"問い合わせパラメーター parents_as_list と parents_as_ids を同時に使用すること"
+"はできません。"
msgid ""
"Cannot use subtree_as_list and subtree_as_ids query params at the same time."
msgstr ""
-"照会パラメーター subtree_as_list と subtree_as_ids を併用することはできませ"
-"ん。"
+"問い合わせパラメーター subtree_as_list と subtree_as_ids を同時に使用すること"
+"はできません。"
+#, fuzzy
msgid ""
"Combining effective and group filter will always result in an empty list."
msgstr ""
-"有効フィルターとグループ・フィルターの組み合わせは常に空のリストになります。"
+"有効フィルターとグループフィルターの組み合わせは常に空のリストになります。"
+#, fuzzy
msgid ""
"Combining effective, domain and inherited filters will always result in an "
"empty list."
msgstr ""
-"有効フィルター、ドメイン・フィルター、および継承フィルターの組み合わせは常に"
-"空のリストになります。"
+"有効フィルター、ドメインフィルター、および継承フィルターの組み合わせは常に空"
+"のリストになります。"
#, python-format
msgid "Conflict occurred attempting to store %(type)s - %(details)s"
-msgstr "%(type)s を保管するときに競合が発生しました - %(details)s"
+msgstr "%(type)s を保存するときに競合が発生しました - %(details)s"
#, python-format
msgid "Conflicting region IDs specified: \"%(url_id)s\" != \"%(ref_id)s\""
-msgstr "矛盾する領域 ID が指定されました: \"%(url_id)s\" != \"%(ref_id)s\""
+msgstr ""
+"矛盾するリージョン ID が指定されました: \"%(url_id)s\" != \"%(ref_id)s\""
msgid "Consumer not found"
msgstr "コンシューマーが見つかりません"
@@ -230,44 +234,45 @@ msgstr "コンシューマーが見つかりません"
msgid ""
"Could not change immutable attribute(s) '%(attributes)s' in target %(target)s"
msgstr ""
-"ターゲット %(target)s で不変の属性 '%(attributes)s' を変更できませんでした"
+"ターゲット %(target)s の変更不可の属性 '%(attributes)s' を変更できませんでし"
+"た"
#, python-format
msgid ""
"Could not find %(group_or_option)s in domain configuration for domain "
"%(domain_id)s"
msgstr ""
-"%(group_or_option)s がドメイン %(domain_id)s のドメイン構成に見つかりませんで"
+"%(group_or_option)s がドメイン %(domain_id)s のドメイン設定に見つかりませんで"
"した"
#, python-format
msgid "Could not find Endpoint Group: %(endpoint_group_id)s"
-msgstr "エンドポイント・グループが見つかりませんでした: %(endpoint_group_id)s"
+msgstr "エンドポイントグループ %(endpoint_group_id)s が見つかりませんでした"
msgid "Could not find Identity Provider identifier in environment"
-msgstr "Identity Provider ID が環境内に見つかりませんでした"
+msgstr "Identity Provider ID が環境情報内に見つかりませんでした"
#, python-format
msgid "Could not find Identity Provider: %(idp_id)s"
-msgstr "ID プロバイダーが見つかりませんでした: %(idp_id)s"
+msgstr "ID プロバイダー %(idp_id)s が見つかりませんでした"
#, python-format
msgid "Could not find Service Provider: %(sp_id)s"
-msgstr "サービス・プロバイダー %(sp_id)s が見つかりませんでした"
+msgstr "サービスプロバイダー %(sp_id)s が見つかりませんでした"
-#, python-format
+#, fuzzy, python-format
msgid "Could not find credential: %(credential_id)s"
msgstr "資格情報が見つかりませんでした: %(credential_id)s"
#, python-format
msgid "Could not find domain: %(domain_id)s"
-msgstr "ドメインが見つかりませんでした: %(domain_id)s"
+msgstr "ドメイン %(domain_id)s が見つかりませんでした"
#, python-format
msgid "Could not find endpoint: %(endpoint_id)s"
-msgstr "エンドポイントが見つかりませんでした: %(endpoint_id)s"
+msgstr "エンドポイント %(endpoint_id)sが見つかりませんでした"
-#, python-format
+#, fuzzy, python-format
msgid ""
"Could not find federated protocol %(protocol_id)s for Identity Provider: "
"%(idp_id)s"
@@ -277,69 +282,70 @@ msgstr ""
#, python-format
msgid "Could not find group: %(group_id)s"
-msgstr "グループが見つかりませんでした: %(group_id)s"
+msgstr "グループ %(group_id)s が見つかりませんでした"
#, python-format
msgid "Could not find mapping: %(mapping_id)s"
-msgstr "マッピングが見つかりませんでした: %(mapping_id)s"
+msgstr "マッピング %(mapping_id)s が見つかりませんでした"
msgid "Could not find policy association"
msgstr "ポリシー関連付けが見つかりませんでした"
#, python-format
msgid "Could not find policy: %(policy_id)s"
-msgstr "ポリシーが見つかりませんでした: %(policy_id)s"
+msgstr "ポリシー %(policy_id)s が見つかりませんでした"
#, python-format
msgid "Could not find project: %(project_id)s"
-msgstr "プロジェクトが見つかりませんでした: %(project_id)s"
+msgstr "プロジェクト %(project_id)s が見つかりませんでした"
#, python-format
msgid "Could not find region: %(region_id)s"
-msgstr "領域が見つかりませんでした: %(region_id)s"
+msgstr "リージョン %(region_id)s が見つかりませんでした"
msgid "Could not find role"
-msgstr "役割が見つかりませんでした"
+msgstr "ロールが見つかりませんでした"
#, python-format
msgid ""
"Could not find role assignment with role: %(role_id)s, user or group: "
"%(actor_id)s, project or domain: %(target_id)s"
msgstr ""
-"役割 %(role_id)s を持つ割り当てが見つかりませんでした。ユーザーまたはグルー"
-"プ: %(actor_id)s、プロジェクトまたはドメイン: %(target_id)s"
+"ロール %(role_id)s を持つ割り当てが見つかりませんでした。ユーザーまたはグルー"
+"プは %(actor_id)s で、プロジェクトまたはドメインが %(target_id)s です"
#, python-format
msgid "Could not find role: %(role_id)s"
-msgstr "役割が見つかりませんでした: %(role_id)s"
+msgstr "ロール %(role_id)s が見つかりませんでした"
#, python-format
msgid "Could not find service: %(service_id)s"
-msgstr "サービスが見つかりませんでした: %(service_id)s"
+msgstr "サービス %(service_id)s が見つかりませんでした"
#, python-format
msgid "Could not find token: %(token_id)s"
-msgstr "トークンが見つかりませんでした: %(token_id)s"
+msgstr "トークン %(token_id)s が見つかりませんでした"
#, python-format
msgid "Could not find trust: %(trust_id)s"
-msgstr "トラストが見つかりませんでした: %(trust_id)s"
+msgstr "トラスト %(trust_id)s が見つかりませんでした"
#, python-format
msgid "Could not find user: %(user_id)s"
-msgstr "ユーザーが見つかりませんでした: %(user_id)s"
+msgstr "ユーザー %(user_id)s が見つかりませんでした:"
#, python-format
msgid "Could not find version: %(version)s"
-msgstr "バージョンが見つかりませんでした: %(version)s"
+msgstr "バージョン %(version)s が見つかりませんでした"
#, python-format
msgid "Could not find: %(target)s"
-msgstr "見つかりませんでした: %(target)s"
+msgstr "%(target)s が見つかりませんでした"
msgid "Could not validate the access token"
-msgstr "アクセス・トークンを検証できませんでした"
+msgstr "アクセストークンを検証できませんでした"
+#, fuzzy
msgid "Credential belongs to another user"
msgstr "資格情報が別のユーザーに属しています"
@@ -349,7 +355,8 @@ msgstr "/domains/%s/config のデータベース"
msgid ""
"Disabling an entity where the 'enable' attribute is ignored by configuration."
-msgstr "「enable」属性が構成によって無視されているエンティティーを無効化中。"
+msgstr ""
+"「enable」属性が設定によって無視されているエンティティーを無効化中です。"
#, python-format
msgid "Domain (%s)"
@@ -365,24 +372,24 @@ msgstr "ドメインに %s という ID を付けることはできません"
#, python-format
msgid "Domain is disabled: %s"
-msgstr "ドメインが無効化されています: %s"
+msgstr "ドメイン %s が無効になっています"
msgid "Domain metadata not supported by LDAP"
-msgstr "ドメイン・メタデータは LDAP ではサポートされません"
+msgstr "ドメインメタデータは LDAP ではサポートされません"
msgid "Domain scoped token is not supported"
-msgstr "ドメインをスコープにしたトークンはサポートされません"
+msgstr "ドメインをスコープにしたトークンはサポートされていません"
#, python-format
msgid ""
"Domain: %(domain)s already has a configuration defined - ignoring file: "
"%(file)s."
msgstr ""
-"ドメイン %(domain)s には既に構成があります - ファイル %(file)s は無視されま"
-"す。"
+"ドメイン %(domain)s には既に定義された設定があります。ファイル %(file)s は無"
+"視されます。"
msgid "Domains are read-only against LDAP"
-msgstr "ドメインが LDAP に対して読み取り専用です"
+msgstr "LDAP の場合はドメインは読み取り専用です"
msgid "Duplicate Entry"
msgstr "重複する項目"
@@ -404,37 +411,37 @@ msgstr "「有効」フィールドはブール値でなければなりません
#, python-format
msgid "Endpoint %(endpoint_id)s not found in project %(project_id)s"
msgstr ""
-"エンドポイント %(endpoint_id)s はプロジェクト %(project_id)s に見つかりません"
+"エンドポイント %(endpoint_id)s がプロジェクト %(project_id)s に見つかりません"
msgid "Endpoint Group Project Association not found"
-msgstr "エンドポイント・グループ・プロジェクト関連付けが見つかりません"
+msgstr "エンドポイントグループとプロジェクトの関連付けが見つかりません"
msgid "Ensure configuration option idp_entity_id is set."
-msgstr "構成オプション idp_entity_id が設定されていることを確認してください。"
+msgstr "設定オプション idp_entity_id が設定されていることを確認してください。"
msgid "Ensure configuration option idp_sso_endpoint is set."
msgstr ""
-"構成オプション idp_sso_endpoint が設定されていることを確認してください。"
+"設定オプション idp_sso_endpoint が設定されていることを確認してください。"
#, python-format
msgid ""
"Error parsing configuration file for domain: %(domain)s, file: %(file)s."
msgstr ""
-"構成ファイルの構文解析エラー。ドメイン: %(domain)s、ファイル: %(file)s。"
+"ドメイン: %(domain)s、ファイル: %(file)s の設定ファイルの構文解析エラー。"
#, python-format
msgid "Error while reading metadata file, %(reason)s"
-msgstr "メタデータ・ファイルの読み取り中にエラーが発生しました。%(reason)s"
+msgstr "メタデータファイルの読み取り中にエラーが発生しました。%(reason)s"
#, python-format
msgid "Expected dict or list: %s"
-msgstr "期待される辞書または一覧: %s"
+msgstr "期待される辞書またはリスト: %s"
msgid ""
"Expected signing certificates are not available on the server. Please check "
"Keystone configuration."
msgstr ""
-"予期された署名証明書がサーバーにありません。Keystone の構成を確認してくださ"
+"想定された署名証明書がサーバーにありません。Keystone の設定を確認してくださ"
"い。"
#, python-format
@@ -443,17 +450,18 @@ msgid ""
"with the request since it is either malformed or otherwise incorrect. The "
"client is assumed to be in error."
msgstr ""
-"%(target)s で %(attribute)s が検出されることが予期されています。要求の形式が"
-"誤っているか、または要求が正しくないため、サーバーは要求に従うことができませ"
-"んでした。クライアントでエラーが発生していると見なされます。"
+"%(target)s に %(attribute)s があることが想定されています。要求の形式が不正も"
+"しくは正しくないため、サーバーは要求に応じることができませんでした。クライア"
+"ントでエラーが発生していると考えられます。"
#, python-format
msgid "Failed to start the %(name)s server"
-msgstr "%(name)s サーバーの始動に失敗しました"
+msgstr "%(name)s サーバーの起動に失敗しました"
msgid "Failed to validate token"
msgstr "トークンの検証に失敗しました"
+#, fuzzy
msgid "Federation token is expired"
msgstr "連合トークンの有効期限が切れています"
@@ -462,33 +470,33 @@ msgid ""
"Field \"remaining_uses\" is set to %(value)s while it must not be set in "
"order to redelegate a trust"
msgstr ""
-"フィールド「remaining_uses」が %(value)s に設定されていますが、トラストを再委"
-"任するにはこのフィールドを設定してはなりません"
+"フィールド \"remaining_uses\" は %(value)s になっていますが、トラストを再委任"
+"するにはこのフィールドが設定されていてはなりません"
msgid "Found invalid token: scoped to both project and domain."
msgstr ""
-"無効なトークンが見つかりました: プロジェクトとドメインの両方にスコープ宣言さ"
-"れています。"
+"無効なトークンが見つかりました: スコープがプロジェクトとドメインの両方に対し"
+"て設定されています。"
#, python-format
msgid "Group %(group)s is not supported for domain specific configurations"
-msgstr "ドメイン固有の構成ではグループ %(group)s はサポートされません"
+msgstr "ドメイン固有の設定ではグループ %(group)s はサポートされません"
#, python-format
msgid ""
"Group %(group_id)s returned by mapping %(mapping_id)s was not found in the "
"backend."
msgstr ""
-"マッピング %(mapping_id)s によって返されたグループ %(group_id)s がバックエン"
-"ドに見つかりませんでした。"
+"マッピング %(mapping_id)s が返したグループ %(group_id)s がバックエンドにあり"
+"ませんでした。"
#, python-format
msgid ""
"Group membership across backend boundaries is not allowed, group in question "
"is %(group_id)s, user is %(user_id)s"
msgstr ""
-"バックエンド境界を越えるグループ・メンバーシップは許可されません。問題となっ"
-"ているグループは %(group_id)s、ユーザーは %(user_id)s です"
+"バックエンド境界をまたぐグループメンバーシップは許可されていません。問題と"
+"なっているグループは %(group_id)s、ユーザーは %(user_id)s です"
#, python-format
msgid "ID attribute %(id_attr)s not found in LDAP object %(dn)s"
@@ -498,6 +506,7 @@ msgstr "ID 属性 %(id_attr)s が LDAP オブジェクト %(dn)s に見つかり
msgid "Identity Provider %(idp)s is disabled"
msgstr "ID プロバイダー %(idp)s は無効になっています"
+#, fuzzy
msgid ""
"Incoming identity provider identifier not included among the accepted "
"identifiers."
@@ -506,30 +515,33 @@ msgstr "着信 ID プロバイダー ID が受諾 ID に含まれていません
#, python-format
msgid "Invalid LDAP TLS certs option: %(option)s. Choose one of: %(options)s"
msgstr ""
-"LDAP TLS 証明書オプション %(option)s が無効です。以下のいずれかを選択してくだ"
-"さい: %(options)s"
+"無効な LDAP TLS 証明書オプション %(option)s です。 %(options)s のいずれかを選"
+"択してください"
#, python-format
msgid "Invalid LDAP TLS_AVAIL option: %s. TLS not available"
-msgstr "無効な LDAP TLS_AVAIL オプション: %s。TLS が利用できません。"
+msgstr "無効な LDAP TLS_AVAIL オプション %s です。TLS が利用できません。"
#, python-format
msgid "Invalid LDAP deref option: %(option)s. Choose one of: %(options)s"
msgstr ""
-"LDAP deref オプションが無効です: %(option)s。%(options)s のいずれかを選択して"
-"ください"
+"無効な LDAP deref オプション %(option)s です。%(options)s のいずれかを選択し"
+"てください"
#, python-format
msgid "Invalid LDAP scope: %(scope)s. Choose one of: %(options)s"
-msgstr "無効な LDAP 範囲: %(scope)s。次のどれかを選んでください: %(options)s"
+msgstr ""
+"無効な LDAP スコープ %(scope)s です。 %(options)s のいずれかを選んでくださ"
+"い: "
msgid "Invalid TLS / LDAPS combination"
-msgstr "無効な TLS / LDAPS の組み合わせ"
+msgstr "無効な TLS / LDAPS の組み合わせです"
#, python-format
msgid "Invalid audit info data type: %(data)s (%(type)s)"
-msgstr "無効な監査情報データ・タイプ: %(data)s (%(type)s)"
+msgstr "無効な監査情報データタイプ %(data)s (%(type)s) です"
+#, fuzzy
msgid "Invalid blob in credential"
msgstr "資格情報内の blob が無効です"
@@ -538,17 +550,18 @@ msgid ""
"Invalid domain name: %(domain)s found in config file name: %(file)s - "
"ignoring this file."
msgstr ""
-"無効なドメイン・ネーム %(domain)s が構成ファイル名 %(file)s に見つかりました "
-"- このファイルは無視されます。"
+"無効なドメイン名 %(domain)s が設定ファイル名 %(file)s に見つかりました。この"
+"ファイルは無視されます。"
#, python-format
msgid "Invalid domain specific configuration: %(reason)s"
-msgstr "ドメイン固有の構成が無効です: %(reason)s"
+msgstr "無効なドメイン固有の設定です: %(reason)s"
#, python-format
msgid "Invalid input for field '%(path)s'. The value is '%(value)s'."
msgstr "フィールド '%(path)s' の入力が無効です。値は '%(value)s' です。"
+#, fuzzy
msgid "Invalid limit value"
msgstr "制限値が無効です"
@@ -585,13 +598,13 @@ msgid "Invalid user / password"
msgstr "ユーザー/パスワードが無効です"
msgid "Invalid username or password"
-msgstr "無効なユーザー名またはパスワード"
+msgstr "無効なユーザー名かパスワード"
#, python-format
msgid "KVS region %s is already configured. Cannot reconfigure."
msgstr "KVS 領域 %s は既に構成されています。再構成はできません。"
-#, python-format
+#, fuzzy, python-format
msgid "Key Value Store not configured: %s"
msgstr "キー値ストアが構成されていません: %s"
@@ -609,19 +622,18 @@ msgstr "LDAP %s の更新"
#, python-format
msgid "Lock Timeout occurred for key, %(target)s"
-msgstr "キー %(target)s についてロック・タイムアウトが発生しました"
+msgstr "キー %(target)s についてロックタイムアウトが発生しました"
#, python-format
msgid "Lock key must match target key: %(lock)s != %(target)s"
msgstr ""
-"ロック・キーがターゲット・キーと一致しなければなりません: %(lock)s != "
-"%(target)s"
+"ロックキーはターゲットキーと一致しなければなりません: %(lock)s != %(target)s"
#, python-format
msgid "Malformed endpoint URL (%(endpoint)s), see ERROR log for details."
msgstr ""
-"エンドポイント URL (%(endpoint)s) の形式が正しくありません。詳しくはエラー・"
-"ログを参照してください。"
+"エンドポイント URL (%(endpoint)s) の形式が正しくありません。詳しくはエラーロ"
+"グを参照してください。"
msgid "Marker could not be found"
msgstr "マーカーが見つかりませんでした"
@@ -639,38 +651,39 @@ msgid "Method not callable: %s"
msgstr "メソッドが呼び出し可能ではありません: %s"
msgid "Missing entity ID from environment"
-msgstr "環境にエンティティー ID がありません"
+msgstr "環境情報にエンティティー ID が見つかりません"
msgid ""
"Modifying \"redelegation_count\" upon redelegation is forbidden. Omitting "
"this parameter is advised."
msgstr ""
-"再委任時の「redelegation_count」の変更は禁止されています。このパラメーターを"
-"省略してください。"
+"再委任時の「redelegation_count」の変更は禁止されています。このパラメーターは"
+"指定しないでください。"
msgid "Multiple domains are not supported"
msgstr "複数のドメインはサポートされていません"
msgid "Must be called within an active lock context."
-msgstr "アクティブ・ロック・コンテキスト内で呼び出されなければなりません。"
+msgstr "アクティブなロックコンテキスト内で呼び出されなければなりません。"
msgid "Must specify either domain or project"
msgstr "ドメインまたはプロジェクトのいずれかを指定する必要があります"
msgid "Name field is required and cannot be empty"
-msgstr "「名前」フィールドは必須フィールドであるため、空にできません"
+msgstr "「名前」フィールドは必須フィールドであり、空にできません"
msgid ""
"No Authorization headers found, cannot proceed with OAuth related calls, if "
"running under HTTPd or Apache, ensure WSGIPassAuthorization is set to On."
msgstr ""
-"許可ヘッダーが見つかりません。OAuth 関連呼び出しを続行できません。HTTPd また"
-"は Apache の下で実行している場合は、WSGIPassAuthorization が On に設定されて"
-"いることを確認してください。"
+"認可に使用するヘッダーが見つからず、OAuth 関連の呼び出しを続行できません。"
+"HTTPd または Apache の下で実行している場合は、WSGIPassAuthorization が On に"
+"設定されていることを確認してください。"
msgid "No authenticated user"
msgstr "認証されていないユーザー"
+#, fuzzy
msgid ""
"No encryption keys found; run keystone-manage fernet_setup to bootstrap one."
msgstr ""
@@ -678,38 +691,38 @@ msgstr ""
"を行ってください。"
msgid "No options specified"
-msgstr "オプション指定なし"
+msgstr "オプションが指定されていません"
#, python-format
msgid "No policy is associated with endpoint %(endpoint_id)s."
msgstr ""
"エンドポイント %(endpoint_id)s に関連付けられているポリシーはありません。"
-#, python-format
+#, fuzzy, python-format
msgid "No remaining uses for trust: %(trust_id)s"
-msgstr "トラストには使用が残っていません: %(trust_id)s"
+msgstr "トラスト %(trust_id)s には使用が残っていません"
msgid "Non-default domain is not supported"
-msgstr "標準以外のドメインはサポートされません"
+msgstr "デフォルト以外のドメインはサポートされません"
msgid "One of the trust agents is disabled or deleted"
-msgstr "トラスト・エージェントの 1 つが無効化または削除されています"
+msgstr "トラストエージェントの 1 つが無効になっているか削除されています"
#, python-format
msgid ""
"Option %(option)s found with no group specified while checking domain "
"configuration request"
msgstr ""
-"ドメイン構成要求の検査中にオプション %(option)s にグループが指定されていない"
-"ことが検出されました"
+"ドメイン設定要求の検査中に、グループが指定されていないオプション %(option)s "
+"が見つかりました"
#, python-format
msgid ""
"Option %(option)s in group %(group)s is not supported for domain specific "
"configurations"
msgstr ""
-"ドメイン固有の構成ではグループ %(group)s 内のオプション %(option)s はサポート"
-"されていません"
+"ドメイン固有の設定ではグループ %(group)s のオプション %(option)s はサポートさ"
+"れていません"
#, python-format
msgid "Project (%s)"
@@ -717,7 +730,7 @@ msgstr "プロジェクト (%s)"
#, python-format
msgid "Project is disabled: %s"
-msgstr "プロジェクトが無効化されています: %s"
+msgstr "プロジェクト %s が無効になっています"
msgid "Redelegation allowed for delegated by trust only"
msgstr "再委任はトラストによる委任にのみ許可されます"
@@ -731,7 +744,7 @@ msgstr ""
"%(max_count)d] を超えています"
msgid "Request Token does not have an authorizing user id"
-msgstr "要求トークンに許可ユーザー ID が含まれていません"
+msgstr "要求されたトークンに許可ユーザー ID が含まれていません"
#, python-format
msgid ""
@@ -739,10 +752,11 @@ msgid ""
"server could not comply with the request because the attribute size is "
"invalid (too large). The client is assumed to be in error."
msgstr ""
-"要求属性 %(attribute)s は %(size)i 以下でなければなりません。属性のサイズが無"
-"効である (大きすぎる) ため、サーバーは要求に従うことができませんでした。クラ"
-"イアントでエラーが発生していると見なされます。"
+"要求された属性 %(attribute)s のサイズは %(size)i 以下でなければなりません。属"
+"性のサイズが無効である (大きすぎる) ため、サーバーは要求に応じることができま"
+"せんでした。クライアントでエラーが発生していると考えられます。"
+#, fuzzy
msgid "Request must have an origin query parameter"
msgstr "要求には起点照会パラメーターが必要です"
@@ -750,7 +764,7 @@ msgid "Request token is expired"
msgstr "要求トークンの有効期限が切れています"
msgid "Request token not found"
-msgstr "要求トークンが見つかりません"
+msgstr "要求されたトークンが見つかりません"
msgid "Requested expiration time is more than redelegated trust can provide"
msgstr "要求された有効期限は再委任されたトラストが提供可能な期間を超えています"
@@ -760,8 +774,8 @@ msgid ""
"Requested redelegation depth of %(requested_count)d is greater than allowed "
"%(max_count)d"
msgstr ""
-"%(requested_count)d の要求された再委任の深さが、許可された %(max_count)d を超"
-"えています"
+"要求された再委任の深さ %(requested_count)d が、許可された上限 %(max_count)d "
+"を超えています"
#, python-format
msgid "Role %s not found"
@@ -774,23 +788,23 @@ msgid ""
msgstr ""
"eventlet を介した keystone の実行は Kilo 以降では推奨されておらず、WSGI サー"
"バー (mod_wsgi など) での実行が推奨されています。eventlet 下での keystone の"
-"サポートは「M」-リリースで削除される予定です。"
+"サポートは「M」リリースで削除される予定です。"
msgid "Scoping to both domain and project is not allowed"
-msgstr "ドメインとプロジェクトの両方をスコープとすることは許可されません"
+msgstr "ドメインとプロジェクトの両方にスコープを設定することはできません"
msgid "Scoping to both domain and trust is not allowed"
-msgstr "ドメインとトラストの両方をスコープとすることは許可されません"
+msgstr "ドメインとトラストの両方にスコープを設定することはできません"
msgid "Scoping to both project and trust is not allowed"
-msgstr "プロジェクトとトラストの両方をスコープとすることは許可されません"
+msgstr "プロジェクトとトラストの両方にスコープを設定することはできません"
#, python-format
msgid "Service Provider %(sp)s is disabled"
-msgstr "サービス・プロバイダー %(sp)s は無効になっています"
+msgstr "サービスプロバイダー %(sp)s は無効になっています"
msgid "Some of requested roles are not in redelegated trust"
-msgstr "要求された役割の一部が再委任されたトラスト内にありません"
+msgstr "要求されたロールの一部が再委任されたトラスト内にありません"
msgid "Specify a domain or project, not both"
msgstr "ドメインかプロジェクトを指定してください。両方は指定しないでください"
@@ -809,27 +823,28 @@ msgid ""
"String length exceeded.The length of string '%(string)s' exceeded the limit "
"of column %(type)s(CHAR(%(length)d))."
msgstr ""
-"ストリングの長さを超えました。ストリング %(string)s' の長さが列 "
-"%(type)s(CHAR(%(length)d)) の制限を超えました。"
+"文字列が長過ぎます。文字列 %(string)s' の長さが列 %(type)s(CHAR(%(length)d)) "
+"の制限を超えました。"
msgid "The --all option cannot be used with the --domain-name option"
msgstr "--all オプションを --domain-name オプションと併用することはできません"
#, python-format
msgid "The Keystone configuration file %(config_file)s could not be found."
-msgstr "Keystone 構成ファイル %(config_file)s が見つかりませんでした。"
+msgstr "Keystone 設定ファイル %(config_file)s が見つかりませんでした。"
#, python-format
msgid ""
"The Keystone domain-specific configuration has specified more than one SQL "
"driver (only one is permitted): %(source)s."
msgstr ""
-"keystone ドメイン固有構成で複数の SQL ドライバーが指定されています (1 つのみ"
-"許可): %(source)s。"
+"keystone ドメイン固有設定で複数の SQL ドライバーが指定されています (1 つしか"
+"指定できません): %(source)s。"
msgid "The action you have requested has not been implemented."
msgstr "要求したアクションは実装されていません。"
+#, fuzzy
msgid "The authenticated user should match the trustor."
msgstr "認証ユーザーは委託者と一致している必要があります。"
@@ -838,8 +853,8 @@ msgid ""
"server does not use PKI tokens otherwise this is the result of "
"misconfiguration."
msgstr ""
-"要求された証明書がありません。このサーバーでは PKI トークンが使用されないか、"
-"または結果的に構成が正しくないことが考えられます。 "
+"要求された証明書がありません。このサーバーでは PKI トークンが使用されていない"
+"か、そうでない場合は設定が間違っていると考えられます。 "
#, python-format
msgid ""
@@ -847,7 +862,7 @@ msgid ""
"not comply with the request because the password is invalid."
msgstr ""
"パスワードの長さは %(size)i 以下でなければなりません。パスワードが無効である"
-"ため、サーバーは要求に従うことができませんでした。"
+"ため、サーバーは要求に応じることができませんでした。"
msgid "The request you have made requires authentication."
msgstr "実行された要求には認証が必要です。"
@@ -869,38 +884,40 @@ msgstr "要求したサービスは現在このサーバーでは使用できま
msgid ""
"The specified parent region %(parent_region_id)s would create a circular "
"region hierarchy."
-msgstr "指定された親領域 %(parent_region_id)s は循環領域階層を作成します。"
+msgstr ""
+"指定された親リージョン %(parent_region_id)s では、リージョン階層構造でループ"
+"が発生してしまいます。"
#, python-format
msgid ""
"The value of group %(group)s specified in the config should be a dictionary "
"of options"
msgstr ""
-"構成で指定されたグループ %(group)s の値はオプションのディクショナリーにする必"
-"要があります"
+"設定で指定されたグループ %(group)s の値はオプションの辞書にする必要があります"
msgid "There should not be any non-oauth parameters"
-msgstr "非 oauth パラメーターが存在していてはなりません"
+msgstr "oauth 関連以外のパラメーターが含まれていてはいけません"
-#, python-format
+#, fuzzy, python-format
msgid "This is not a recognized Fernet payload version: %s"
-msgstr "これは認識された Fernet ペイロード・バージョンではありません: %s"
+msgstr "これは認識された Fernet ペイロードバージョンではありません: %s"
+#, fuzzy
msgid ""
"This is not a v2.0 Fernet token. Use v3 for trust, domain, or federated "
"tokens."
msgstr ""
-"これは v2.0 Fernet トークンではありません。トラスト・トークン、ドメイン・トー"
-"クン、または統合トークンには v3 を使用してください。"
+"これは v2.0 Fernet トークンではありません。トラストトークン、ドメイントーク"
+"ン、または統合トークンには v3 を使用してください。"
msgid ""
"Timestamp not in expected format. The server could not comply with the "
"request since it is either malformed or otherwise incorrect. The client is "
"assumed to be in error."
msgstr ""
-"タイム・スタンプが、予期された形式になっていません。要求の形式が誤っている"
-"か、または要求が正しくないため、サーバーは要求に応じることができませんでし"
-"た。クライアントはエラーになっているとみなされます。"
+"タイムスタンプが想定された形式になっていません。要求の形式が不正もしくは正し"
+"くないため、サーバーは要求に応じることができませんでした。クライアントでエ"
+"ラーが発生していると考えられます。"
#, python-format
msgid ""
@@ -908,8 +925,8 @@ msgid ""
"the specific domain, i.e.: keystone-manage domain_config_upload --domain-"
"name %s"
msgstr ""
-"このエラーに関する詳細を得るには、次のように、特定ドメインに対してこのコマン"
-"ドを再実行してください: keystone-manage domain_config_upload --domain-name %s"
+"このエラーに関する詳細を得るには、特定ドメインに対してこのコマンドを再実行し"
+"てください: keystone-manage domain_config_upload --domain-name %s"
msgid "Token belongs to another user"
msgstr "トークンが別のユーザーに属しています"
@@ -917,9 +934,11 @@ msgstr "トークンが別のユーザーに属しています"
msgid "Token does not belong to specified tenant."
msgstr "トークンが指定されたテナントに所属していません。"
+#, fuzzy
msgid "Trustee has no delegated roles."
-msgstr "受託者に委任された役割がありません。"
+msgstr "受託者に委任されたロールがありません。"
+#, fuzzy
msgid "Trustor is disabled."
msgstr "委託者は無効です。"
@@ -928,50 +947,51 @@ msgid ""
"Trying to update group %(group)s, so that, and only that, group must be "
"specified in the config"
msgstr ""
-"グループ %(group)s を更新しようとしているため、そのオプションのみを構成で指定"
-"する必要があります"
+"グループ %(group)s を更新しようとしていますが、その場合は設定でグループのみを"
+"指定する必要があります"
#, python-format
msgid ""
"Trying to update option %(option)s in group %(group)s, but config provided "
"contains option %(option_other)s instead"
msgstr ""
-"グループ %(group)s 内のオプション %(option)s を更新しようとしていますが、指定"
-"された構成には代わりにオプション %(option_other)s が含まれています"
+"グループ %(group)s のオプション %(option)s を更新しようとしましたが、指定され"
+"た設定には代わりにオプション %(option_other)s が含まれています"
#, python-format
msgid ""
"Trying to update option %(option)s in group %(group)s, so that, and only "
"that, option must be specified in the config"
msgstr ""
-"グループ %(group)s 内のオプション %(option)s を更新しようとしているため、その"
-"オプションのみを構成で指定する必要があります"
+"グループ %(group)s のオプション %(option)s を更新しようとしていますが、その場"
+"合は設定でオプションのみを指定する必要があります"
msgid ""
"Unable to access the keystone database, please check it is configured "
"correctly."
msgstr ""
-"keystone データベースにアクセスできません。このデータベースが正しく構成されて"
+"keystone データベースにアクセスできません。このデータベースが正しく設定されて"
"いるかどうかを確認してください。"
-#, python-format
+#, fuzzy, python-format
msgid "Unable to consume trust %(trust_id)s, unable to acquire lock."
-msgstr "トラスト %(trust_id)s を使用できず、ロックを取得できません。"
+msgstr "トラスト %(trust_id)s を消費できず、ロックを取得できません。"
#, python-format
msgid ""
"Unable to delete region %(region_id)s because it or its child regions have "
"associated endpoints."
msgstr ""
-"領域 %(region_id)s またはその子領域にエンドポイントが関連付けられているため、"
-"この領域を削除できません。"
+"リージョン %(region_id)s またはその子リージョンがエンドポイントに関連付けられ"
+"ているため、このリージョンを削除できません。"
#, python-format
msgid "Unable to find valid groups while using mapping %(mapping_id)s"
msgstr ""
-"マッピング %(mapping_id)s の使用中に有効なグループが見つかりませんでした"
+"マッピング %(mapping_id)s を使用する際に、有効なグループが見つかりませんでし"
+"た"
-#, python-format
+#, fuzzy, python-format
msgid ""
"Unable to get a connection from pool id %(id)s after %(seconds)s seconds."
msgstr ""
@@ -979,13 +999,13 @@ msgstr ""
#, python-format
msgid "Unable to locate domain config directory: %s"
-msgstr "ドメイン構成ディレクトリーが見つかりません: %s"
+msgstr "ドメイン設定ディレクトリーが見つかりません: %s"
#, python-format
msgid "Unable to lookup user %s"
msgstr "ユーザー %s を検索できません"
-#, python-format
+#, fuzzy, python-format
msgid ""
"Unable to reconcile identity attribute %(attribute)s as it has conflicting "
"values %(new)s and %(old)s"
@@ -1000,12 +1020,12 @@ msgid ""
"%(reason)s"
msgstr ""
"SAML アサーションに署名できません。このサーバーに xmlsec1 がインストールされ"
-"ていないか、誤った構成による結果と考えられます。理由: %(reason)s"
+"ていないか、設定が誤っているためと考えられます。理由: %(reason)s"
msgid "Unable to sign token."
msgstr "トークンに署名できません。"
-#, python-format
+#, fuzzy, python-format
msgid "Unexpected assignment type encountered, %s"
msgstr "無効な割り当てタイプ %s が検出されました"
@@ -1014,10 +1034,10 @@ msgid ""
"Unexpected combination of grant attributes - User: %(user_id)s, Group: "
"%(group_id)s, Project: %(project_id)s, Domain: %(domain_id)s"
msgstr ""
-"認可属性 (ユーザー: %(user_id)s、グループ: %(group_id)s、プロジェクト: "
-"%(project_id)s、ドメイン: %(domain_id)s) の組み合わせが正しくありません。"
+"認可属性 の組み合わせ (ユーザー: %(user_id)s、グループ: %(group_id)s、プロ"
+"ジェクト: %(project_id)s、ドメイン: %(domain_id)s) が正しくありません。"
-#, python-format
+#, fuzzy, python-format
msgid "Unexpected status requested for JSON Home response, %s"
msgstr "JSON ホーム応答に対して予期しない状況が要求されました。%s"
@@ -1026,23 +1046,23 @@ msgstr "不明なターゲット"
#, python-format
msgid "Unknown domain '%(name)s' specified by --domain-name"
-msgstr "不明なドメイン '%(name)s' が --domain-name によって指定されました"
+msgstr "不明なドメイン '%(name)s' が --domain-name で指定されました"
#, python-format
msgid "Unknown token version %s"
-msgstr "トークン・バージョン %s は不明です"
+msgstr "トークンバージョン %s は不明です"
#, python-format
msgid "Unregistered dependency: %(name)s for %(targets)s"
-msgstr "未登録の依存関係: %(targets)s の %(name)s"
+msgstr "未登録の依存関係: %(targets)s に対する %(name)s"
msgid "Update of `parent_id` is not allowed."
-msgstr "「parent_id」の更新は許可されていません。"
+msgstr "\"parent_id\" の更新は許可されていません。"
msgid "Use a project scoped token when attempting to create a SAML assertion"
msgstr ""
-"SAML アサーションの作成を試みるときは、プロジェクト範囲トークンを使用してくだ"
-"さい。"
+"SAML アサーションの作成を行うときは、プロジェクトにスコープが設定されたトーク"
+"ンを使用してください"
#, python-format
msgid "User %(u_id)s is unauthorized for tenant %(t_id)s"
@@ -1051,19 +1071,19 @@ msgstr "ユーザー %(u_id)s はテナント %(t_id)s のアクセス権限が�
#, python-format
msgid "User %(user_id)s already has role %(role_id)s in tenant %(tenant_id)s"
msgstr ""
-"ユーザー %(user_id)s には既に役割 %(role_id)s がテナント %(tenant_id)s にあり"
-"ます"
+"ユーザー %(user_id)s にはすでにテナント %(tenant_id)s でロール %(role_id)s が"
+"割り当てられています。"
#, python-format
msgid "User %(user_id)s has no access to domain %(domain_id)s"
msgstr ""
-"ユーザー %(user_id)s にはドメイン %(domain_id)s へのアクセス権限がありません"
+"ユーザー %(user_id)s はドメイン %(domain_id)s へのアクセス権限がありません"
#, python-format
msgid "User %(user_id)s has no access to project %(project_id)s"
msgstr ""
-"ユーザー %(user_id)s にはプロジェクト %(project_id)s へのアクセス権限がありま"
-"せん"
+"ユーザー %(user_id)s はプロジェクト %(project_id)s へのアクセス権限がありませ"
+"ん"
#, python-format
msgid "User %(user_id)s is already a member of group %(group_id)s"
@@ -1078,20 +1098,21 @@ msgstr "ユーザー ID が一致しません"
#, python-format
msgid "User is disabled: %s"
-msgstr "ユーザーが無効化されています: %s"
+msgstr "ユーザーが無効になっています: %s"
msgid "User is not a member of the requested project"
msgstr "ユーザーは、要求されたプロジェクトのメンバーではありません"
+#, fuzzy
msgid "User is not a trustee."
msgstr "ユーザーは受託者ではありません。"
msgid "User not found"
-msgstr "ユーザーが見つかりませんでした"
+msgstr "ユーザーが見つかりません"
-#, python-format
+#, fuzzy, python-format
msgid "User type %s not supported"
-msgstr "ユーザー・タイプ %s はサポートされていません"
+msgstr "ユーザー型 %s はサポートされていません"
msgid "You are not authorized to perform the requested action."
msgstr "要求されたアクションを実行する許可がありません。"
@@ -1109,30 +1130,34 @@ msgstr "`key_mangler` オプションは関数参照でなければなりませ�
msgid "any options"
msgstr "任意のオプション"
+#, fuzzy
msgid "auth_type is not Negotiate"
msgstr "auth_type は折衝されていません"
msgid "authorizing user does not have role required"
-msgstr "許可を与えるユーザーに、必要な役割がありません"
+msgstr "ユーザーを認可するのに必要なロールがありません"
+#, fuzzy
msgid "cache_collection name is required"
msgstr "cache_collection name は必須です"
#, python-format
msgid "cannot create a project in a branch containing a disabled project: %s"
msgstr ""
-"無効なプロジェクトを含むブランチにプロジェクトを作成することはできません: %s"
+"無効になっているプロジェクトを含むブランチにプロジェクトを作成することはでき"
+"ません: %s"
msgid "cannot create a project within a different domain than its parents."
-msgstr "親とは別のドメイン内にプロジェクトを作成することはできません。"
+msgstr "プロジェクトは親とは別のドメイン内には作成できません。"
msgid "cannot delete a domain that is enabled, please disable it first."
msgstr ""
-"有効なドメインは削除できません。最初に有効なドメインを無効にしてください。"
+"有効になっているドメインは削除できません。最初にそのドメインを無効にしてくだ"
+"さい。"
#, python-format
msgid "cannot delete the project %s since it is not a leaf in the hierarchy."
-msgstr "プロジェクト %s は階層内のリーフではないため、削除できません。"
+msgstr "プロジェクト %s は階層内の末端ではないため、削除できません。"
#, python-format
msgid "cannot disable project %s since its subtree contains enabled projects"
@@ -1142,8 +1167,9 @@ msgstr ""
#, python-format
msgid "cannot enable project %s since it has disabled parents"
-msgstr "プロジェクト %s は無効になっている親を含むため、有効にできません"
+msgstr "親が無効になっているプロジェクト %s は有効にできません"
+#, fuzzy
msgid "database db_name is required"
msgstr "database db_name は必須です"
@@ -1151,7 +1177,7 @@ msgid "db_hosts value is required"
msgstr "db_hosts 値は必須です"
msgid "delete the default domain"
-msgstr "デフォルト・ドメインを削除してください"
+msgstr "デフォルトドメインを削除してください"
#, python-format
msgid "group %(group)s"
@@ -1161,8 +1187,8 @@ msgid ""
"idp_contact_type must be one of: [technical, other, support, administrative "
"or billing."
msgstr ""
-"idp_contact_type は technical、other、support、administrative、または "
-"billing のいずれかでなければなりません。"
+"idp_contact_type は technical、other、support、administrative、billing のいず"
+"れかでなければなりません。"
msgid "integer value expected for mongo_ttl_seconds"
msgstr "mongo_ttl_seconds には整数値が必要です"
@@ -1183,23 +1209,28 @@ msgstr "使用可能な SSL サポートがありません"
#, python-format
msgid "option %(option)s in group %(group)s"
-msgstr "グループ %(group)s 内のオプション %(option)s"
+msgstr "グループ %(group)s のオプション %(option)s"
+#, fuzzy
msgid "pad must be single character"
msgstr "埋め込みは単一文字でなければなりません"
+#, fuzzy
msgid "padded base64url text must be multiple of 4 characters"
msgstr "埋め込まれた base64url テキストは 4 の倍数の文字数でなければなりません"
msgid "provided consumer key does not match stored consumer key"
-msgstr "指定されたコンシューマー鍵は保管済みコンシューマー鍵と一致しません"
+msgstr ""
+"指定されたコンシューマー鍵は保存されているコンシューマー鍵と一致しません"
msgid "provided request key does not match stored request key"
-msgstr "指定された要求鍵は保管済み要求鍵と一致しません"
+msgstr "指定された要求鍵は保管されている要求鍵と一致しません"
+#, fuzzy
msgid "provided verifier does not match stored verifier"
-msgstr "指定されたベリファイヤーは保管済みベリファイヤーと一致しません"
+msgstr "指定されたベリファイヤーは保存されているベリファイヤーと一致しません"
+#, fuzzy
msgid "region not type dogpile.cache.CacheRegion"
msgstr "領域のタイプが dogpile.cache.CacheRegion ではありません"
@@ -1210,45 +1241,43 @@ msgid "remaining_uses must not be set if redelegation is allowed"
msgstr "再委任が許可されている場合は remaining_uses を設定してはなりません"
msgid "replicaset_name required when use_replica is True"
-msgstr "use_replica が TRUE の場合は replicaset_name が必要です"
+msgstr "use_replica が True の場合は replicaset_name が必要です"
#, python-format
msgid ""
"request to update group %(group)s, but config provided contains group "
"%(group_other)s instead"
msgstr ""
-"グループ %(group)s の更新を要求しましたが、指定された構成には代わりにグルー"
+"グループ %(group)s の更新を要求しましたが、指定された設定には代わりにグルー"
"プ %(group_other)s が含まれています"
msgid "rescope a scoped token"
-msgstr "スコープ宣言されたトークンを再スコープ宣言します"
+msgstr "スコープが設定されたトークンのスコープを設定し直します"
-#, python-format
+#, fuzzy, python-format
msgid "text is multiple of 4, but pad \"%s\" occurs before 2nd to last char"
msgstr ""
"テキストは 4 の倍数ですが、最後から2 つ目の文字の前に埋め込み \"%s\" あります"
-#, python-format
+#, fuzzy, python-format
msgid "text is multiple of 4, but pad \"%s\" occurs before non-pad last char"
msgstr ""
"テキストは 4 の倍数ですが、埋め込みではない最後の文字の前に埋め込み \"%s\" あ"
"ります"
-#, python-format
+#, fuzzy, python-format
msgid "text is not a multiple of 4, but contains pad \"%s\""
msgstr "テキストは 4 の倍数ではありませんが、埋め込み \"%s\" が含まれています"
#, python-format
msgid "tls_cacertdir %s not found or is not a directory"
msgstr ""
-"tls_cacertdir %s が見つかりませんでした。または、ディレクトリではありません。"
+"tls_cacertdir %s が見つからない、もしくは、ディレクトリではありません。"
#, python-format
msgid "tls_cacertfile %s not found or is not a file"
-msgstr ""
-"tls_cacertfile %s が見つかりませんでした。または、ファイルではありません。"
+msgstr "tls_cacertfile %s が見つからない、もしくは、ファイルではありません。"
#, python-format
msgid "token reference must be a KeystoneToken type, got: %s"
-msgstr ""
-"トークン参照は KeystoneToken タイプである必要があります。%s を受け取りました"
+msgstr "トークン参照は KeystoneToken 型である必要があります。%s を受信しました"
diff --git a/keystone-moon/keystone/locale/keystone-log-warning.pot b/keystone-moon/keystone/locale/keystone-log-warning.pot
index c591d798..3beb3a24 100644
--- a/keystone-moon/keystone/locale/keystone-log-warning.pot
+++ b/keystone-moon/keystone/locale/keystone-log-warning.pot
@@ -6,16 +6,16 @@
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.0.0rc2.dev1\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
+"POT-Creation-Date: 2015-10-01 06:09+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#: keystone/exception.py:48
msgid "missing exception kwargs (programmer error)"
diff --git a/keystone-moon/keystone/locale/keystone.pot b/keystone-moon/keystone/locale/keystone.pot
index 64eab4ed..ce32fa88 100644
--- a/keystone-moon/keystone/locale/keystone.pot
+++ b/keystone-moon/keystone/locale/keystone.pot
@@ -6,16 +6,16 @@
#, fuzzy
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.0.0rc2.dev1\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
+"POT-Creation-Date: 2015-10-01 06:09+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#: keystone/exception.py:78
#, python-format
diff --git a/keystone-moon/keystone/locale/ko_KR/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/ko_KR/LC_MESSAGES/keystone-log-critical.po
index ae6dc845..d7739156 100644
--- a/keystone-moon/keystone/locale/ko_KR/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/ko_KR/LC_MESSAGES/keystone-log-critical.po
@@ -6,19 +6,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Korean (Korea) (http://www.transifex.com/openstack/keystone/"
-"language/ko_KR/)\n"
+"Language-Team: Korean (South Korea)\n"
"Language: ko-KR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
#, python-format
diff --git a/keystone-moon/keystone/locale/ko_KR/LC_MESSAGES/keystone.po b/keystone-moon/keystone/locale/ko_KR/LC_MESSAGES/keystone.po
index f6e0fab8..123379ce 100644
--- a/keystone-moon/keystone/locale/ko_KR/LC_MESSAGES/keystone.po
+++ b/keystone-moon/keystone/locale/ko_KR/LC_MESSAGES/keystone.po
@@ -8,18 +8,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-09-03 12:54+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Korean (Korea) (http://www.transifex.com/openstack/keystone/"
-"language/ko_KR/)\n"
+"Language: ko_KR\n"
+"Language-Team: Korean (South Korea)\n"
"Plural-Forms: nplurals=1; plural=0\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#, python-format
msgid "%(detail)s"
diff --git a/keystone-moon/keystone/locale/pl_PL/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/pl_PL/LC_MESSAGES/keystone-log-critical.po
index 0d4ec217..c57f0c55 100644
--- a/keystone-moon/keystone/locale/pl_PL/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/pl_PL/LC_MESSAGES/keystone-log-critical.po
@@ -6,20 +6,19 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Polish (Poland) (http://www.transifex.com/openstack/keystone/"
-"language/pl_PL/)\n"
+"Language-Team: Polish (Poland)\n"
"Language: pl-PL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
#, python-format
diff --git a/keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone-log-critical.po
index cda7507a..f3b25b5e 100644
--- a/keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone-log-critical.po
@@ -6,19 +6,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Portuguese (Brazil) (http://www.transifex.com/openstack/"
-"keystone/language/pt_BR/)\n"
+"Language-Team: Portuguese (Brazil)\n"
"Language: pt-BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
#, python-format
diff --git a/keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone-log-error.po b/keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone-log-error.po
index f56ca03e..2302f6a9 100644
--- a/keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone-log-error.po
+++ b/keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone-log-error.po
@@ -6,19 +6,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-06-26 05:13+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Portuguese (Brazil) (http://www.transifex.com/openstack/"
-"keystone/language/pt_BR/)\n"
+"Language-Team: Portuguese (Brazil)\n"
"Language: pt-BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
msgid ""
diff --git a/keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone.po b/keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone.po
index 9adc7d82..8bda14f0 100644
--- a/keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone.po
+++ b/keystone-moon/keystone/locale/pt_BR/LC_MESSAGES/keystone.po
@@ -10,18 +10,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-09-03 12:54+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Portuguese (Brazil) (http://www.transifex.com/openstack/"
-"keystone/language/pt_BR/)\n"
+"Language: pt_BR\n"
+"Language-Team: Portuguese (Brazil)\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#, python-format
msgid "%(detail)s"
diff --git a/keystone-moon/keystone/locale/ru/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/ru/LC_MESSAGES/keystone-log-critical.po
index 4ec0cb4b..9435231b 100644
--- a/keystone-moon/keystone/locale/ru/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/ru/LC_MESSAGES/keystone-log-critical.po
@@ -3,23 +3,24 @@
# This file is distributed under the same license as the keystone project.
#
# Translators:
+# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: Keystone\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-08-06 06:28+0000\n"
-"PO-Revision-Date: 2014-08-31 15:19+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
+"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Russian (http://www.transifex.com/openstack/keystone/language/"
-"ru/)\n"
+"Language-Team: Russian\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
+"Generated-By: Babel 2.0\n"
+"X-Generator: Zanata 3.7.1\n"
#, python-format
msgid "Unable to open template file %s"
diff --git a/keystone-moon/keystone/locale/ru/LC_MESSAGES/keystone.po b/keystone-moon/keystone/locale/ru/LC_MESSAGES/keystone.po
index 31b8e98d..1188d316 100644
--- a/keystone-moon/keystone/locale/ru/LC_MESSAGES/keystone.po
+++ b/keystone-moon/keystone/locale/ru/LC_MESSAGES/keystone.po
@@ -9,20 +9,20 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-09-03 12:54+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Russian (http://www.transifex.com/openstack/keystone/language/"
-"ru/)\n"
+"Language: ru\n"
+"Language-Team: Russian\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#, python-format
msgid "%(detail)s"
diff --git a/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-critical.po
index 78c74c70..4c59ad09 100644
--- a/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-critical.po
@@ -6,19 +6,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-08-04 01:49+0000\n"
"Last-Translator: İşbaran Akçayır <isbaran@gmail.com>\n"
-"Language-Team: Turkish (Turkey) (http://www.transifex.com/openstack/keystone/"
-"language/tr_TR/)\n"
+"Language-Team: Turkish (Turkey)\n"
"Language: tr-TR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
#, python-format
diff --git a/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-error.po b/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-error.po
index dd35769a..de599919 100644
--- a/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-error.po
+++ b/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-error.po
@@ -6,19 +6,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-08-04 01:50+0000\n"
"Last-Translator: İşbaran Akçayır <isbaran@gmail.com>\n"
-"Language-Team: Turkish (Turkey) (http://www.transifex.com/openstack/keystone/"
-"language/tr_TR/)\n"
+"Language-Team: Turkish (Turkey)\n"
"Language: tr-TR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
msgid "Cannot retrieve Authorization headers"
diff --git a/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-info.po b/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-info.po
index 65f66f3b..a3451130 100644
--- a/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-info.po
+++ b/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-info.po
@@ -6,19 +6,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-08-04 01:49+0000\n"
"Last-Translator: İşbaran Akçayır <isbaran@gmail.com>\n"
-"Language-Team: Turkish (Turkey) (http://www.transifex.com/openstack/keystone/"
-"language/tr_TR/)\n"
+"Language-Team: Turkish (Turkey)\n"
"Language: tr-TR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
#, python-format
diff --git a/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-warning.po b/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-warning.po
index d15319e2..aeae0585 100644
--- a/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-warning.po
+++ b/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone-log-warning.po
@@ -6,19 +6,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-09-03 12:54+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Turkish (Turkey) (http://www.transifex.com/openstack/keystone/"
-"language/tr_TR/)\n"
+"Language-Team: Turkish (Turkey)\n"
"Language: tr-TR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
#, python-format
diff --git a/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone.po b/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone.po
index 5a378314..3ded8a93 100644
--- a/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone.po
+++ b/keystone-moon/keystone/locale/tr_TR/LC_MESSAGES/keystone.po
@@ -9,18 +9,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-09-03 12:54+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Turkish (Turkey) (http://www.transifex.com/openstack/keystone/"
-"language/tr_TR/)\n"
+"Language: tr_TR\n"
+"Language-Team: Turkish (Turkey)\n"
"Plural-Forms: nplurals=1; plural=0\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#, python-format
msgid "%(detail)s"
diff --git a/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-critical.po
index 9f87b4ea..44dbbe37 100644
--- a/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-critical.po
@@ -6,19 +6,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Chinese (China) (http://www.transifex.com/openstack/keystone/"
-"language/zh_CN/)\n"
+"Language-Team: Chinese (China)\n"
"Language: zh-CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
#, python-format
diff --git a/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-error.po b/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-error.po
index 6017737b..791681d7 100644
--- a/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-error.po
+++ b/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-error.po
@@ -8,19 +8,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-06-26 05:13+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Chinese (China) (http://www.transifex.com/openstack/keystone/"
-"language/zh_CN/)\n"
+"Language-Team: Chinese (China)\n"
"Language: zh-CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
msgid "Cannot retrieve Authorization headers"
diff --git a/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-info.po b/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-info.po
index 46a6fa21..8a756333 100644
--- a/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-info.po
+++ b/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone-log-info.po
@@ -7,19 +7,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-08-01 06:26+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Chinese (China) (http://www.transifex.com/openstack/keystone/"
-"language/zh_CN/)\n"
+"Language-Team: Chinese (China)\n"
"Language: zh-CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
#, python-format
diff --git a/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone.po b/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone.po
index 2a970c85..6479984c 100644
--- a/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone.po
+++ b/keystone-moon/keystone/locale/zh_CN/LC_MESSAGES/keystone.po
@@ -11,18 +11,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-09-03 12:54+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Chinese (China) (http://www.transifex.com/openstack/keystone/"
-"language/zh_CN/)\n"
+"Language: zh_Hans_CN\n"
+"Language-Team: Chinese (China)\n"
"Plural-Forms: nplurals=1; plural=0\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#, python-format
msgid "%(detail)s"
diff --git a/keystone-moon/keystone/locale/zh_TW/LC_MESSAGES/keystone-log-critical.po b/keystone-moon/keystone/locale/zh_TW/LC_MESSAGES/keystone-log-critical.po
index fda12669..0b7082e0 100644
--- a/keystone-moon/keystone/locale/zh_TW/LC_MESSAGES/keystone-log-critical.po
+++ b/keystone-moon/keystone/locale/zh_TW/LC_MESSAGES/keystone-log-critical.po
@@ -6,19 +6,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 8.0.0.0b4.dev56\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-21 06:08+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2014-08-31 03:19+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Chinese (Taiwan) (http://www.transifex.com/openstack/keystone/"
-"language/zh_TW/)\n"
+"Language-Team: Chinese (Taiwan)\n"
"Language: zh-TW\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
"Plural-Forms: nplurals=1; plural=0;\n"
+"Generated-By: Babel 2.0\n"
"X-Generator: Zanata 3.7.1\n"
#, python-format
diff --git a/keystone-moon/keystone/locale/zh_TW/LC_MESSAGES/keystone.po b/keystone-moon/keystone/locale/zh_TW/LC_MESSAGES/keystone.po
index 7a51b29a..0c01497a 100644
--- a/keystone-moon/keystone/locale/zh_TW/LC_MESSAGES/keystone.po
+++ b/keystone-moon/keystone/locale/zh_TW/LC_MESSAGES/keystone.po
@@ -7,18 +7,18 @@
# OpenStack Infra <zanata@openstack.org>, 2015. #zanata
msgid ""
msgstr ""
-"Project-Id-Version: keystone 9.0.0.dev14\n"
+"Project-Id-Version: keystone 8.0.1.dev11\n"
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/keystone\n"
-"POT-Creation-Date: 2015-09-24 06:09+0000\n"
+"POT-Creation-Date: 2015-11-05 06:13+0000\n"
"PO-Revision-Date: 2015-09-03 12:54+0000\n"
"Last-Translator: openstackjenkins <jenkins@openstack.org>\n"
-"Language-Team: Chinese (Taiwan) (http://www.transifex.com/openstack/keystone/"
-"language/zh_TW/)\n"
+"Language: zh_Hant_TW\n"
+"Language-Team: Chinese (Taiwan)\n"
"Plural-Forms: nplurals=1; plural=0\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 2.0\n"
+"Generated-By: Babel 2.1.1\n"
#, python-format
msgid "%(detail)s"
diff --git a/keystone-moon/keystone/resource/controllers.py b/keystone-moon/keystone/resource/controllers.py
index 60c4e025..4fbeb715 100644
--- a/keystone-moon/keystone/resource/controllers.py
+++ b/keystone-moon/keystone/resource/controllers.py
@@ -90,9 +90,11 @@ class Tenant(controller.V2Controller):
self.assert_admin(context)
tenant_ref['id'] = tenant_ref.get('id', uuid.uuid4().hex)
+ initiator = notifications._get_request_audit_info(context)
tenant = self.resource_api.create_project(
tenant_ref['id'],
- self._normalize_domain_id(context, tenant_ref))
+ self._normalize_domain_id(context, tenant_ref),
+ initiator)
return {'tenant': self.v3_to_v2_project(tenant)}
@controller.v2_deprecated
@@ -104,15 +106,17 @@ class Tenant(controller.V2Controller):
clean_tenant = tenant.copy()
clean_tenant.pop('domain_id', None)
clean_tenant.pop('is_domain', None)
+ initiator = notifications._get_request_audit_info(context)
tenant_ref = self.resource_api.update_project(
- tenant_id, clean_tenant)
+ tenant_id, clean_tenant, initiator)
return {'tenant': self.v3_to_v2_project(tenant_ref)}
@controller.v2_deprecated
def delete_project(self, context, tenant_id):
self.assert_admin(context)
self._assert_not_is_domain_project(tenant_id)
- self.resource_api.delete_project(tenant_id)
+ initiator = notifications._get_request_audit_info(context)
+ self.resource_api.delete_project(tenant_id, initiator)
@dependency.requires('resource_api')
diff --git a/keystone-moon/keystone/resource/core.py b/keystone-moon/keystone/resource/core.py
index 6015107d..6891c572 100644
--- a/keystone-moon/keystone/resource/core.py
+++ b/keystone-moon/keystone/resource/core.py
@@ -841,6 +841,7 @@ class DomainConfigManager(manager.Manager):
'user_attribute_ignore', 'user_default_project_id_attribute',
'user_allow_create', 'user_allow_update', 'user_allow_delete',
'user_enabled_emulation', 'user_enabled_emulation_dn',
+ 'user_enabled_emulation_use_group_config',
'user_additional_attribute_mapping', 'group_tree_dn',
'group_filter', 'group_objectclass', 'group_id_attribute',
'group_name_attribute', 'group_member_attribute',
diff --git a/keystone-moon/keystone/tests/unit/common/test_notifications.py b/keystone-moon/keystone/tests/unit/common/test_notifications.py
index ec087c41..1ad8d50d 100644
--- a/keystone-moon/keystone/tests/unit/common/test_notifications.py
+++ b/keystone-moon/keystone/tests/unit/common/test_notifications.py
@@ -279,6 +279,16 @@ class BaseNotificationTest(test_v3.RestfulTestCase):
self.assertEqual(event_type, audit['event_type'])
self.assertTrue(audit['send_notification_called'])
+ def _assert_initiator_data_is_set(self, operation, resource_type, typeURI):
+ self.assertTrue(len(self._audits) > 0)
+ audit = self._audits[-1]
+ payload = audit['payload']
+ self.assertEqual(self.user_id, payload['initiator']['id'])
+ self.assertEqual(self.project_id, payload['initiator']['project_id'])
+ self.assertEqual(typeURI, payload['target']['typeURI'])
+ action = '%s.%s' % (operation, resource_type)
+ self.assertEqual(action, payload['action'])
+
def _assert_notify_not_sent(self, resource_id, operation, resource_type,
public=True):
unexpected = {
@@ -633,11 +643,154 @@ class CADFNotificationsForEntities(NotificationsForEntities):
resource_id = resp.result.get('domain').get('id')
self._assert_last_audit(resource_id, CREATED_OPERATION, 'domain',
cadftaxonomy.SECURITY_DOMAIN)
- self.assertTrue(len(self._audits) > 0)
- audit = self._audits[-1]
- payload = audit['payload']
- self.assertEqual(self.user_id, payload['initiator']['id'])
- self.assertEqual(self.project_id, payload['initiator']['project_id'])
+ self._assert_initiator_data_is_set(CREATED_OPERATION,
+ 'domain',
+ cadftaxonomy.SECURITY_DOMAIN)
+
+
+class V2Notifications(BaseNotificationTest):
+
+ def setUp(self):
+ super(V2Notifications, self).setUp()
+ self.config_fixture.config(notification_format='cadf')
+
+ def test_user(self):
+ token = self.get_scoped_token()
+ resp = self.admin_request(
+ method='POST',
+ path='/v2.0/users',
+ body={
+ 'user': {
+ 'name': uuid.uuid4().hex,
+ 'password': uuid.uuid4().hex,
+ 'enabled': True,
+ },
+ },
+ token=token,
+ )
+ user_id = resp.result.get('user').get('id')
+ self._assert_initiator_data_is_set(CREATED_OPERATION,
+ 'user',
+ cadftaxonomy.SECURITY_ACCOUNT_USER)
+ # test for delete user
+ self.admin_request(
+ method='DELETE',
+ path='/v2.0/users/%s' % user_id,
+ token=token,
+ )
+ self._assert_initiator_data_is_set(DELETED_OPERATION,
+ 'user',
+ cadftaxonomy.SECURITY_ACCOUNT_USER)
+
+ def test_role(self):
+ token = self.get_scoped_token()
+ resp = self.admin_request(
+ method='POST',
+ path='/v2.0/OS-KSADM/roles',
+ body={
+ 'role': {
+ 'name': uuid.uuid4().hex,
+ 'description': uuid.uuid4().hex,
+ },
+ },
+ token=token,
+ )
+ role_id = resp.result.get('role').get('id')
+ self._assert_initiator_data_is_set(CREATED_OPERATION,
+ 'role',
+ cadftaxonomy.SECURITY_ROLE)
+ # test for delete role
+ self.admin_request(
+ method='DELETE',
+ path='/v2.0/OS-KSADM/roles/%s' % role_id,
+ token=token,
+ )
+ self._assert_initiator_data_is_set(DELETED_OPERATION,
+ 'role',
+ cadftaxonomy.SECURITY_ROLE)
+
+ def test_service_and_endpoint(self):
+ token = self.get_scoped_token()
+ resp = self.admin_request(
+ method='POST',
+ path='/v2.0/OS-KSADM/services',
+ body={
+ 'OS-KSADM:service': {
+ 'name': uuid.uuid4().hex,
+ 'type': uuid.uuid4().hex,
+ 'description': uuid.uuid4().hex,
+ },
+ },
+ token=token,
+ )
+ service_id = resp.result.get('OS-KSADM:service').get('id')
+ self._assert_initiator_data_is_set(CREATED_OPERATION,
+ 'service',
+ cadftaxonomy.SECURITY_SERVICE)
+ resp = self.admin_request(
+ method='POST',
+ path='/v2.0/endpoints',
+ body={
+ 'endpoint': {
+ 'region': uuid.uuid4().hex,
+ 'service_id': service_id,
+ 'publicurl': uuid.uuid4().hex,
+ 'adminurl': uuid.uuid4().hex,
+ 'internalurl': uuid.uuid4().hex,
+ },
+ },
+ token=token,
+ )
+ endpoint_id = resp.result.get('endpoint').get('id')
+ self._assert_initiator_data_is_set(CREATED_OPERATION,
+ 'endpoint',
+ cadftaxonomy.SECURITY_ENDPOINT)
+ # test for delete endpoint
+ self.admin_request(
+ method='DELETE',
+ path='/v2.0/endpoints/%s' % endpoint_id,
+ token=token,
+ )
+ self._assert_initiator_data_is_set(DELETED_OPERATION,
+ 'endpoint',
+ cadftaxonomy.SECURITY_ENDPOINT)
+ # test for delete service
+ self.admin_request(
+ method='DELETE',
+ path='/v2.0/OS-KSADM/services/%s' % service_id,
+ token=token,
+ )
+ self._assert_initiator_data_is_set(DELETED_OPERATION,
+ 'service',
+ cadftaxonomy.SECURITY_SERVICE)
+
+ def test_project(self):
+ token = self.get_scoped_token()
+ resp = self.admin_request(
+ method='POST',
+ path='/v2.0/tenants',
+ body={
+ 'tenant': {
+ 'name': uuid.uuid4().hex,
+ 'description': uuid.uuid4().hex,
+ 'enabled': True
+ },
+ },
+ token=token,
+ )
+ project_id = resp.result.get('tenant').get('id')
+ self._assert_initiator_data_is_set(CREATED_OPERATION,
+ 'project',
+ cadftaxonomy.SECURITY_PROJECT)
+ # test for delete project
+ self.admin_request(
+ method='DELETE',
+ path='/v2.0/tenants/%s' % project_id,
+ token=token,
+ )
+ self._assert_initiator_data_is_set(DELETED_OPERATION,
+ 'project',
+ cadftaxonomy.SECURITY_PROJECT)
class TestEventCallbacks(test_v3.RestfulTestCase):
diff --git a/keystone-moon/keystone/tests/unit/rest.py b/keystone-moon/keystone/tests/unit/rest.py
index da24019f..35b47e2b 100644
--- a/keystone-moon/keystone/tests/unit/rest.py
+++ b/keystone-moon/keystone/tests/unit/rest.py
@@ -114,7 +114,7 @@ class RestfulTestCase(unit.TestCase):
example::
- self.assertResponseStatus(response, http_client.NO_CONTENT)
+ self.assertResponseStatus(response, 204)
"""
self.assertEqual(
response.status_code,
diff --git a/keystone-moon/keystone/tests/unit/test_associate_project_endpoint_extension.py b/keystone-moon/keystone/tests/unit/test_associate_project_endpoint_extension.py
index 4c574549..24fc82dd 100644
--- a/keystone-moon/keystone/tests/unit/test_associate_project_endpoint_extension.py
+++ b/keystone-moon/keystone/tests/unit/test_associate_project_endpoint_extension.py
@@ -48,7 +48,8 @@ class EndpointFilterCRUDTestCase(TestExtensionCase):
Valid endpoint and project id test case.
"""
- self.put(self.default_request_url)
+ self.put(self.default_request_url,
+ expected_status=204)
def test_create_endpoint_project_association_with_invalid_project(self):
"""PUT OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id}
@@ -81,7 +82,8 @@ class EndpointFilterCRUDTestCase(TestExtensionCase):
"""
self.put(self.default_request_url,
- body={'project_id': self.default_domain_project_id})
+ body={'project_id': self.default_domain_project_id},
+ expected_status=204)
def test_check_endpoint_project_association(self):
"""HEAD /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id}
@@ -89,11 +91,13 @@ class EndpointFilterCRUDTestCase(TestExtensionCase):
Valid project and endpoint id test case.
"""
- self.put(self.default_request_url)
+ self.put(self.default_request_url,
+ expected_status=204)
self.head('/OS-EP-FILTER/projects/%(project_id)s'
'/endpoints/%(endpoint_id)s' % {
'project_id': self.default_domain_project_id,
- 'endpoint_id': self.endpoint_id})
+ 'endpoint_id': self.endpoint_id},
+ expected_status=204)
def test_check_endpoint_project_association_with_invalid_project(self):
"""HEAD /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id}
@@ -165,7 +169,8 @@ class EndpointFilterCRUDTestCase(TestExtensionCase):
"""
r = self.get('/OS-EP-FILTER/endpoints/%(endpoint_id)s/projects' %
- {'endpoint_id': self.endpoint_id})
+ {'endpoint_id': self.endpoint_id},
+ expected_status=200)
self.assertValidProjectListResponse(r, expected_length=0)
def test_list_projects_associated_with_invalid_endpoint(self):
@@ -188,7 +193,8 @@ class EndpointFilterCRUDTestCase(TestExtensionCase):
self.delete('/OS-EP-FILTER/projects/%(project_id)s'
'/endpoints/%(endpoint_id)s' % {
'project_id': self.default_domain_project_id,
- 'endpoint_id': self.endpoint_id})
+ 'endpoint_id': self.endpoint_id},
+ expected_status=204)
def test_remove_endpoint_project_association_with_invalid_project(self):
"""DELETE /OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id}
@@ -220,26 +226,26 @@ class EndpointFilterCRUDTestCase(TestExtensionCase):
self.put(self.default_request_url)
association_url = ('/OS-EP-FILTER/endpoints/%(endpoint_id)s/projects' %
{'endpoint_id': self.endpoint_id})
- r = self.get(association_url)
+ r = self.get(association_url, expected_status=200)
self.assertValidProjectListResponse(r, expected_length=1)
self.delete('/projects/%(project_id)s' % {
'project_id': self.default_domain_project_id})
- r = self.get(association_url)
+ r = self.get(association_url, expected_status=200)
self.assertValidProjectListResponse(r, expected_length=0)
def test_endpoint_project_association_cleanup_when_endpoint_deleted(self):
self.put(self.default_request_url)
association_url = '/OS-EP-FILTER/projects/%(project_id)s/endpoints' % {
'project_id': self.default_domain_project_id}
- r = self.get(association_url)
+ r = self.get(association_url, expected_status=200)
self.assertValidEndpointListResponse(r, expected_length=1)
self.delete('/endpoints/%(endpoint_id)s' % {
'endpoint_id': self.endpoint_id})
- r = self.get(association_url)
+ r = self.get(association_url, expected_status=200)
self.assertValidEndpointListResponse(r, expected_length=0)
@@ -270,7 +276,8 @@ class EndpointFilterTokenRequestTestCase(TestExtensionCase):
self.put('/OS-EP-FILTER/projects/%(project_id)s'
'/endpoints/%(endpoint_id)s' % {
'project_id': project['id'],
- 'endpoint_id': self.endpoint_id})
+ 'endpoint_id': self.endpoint_id},
+ expected_status=204)
# attempt to authenticate without requesting a project
auth_data = self.build_authentication_request(
@@ -290,7 +297,8 @@ class EndpointFilterTokenRequestTestCase(TestExtensionCase):
self.put('/OS-EP-FILTER/projects/%(project_id)s'
'/endpoints/%(endpoint_id)s' % {
'project_id': self.project['id'],
- 'endpoint_id': self.endpoint_id})
+ 'endpoint_id': self.endpoint_id},
+ expected_status=204)
auth_data = self.build_authentication_request(
user_id=self.user['id'],
@@ -310,7 +318,8 @@ class EndpointFilterTokenRequestTestCase(TestExtensionCase):
self.put('/OS-EP-FILTER/projects/%(project_id)s'
'/endpoints/%(endpoint_id)s' % {
'project_id': self.project['id'],
- 'endpoint_id': self.endpoint_id})
+ 'endpoint_id': self.endpoint_id},
+ expected_status=204)
auth_data = self.build_authentication_request(
user_id=self.user['id'],
@@ -329,7 +338,8 @@ class EndpointFilterTokenRequestTestCase(TestExtensionCase):
self.put('/OS-EP-FILTER/projects/%(project_id)s'
'/endpoints/%(endpoint_id)s' % {
'project_id': self.project['id'],
- 'endpoint_id': self.endpoint_id})
+ 'endpoint_id': self.endpoint_id},
+ expected_status=204)
# create a second temporary endpoint
self.endpoint_id2 = uuid.uuid4().hex
@@ -343,7 +353,8 @@ class EndpointFilterTokenRequestTestCase(TestExtensionCase):
self.put('/OS-EP-FILTER/projects/%(project_id)s'
'/endpoints/%(endpoint_id)s' % {
'project_id': self.project['id'],
- 'endpoint_id': self.endpoint_id2})
+ 'endpoint_id': self.endpoint_id2},
+ expected_status=204)
# remove the temporary reference
# this will create inconsistency in the endpoint filter table
@@ -369,7 +380,8 @@ class EndpointFilterTokenRequestTestCase(TestExtensionCase):
self.put('/OS-EP-FILTER/projects/%(project_id)s'
'/endpoints/%(endpoint_id)s' % {
'project_id': self.project['id'],
- 'endpoint_id': self.endpoint_id})
+ 'endpoint_id': self.endpoint_id},
+ expected_status=204)
# Add a disabled endpoint to the default project.
@@ -387,7 +399,8 @@ class EndpointFilterTokenRequestTestCase(TestExtensionCase):
self.put('/OS-EP-FILTER/projects/%(project_id)s'
'/endpoints/%(endpoint_id)s' % {
'project_id': self.project['id'],
- 'endpoint_id': disabled_endpoint_id})
+ 'endpoint_id': disabled_endpoint_id},
+ expected_status=204)
# Authenticate to get token with catalog
auth_data = self.build_authentication_request(
@@ -416,11 +429,13 @@ class EndpointFilterTokenRequestTestCase(TestExtensionCase):
self.put('/OS-EP-FILTER/projects/%(project_id)s'
'/endpoints/%(endpoint_id)s' % {
'project_id': self.project['id'],
- 'endpoint_id': endpoint_id1})
+ 'endpoint_id': endpoint_id1},
+ expected_status=204)
self.put('/OS-EP-FILTER/projects/%(project_id)s'
'/endpoints/%(endpoint_id)s' % {
'project_id': self.project['id'],
- 'endpoint_id': endpoint_id2})
+ 'endpoint_id': endpoint_id2},
+ expected_status=204)
# there should be only two endpoints in token catalog
auth_data = self.build_authentication_request(
@@ -439,7 +454,8 @@ class EndpointFilterTokenRequestTestCase(TestExtensionCase):
self.put('/OS-EP-FILTER/projects/%(project_id)s'
'/endpoints/%(endpoint_id)s' % {
'project_id': self.project['id'],
- 'endpoint_id': self.endpoint_id})
+ 'endpoint_id': self.endpoint_id},
+ expected_status=204)
auth_data = self.build_authentication_request(
user_id=self.user['id'],
@@ -622,7 +638,7 @@ class EndpointGroupCRUDTestCase(TestExtensionCase):
self.DEFAULT_ENDPOINT_GROUP_URL, self.DEFAULT_ENDPOINT_GROUP_BODY)
url = '/OS-EP-FILTER/endpoint_groups/%(endpoint_group_id)s' % {
'endpoint_group_id': endpoint_group_id}
- self.head(url, expected_status=http_client.OK)
+ self.head(url, expected_status=200)
def test_check_invalid_endpoint_group(self):
"""HEAD /OS-EP-FILTER/endpoint_groups/{endpoint_group_id}
@@ -816,7 +832,7 @@ class EndpointGroupCRUDTestCase(TestExtensionCase):
self.project_id)
url = self._get_project_endpoint_group_url(
endpoint_group_id, self.project_id)
- self.head(url, expected_status=http_client.OK)
+ self.head(url, expected_status=200)
def test_check_endpoint_group_to_project_with_invalid_project_id(self):
"""Test HEAD with an invalid endpoint group and project association."""
diff --git a/keystone-moon/keystone/tests/unit/test_backend.py b/keystone-moon/keystone/tests/unit/test_backend.py
index d3b51edd..302fc2c2 100644
--- a/keystone-moon/keystone/tests/unit/test_backend.py
+++ b/keystone-moon/keystone/tests/unit/test_backend.py
@@ -4671,7 +4671,7 @@ class TokenTests(object):
def test_list_revoked_tokens_for_multiple_tokens(self):
self.check_list_revoked_tokens([self.delete_token()
- for x in range(2)])
+ for x in six.moves.range(2)])
def test_flush_expired_token(self):
token_id = uuid.uuid4().hex
diff --git a/keystone-moon/keystone/tests/unit/test_backend_ldap.py b/keystone-moon/keystone/tests/unit/test_backend_ldap.py
index 808922a7..d96ec376 100644
--- a/keystone-moon/keystone/tests/unit/test_backend_ldap.py
+++ b/keystone-moon/keystone/tests/unit/test_backend_ldap.py
@@ -21,7 +21,6 @@ import ldap
import mock
from oslo_config import cfg
import pkg_resources
-from six.moves import http_client
from six.moves import range
from testtools import matchers
@@ -2182,6 +2181,26 @@ class LDAPIdentityEnabledEmulation(LDAPIdentity):
self.skipTest(
"Enabled emulation conflicts with enabled mask")
+ def test_user_enabled_use_group_config(self):
+ self.config_fixture.config(
+ group='ldap',
+ user_enabled_emulation_use_group_config=True,
+ group_member_attribute='uniqueMember',
+ group_objectclass='groupOfUniqueNames')
+ self.ldapdb.clear()
+ self.load_backends()
+ self.load_fixtures(default_fixtures)
+
+ # Create a user and ensure they are enabled.
+ user1 = {'name': u'fäké1', 'enabled': True,
+ 'domain_id': CONF.identity.default_domain_id}
+ user_ref = self.identity_api.create_user(user1)
+ self.assertIs(True, user_ref['enabled'])
+
+ # Get a user and ensure they are enabled.
+ user_ref = self.identity_api.get_user(user_ref['id'])
+ self.assertIs(True, user_ref['enabled'])
+
def test_user_enabled_invert(self):
self.config_fixture.config(group='ldap', user_enabled_invert=True,
user_enabled_default=False)
@@ -2487,7 +2506,7 @@ class BaseMultiLDAPandSQLIdentity(object):
self.identity_api._get_domain_driver_and_entity_id(
user['id']))
- if expected_status == http_client.OK:
+ if expected_status == 200:
ref = driver.get_user(entity_id)
ref = self.identity_api._set_domain_id_and_mapping(
ref, domain_id, driver, map.EntityType.USER)
@@ -2661,23 +2680,21 @@ class MultiLDAPandSQLIdentity(BaseLDAPIdentity, unit.SQLDriverOverrides,
check_user = self.check_user
check_user(self.users['user0'],
- self.domains['domain_default']['id'], http_client.OK)
+ self.domains['domain_default']['id'], 200)
for domain in [self.domains['domain1']['id'],
self.domains['domain2']['id'],
self.domains['domain3']['id'],
self.domains['domain4']['id']]:
check_user(self.users['user0'], domain, exception.UserNotFound)
- check_user(self.users['user1'], self.domains['domain1']['id'],
- http_client.OK)
+ check_user(self.users['user1'], self.domains['domain1']['id'], 200)
for domain in [self.domains['domain_default']['id'],
self.domains['domain2']['id'],
self.domains['domain3']['id'],
self.domains['domain4']['id']]:
check_user(self.users['user1'], domain, exception.UserNotFound)
- check_user(self.users['user2'], self.domains['domain2']['id'],
- http_client.OK)
+ check_user(self.users['user2'], self.domains['domain2']['id'], 200)
for domain in [self.domains['domain_default']['id'],
self.domains['domain1']['id'],
self.domains['domain3']['id'],
@@ -2687,14 +2704,10 @@ class MultiLDAPandSQLIdentity(BaseLDAPIdentity, unit.SQLDriverOverrides,
# domain3 and domain4 share the same backend, so you should be
# able to see user3 and user4 from either.
- check_user(self.users['user3'], self.domains['domain3']['id'],
- http_client.OK)
- check_user(self.users['user3'], self.domains['domain4']['id'],
- http_client.OK)
- check_user(self.users['user4'], self.domains['domain3']['id'],
- http_client.OK)
- check_user(self.users['user4'], self.domains['domain4']['id'],
- http_client.OK)
+ check_user(self.users['user3'], self.domains['domain3']['id'], 200)
+ check_user(self.users['user3'], self.domains['domain4']['id'], 200)
+ check_user(self.users['user4'], self.domains['domain3']['id'], 200)
+ check_user(self.users['user4'], self.domains['domain4']['id'], 200)
for domain in [self.domains['domain_default']['id'],
self.domains['domain1']['id'],
@@ -3151,12 +3164,12 @@ class DomainSpecificLDAPandSQLIdentity(
# driver, but won't find it via any other domain driver
self.check_user(self.users['user0'],
- self.domains['domain_default']['id'], http_client.OK)
+ self.domains['domain_default']['id'], 200)
self.check_user(self.users['user0'],
self.domains['domain1']['id'], exception.UserNotFound)
self.check_user(self.users['user1'],
- self.domains['domain1']['id'], http_client.OK)
+ self.domains['domain1']['id'], 200)
self.check_user(self.users['user1'],
self.domains['domain_default']['id'],
exception.UserNotFound)
diff --git a/keystone-moon/keystone/tests/unit/test_catalog.py b/keystone-moon/keystone/tests/unit/test_catalog.py
index 85acfedf..ada2de43 100644
--- a/keystone-moon/keystone/tests/unit/test_catalog.py
+++ b/keystone-moon/keystone/tests/unit/test_catalog.py
@@ -53,8 +53,7 @@ class V2CatalogTestCase(rest.RestfulTestCase):
"""Applicable only to JSON."""
return r.result['access']['token']['id']
- def _endpoint_create(self, expected_status=http_client.OK,
- service_id=SERVICE_FIXTURE,
+ def _endpoint_create(self, expected_status=200, service_id=SERVICE_FIXTURE,
publicurl='http://localhost:8080',
internalurl='http://localhost:8080',
adminurl='http://localhost:8080'):
@@ -77,6 +76,18 @@ class V2CatalogTestCase(rest.RestfulTestCase):
body=body)
return body, r
+ def _region_create(self):
+ region_id = uuid.uuid4().hex
+ self.catalog_api.create_region({'id': region_id})
+ return region_id
+
+ def _service_create(self):
+ service_id = uuid.uuid4().hex
+ service = unit.new_service_ref()
+ service['id'] = service_id
+ self.catalog_api.create_service(service_id, service)
+ return service_id
+
def test_endpoint_create(self):
req_body, response = self._endpoint_create()
self.assertIn('endpoint', response.result)
@@ -84,6 +95,78 @@ class V2CatalogTestCase(rest.RestfulTestCase):
for field, value in req_body['endpoint'].items():
self.assertEqual(response.result['endpoint'][field], value)
+ def test_pure_v3_endpoint_with_publicurl_visible_from_v2(self):
+ """Test pure v3 endpoint can be fetched via v2 API.
+
+ For those who are using v2 APIs, endpoints created by v3 API should
+ also be visible as there are no differences about the endpoints
+ except the format or the internal implementation.
+ And because public url is required for v2 API, so only the v3 endpoints
+ of the service which has the public interface endpoint will be
+ converted into v2 endpoints.
+ """
+ region_id = self._region_create()
+ service_id = self._service_create()
+ # create a v3 endpoint with three interfaces
+ body = {
+ 'endpoint': unit.new_endpoint_ref(service_id,
+ default_region_id=region_id)
+ }
+ for interface in catalog.controllers.INTERFACES:
+ body['endpoint']['interface'] = interface
+ self.admin_request(method='POST',
+ token=self.get_scoped_token(),
+ path='/v3/endpoints',
+ expected_status=http_client.CREATED,
+ body=body)
+
+ r = self.admin_request(token=self.get_scoped_token(),
+ path='/v2.0/endpoints')
+ # v3 endpoints having public url can be fetched via v2.0 API
+ self.assertEqual(1, len(r.result['endpoints']))
+ v2_endpoint = r.result['endpoints'][0]
+ self.assertEqual(service_id, v2_endpoint['service_id'])
+ # check urls just in case.
+ # This is not the focus of this test, so no different urls are used.
+ self.assertEqual(body['endpoint']['url'], v2_endpoint['publicurl'])
+ self.assertEqual(body['endpoint']['url'], v2_endpoint['adminurl'])
+ self.assertEqual(body['endpoint']['url'], v2_endpoint['internalurl'])
+ self.assertNotIn('name', v2_endpoint)
+
+ v3_endpoint = self.catalog_api.get_endpoint(v2_endpoint['id'])
+ # it's the v3 public endpoint's id as the generated v2 endpoint
+ self.assertEqual('public', v3_endpoint['interface'])
+ self.assertEqual(service_id, v3_endpoint['service_id'])
+
+ def test_pure_v3_endpoint_without_publicurl_invisible_from_v2(self):
+ """Test pure v3 endpoint without public url can't be fetched via v2 API.
+
+ V2 API will return endpoints created by v3 API, but because public url
+ is required for v2 API, so v3 endpoints without public url will be
+ ignored.
+ """
+ region_id = self._region_create()
+ service_id = self._service_create()
+ # create a v3 endpoint without public interface
+ body = {
+ 'endpoint': unit.new_endpoint_ref(service_id,
+ default_region_id=region_id)
+ }
+ for interface in catalog.controllers.INTERFACES:
+ if interface == 'public':
+ continue
+ body['endpoint']['interface'] = interface
+ self.admin_request(method='POST',
+ token=self.get_scoped_token(),
+ path='/v3/endpoints',
+ expected_status=http_client.CREATED,
+ body=body)
+
+ r = self.admin_request(token=self.get_scoped_token(),
+ path='/v2.0/endpoints')
+ # v3 endpoints without public url won't be fetched via v2.0 API
+ self.assertEqual(0, len(r.result['endpoints']))
+
def test_endpoint_create_with_null_adminurl(self):
req_body, response = self._endpoint_create(adminurl=None)
self.assertIsNone(req_body['endpoint']['adminurl'])
@@ -126,7 +209,7 @@ class V2CatalogTestCase(rest.RestfulTestCase):
valid_url = 'http://127.0.0.1:8774/v1.1/$(tenant_id)s'
# baseline tests that all valid URLs works
- self._endpoint_create(expected_status=http_client.OK,
+ self._endpoint_create(expected_status=200,
publicurl=valid_url,
internalurl=valid_url,
adminurl=valid_url)
diff --git a/keystone-moon/keystone/tests/unit/test_cert_setup.py b/keystone-moon/keystone/tests/unit/test_cert_setup.py
index 47a99810..769e7c8e 100644
--- a/keystone-moon/keystone/tests/unit/test_cert_setup.py
+++ b/keystone-moon/keystone/tests/unit/test_cert_setup.py
@@ -17,7 +17,6 @@ import os
import shutil
import mock
-from six.moves import http_client
from testtools import matchers
from keystone.common import environment
@@ -114,13 +113,11 @@ class CertSetupTestCase(rest.RestfulTestCase):
# requests don't have some of the normal information
signing_resp = self.request(self.public_app,
'/v2.0/certificates/signing',
- method='GET',
- expected_status=http_client.OK)
+ method='GET', expected_status=200)
cacert_resp = self.request(self.public_app,
'/v2.0/certificates/ca',
- method='GET',
- expected_status=http_client.OK)
+ method='GET', expected_status=200)
with open(CONF.signing.certfile) as f:
self.assertEqual(f.read(), signing_resp.text)
@@ -136,7 +133,7 @@ class CertSetupTestCase(rest.RestfulTestCase):
for accept in [None, 'text/html', 'application/json', 'text/xml']:
headers = {'Accept': accept} if accept else {}
resp = self.request(self.public_app, path, method='GET',
- expected_status=http_client.OK,
+ expected_status=200,
headers=headers)
self.assertEqual('text/html', resp.content_type)
@@ -149,7 +146,7 @@ class CertSetupTestCase(rest.RestfulTestCase):
def test_failure(self):
for path in ['/v2.0/certificates/signing', '/v2.0/certificates/ca']:
self.request(self.public_app, path, method='GET',
- expected_status=http_client.INTERNAL_SERVER_ERROR)
+ expected_status=500)
def test_pki_certs_rebuild(self):
self.test_create_pki_certs()
diff --git a/keystone-moon/keystone/tests/unit/test_contrib_simple_cert.py b/keystone-moon/keystone/tests/unit/test_contrib_simple_cert.py
index b241b41b..8664e2c3 100644
--- a/keystone-moon/keystone/tests/unit/test_contrib_simple_cert.py
+++ b/keystone-moon/keystone/tests/unit/test_contrib_simple_cert.py
@@ -12,8 +12,6 @@
import uuid
-from six.moves import http_client
-
from keystone.tests.unit import test_v3
@@ -33,7 +31,7 @@ class TestSimpleCert(BaseTestCase):
method='GET',
path=path,
headers={'Accept': content_type},
- expected_status=http_client.OK)
+ expected_status=200)
self.assertEqual(content_type, response.content_type.lower())
self.assertIn('---BEGIN', response.body)
@@ -56,4 +54,4 @@ class TestSimpleCert(BaseTestCase):
self.request(app=self.public_app,
method='GET',
path=path,
- expected_status=http_client.INTERNAL_SERVER_ERROR)
+ expected_status=500)
diff --git a/keystone-moon/keystone/tests/unit/test_policy.py b/keystone-moon/keystone/tests/unit/test_policy.py
index b2f0e525..686e2b70 100644
--- a/keystone-moon/keystone/tests/unit/test_policy.py
+++ b/keystone-moon/keystone/tests/unit/test_policy.py
@@ -16,10 +16,8 @@
import json
import os
-import mock
from oslo_policy import policy as common_policy
import six
-from six.moves.urllib import request as urlrequest
from testtools import matchers
from keystone import exception
@@ -118,28 +116,6 @@ class PolicyTestCase(BasePolicyTestCase):
action = "example:allowed"
rules.enforce(self.credentials, action, self.target)
- def test_enforce_http_true(self):
-
- def fakeurlopen(url, post_data):
- return six.StringIO("True")
-
- action = "example:get_http"
- target = {}
- with mock.patch.object(urlrequest, 'urlopen', fakeurlopen):
- result = rules.enforce(self.credentials, action, target)
- self.assertTrue(result)
-
- def test_enforce_http_false(self):
-
- def fakeurlopen(url, post_data):
- return six.StringIO("False")
-
- action = "example:get_http"
- target = {}
- with mock.patch.object(urlrequest, 'urlopen', fakeurlopen):
- self.assertRaises(exception.ForbiddenAction, rules.enforce,
- self.credentials, action, target)
-
def test_templatized_enforcement(self):
target_mine = {'project_id': 'fake'}
target_not_mine = {'project_id': 'another'}
diff --git a/keystone-moon/keystone/tests/unit/test_sql_migrate_extensions.py b/keystone-moon/keystone/tests/unit/test_sql_migrate_extensions.py
index 87b3d48d..f498fe94 100644
--- a/keystone-moon/keystone/tests/unit/test_sql_migrate_extensions.py
+++ b/keystone-moon/keystone/tests/unit/test_sql_migrate_extensions.py
@@ -180,6 +180,7 @@ class FederationExtension(test_sql_upgrade.SqlMigrateBase):
self.federation_protocol = 'federation_protocol'
self.service_provider = 'service_provider'
self.mapping = 'mapping'
+ self.remote_id_table = 'idp_remote_ids'
def repo_package(self):
return federation
@@ -310,6 +311,68 @@ class FederationExtension(test_sql_upgrade.SqlMigrateBase):
self.assertEqual('', sp.auth_url)
self.assertEqual('', sp.sp_url)
+ def test_propagate_remote_id_to_separate_column(self):
+ """Make sure empty remote_id is not propagated.
+ Test scenario:
+ - Upgrade database to version 6 where identity_provider table has a
+ remote_id column
+ - Add 3 identity provider objects, where idp1 and idp2 have valid
+ remote_id parameter set, and idp3 has it empty (None).
+ - Upgrade database to version 7 and expect migration scripts to
+ properly move data rom identity_provider.remote_id column into
+ separate table idp_remote_ids.
+ - In the idp_remote_ids table expect to find entries for idp1 and idp2
+ and not find anything for idp3 (identitified by idp's id)
+
+ """
+ session = self.Session()
+ idp1 = {'id': uuid.uuid4().hex,
+ 'remote_id': uuid.uuid4().hex,
+ 'description': uuid.uuid4().hex,
+ 'enabled': True}
+ idp2 = {'id': uuid.uuid4().hex,
+ 'remote_id': uuid.uuid4().hex,
+ 'description': uuid.uuid4().hex,
+ 'enabled': True}
+ idp3 = {'id': uuid.uuid4().hex,
+ 'remote_id': None,
+ 'description': uuid.uuid4().hex,
+ 'enabled': True}
+ self.upgrade(6, repository=self.repo_path)
+ self.assertTableColumns(self.identity_provider,
+ ['id', 'description', 'enabled', 'remote_id'])
+
+ self.insert_dict(session, self.identity_provider, idp1)
+ self.insert_dict(session, self.identity_provider, idp2)
+ self.insert_dict(session, self.identity_provider, idp3)
+
+ session.close()
+ self.upgrade(7, repository=self.repo_path)
+
+ self.assertTableColumns(self.identity_provider,
+ ['id', 'description', 'enabled'])
+ remote_id_table = sqlalchemy.Table(self.remote_id_table,
+ self.metadata,
+ autoload=True)
+
+ session = self.Session()
+ self.metadata.clear()
+
+ idp = session.query(remote_id_table).filter(
+ remote_id_table.c.idp_id == idp1['id'])[0]
+ self.assertEqual(idp1['remote_id'], idp.remote_id)
+
+ idp = session.query(remote_id_table).filter(
+ remote_id_table.c.idp_id == idp2['id'])[0]
+ self.assertEqual(idp2['remote_id'], idp.remote_id)
+
+ idp = session.query(remote_id_table).filter(
+ remote_id_table.c.idp_id == idp3['id'])
+ # NOTE(marek-denis): As idp3 had empty 'remote_id' attribute we expect
+ # not to find it in the 'remote_id_table' table, hence count should be
+ # 0.real
+ self.assertEqual(0, idp.count())
+
def test_add_relay_state_column(self):
self.upgrade(8, repository=self.repo_path)
self.assertTableColumns(self.service_provider,
diff --git a/keystone-moon/keystone/tests/unit/test_v2.py b/keystone-moon/keystone/tests/unit/test_v2.py
index 99b5a897..acdfca5f 100644
--- a/keystone-moon/keystone/tests/unit/test_v2.py
+++ b/keystone-moon/keystone/tests/unit/test_v2.py
@@ -132,7 +132,7 @@ class CoreApiTests(object):
'tenantId': self.tenant_bar['id'],
},
},
- expected_status=http_client.OK)
+ expected_status=200)
self.assertValidAuthenticationResponse(r, require_service_catalog=True)
def test_authenticate_unscoped(self):
@@ -147,7 +147,7 @@ class CoreApiTests(object):
},
},
},
- expected_status=http_client.OK)
+ expected_status=200)
self.assertValidAuthenticationResponse(r)
def test_get_tenants_for_token(self):
@@ -234,7 +234,7 @@ class CoreApiTests(object):
'token_id': token,
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
def test_endpoints(self):
token = self.get_scoped_token()
@@ -370,7 +370,7 @@ class CoreApiTests(object):
},
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
def test_error_response(self):
"""This triggers assertValidErrorResponse by convention."""
@@ -459,7 +459,7 @@ class CoreApiTests(object):
},
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
user_id = self._get_user_id(r.result)
@@ -470,7 +470,7 @@ class CoreApiTests(object):
'user_id': user_id
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
self.assertEqual(CONF.member_role_name, self._get_role_name(r.result))
# Create a new tenant
@@ -485,7 +485,7 @@ class CoreApiTests(object):
},
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
project_id = self._get_project_id(r.result)
@@ -501,7 +501,7 @@ class CoreApiTests(object):
},
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
# 'member_role' should be in new_tenant
r = self.admin_request(
@@ -510,7 +510,7 @@ class CoreApiTests(object):
'user_id': user_id
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
self.assertEqual('_member_', self._get_role_name(r.result))
# 'member_role' should not be in tenant_bar any more
@@ -520,7 +520,7 @@ class CoreApiTests(object):
'user_id': user_id
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
self.assertNoRoles(r.result)
def test_update_user_with_invalid_tenant(self):
@@ -539,7 +539,7 @@ class CoreApiTests(object):
},
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
user_id = self._get_user_id(r.result)
# Update user with an invalid tenant
@@ -571,7 +571,7 @@ class CoreApiTests(object):
},
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
user_id = self._get_user_id(r.result)
# Update user with an invalid tenant
@@ -604,7 +604,7 @@ class CoreApiTests(object):
},
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
user_id = self._get_user_id(r.result)
@@ -615,7 +615,7 @@ class CoreApiTests(object):
'user_id': user_id
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
self.assertEqual(CONF.member_role_name, self._get_role_name(r.result))
# Update user's tenant with old tenant id
@@ -630,7 +630,7 @@ class CoreApiTests(object):
},
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
# 'member_role' should still be in tenant_bar
r = self.admin_request(
@@ -639,7 +639,7 @@ class CoreApiTests(object):
'user_id': user_id
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
self.assertEqual('_member_', self._get_role_name(r.result))
def test_authenticating_a_user_with_no_password(self):
@@ -721,7 +721,7 @@ class LegacyV2UsernameTests(object):
path='/v2.0/users',
token=token,
body=body,
- expected_status=http_client.OK)
+ expected_status=200)
def test_create_with_extra_username(self):
"""The response for creating a user will contain the extra fields."""
@@ -772,7 +772,7 @@ class LegacyV2UsernameTests(object):
'enabled': enabled,
},
},
- expected_status=http_client.OK)
+ expected_status=200)
self.assertValidUserResponse(r)
@@ -802,7 +802,7 @@ class LegacyV2UsernameTests(object):
'enabled': enabled,
},
},
- expected_status=http_client.OK)
+ expected_status=200)
self.assertValidUserResponse(r)
@@ -881,7 +881,7 @@ class LegacyV2UsernameTests(object):
'enabled': enabled,
},
},
- expected_status=http_client.OK)
+ expected_status=200)
self.assertValidUserResponse(r)
@@ -911,7 +911,7 @@ class LegacyV2UsernameTests(object):
'enabled': enabled,
},
},
- expected_status=http_client.OK)
+ expected_status=200)
self.assertValidUserResponse(r)
@@ -931,7 +931,7 @@ class LegacyV2UsernameTests(object):
'enabled': True,
},
},
- expected_status=http_client.OK)
+ expected_status=200)
self.assertValidUserResponse(r)
@@ -956,7 +956,7 @@ class LegacyV2UsernameTests(object):
'enabled': enabled,
},
},
- expected_status=http_client.OK)
+ expected_status=200)
self.assertValidUserResponse(r)
@@ -1200,7 +1200,7 @@ class V2TestCase(RestfulTestCase, CoreApiTests, LegacyV2UsernameTests):
method='GET',
path='/v2.0/tokens/revoked',
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
self.assertValidRevocationListResponse(r)
def assertValidRevocationListResponse(self, response):
@@ -1231,7 +1231,7 @@ class V2TestCase(RestfulTestCase, CoreApiTests, LegacyV2UsernameTests):
method='GET',
path='/v2.0/tokens/revoked',
token=token1,
- expected_status=http_client.OK)
+ expected_status=200)
signed_text = r.result['signed']
data_json = cms.cms_verify(signed_text, CONF.signing.certfile,
@@ -1333,7 +1333,7 @@ class V2TestCase(RestfulTestCase, CoreApiTests, LegacyV2UsernameTests):
},
},
},
- expected_status=http_client.OK)
+ expected_status=200)
# ensure password doesn't leak
user_id = r.result['user']['id']
@@ -1341,7 +1341,7 @@ class V2TestCase(RestfulTestCase, CoreApiTests, LegacyV2UsernameTests):
method='GET',
path='/v2.0/users/%s' % user_id,
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
self.assertNotIn('OS-KSADM:password', r.result['user'])
def test_updating_a_user_with_an_OSKSADM_password(self):
@@ -1360,7 +1360,7 @@ class V2TestCase(RestfulTestCase, CoreApiTests, LegacyV2UsernameTests):
},
},
token=token,
- expected_status=http_client.OK)
+ expected_status=200)
# successfully authenticate
self.public_request(
@@ -1374,7 +1374,7 @@ class V2TestCase(RestfulTestCase, CoreApiTests, LegacyV2UsernameTests):
},
},
},
- expected_status=http_client.OK)
+ expected_status=200)
class RevokeApiTestCase(V2TestCase):
@@ -1436,7 +1436,7 @@ class TestFernetTokenProviderV2(RestfulTestCase):
method='GET',
path=path,
token=admin_token,
- expected_status=http_client.OK)
+ expected_status=200)
def test_authenticate_scoped_token(self):
project_ref = self.new_project_ref()
@@ -1466,7 +1466,7 @@ class TestFernetTokenProviderV2(RestfulTestCase):
method='GET',
path=path,
token=admin_token,
- expected_status=http_client.OK)
+ expected_status=200)
def test_token_authentication_and_validation(self):
"""Test token authentication for Fernet token provider.
@@ -1491,7 +1491,7 @@ class TestFernetTokenProviderV2(RestfulTestCase):
}
}
},
- expected_status=http_client.OK)
+ expected_status=200)
token_id = self._get_token_id(r)
path = ('/v2.0/tokens/%s?belongsTo=%s' % (token_id, project_ref['id']))
@@ -1500,7 +1500,7 @@ class TestFernetTokenProviderV2(RestfulTestCase):
method='GET',
path=path,
token=CONF.admin_token,
- expected_status=http_client.OK)
+ expected_status=200)
def test_rescoped_tokens_maintain_original_expiration(self):
project_ref = self.new_project_ref()
@@ -1522,7 +1522,7 @@ class TestFernetTokenProviderV2(RestfulTestCase):
},
# NOTE(lbragstad): This test may need to be refactored if Keystone
# decides to disallow rescoping using a scoped token.
- expected_status=http_client.OK)
+ expected_status=200)
original_token = resp.result['access']['token']['id']
original_expiration = resp.result['access']['token']['expires']
@@ -1537,7 +1537,7 @@ class TestFernetTokenProviderV2(RestfulTestCase):
}
}
},
- expected_status=http_client.OK)
+ expected_status=200)
rescoped_token = resp.result['access']['token']['id']
rescoped_expiration = resp.result['access']['token']['expires']
self.assertNotEqual(original_token, rescoped_token)
diff --git a/keystone-moon/keystone/tests/unit/test_v2_keystoneclient.py b/keystone-moon/keystone/tests/unit/test_v2_keystoneclient.py
index 8d6d9eb7..2a3fad86 100644
--- a/keystone-moon/keystone/tests/unit/test_v2_keystoneclient.py
+++ b/keystone-moon/keystone/tests/unit/test_v2_keystoneclient.py
@@ -1137,7 +1137,7 @@ class ClientDrivenTestCase(unit.TestCase):
credentials, signature = self._generate_default_user_ec2_credentials()
credentials['signature'] = signature
resp, token = self._send_ec2_auth_request(credentials)
- self.assertEqual(http_client.OK, resp.status_code)
+ self.assertEqual(200, resp.status_code)
self.assertIn('access', token)
def test_ec2_auth_success_trust(self):
@@ -1169,7 +1169,7 @@ class ClientDrivenTestCase(unit.TestCase):
cred.access, cred.secret)
credentials['signature'] = signature
resp, token = self._send_ec2_auth_request(credentials)
- self.assertEqual(http_client.OK, resp.status_code)
+ self.assertEqual(200, resp.status_code)
self.assertEqual(trust_id, token['access']['trust']['id'])
# TODO(shardy) we really want to check the roles and trustee
# but because of where the stubbing happens we don't seem to
diff --git a/keystone-moon/keystone/tests/unit/test_v3.py b/keystone-moon/keystone/tests/unit/test_v3.py
index 7afe6ad8..32c5e295 100644
--- a/keystone-moon/keystone/tests/unit/test_v3.py
+++ b/keystone-moon/keystone/tests/unit/test_v3.py
@@ -18,7 +18,6 @@ import uuid
from oslo_config import cfg
from oslo_serialization import jsonutils
from oslo_utils import timeutils
-from six.moves import http_client
from testtools import matchers
from keystone import auth
@@ -412,7 +411,7 @@ class RestfulTestCase(unit.SQLDriverOverrides, rest.RestfulTestCase,
r = self.v3_authenticate_token(auth)
return r.headers.get('X-Subject-Token')
- def v3_authenticate_token(self, auth, expected_status=http_client.CREATED):
+ def v3_authenticate_token(self, auth, expected_status=201):
return self.admin_request(method='POST',
path='/v3/auth/tokens',
body=auth,
@@ -441,31 +440,42 @@ class RestfulTestCase(unit.SQLDriverOverrides, rest.RestfulTestCase,
return self.admin_request(path=path, token=token, **kwargs)
- def get(self, path, expected_status=http_client.OK, **kwargs):
- return self.v3_request(path, method='GET',
- expected_status=expected_status, **kwargs)
+ def get(self, path, **kwargs):
+ r = self.v3_request(method='GET', path=path, **kwargs)
+ if 'expected_status' not in kwargs:
+ self.assertResponseStatus(r, 200)
+ return r
- def head(self, path, expected_status=http_client.NO_CONTENT, **kwargs):
- r = self.v3_request(path, method='HEAD',
- expected_status=expected_status, **kwargs)
+ def head(self, path, **kwargs):
+ r = self.v3_request(method='HEAD', path=path, **kwargs)
+ if 'expected_status' not in kwargs:
+ self.assertResponseStatus(r, 204)
self.assertEqual('', r.body)
return r
- def post(self, path, expected_status=http_client.CREATED, **kwargs):
- return self.v3_request(path, method='POST',
- expected_status=expected_status, **kwargs)
+ def post(self, path, **kwargs):
+ r = self.v3_request(method='POST', path=path, **kwargs)
+ if 'expected_status' not in kwargs:
+ self.assertResponseStatus(r, 201)
+ return r
- def put(self, path, expected_status=http_client.NO_CONTENT, **kwargs):
- return self.v3_request(path, method='PUT',
- expected_status=expected_status, **kwargs)
+ def put(self, path, **kwargs):
+ r = self.v3_request(method='PUT', path=path, **kwargs)
+ if 'expected_status' not in kwargs:
+ self.assertResponseStatus(r, 204)
+ return r
- def patch(self, path, expected_status=http_client.OK, **kwargs):
- return self.v3_request(path, method='PATCH',
- expected_status=expected_status, **kwargs)
+ def patch(self, path, **kwargs):
+ r = self.v3_request(method='PATCH', path=path, **kwargs)
+ if 'expected_status' not in kwargs:
+ self.assertResponseStatus(r, 200)
+ return r
- def delete(self, path, expected_status=http_client.NO_CONTENT, **kwargs):
- return self.v3_request(path, method='DELETE',
- expected_status=expected_status, **kwargs)
+ def delete(self, path, **kwargs):
+ r = self.v3_request(method='DELETE', path=path, **kwargs)
+ if 'expected_status' not in kwargs:
+ self.assertResponseStatus(r, 204)
+ return r
def assertValidErrorResponse(self, r):
resp = r.result
diff --git a/keystone-moon/keystone/tests/unit/test_v3_assignment.py b/keystone-moon/keystone/tests/unit/test_v3_assignment.py
index f22e9f2b..6b15b1c3 100644
--- a/keystone-moon/keystone/tests/unit/test_v3_assignment.py
+++ b/keystone-moon/keystone/tests/unit/test_v3_assignment.py
@@ -363,13 +363,14 @@ class AssignmentTestCase(test_v3.RestfulTestCase,
# validates the returned token and it should be valid.
self.head('/auth/tokens',
headers={'x-subject-token': subject_token},
- expected_status=http_client.OK)
+ expected_status=200)
# now disable the domain
self.domain['enabled'] = False
url = "/domains/%(domain_id)s" % {'domain_id': self.domain['id']}
self.patch(url,
- body={'domain': {'enabled': False}})
+ body={'domain': {'enabled': False}},
+ expected_status=200)
# validates the same token again and it should be 'not found'
# as the domain has already been disabled.
@@ -511,7 +512,7 @@ class AssignmentTestCase(test_v3.RestfulTestCase,
ref = self.new_project_ref(domain_id=self.domain_id, is_domain=True)
self.post('/projects',
body={'project': ref},
- expected_status=http_client.NOT_IMPLEMENTED)
+ expected_status=501)
@utils.wip('waiting for projects acting as domains implementation')
def test_create_project_without_parent_id_and_without_domain_id(self):
@@ -1289,9 +1290,9 @@ class AssignmentTestCase(test_v3.RestfulTestCase,
member_url = ('%(collection_url)s/%(role_id)s' % {
'collection_url': collection_url,
'role_id': self.role_id})
- self.put(member_url)
+ self.put(member_url, expected_status=204)
# Check the user has the role assigned
- self.head(member_url)
+ self.head(member_url, expected_status=204)
return member_url, user_ref
def test_delete_user_before_removing_role_assignment_succeeds(self):
@@ -1300,7 +1301,7 @@ class AssignmentTestCase(test_v3.RestfulTestCase,
# Delete the user from identity backend
self.identity_api.driver.delete_user(user['id'])
# Clean up the role assignment
- self.delete(member_url)
+ self.delete(member_url, expected_status=204)
# Make sure the role is gone
self.head(member_url, expected_status=http_client.NOT_FOUND)
@@ -1343,7 +1344,7 @@ class AssignmentTestCase(test_v3.RestfulTestCase,
# validates the returned token; it should be valid.
self.head('/auth/tokens',
headers={'x-subject-token': token},
- expected_status=http_client.OK)
+ expected_status=200)
# revokes the grant from group on project.
self.assignment_api.delete_grant(role_id=self.role['id'],
@@ -1868,7 +1869,7 @@ class RoleAssignmentBaseTestCase(test_v3.RestfulTestCase,
self.default_user_id = self.user_ids[0]
self.default_group_id = self.group_ids[0]
- def get_role_assignments(self, expected_status=http_client.OK, **filters):
+ def get_role_assignments(self, expected_status=200, **filters):
"""Returns the result from querying role assignment API + queried URL.
Calls GET /v3/role_assignments?<params> and returns its result, where
diff --git a/keystone-moon/keystone/tests/unit/test_v3_auth.py b/keystone-moon/keystone/tests/unit/test_v3_auth.py
index 496a75c0..d53a85df 100644
--- a/keystone-moon/keystone/tests/unit/test_v3_auth.py
+++ b/keystone-moon/keystone/tests/unit/test_v3_auth.py
@@ -384,8 +384,9 @@ class TokenAPITests(object):
v2_token = r.result['access']['token']['id']
# Delete the v2 token using v3.
- self.delete(
+ resp = self.delete(
'/auth/tokens', headers={'X-Subject-Token': v2_token})
+ self.assertEqual(resp.status_code, 204)
# Attempting to use the deleted token on v2 should fail.
self.admin_request(
@@ -405,8 +406,7 @@ class TokenAPITests(object):
self.assertEqual(expires, r.result['token']['expires_at'])
def test_check_token(self):
- self.head('/auth/tokens', headers=self.headers,
- expected_status=http_client.OK)
+ self.head('/auth/tokens', headers=self.headers, expected_status=200)
def test_validate_token(self):
r = self.get('/auth/tokens', headers=self.headers)
@@ -655,13 +655,11 @@ class TestTokenRevokeSelfAndAdmin(test_v3.RestfulTestCase):
password=self.userAdminA['password'],
domain_name=self.domainA['name']))
- self.head('/auth/tokens', headers=headers,
- expected_status=http_client.OK,
+ self.head('/auth/tokens', headers=headers, expected_status=200,
token=adminA_token)
- self.head('/auth/tokens', headers=headers,
- expected_status=http_client.OK,
+ self.head('/auth/tokens', headers=headers, expected_status=200,
token=user_token)
- self.delete('/auth/tokens', headers=headers,
+ self.delete('/auth/tokens', headers=headers, expected_status=204,
token=user_token)
# invalid X-Auth-Token and invalid X-Subject-Token
self.head('/auth/tokens', headers=headers,
@@ -695,13 +693,11 @@ class TestTokenRevokeSelfAndAdmin(test_v3.RestfulTestCase):
password=self.userAdminA['password'],
domain_name=self.domainA['name']))
- self.head('/auth/tokens', headers=headers,
- expected_status=http_client.OK,
+ self.head('/auth/tokens', headers=headers, expected_status=200,
token=adminA_token)
- self.head('/auth/tokens', headers=headers,
- expected_status=http_client.OK,
+ self.head('/auth/tokens', headers=headers, expected_status=200,
token=user_token)
- self.delete('/auth/tokens', headers=headers,
+ self.delete('/auth/tokens', headers=headers, expected_status=204,
token=adminA_token)
# invalid X-Auth-Token and invalid X-Subject-Token
self.head('/auth/tokens', headers=headers,
@@ -868,10 +864,10 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# confirm both tokens are valid
self.head('/auth/tokens',
headers={'X-Subject-Token': unscoped_token},
- expected_status=http_client.OK)
+ expected_status=200)
self.head('/auth/tokens',
headers={'X-Subject-Token': scoped_token},
- expected_status=http_client.OK)
+ expected_status=200)
# create a new role
role = self.new_role_ref()
@@ -887,10 +883,10 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# both tokens should remain valid
self.head('/auth/tokens',
headers={'X-Subject-Token': unscoped_token},
- expected_status=http_client.OK)
+ expected_status=200)
self.head('/auth/tokens',
headers={'X-Subject-Token': scoped_token},
- expected_status=http_client.OK)
+ expected_status=200)
def test_deleting_user_grant_revokes_token(self):
"""Test deleting a user grant revokes token.
@@ -910,7 +906,7 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# Confirm token is valid
self.head('/auth/tokens',
headers={'X-Subject-Token': token},
- expected_status=http_client.OK)
+ expected_status=200)
# Delete the grant, which should invalidate the token
grant_url = (
'/projects/%(project_id)s/users/%(user_id)s/'
@@ -1012,19 +1008,19 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# Confirm tokens are valid
self.head('/auth/tokens',
headers={'X-Subject-Token': tokenA},
- expected_status=http_client.OK)
+ expected_status=200)
self.head('/auth/tokens',
headers={'X-Subject-Token': tokenB},
- expected_status=http_client.OK)
+ expected_status=200)
self.head('/auth/tokens',
headers={'X-Subject-Token': tokenC},
- expected_status=http_client.OK)
+ expected_status=200)
self.head('/auth/tokens',
headers={'X-Subject-Token': tokenD},
- expected_status=http_client.OK)
+ expected_status=200)
self.head('/auth/tokens',
headers={'X-Subject-Token': tokenE},
- expected_status=http_client.OK)
+ expected_status=200)
# Delete the role, which should invalidate the tokens
role_url = '/roles/%s' % self.role1['id']
@@ -1047,7 +1043,7 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# ...but the one using role2 is still valid
self.head('/auth/tokens',
headers={'X-Subject-Token': tokenC},
- expected_status=http_client.OK)
+ expected_status=200)
def test_domain_user_role_assignment_maintains_token(self):
"""Test user-domain role assignment maintains existing token.
@@ -1067,7 +1063,7 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# Confirm token is valid
self.head('/auth/tokens',
headers={'X-Subject-Token': token},
- expected_status=http_client.OK)
+ expected_status=200)
# Assign a role, which should not affect the token
grant_url = (
'/domains/%(domain_id)s/users/%(user_id)s/'
@@ -1078,7 +1074,7 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
self.put(grant_url)
self.head('/auth/tokens',
headers={'X-Subject-Token': token},
- expected_status=http_client.OK)
+ expected_status=200)
def test_disabling_project_revokes_token(self):
token = self.get_requested_token(
@@ -1090,7 +1086,7 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# confirm token is valid
self.head('/auth/tokens',
headers={'X-Subject-Token': token},
- expected_status=http_client.OK)
+ expected_status=200)
# disable the project, which should invalidate the token
self.patch(
@@ -1118,7 +1114,7 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# confirm token is valid
self.head('/auth/tokens',
headers={'X-Subject-Token': token},
- expected_status=http_client.OK)
+ expected_status=200)
# delete the project, which should invalidate the token
self.delete(
@@ -1167,13 +1163,13 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# Confirm tokens are valid
self.head('/auth/tokens',
headers={'X-Subject-Token': token1},
- expected_status=http_client.OK)
+ expected_status=200)
self.head('/auth/tokens',
headers={'X-Subject-Token': token2},
- expected_status=http_client.OK)
+ expected_status=200)
self.head('/auth/tokens',
headers={'X-Subject-Token': token3},
- expected_status=http_client.OK)
+ expected_status=200)
# Delete the group grant, which should invalidate the
# tokens for user1 and user2
grant_url = (
@@ -1213,7 +1209,7 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# Confirm token is valid
self.head('/auth/tokens',
headers={'X-Subject-Token': token},
- expected_status=http_client.OK)
+ expected_status=200)
# Delete the grant, which should invalidate the token
grant_url = (
'/domains/%(domain_id)s/groups/%(group_id)s/'
@@ -1224,7 +1220,7 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
self.put(grant_url)
self.head('/auth/tokens',
headers={'X-Subject-Token': token},
- expected_status=http_client.OK)
+ expected_status=200)
def test_group_membership_changes_revokes_token(self):
"""Test add/removal to/from group revokes token.
@@ -1254,10 +1250,10 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# Confirm tokens are valid
self.head('/auth/tokens',
headers={'X-Subject-Token': token1},
- expected_status=http_client.OK)
+ expected_status=200)
self.head('/auth/tokens',
headers={'X-Subject-Token': token2},
- expected_status=http_client.OK)
+ expected_status=200)
# Remove user1 from group1, which should invalidate
# the token
self.delete('/groups/%(group_id)s/users/%(user_id)s' % {
@@ -1269,14 +1265,14 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# But user2's token should still be valid
self.head('/auth/tokens',
headers={'X-Subject-Token': token2},
- expected_status=http_client.OK)
+ expected_status=200)
# Adding user2 to a group should not invalidate token
self.put('/groups/%(group_id)s/users/%(user_id)s' % {
'group_id': self.group2['id'],
'user_id': self.user2['id']})
self.head('/auth/tokens',
headers={'X-Subject-Token': token2},
- expected_status=http_client.OK)
+ expected_status=200)
def test_removing_role_assignment_does_not_affect_other_users(self):
"""Revoking a role from one user should not affect other users."""
@@ -1320,7 +1316,7 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# authorization for the second user should still succeed
self.head('/auth/tokens',
headers={'X-Subject-Token': user3_token},
- expected_status=http_client.OK)
+ expected_status=200)
self.v3_authenticate_token(
self.build_authentication_request(
user_id=self.user3['id'],
@@ -1370,7 +1366,8 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
token = self.get_v2_token()
self.delete('/auth/tokens',
- headers={'X-Subject-Token': token})
+ headers={'X-Subject-Token': token},
+ expected_status=204)
self.head('/auth/tokens',
headers={'X-Subject-Token': token},
@@ -1400,7 +1397,8 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# revoke the project-scoped token.
self.delete('/auth/tokens',
- headers={'X-Subject-Token': project_scoped_token})
+ headers={'X-Subject-Token': project_scoped_token},
+ expected_status=204)
# The project-scoped token is invalidated.
self.head('/auth/tokens',
@@ -1410,16 +1408,17 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# The unscoped token should still be valid.
self.head('/auth/tokens',
headers={'X-Subject-Token': unscoped_token},
- expected_status=http_client.OK)
+ expected_status=200)
# The domain-scoped token should still be valid.
self.head('/auth/tokens',
headers={'X-Subject-Token': domain_scoped_token},
- expected_status=http_client.OK)
+ expected_status=200)
# revoke the domain-scoped token.
self.delete('/auth/tokens',
- headers={'X-Subject-Token': domain_scoped_token})
+ headers={'X-Subject-Token': domain_scoped_token},
+ expected_status=204)
# The domain-scoped token is invalid.
self.head('/auth/tokens',
@@ -1429,7 +1428,7 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# The unscoped token should still be valid.
self.head('/auth/tokens',
headers={'X-Subject-Token': unscoped_token},
- expected_status=http_client.OK)
+ expected_status=200)
def test_revoke_token_from_token_v2(self):
# Test that a scoped token can be requested from an unscoped token,
@@ -1447,7 +1446,8 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# revoke the project-scoped token.
self.delete('/auth/tokens',
- headers={'X-Subject-Token': project_scoped_token})
+ headers={'X-Subject-Token': project_scoped_token},
+ expected_status=204)
# The project-scoped token is invalidated.
self.head('/auth/tokens',
@@ -1457,7 +1457,7 @@ class TestTokenRevokeById(test_v3.RestfulTestCase):
# The unscoped token should still be valid.
self.head('/auth/tokens',
headers={'X-Subject-Token': unscoped_token},
- expected_status=http_client.OK)
+ expected_status=200)
class TestTokenRevokeByAssignment(TestTokenRevokeById):
@@ -1501,7 +1501,7 @@ class TestTokenRevokeByAssignment(TestTokenRevokeById):
# authorization for the projectA should still succeed
self.head('/auth/tokens',
headers={'X-Subject-Token': other_project_token},
- expected_status=http_client.OK)
+ expected_status=200)
# while token for the projectB should not
self.head('/auth/tokens',
headers={'X-Subject-Token': project_token},
@@ -1563,24 +1563,27 @@ class TestTokenRevokeApi(TestTokenRevokeById):
def test_revoke_token(self):
scoped_token = self.get_scoped_token()
headers = {'X-Subject-Token': scoped_token}
- response = self.get('/auth/tokens', headers=headers).json_body['token']
+ response = self.get('/auth/tokens', headers=headers,
+ expected_status=200).json_body['token']
- self.delete('/auth/tokens', headers=headers)
+ self.delete('/auth/tokens', headers=headers, expected_status=204)
self.head('/auth/tokens', headers=headers,
expected_status=http_client.NOT_FOUND)
- events_response = self.get('/OS-REVOKE/events').json_body
+ events_response = self.get('/OS-REVOKE/events',
+ expected_status=200).json_body
self.assertValidRevokedTokenResponse(events_response,
audit_id=response['audit_ids'][0])
def test_revoke_v2_token(self):
token = self.get_v2_token()
headers = {'X-Subject-Token': token}
- response = self.get('/auth/tokens',
- headers=headers).json_body['token']
- self.delete('/auth/tokens', headers=headers)
+ response = self.get('/auth/tokens', headers=headers,
+ expected_status=200).json_body['token']
+ self.delete('/auth/tokens', headers=headers, expected_status=204)
self.head('/auth/tokens', headers=headers,
expected_status=http_client.NOT_FOUND)
- events_response = self.get('/OS-REVOKE/events').json_body
+ events_response = self.get('/OS-REVOKE/events',
+ expected_status=200).json_body
self.assertValidRevokedTokenResponse(
events_response,
@@ -1592,24 +1595,28 @@ class TestTokenRevokeApi(TestTokenRevokeById):
def test_list_delete_project_shows_in_event_list(self):
self.role_data_fixtures()
- events = self.get('/OS-REVOKE/events').json_body['events']
+ events = self.get('/OS-REVOKE/events',
+ expected_status=200).json_body['events']
self.assertEqual([], events)
self.delete(
'/projects/%(project_id)s' % {'project_id': self.projectA['id']})
- events_response = self.get('/OS-REVOKE/events').json_body
+ events_response = self.get('/OS-REVOKE/events',
+ expected_status=200).json_body
self.assertValidDeletedProjectResponse(events_response,
self.projectA['id'])
def test_disable_domain_shows_in_event_list(self):
- events = self.get('/OS-REVOKE/events').json_body['events']
+ events = self.get('/OS-REVOKE/events',
+ expected_status=200).json_body['events']
self.assertEqual([], events)
disable_body = {'domain': {'enabled': False}}
self.patch(
'/domains/%(project_id)s' % {'project_id': self.domainA['id']},
body=disable_body)
- events = self.get('/OS-REVOKE/events').json_body
+ events = self.get('/OS-REVOKE/events',
+ expected_status=200).json_body
self.assertDomainInList(events, self.domainA['id'])
@@ -1639,7 +1646,8 @@ class TestTokenRevokeApi(TestTokenRevokeById):
def test_list_delete_token_shows_in_event_list(self):
self.role_data_fixtures()
- events = self.get('/OS-REVOKE/events').json_body['events']
+ events = self.get('/OS-REVOKE/events',
+ expected_status=200).json_body['events']
self.assertEqual([], events)
scoped_token = self.get_scoped_token()
@@ -1653,17 +1661,15 @@ class TestTokenRevokeApi(TestTokenRevokeById):
response.json_body['token']
headers3 = {'X-Subject-Token': response.headers['X-Subject-Token']}
- self.head('/auth/tokens', headers=headers,
- expected_status=http_client.OK)
- self.head('/auth/tokens', headers=headers2,
- expected_status=http_client.OK)
- self.head('/auth/tokens', headers=headers3,
- expected_status=http_client.OK)
+ self.head('/auth/tokens', headers=headers, expected_status=200)
+ self.head('/auth/tokens', headers=headers2, expected_status=200)
+ self.head('/auth/tokens', headers=headers3, expected_status=200)
- self.delete('/auth/tokens', headers=headers)
+ self.delete('/auth/tokens', headers=headers, expected_status=204)
# NOTE(ayoung): not deleting token3, as it should be deleted
# by previous
- events_response = self.get('/OS-REVOKE/events').json_body
+ events_response = self.get('/OS-REVOKE/events',
+ expected_status=200).json_body
events = events_response['events']
self.assertEqual(1, len(events))
self.assertEventDataInList(
@@ -1671,32 +1677,32 @@ class TestTokenRevokeApi(TestTokenRevokeById):
audit_id=token2['audit_ids'][1])
self.head('/auth/tokens', headers=headers,
expected_status=http_client.NOT_FOUND)
- self.head('/auth/tokens', headers=headers2,
- expected_status=http_client.OK)
- self.head('/auth/tokens', headers=headers3,
- expected_status=http_client.OK)
+ self.head('/auth/tokens', headers=headers2, expected_status=200)
+ self.head('/auth/tokens', headers=headers3, expected_status=200)
def test_list_with_filter(self):
self.role_data_fixtures()
- events = self.get('/OS-REVOKE/events').json_body['events']
+ events = self.get('/OS-REVOKE/events',
+ expected_status=200).json_body['events']
self.assertEqual(0, len(events))
scoped_token = self.get_scoped_token()
headers = {'X-Subject-Token': scoped_token}
auth = self.build_authentication_request(token=scoped_token)
headers2 = {'X-Subject-Token': self.get_requested_token(auth)}
- self.delete('/auth/tokens', headers=headers)
- self.delete('/auth/tokens', headers=headers2)
+ self.delete('/auth/tokens', headers=headers, expected_status=204)
+ self.delete('/auth/tokens', headers=headers2, expected_status=204)
- events = self.get('/OS-REVOKE/events').json_body['events']
+ events = self.get('/OS-REVOKE/events',
+ expected_status=200).json_body['events']
self.assertEqual(2, len(events))
future = utils.isotime(timeutils.utcnow() +
datetime.timedelta(seconds=1000))
- events = self.get('/OS-REVOKE/events?since=%s' % (future)
- ).json_body['events']
+ events = self.get('/OS-REVOKE/events?since=%s' % (future),
+ expected_status=200).json_body['events']
self.assertEqual(0, len(events))
@@ -3106,7 +3112,8 @@ class TestTrustChain(test_v3.RestfulTestCase):
def test_delete_trust_cascade(self):
self.assert_user_authenticate(self.user_chain[0])
self.delete('/OS-TRUST/trusts/%(trust_id)s' % {
- 'trust_id': self.trust_chain[0]['id']})
+ 'trust_id': self.trust_chain[0]['id']},
+ expected_status=204)
headers = {'X-Subject-Token': self.last_token}
self.head('/auth/tokens', headers=headers,
@@ -3116,10 +3123,12 @@ class TestTrustChain(test_v3.RestfulTestCase):
def test_delete_broken_chain(self):
self.assert_user_authenticate(self.user_chain[0])
self.delete('/OS-TRUST/trusts/%(trust_id)s' % {
- 'trust_id': self.trust_chain[1]['id']})
+ 'trust_id': self.trust_chain[1]['id']},
+ expected_status=204)
self.delete('/OS-TRUST/trusts/%(trust_id)s' % {
- 'trust_id': self.trust_chain[0]['id']})
+ 'trust_id': self.trust_chain[0]['id']},
+ expected_status=204)
def test_trustor_roles_revoked(self):
self.assert_user_authenticate(self.user_chain[0])
@@ -3214,7 +3223,8 @@ class TestTrustAuth(test_v3.RestfulTestCase):
# make sure the trust exists
trust = self.assertValidTrustResponse(r, ref)
r = self.get(
- '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']})
+ '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']},
+ expected_status=200)
# get a token for the trustee
auth_data = self.build_authentication_request(
user_id=self.trustee_user['id'],
@@ -3232,7 +3242,8 @@ class TestTrustAuth(test_v3.RestfulTestCase):
trust = self._initialize_test_consume_trust(2)
# check decremented value
r = self.get(
- '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']})
+ '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']},
+ expected_status=200)
trust = r.result.get('trust')
self.assertIsNotNone(trust)
self.assertEqual(1, trust['remaining_uses'])
@@ -3310,7 +3321,8 @@ class TestTrustAuth(test_v3.RestfulTestCase):
trust = self.assertValidTrustResponse(r, ref)
r = self.get(
- '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']})
+ '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']},
+ expected_status=200)
auth_data = self.build_authentication_request(
user_id=self.trustee_user['id'],
password=self.trustee_user['password'])
@@ -3321,7 +3333,8 @@ class TestTrustAuth(test_v3.RestfulTestCase):
trust_id=trust['id'])
r = self.v3_authenticate_token(auth_data)
r = self.get(
- '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']})
+ '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']},
+ expected_status=200)
trust = r.result.get('trust')
self.assertIsNone(trust['remaining_uses'])
@@ -3335,27 +3348,30 @@ class TestTrustAuth(test_v3.RestfulTestCase):
trust = self.assertValidTrustResponse(r, ref)
r = self.get(
- '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']})
+ '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']},
+ expected_status=200)
self.assertValidTrustResponse(r, ref)
# validate roles on the trust
r = self.get(
'/OS-TRUST/trusts/%(trust_id)s/roles' % {
- 'trust_id': trust['id']})
+ 'trust_id': trust['id']},
+ expected_status=200)
roles = self.assertValidRoleListResponse(r, self.role)
self.assertIn(self.role['id'], [x['id'] for x in roles])
self.head(
'/OS-TRUST/trusts/%(trust_id)s/roles/%(role_id)s' % {
'trust_id': trust['id'],
'role_id': self.role['id']},
- expected_status=http_client.OK)
+ expected_status=200)
r = self.get(
'/OS-TRUST/trusts/%(trust_id)s/roles/%(role_id)s' % {
'trust_id': trust['id'],
- 'role_id': self.role['id']})
+ 'role_id': self.role['id']},
+ expected_status=200)
self.assertValidRoleResponse(r, self.role)
- r = self.get('/OS-TRUST/trusts')
+ r = self.get('/OS-TRUST/trusts', expected_status=200)
self.assertValidTrustListResponse(r, trust)
# trusts are immutable
@@ -3365,7 +3381,8 @@ class TestTrustAuth(test_v3.RestfulTestCase):
expected_status=http_client.NOT_FOUND)
self.delete(
- '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']})
+ '/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']},
+ expected_status=204)
self.get(
'/OS-TRUST/trusts/%(trust_id)s' % {'trust_id': trust['id']},
@@ -3554,7 +3571,7 @@ class TestTrustAuth(test_v3.RestfulTestCase):
path = '/v2.0/tokens/%s' % (token)
self.admin_request(
path=path, token=CONF.admin_token,
- method='GET', expected_status=http_client.OK)
+ method='GET', expected_status=200)
def test_exercise_trust_scoped_token_without_impersonation(self):
ref = self.new_trust_ref(
@@ -3758,7 +3775,8 @@ class TestTrustAuth(test_v3.RestfulTestCase):
expected_status=http_client.FORBIDDEN)
def assertTrustTokensRevoked(self, trust_id):
- revocation_response = self.get('/OS-REVOKE/events')
+ revocation_response = self.get('/OS-REVOKE/events',
+ expected_status=200)
revocation_events = revocation_response.json_body['events']
found = False
for event in revocation_events:
@@ -3787,7 +3805,8 @@ class TestTrustAuth(test_v3.RestfulTestCase):
r, self.trustee_user)
trust_token = r.headers['X-Subject-Token']
self.delete('/OS-TRUST/trusts/%(trust_id)s' % {
- 'trust_id': trust_id})
+ 'trust_id': trust_id},
+ expected_status=204)
headers = {'X-Subject-Token': trust_token}
self.head('/auth/tokens', headers=headers,
expected_status=http_client.NOT_FOUND)
@@ -3814,7 +3833,7 @@ class TestTrustAuth(test_v3.RestfulTestCase):
user_id=self.trustee_user['id'],
password=self.trustee_user['password'],
trust_id=trust['id'])
- self.v3_authenticate_token(auth_data)
+ self.v3_authenticate_token(auth_data, expected_status=201)
self.disable_user(self.user)
@@ -3842,7 +3861,7 @@ class TestTrustAuth(test_v3.RestfulTestCase):
user_id=self.trustee_user['id'],
password=self.trustee_user['password'],
trust_id=trust['id'])
- self.v3_authenticate_token(auth_data)
+ self.v3_authenticate_token(auth_data, expected_status=201)
self.disable_user(self.trustee_user)
@@ -3867,7 +3886,8 @@ class TestTrustAuth(test_v3.RestfulTestCase):
trust = self.assertValidTrustResponse(r, ref)
self.delete('/OS-TRUST/trusts/%(trust_id)s' % {
- 'trust_id': trust['id']})
+ 'trust_id': trust['id']},
+ expected_status=204)
self.get('/OS-TRUST/trusts/%(trust_id)s' % {
'trust_id': trust['id']},
@@ -3897,19 +3917,19 @@ class TestTrustAuth(test_v3.RestfulTestCase):
r = self.post('/OS-TRUST/trusts', body={'trust': ref})
self.assertValidTrustResponse(r, ref)
- r = self.get('/OS-TRUST/trusts')
+ r = self.get('/OS-TRUST/trusts', expected_status=200)
trusts = r.result['trusts']
self.assertEqual(3, len(trusts))
self.assertValidTrustListResponse(r)
r = self.get('/OS-TRUST/trusts?trustor_user_id=%s' %
- self.user_id)
+ self.user_id, expected_status=200)
trusts = r.result['trusts']
self.assertEqual(3, len(trusts))
self.assertValidTrustListResponse(r)
r = self.get('/OS-TRUST/trusts?trustee_user_id=%s' %
- self.user_id)
+ self.user_id, expected_status=200)
trusts = r.result['trusts']
self.assertEqual(0, len(trusts))
@@ -3935,11 +3955,13 @@ class TestTrustAuth(test_v3.RestfulTestCase):
trust_token = r.headers.get('X-Subject-Token')
self.get('/OS-TRUST/trusts?trustor_user_id=%s' %
- self.user_id, token=trust_token)
+ self.user_id, expected_status=200,
+ token=trust_token)
self.assertValidUserResponse(
self.patch('/users/%s' % self.trustee_user['id'],
- body={'user': {'password': uuid.uuid4().hex}}))
+ body={'user': {'password': uuid.uuid4().hex}},
+ expected_status=200))
self.get('/OS-TRUST/trusts?trustor_user_id=%s' %
self.user_id, expected_status=http_client.UNAUTHORIZED,
@@ -3971,13 +3993,14 @@ class TestTrustAuth(test_v3.RestfulTestCase):
'trust_id': trust['id'],
'role_id': self.role['id']},
auth=auth_data,
- expected_status=http_client.OK)
+ expected_status=200)
r = self.get(
'/OS-TRUST/trusts/%(trust_id)s/roles/%(role_id)s' % {
'trust_id': trust['id'],
'role_id': self.role['id']},
- auth=auth_data)
+ auth=auth_data,
+ expected_status=200)
self.assertValidRoleResponse(r, self.role)
def test_do_not_consume_remaining_uses_when_get_token_fails(self):
@@ -4022,7 +4045,7 @@ class TestAPIProtectionWithoutAuthContextMiddleware(test_v3.RestfulTestCase):
'query_string': {},
'environment': {}}
r = auth_controller.validate_token(context)
- self.assertEqual(http_client.OK, r.status_code)
+ self.assertEqual(200, r.status_code)
class TestAuthContext(unit.TestCase):
@@ -4082,7 +4105,9 @@ class TestAuthSpecificData(test_v3.RestfulTestCase):
def test_get_catalog_project_scoped_token(self):
"""Call ``GET /auth/catalog`` with a project-scoped token."""
- r = self.get('/auth/catalog')
+ r = self.get(
+ '/auth/catalog',
+ expected_status=200)
self.assertValidCatalogResponse(r)
def test_get_catalog_domain_scoped_token(self):
@@ -4116,7 +4141,7 @@ class TestAuthSpecificData(test_v3.RestfulTestCase):
expected_status=http_client.UNAUTHORIZED)
def test_get_projects_project_scoped_token(self):
- r = self.get('/auth/projects')
+ r = self.get('/auth/projects', expected_status=200)
self.assertThat(r.json['projects'], matchers.HasLength(1))
self.assertValidProjectListResponse(r)
@@ -4124,7 +4149,7 @@ class TestAuthSpecificData(test_v3.RestfulTestCase):
self.put(path='/domains/%s/users/%s/roles/%s' % (
self.domain['id'], self.user['id'], self.role['id']))
- r = self.get('/auth/domains')
+ r = self.get('/auth/domains', expected_status=200)
self.assertThat(r.json['domains'], matchers.HasLength(1))
self.assertValidDomainListResponse(r)
@@ -4135,7 +4160,7 @@ class TestFernetTokenProvider(test_v3.RestfulTestCase):
self.useFixture(ksfixtures.KeyRepository(self.config_fixture))
def _make_auth_request(self, auth_data):
- resp = self.post('/auth/tokens', body=auth_data)
+ resp = self.post('/auth/tokens', body=auth_data, expected_status=201)
token = resp.headers.get('X-Subject-Token')
self.assertLess(len(token), 255)
return token
@@ -4167,13 +4192,13 @@ class TestFernetTokenProvider(test_v3.RestfulTestCase):
trust_id=trust['id'])
return self._make_auth_request(auth_data)
- def _validate_token(self, token, expected_status=http_client.OK):
+ def _validate_token(self, token, expected_status=200):
return self.get(
'/auth/tokens',
headers={'X-Subject-Token': token},
expected_status=expected_status)
- def _revoke_token(self, token, expected_status=http_client.NO_CONTENT):
+ def _revoke_token(self, token, expected_status=204):
return self.delete(
'/auth/tokens',
headers={'X-Subject-Token': token},
@@ -4547,8 +4572,7 @@ class TestAuthFernetTokenProvider(TestAuth):
self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
# Bind not current supported by Fernet, see bug 1433311.
- self.v3_authenticate_token(auth_data,
- expected_status=http_client.NOT_IMPLEMENTED)
+ self.v3_authenticate_token(auth_data, expected_status=501)
def test_v2_v3_bind_token_intermix(self):
self.config_fixture.config(group='token', bind='kerberos')
@@ -4563,7 +4587,7 @@ class TestAuthFernetTokenProvider(TestAuth):
self.admin_request(path='/v2.0/tokens',
method='POST',
body=body,
- expected_status=http_client.NOT_IMPLEMENTED)
+ expected_status=501)
def test_auth_with_bind_token(self):
self.config_fixture.config(group='token', bind=['kerberos'])
@@ -4573,5 +4597,4 @@ class TestAuthFernetTokenProvider(TestAuth):
self.admin_app.extra_environ.update({'REMOTE_USER': remote_user,
'AUTH_TYPE': 'Negotiate'})
# Bind not current supported by Fernet, see bug 1433311.
- self.v3_authenticate_token(auth_data,
- expected_status=http_client.NOT_IMPLEMENTED)
+ self.v3_authenticate_token(auth_data, expected_status=501)
diff --git a/keystone-moon/keystone/tests/unit/test_v3_catalog.py b/keystone-moon/keystone/tests/unit/test_v3_catalog.py
index 0d82390d..c536169a 100644
--- a/keystone-moon/keystone/tests/unit/test_v3_catalog.py
+++ b/keystone-moon/keystone/tests/unit/test_v3_catalog.py
@@ -36,7 +36,7 @@ class CatalogTestCase(test_v3.RestfulTestCase):
r = self.put(
'/regions/%s' % region_id,
body={'region': ref},
- expected_status=http_client.CREATED)
+ expected_status=201)
self.assertValidRegionResponse(r, ref)
# Double-check that the region ID was kept as-is and not
# populated with a UUID, as is the case with POST /v3/regions
@@ -49,7 +49,7 @@ class CatalogTestCase(test_v3.RestfulTestCase):
r = self.put(
'/regions/%s' % region_id,
body={'region': ref},
- expected_status=http_client.CREATED)
+ expected_status=201)
self.assertValidRegionResponse(r, ref)
# Double-check that the region ID was kept as-is and not
# populated with a UUID, as is the case with POST /v3/regions
@@ -60,7 +60,7 @@ class CatalogTestCase(test_v3.RestfulTestCase):
ref = dict(description="my region")
self.put(
'/regions/myregion',
- body={'region': ref}, expected_status=http_client.CREATED)
+ body={'region': ref}, expected_status=201)
# Create region again with duplicate id
self.put(
'/regions/myregion',
@@ -86,7 +86,9 @@ class CatalogTestCase(test_v3.RestfulTestCase):
ref = self.new_region_ref()
ref['id'] = ''
- r = self.post('/regions', body={'region': ref})
+ r = self.post(
+ '/regions',
+ body={'region': ref}, expected_status=201)
self.assertValidRegionResponse(r, ref)
self.assertNotEmpty(r.result['region'].get('id'))
@@ -98,7 +100,10 @@ class CatalogTestCase(test_v3.RestfulTestCase):
del ref['id']
# let the service define the ID
- r = self.post('/regions', body={'region': ref})
+ r = self.post(
+ '/regions',
+ body={'region': ref},
+ expected_status=201)
self.assertValidRegionResponse(r, ref)
def test_create_region_without_description(self):
@@ -107,7 +112,10 @@ class CatalogTestCase(test_v3.RestfulTestCase):
del ref['description']
- r = self.post('/regions', body={'region': ref})
+ r = self.post(
+ '/regions',
+ body={'region': ref},
+ expected_status=201)
# Create the description in the reference to compare to since the
# response should now have a description, even though we didn't send
# it with the original reference.
@@ -127,10 +135,16 @@ class CatalogTestCase(test_v3.RestfulTestCase):
ref1['description'] = region_desc
ref2['description'] = region_desc
- resp1 = self.post('/regions', body={'region': ref1})
+ resp1 = self.post(
+ '/regions',
+ body={'region': ref1},
+ expected_status=201)
self.assertValidRegionResponse(resp1, ref1)
- resp2 = self.post('/regions', body={'region': ref2})
+ resp2 = self.post(
+ '/regions',
+ body={'region': ref2},
+ expected_status=201)
self.assertValidRegionResponse(resp2, ref2)
def test_create_regions_without_descriptions(self):
@@ -145,9 +159,15 @@ class CatalogTestCase(test_v3.RestfulTestCase):
del ref1['description']
ref2['description'] = None
- resp1 = self.post('/regions', body={'region': ref1})
+ resp1 = self.post(
+ '/regions',
+ body={'region': ref1},
+ expected_status=201)
- resp2 = self.post('/regions', body={'region': ref2})
+ resp2 = self.post(
+ '/regions',
+ body={'region': ref2},
+ expected_status=201)
# Create the descriptions in the references to compare to since the
# responses should now have descriptions, even though we didn't send
# a description with the original references.
@@ -211,14 +231,16 @@ class CatalogTestCase(test_v3.RestfulTestCase):
"""Call ``PATCH /regions/{region_id}``."""
region_ref = self.new_region_ref()
- resp = self.post('/regions', body={'region': region_ref})
+ resp = self.post('/regions', body={'region': region_ref},
+ expected_status=201)
region_updates = {
# update with something that's not the description
'parent_region_id': self.region_id,
}
resp = self.patch('/regions/%s' % region_ref['id'],
- body={'region': region_updates})
+ body={'region': region_updates},
+ expected_status=200)
# NOTE(dstanek): Keystone should keep the original description.
self.assertEqual(region_ref['description'],
@@ -591,7 +613,7 @@ class CatalogTestCase(test_v3.RestfulTestCase):
ref = self.new_endpoint_ref(service_id=self.service_id)
ref["region"] = uuid.uuid4().hex
ref.pop('region_id')
- self.post('/endpoints', body={'endpoint': ref})
+ self.post('/endpoints', body={'endpoint': ref}, expected_status=201)
# Make sure the region is created
self.get('/regions/%(region_id)s' % {
'region_id': ref["region"]})
@@ -600,7 +622,7 @@ class CatalogTestCase(test_v3.RestfulTestCase):
"""EndpointV3 allows to creates the endpoint without region."""
ref = self.new_endpoint_ref(service_id=self.service_id)
ref.pop('region_id')
- self.post('/endpoints', body={'endpoint': ref})
+ self.post('/endpoints', body={'endpoint': ref}, expected_status=201)
def test_create_endpoint_with_empty_url(self):
"""Call ``POST /endpoints``."""
@@ -756,7 +778,9 @@ class CatalogTestCase(test_v3.RestfulTestCase):
ref = self.new_endpoint_ref(self.service_id)
ref['url'] = valid_url
- self.post('/endpoints', body={'endpoint': ref})
+ self.post('/endpoints',
+ body={'endpoint': ref},
+ expected_status=201)
def test_endpoint_create_with_invalid_url(self):
"""Test the invalid cases: substitutions is not exactly right.
diff --git a/keystone-moon/keystone/tests/unit/test_v3_credential.py b/keystone-moon/keystone/tests/unit/test_v3_credential.py
index cf504b00..dd8cf2dd 100644
--- a/keystone-moon/keystone/tests/unit/test_v3_credential.py
+++ b/keystone-moon/keystone/tests/unit/test_v3_credential.py
@@ -382,7 +382,7 @@ class TestCredentialEc2(CredentialBaseTestCase):
r = self.post(
'/ec2tokens',
body={'ec2Credentials': sig_ref},
- expected_status=http_client.OK)
+ expected_status=200)
self.assertValidTokenResponse(r)
def test_ec2_credential_signature_validate(self):
diff --git a/keystone-moon/keystone/tests/unit/test_v3_domain_config.py b/keystone-moon/keystone/tests/unit/test_v3_domain_config.py
index 3f7af87d..701cd3cf 100644
--- a/keystone-moon/keystone/tests/unit/test_v3_domain_config.py
+++ b/keystone-moon/keystone/tests/unit/test_v3_domain_config.py
@@ -40,7 +40,7 @@ class DomainConfigTestCase(test_v3.RestfulTestCase):
url = '/domains/%(domain_id)s/config' % {
'domain_id': self.domain['id']}
r = self.put(url, body={'config': self.config},
- expected_status=http_client.CREATED)
+ expected_status=201)
res = self.domain_config_api.get_config(self.domain['id'])
self.assertEqual(self.config, r.result['config'])
self.assertEqual(self.config, res)
@@ -50,11 +50,11 @@ class DomainConfigTestCase(test_v3.RestfulTestCase):
self.put('/domains/%(domain_id)s/config' % {
'domain_id': self.domain['id']},
body={'config': self.config},
- expected_status=http_client.CREATED)
+ expected_status=201)
self.put('/domains/%(domain_id)s/config' % {
'domain_id': self.domain['id']},
body={'config': self.config},
- expected_status=http_client.OK)
+ expected_status=200)
def test_delete_config(self):
"""Call ``DELETE /domains{domain_id}/config``."""
@@ -80,7 +80,7 @@ class DomainConfigTestCase(test_v3.RestfulTestCase):
'domain_id': self.domain['id']}
r = self.get(url)
self.assertEqual(self.config, r.result['config'])
- self.head(url, expected_status=http_client.OK)
+ self.head(url, expected_status=200)
def test_get_config_by_group(self):
"""Call ``GET & HEAD /domains{domain_id}/config/{group}``."""
@@ -89,7 +89,7 @@ class DomainConfigTestCase(test_v3.RestfulTestCase):
'domain_id': self.domain['id']}
r = self.get(url)
self.assertEqual({'ldap': self.config['ldap']}, r.result['config'])
- self.head(url, expected_status=http_client.OK)
+ self.head(url, expected_status=200)
def test_get_config_by_option(self):
"""Call ``GET & HEAD /domains{domain_id}/config/{group}/{option}``."""
@@ -99,7 +99,7 @@ class DomainConfigTestCase(test_v3.RestfulTestCase):
r = self.get(url)
self.assertEqual({'url': self.config['ldap']['url']},
r.result['config'])
- self.head(url, expected_status=http_client.OK)
+ self.head(url, expected_status=200)
def test_get_non_existant_config(self):
"""Call ``GET /domains{domain_id}/config when no config defined``."""
diff --git a/keystone-moon/keystone/tests/unit/test_v3_endpoint_policy.py b/keystone-moon/keystone/tests/unit/test_v3_endpoint_policy.py
index b0c8256e..3423d2d8 100644
--- a/keystone-moon/keystone/tests/unit/test_v3_endpoint_policy.py
+++ b/keystone-moon/keystone/tests/unit/test_v3_endpoint_policy.py
@@ -53,14 +53,12 @@ class EndpointPolicyTestCase(test_v3.RestfulTestCase):
url,
expected_status=http_client.NOT_FOUND)
- self.put(url)
+ self.put(url, expected_status=204)
# test that the new resource is accessible.
- self.assert_head_and_get_return_same_response(
- url,
- expected_status=http_client.NO_CONTENT)
+ self.assert_head_and_get_return_same_response(url, expected_status=204)
- self.delete(url)
+ self.delete(url, expected_status=204)
# test that the deleted resource is no longer accessible
self.assert_head_and_get_return_same_response(
@@ -101,16 +99,18 @@ class EndpointPolicyTestCase(test_v3.RestfulTestCase):
self.put('/policies/%(policy_id)s/OS-ENDPOINT-POLICY'
'/endpoints/%(endpoint_id)s' % {
'policy_id': self.policy['id'],
- 'endpoint_id': self.endpoint['id']})
+ 'endpoint_id': self.endpoint['id']},
+ expected_status=204)
self.head('/endpoints/%(endpoint_id)s/OS-ENDPOINT-POLICY'
'/policy' % {
'endpoint_id': self.endpoint['id']},
- expected_status=http_client.OK)
+ expected_status=200)
r = self.get('/endpoints/%(endpoint_id)s/OS-ENDPOINT-POLICY'
'/policy' % {
- 'endpoint_id': self.endpoint['id']})
+ 'endpoint_id': self.endpoint['id']},
+ expected_status=200)
self.assertValidPolicyResponse(r, ref=self.policy)
def test_list_endpoints_for_policy(self):
@@ -119,11 +119,13 @@ class EndpointPolicyTestCase(test_v3.RestfulTestCase):
self.put('/policies/%(policy_id)s/OS-ENDPOINT-POLICY'
'/endpoints/%(endpoint_id)s' % {
'policy_id': self.policy['id'],
- 'endpoint_id': self.endpoint['id']})
+ 'endpoint_id': self.endpoint['id']},
+ expected_status=204)
r = self.get('/policies/%(policy_id)s/OS-ENDPOINT-POLICY'
'/endpoints' % {
- 'policy_id': self.policy['id']})
+ 'policy_id': self.policy['id']},
+ expected_status=200)
self.assertValidEndpointListResponse(r, ref=self.endpoint)
self.assertThat(r.result.get('endpoints'), matchers.HasLength(1))
@@ -133,8 +135,8 @@ class EndpointPolicyTestCase(test_v3.RestfulTestCase):
'policy_id': self.policy['id'],
'endpoint_id': self.endpoint['id']}
- self.put(url)
- self.head(url)
+ self.put(url, expected_status=204)
+ self.head(url, expected_status=204)
self.delete('/endpoints/%(endpoint_id)s' % {
'endpoint_id': self.endpoint['id']})
@@ -148,8 +150,8 @@ class EndpointPolicyTestCase(test_v3.RestfulTestCase):
'service_id': self.service['id'],
'region_id': self.region['id']}
- self.put(url)
- self.head(url)
+ self.put(url, expected_status=204)
+ self.head(url, expected_status=204)
self.delete('/regions/%(region_id)s' % {
'region_id': self.region['id']})
@@ -163,8 +165,8 @@ class EndpointPolicyTestCase(test_v3.RestfulTestCase):
'service_id': self.service['id'],
'region_id': self.region['id']}
- self.put(url)
- self.head(url)
+ self.put(url, expected_status=204)
+ self.head(url, expected_status=204)
self.delete('/services/%(service_id)s' % {
'service_id': self.service['id']})
@@ -177,8 +179,8 @@ class EndpointPolicyTestCase(test_v3.RestfulTestCase):
'policy_id': self.policy['id'],
'service_id': self.service['id']}
- self.put(url)
- self.get(url, expected_status=http_client.NO_CONTENT)
+ self.put(url, expected_status=204)
+ self.get(url, expected_status=204)
self.delete('/policies/%(policy_id)s' % {
'policy_id': self.policy['id']})
@@ -191,8 +193,8 @@ class EndpointPolicyTestCase(test_v3.RestfulTestCase):
'policy_id': self.policy['id'],
'service_id': self.service['id']}
- self.put(url)
- self.get(url, expected_status=http_client.NO_CONTENT)
+ self.put(url, expected_status=204)
+ self.get(url, expected_status=204)
self.delete('/services/%(service_id)s' % {
'service_id': self.service['id']})
diff --git a/keystone-moon/keystone/tests/unit/test_v3_federation.py b/keystone-moon/keystone/tests/unit/test_v3_federation.py
index 5717e67b..4d7dcaab 100644
--- a/keystone-moon/keystone/tests/unit/test_v3_federation.py
+++ b/keystone-moon/keystone/tests/unit/test_v3_federation.py
@@ -815,7 +815,7 @@ class FederatedIdentityProviderTests(FederationTests):
if body is None:
body = self._http_idp_input()
resp = self.put(url, body={'identity_provider': body},
- expected_status=http_client.CREATED)
+ expected_status=201)
return resp
def _http_idp_input(self, **kwargs):
@@ -1027,7 +1027,7 @@ class FederatedIdentityProviderTests(FederationTests):
url = self.base_url(suffix=uuid.uuid4().hex)
body = self._http_idp_input()
self.put(url, body={'identity_provider': body},
- expected_status=http_client.CREATED)
+ expected_status=201)
self.put(url, body={'identity_provider': body},
expected_status=http_client.CONFLICT)
@@ -1084,7 +1084,7 @@ class FederatedIdentityProviderTests(FederationTests):
idp_url = self.base_url(suffix=idp_id)
# assign protocol to IdP
- kwargs = {'expected_status': http_client.CREATED}
+ kwargs = {'expected_status': 201}
resp, idp_id, proto = self._assign_protocol_to_idp(
url=url,
idp_id=idp_id,
@@ -1179,7 +1179,7 @@ class FederatedIdentityProviderTests(FederationTests):
def test_assign_protocol_to_idp(self):
"""Assign a protocol to existing IdP."""
- self._assign_protocol_to_idp(expected_status=http_client.CREATED)
+ self._assign_protocol_to_idp(expected_status=201)
def test_protocol_composite_pk(self):
"""Test whether Keystone let's add two entities with identical
@@ -1193,7 +1193,7 @@ class FederatedIdentityProviderTests(FederationTests):
"""
url = self.base_url(suffix='%(idp_id)s/protocols/%(protocol_id)s')
- kwargs = {'expected_status': http_client.CREATED}
+ kwargs = {'expected_status': 201}
self._assign_protocol_to_idp(proto='saml2',
url=url, **kwargs)
@@ -1209,7 +1209,7 @@ class FederatedIdentityProviderTests(FederationTests):
"""
url = self.base_url(suffix='%(idp_id)s/protocols/%(protocol_id)s')
- kwargs = {'expected_status': http_client.CREATED}
+ kwargs = {'expected_status': 201}
resp, idp_id, proto = self._assign_protocol_to_idp(proto='saml2',
url=url, **kwargs)
kwargs = {'expected_status': http_client.CONFLICT}
@@ -1235,8 +1235,7 @@ class FederatedIdentityProviderTests(FederationTests):
def test_get_protocol(self):
"""Create and later fetch protocol tied to IdP."""
- resp, idp_id, proto = self._assign_protocol_to_idp(
- expected_status=http_client.CREATED)
+ resp, idp_id, proto = self._assign_protocol_to_idp(expected_status=201)
proto_id = self._fetch_attribute_from_response(resp, 'protocol')['id']
url = "%s/protocols/%s" % (idp_id, proto_id)
url = self.base_url(suffix=url)
@@ -1255,14 +1254,12 @@ class FederatedIdentityProviderTests(FederationTests):
Compare input and output id sets.
"""
- resp, idp_id, proto = self._assign_protocol_to_idp(
- expected_status=http_client.CREATED)
+ resp, idp_id, proto = self._assign_protocol_to_idp(expected_status=201)
iterations = random.randint(0, 16)
protocol_ids = []
for _ in range(iterations):
- resp, _, proto = self._assign_protocol_to_idp(
- idp_id=idp_id,
- expected_status=http_client.CREATED)
+ resp, _, proto = self._assign_protocol_to_idp(idp_id=idp_id,
+ expected_status=201)
proto_id = self._fetch_attribute_from_response(resp, 'protocol')
proto_id = proto_id['id']
protocol_ids.append(proto_id)
@@ -1281,8 +1278,7 @@ class FederatedIdentityProviderTests(FederationTests):
def test_update_protocols_attribute(self):
"""Update protocol's attribute."""
- resp, idp_id, proto = self._assign_protocol_to_idp(
- expected_status=http_client.CREATED)
+ resp, idp_id, proto = self._assign_protocol_to_idp(expected_status=201)
new_mapping_id = uuid.uuid4().hex
url = "%s/protocols/%s" % (idp_id, proto)
@@ -1303,8 +1299,7 @@ class FederatedIdentityProviderTests(FederationTests):
"""
url = self.base_url(suffix='/%(idp_id)s/'
'protocols/%(protocol_id)s')
- resp, idp_id, proto = self._assign_protocol_to_idp(
- expected_status=http_client.CREATED)
+ resp, idp_id, proto = self._assign_protocol_to_idp(expected_status=201)
url = url % {'idp_id': idp_id,
'protocol_id': proto}
self.delete(url)
@@ -1345,7 +1340,7 @@ class MappingCRUDTests(FederationTests):
url = self.MAPPING_URL + uuid.uuid4().hex
resp = self.put(url,
body={'mapping': mapping_fixtures.MAPPING_LARGE},
- expected_status=http_client.CREATED)
+ expected_status=201)
return resp
def _get_id_from_response(self, resp):
@@ -1362,7 +1357,7 @@ class MappingCRUDTests(FederationTests):
resp = self.get(url)
entities = resp.result.get('mappings')
self.assertIsNotNone(entities)
- self.assertResponseStatus(resp, http_client.OK)
+ self.assertResponseStatus(resp, 200)
self.assertValidListLinks(resp.result.get('links'))
self.assertEqual(1, len(entities))
@@ -1372,7 +1367,7 @@ class MappingCRUDTests(FederationTests):
mapping_id = self._get_id_from_response(resp)
url = url % {'mapping_id': str(mapping_id)}
resp = self.delete(url)
- self.assertResponseStatus(resp, http_client.NO_CONTENT)
+ self.assertResponseStatus(resp, 204)
self.get(url, expected_status=http_client.NOT_FOUND)
def test_mapping_get(self):
@@ -1976,8 +1971,7 @@ class FederatedTokenTests(FederationTests, FederatedSetupMixin):
token_id, 'project',
self.project_all['id'])
- self.v3_authenticate_token(
- scoped_token, expected_status=http_client.INTERNAL_SERVER_ERROR)
+ self.v3_authenticate_token(scoped_token, expected_status=500)
def test_lists_with_missing_group_in_backend(self):
"""Test a mapping that points to a group that does not exist
@@ -2529,7 +2523,7 @@ class SAMLGenerationTests(FederationTests):
self.sp = self.sp_ref()
url = '/OS-FEDERATION/service_providers/' + self.SERVICE_PROVDIER_ID
self.put(url, body={'service_provider': self.sp},
- expected_status=http_client.CREATED)
+ expected_status=201)
def test_samlize_token_values(self):
"""Test the SAML generator produces a SAML object.
@@ -2763,7 +2757,7 @@ class SAMLGenerationTests(FederationTests):
return_value=self.signed_assertion):
http_response = self.post(self.SAML_GENERATION_ROUTE, body=body,
response_content_type='text/xml',
- expected_status=http_client.OK)
+ expected_status=200)
response = etree.fromstring(http_response.result)
issuer = response[0]
@@ -2879,7 +2873,7 @@ class SAMLGenerationTests(FederationTests):
return_value=self.signed_assertion):
http_response = self.post(self.ECP_GENERATION_ROUTE, body=body,
response_content_type='text/xml',
- expected_status=http_client.OK)
+ expected_status=200)
env_response = etree.fromstring(http_response.result)
header = env_response[0]
@@ -3079,13 +3073,13 @@ class IdPMetadataGenerationTests(FederationTests):
self.generator.generate_metadata)
def test_get_metadata_with_no_metadata_file_configured(self):
- self.get(self.METADATA_URL,
- expected_status=http_client.INTERNAL_SERVER_ERROR)
+ self.get(self.METADATA_URL, expected_status=500)
def test_get_metadata(self):
self.config_fixture.config(
group='saml', idp_metadata_path=XMLDIR + '/idp_saml2_metadata.xml')
- r = self.get(self.METADATA_URL, response_content_type='text/xml')
+ r = self.get(self.METADATA_URL, response_content_type='text/xml',
+ expected_status=200)
self.assertEqual('text/xml', r.headers.get('Content-Type'))
reference_file = _load_xml('idp_saml2_metadata.xml')
@@ -3108,7 +3102,7 @@ class ServiceProviderTests(FederationTests):
self.SP_REF = self.sp_ref()
self.SERVICE_PROVIDER = self.put(
url, body={'service_provider': self.SP_REF},
- expected_status=http_client.CREATED).result
+ expected_status=201).result
def sp_ref(self):
ref = {
@@ -3127,7 +3121,7 @@ class ServiceProviderTests(FederationTests):
def test_get_service_provider(self):
url = self.base_url(suffix=self.SERVICE_PROVIDER_ID)
- resp = self.get(url)
+ resp = self.get(url, expected_status=200)
self.assertValidEntity(resp.result['service_provider'],
keys_to_check=self.SP_KEYS)
@@ -3139,7 +3133,7 @@ class ServiceProviderTests(FederationTests):
url = self.base_url(suffix=uuid.uuid4().hex)
sp = self.sp_ref()
resp = self.put(url, body={'service_provider': sp},
- expected_status=http_client.CREATED)
+ expected_status=201)
self.assertValidEntity(resp.result['service_provider'],
keys_to_check=self.SP_KEYS)
@@ -3149,7 +3143,7 @@ class ServiceProviderTests(FederationTests):
sp = self.sp_ref()
del sp['relay_state_prefix']
resp = self.put(url, body={'service_provider': sp},
- expected_status=http_client.CREATED)
+ expected_status=201)
sp_result = resp.result['service_provider']
self.assertEqual(CONF.saml.relay_state_prefix,
sp_result['relay_state_prefix'])
@@ -3161,7 +3155,7 @@ class ServiceProviderTests(FederationTests):
non_default_prefix = uuid.uuid4().hex
sp['relay_state_prefix'] = non_default_prefix
resp = self.put(url, body={'service_provider': sp},
- expected_status=http_client.CREATED)
+ expected_status=201)
sp_result = resp.result['service_provider']
self.assertEqual(non_default_prefix,
sp_result['relay_state_prefix'])
@@ -3188,8 +3182,7 @@ class ServiceProviderTests(FederationTests):
}
for id, sp in ref_service_providers.items():
url = self.base_url(suffix=id)
- self.put(url, body={'service_provider': sp},
- expected_status=http_client.CREATED)
+ self.put(url, body={'service_provider': sp}, expected_status=201)
# Insert ids into service provider object, we will compare it with
# responses from server and those include 'id' attribute.
@@ -3216,14 +3209,15 @@ class ServiceProviderTests(FederationTests):
"""
new_sp_ref = self.sp_ref()
url = self.base_url(suffix=self.SERVICE_PROVIDER_ID)
- resp = self.patch(url, body={'service_provider': new_sp_ref})
+ resp = self.patch(url, body={'service_provider': new_sp_ref},
+ expected_status=200)
patch_result = resp.result
new_sp_ref['id'] = self.SERVICE_PROVIDER_ID
self.assertValidEntity(patch_result['service_provider'],
ref=new_sp_ref,
keys_to_check=self.SP_KEYS)
- resp = self.get(url)
+ resp = self.get(url, expected_status=200)
get_result = resp.result
self.assertDictEqual(patch_result['service_provider'],
@@ -3261,14 +3255,15 @@ class ServiceProviderTests(FederationTests):
non_default_prefix = uuid.uuid4().hex
new_sp_ref['relay_state_prefix'] = non_default_prefix
url = self.base_url(suffix=self.SERVICE_PROVIDER_ID)
- resp = self.patch(url, body={'service_provider': new_sp_ref})
+ resp = self.patch(url, body={'service_provider': new_sp_ref},
+ expected_status=200)
sp_result = resp.result['service_provider']
self.assertEqual(non_default_prefix,
sp_result['relay_state_prefix'])
def test_delete_service_provider(self):
url = self.base_url(suffix=self.SERVICE_PROVIDER_ID)
- self.delete(url)
+ self.delete(url, expected_status=204)
def test_delete_service_provider_404(self):
url = self.base_url(suffix=uuid.uuid4().hex)
diff --git a/keystone-moon/keystone/tests/unit/test_v3_identity.py b/keystone-moon/keystone/tests/unit/test_v3_identity.py
index 3d424cea..5a8e4fd5 100644
--- a/keystone-moon/keystone/tests/unit/test_v3_identity.py
+++ b/keystone-moon/keystone/tests/unit/test_v3_identity.py
@@ -295,17 +295,18 @@ class IdentityTestCase(test_v3.RestfulTestCase):
old_password_auth = self.build_authentication_request(
user_id=user_ref['id'],
password=password)
- r = self.v3_authenticate_token(old_password_auth)
+ r = self.v3_authenticate_token(old_password_auth, expected_status=201)
old_token = r.headers.get('X-Subject-Token')
# auth as user with a token should work before a password change
old_token_auth = self.build_authentication_request(token=old_token)
- self.v3_authenticate_token(old_token_auth)
+ self.v3_authenticate_token(old_token_auth, expected_status=201)
# administrative password reset
new_password = uuid.uuid4().hex
self.patch('/users/%s' % user_ref['id'],
- body={'user': {'password': new_password}})
+ body={'user': {'password': new_password}},
+ expected_status=200)
# auth as user with original password should not work after change
self.v3_authenticate_token(old_password_auth,
@@ -319,7 +320,7 @@ class IdentityTestCase(test_v3.RestfulTestCase):
new_password_auth = self.build_authentication_request(
user_id=user_ref['id'],
password=new_password)
- self.v3_authenticate_token(new_password_auth)
+ self.v3_authenticate_token(new_password_auth, expected_status=201)
def test_update_user_domain_id(self):
"""Call ``PATCH /users/{user_id}`` with domain_id."""
@@ -370,7 +371,7 @@ class IdentityTestCase(test_v3.RestfulTestCase):
# Confirm token is valid for now
self.head('/auth/tokens',
headers={'X-Subject-Token': token},
- expected_status=http_client.OK)
+ expected_status=200)
# Now delete the user
self.delete('/users/%(user_id)s' % {
@@ -473,7 +474,8 @@ class IdentityTestCase(test_v3.RestfulTestCase):
# administrative password reset
new_password = uuid.uuid4().hex
self.patch('/users/%s' % user_ref['id'],
- body={'user': {'password': new_password}})
+ body={'user': {'password': new_password}},
+ expected_status=200)
self.assertNotIn(password, log_fix.output)
self.assertNotIn(new_password, log_fix.output)
@@ -559,8 +561,7 @@ class UserSelfServiceChangingPasswordsTestCase(test_v3.RestfulTestCase):
password = self.user_ref['password']
self.user_ref = self.identity_api.create_user(self.user_ref)
self.user_ref['password'] = password
- self.token = self.get_request_token(self.user_ref['password'],
- http_client.CREATED)
+ self.token = self.get_request_token(self.user_ref['password'], 201)
def get_request_token(self, password, expected_status):
auth_data = self.build_authentication_request(
@@ -580,16 +581,16 @@ class UserSelfServiceChangingPasswordsTestCase(test_v3.RestfulTestCase):
def test_changing_password(self):
# original password works
token_id = self.get_request_token(self.user_ref['password'],
- expected_status=http_client.CREATED)
+ expected_status=201)
# original token works
old_token_auth = self.build_authentication_request(token=token_id)
- self.v3_authenticate_token(old_token_auth)
+ self.v3_authenticate_token(old_token_auth, expected_status=201)
# change password
new_password = uuid.uuid4().hex
self.change_password(password=new_password,
original_password=self.user_ref['password'],
- expected_status=http_client.NO_CONTENT)
+ expected_status=204)
# old password fails
self.get_request_token(self.user_ref['password'],
@@ -600,8 +601,7 @@ class UserSelfServiceChangingPasswordsTestCase(test_v3.RestfulTestCase):
expected_status=http_client.NOT_FOUND)
# new password works
- self.get_request_token(new_password,
- expected_status=http_client.CREATED)
+ self.get_request_token(new_password, expected_status=201)
def test_changing_password_with_missing_original_password_fails(self):
r = self.change_password(password=uuid.uuid4().hex,
@@ -640,7 +640,7 @@ class UserSelfServiceChangingPasswordsTestCase(test_v3.RestfulTestCase):
new_password = uuid.uuid4().hex
self.change_password(password=new_password,
original_password=self.user_ref['password'],
- expected_status=http_client.NO_CONTENT)
+ expected_status=204)
self.assertNotIn(self.user_ref['password'], log_fix.output)
self.assertNotIn(new_password, log_fix.output)
diff --git a/keystone-moon/keystone/tests/unit/test_v3_oauth1.py b/keystone-moon/keystone/tests/unit/test_v3_oauth1.py
index 3a0d481c..8794a426 100644
--- a/keystone-moon/keystone/tests/unit/test_v3_oauth1.py
+++ b/keystone-moon/keystone/tests/unit/test_v3_oauth1.py
@@ -140,7 +140,7 @@ class ConsumerCRUDTests(OAuth1Tests):
consumer = self._create_single_consumer()
consumer_id = consumer['id']
resp = self.delete(self.CONSUMER_URL + '/%s' % consumer_id)
- self.assertResponseStatus(resp, http_client.NO_CONTENT)
+ self.assertResponseStatus(resp, 204)
def test_consumer_get(self):
consumer = self._create_single_consumer()
@@ -262,7 +262,7 @@ class OAuthFlowTests(OAuth1Tests):
url = self._authorize_request_token(request_key)
body = {'roles': [{'id': self.role_id}]}
- resp = self.put(url, body=body, expected_status=http_client.OK)
+ resp = self.put(url, body=body, expected_status=200)
self.verifier = resp.result['token']['oauth_verifier']
self.assertTrue(all(i in core.VERIFIER_CHARS for i in self.verifier))
self.assertEqual(8, len(self.verifier))
@@ -357,7 +357,7 @@ class AccessTokenCRUDTests(OAuthFlowTests):
resp = self.delete('/users/%(user)s/OS-OAUTH1/access_tokens/%(auth)s'
% {'user': self.user_id,
'auth': self.access_token.key})
- self.assertResponseStatus(resp, http_client.NO_CONTENT)
+ self.assertResponseStatus(resp, 204)
# List access_token should be 0
resp = self.get('/users/%(user_id)s/OS-OAUTH1/access_tokens'
@@ -400,7 +400,7 @@ class AuthTokenTests(OAuthFlowTests):
resp = self.delete('/users/%(user)s/OS-OAUTH1/access_tokens/%(auth)s'
% {'user': self.user_id,
'auth': self.access_token.key})
- self.assertResponseStatus(resp, http_client.NO_CONTENT)
+ self.assertResponseStatus(resp, 204)
# Check Keystone Token no longer exists
headers = {'X-Subject-Token': self.keystone_token_id,
@@ -415,7 +415,7 @@ class AuthTokenTests(OAuthFlowTests):
consumer_id = self.consumer['key']
resp = self.delete('/OS-OAUTH1/consumers/%(consumer_id)s'
% {'consumer_id': consumer_id})
- self.assertResponseStatus(resp, http_client.NO_CONTENT)
+ self.assertResponseStatus(resp, 204)
# List access_token should be 0
resp = self.get('/users/%(user_id)s/OS-OAUTH1/access_tokens'
@@ -645,7 +645,7 @@ class MaliciousOAuth1Tests(OAuth1Tests):
url = self._authorize_request_token(request_key)
body = {'roles': [{'id': self.role_id}]}
- resp = self.put(url, body=body, expected_status=http_client.OK)
+ resp = self.put(url, body=body, expected_status=200)
verifier = resp.result['token']['oauth_verifier']
self.assertIsNotNone(verifier)
@@ -719,7 +719,7 @@ class MaliciousOAuth1Tests(OAuth1Tests):
url = self._authorize_request_token(request_key)
body = {'roles': [{'id': self.role_id}]}
- resp = self.put(url, body=body, expected_status=http_client.OK)
+ resp = self.put(url, body=body, expected_status=200)
self.verifier = resp.result['token']['oauth_verifier']
self.request_token.set_verifier(self.verifier)
@@ -753,8 +753,7 @@ class MaliciousOAuth1Tests(OAuth1Tests):
# NOTE(stevemar): To simulate this error, we remove the Authorization
# header from the post request.
del headers['Authorization']
- self.post(endpoint, headers=headers,
- expected_status=http_client.INTERNAL_SERVER_ERROR)
+ self.post(endpoint, headers=headers, expected_status=500)
class OAuthNotificationTests(OAuth1Tests,
@@ -830,7 +829,7 @@ class OAuthNotificationTests(OAuth1Tests,
url = self._authorize_request_token(request_key)
body = {'roles': [{'id': self.role_id}]}
- resp = self.put(url, body=body, expected_status=http_client.OK)
+ resp = self.put(url, body=body, expected_status=200)
self.verifier = resp.result['token']['oauth_verifier']
self.assertTrue(all(i in core.VERIFIER_CHARS for i in self.verifier))
self.assertEqual(8, len(self.verifier))
@@ -859,7 +858,7 @@ class OAuthNotificationTests(OAuth1Tests,
resp = self.delete('/users/%(user)s/OS-OAUTH1/access_tokens/%(auth)s'
% {'user': self.user_id,
'auth': self.access_token.key})
- self.assertResponseStatus(resp, http_client.NO_CONTENT)
+ self.assertResponseStatus(resp, 204)
# Test to ensure the delete access token notification is sent
self._assert_notify_sent(access_key,
diff --git a/keystone-moon/keystone/tests/unit/test_v3_protection.py b/keystone-moon/keystone/tests/unit/test_v3_protection.py
index 296e1d4b..9922ae5e 100644
--- a/keystone-moon/keystone/tests/unit/test_v3_protection.py
+++ b/keystone-moon/keystone/tests/unit/test_v3_protection.py
@@ -461,8 +461,7 @@ class IdentityTestPolicySample(test_v3.RestfulTestCase):
token = self.get_requested_token(auth)
self.head('/auth/tokens', token=token,
- headers={'X-Subject-Token': token},
- expected_status=http_client.OK)
+ headers={'X-Subject-Token': token}, expected_status=200)
def test_user_check_user_token(self):
# A user can check one of their own tokens.
@@ -475,8 +474,7 @@ class IdentityTestPolicySample(test_v3.RestfulTestCase):
token2 = self.get_requested_token(auth)
self.head('/auth/tokens', token=token1,
- headers={'X-Subject-Token': token2},
- expected_status=http_client.OK)
+ headers={'X-Subject-Token': token2}, expected_status=200)
def test_user_check_other_user_token_rejected(self):
# A user cannot check another user's token.
@@ -512,8 +510,7 @@ class IdentityTestPolicySample(test_v3.RestfulTestCase):
user_token = self.get_requested_token(user_auth)
self.head('/auth/tokens', token=admin_token,
- headers={'X-Subject-Token': user_token},
- expected_status=http_client.OK)
+ headers={'X-Subject-Token': user_token}, expected_status=200)
def test_user_revoke_same_token(self):
# Given a non-admin user token, the token can be used to revoke
@@ -686,8 +683,7 @@ class IdentityTestv3CloudPolicySample(test_v3.RestfulTestCase,
# Return the expected return codes for APIs with and without data
# with any specified status overriding the normal values
if expected_status is None:
- return (http_client.OK, http_client.CREATED,
- http_client.NO_CONTENT)
+ return (200, 201, 204)
else:
return (expected_status, expected_status, expected_status)
@@ -1054,7 +1050,7 @@ class IdentityTestv3CloudPolicySample(test_v3.RestfulTestCase,
password=self.domain_admin_user['password'],
domain_id=self.domainA['id'])
entity_url = '/domains/%s' % self.domainA['id']
- self.get(entity_url, auth=self.auth)
+ self.get(entity_url, auth=self.auth, expected_status=200)
def test_list_user_credentials(self):
self.credential_user = self.new_credential_ref(self.just_a_user['id'])
@@ -1186,8 +1182,7 @@ class IdentityTestv3CloudPolicySample(test_v3.RestfulTestCase,
token = self.get_requested_token(auth)
self.head('/auth/tokens', token=token,
- headers={'X-Subject-Token': token},
- expected_status=http_client.OK)
+ headers={'X-Subject-Token': token}, expected_status=200)
def test_user_check_user_token(self):
# A user can check one of their own tokens.
@@ -1200,8 +1195,7 @@ class IdentityTestv3CloudPolicySample(test_v3.RestfulTestCase,
token2 = self.get_requested_token(auth)
self.head('/auth/tokens', token=token1,
- headers={'X-Subject-Token': token2},
- expected_status=http_client.OK)
+ headers={'X-Subject-Token': token2}, expected_status=200)
def test_user_check_other_user_token_rejected(self):
# A user cannot check another user's token.
@@ -1237,8 +1231,7 @@ class IdentityTestv3CloudPolicySample(test_v3.RestfulTestCase,
user_token = self.get_requested_token(user_auth)
self.head('/auth/tokens', token=admin_token,
- headers={'X-Subject-Token': user_token},
- expected_status=http_client.OK)
+ headers={'X-Subject-Token': user_token}, expected_status=200)
def test_user_revoke_same_token(self):
# Given a non-admin user token, the token can be used to revoke
diff --git a/keystone-moon/keystone/tests/unit/test_versions.py b/keystone-moon/keystone/tests/unit/test_versions.py
index fc8051b2..40814588 100644
--- a/keystone-moon/keystone/tests/unit/test_versions.py
+++ b/keystone-moon/keystone/tests/unit/test_versions.py
@@ -751,7 +751,7 @@ class VersionTestCase(unit.TestCase):
def test_public_version_v2(self):
client = TestClient(self.public_app)
resp = client.get('/v2.0/')
- self.assertEqual(http_client.OK, resp.status_int)
+ self.assertEqual(200, resp.status_int)
data = jsonutils.loads(resp.body)
expected = v2_VERSION_RESPONSE
self._paste_in_port(expected['version'],
@@ -762,7 +762,7 @@ class VersionTestCase(unit.TestCase):
def test_admin_version_v2(self):
client = TestClient(self.admin_app)
resp = client.get('/v2.0/')
- self.assertEqual(http_client.OK, resp.status_int)
+ self.assertEqual(200, resp.status_int)
data = jsonutils.loads(resp.body)
expected = v2_VERSION_RESPONSE
self._paste_in_port(expected['version'],
@@ -775,7 +775,7 @@ class VersionTestCase(unit.TestCase):
for app in (self.public_app, self.admin_app):
client = TestClient(app)
resp = client.get('/v2.0/')
- self.assertEqual(http_client.OK, resp.status_int)
+ self.assertEqual(200, resp.status_int)
data = jsonutils.loads(resp.body)
expected = v2_VERSION_RESPONSE
self._paste_in_port(expected['version'], 'http://localhost/v2.0/')
@@ -784,7 +784,7 @@ class VersionTestCase(unit.TestCase):
def test_public_version_v3(self):
client = TestClient(self.public_app)
resp = client.get('/v3/')
- self.assertEqual(http_client.OK, resp.status_int)
+ self.assertEqual(200, resp.status_int)
data = jsonutils.loads(resp.body)
expected = v3_VERSION_RESPONSE
self._paste_in_port(expected['version'],
@@ -796,7 +796,7 @@ class VersionTestCase(unit.TestCase):
def test_admin_version_v3(self):
client = TestClient(self.admin_app)
resp = client.get('/v3/')
- self.assertEqual(http_client.OK, resp.status_int)
+ self.assertEqual(200, resp.status_int)
data = jsonutils.loads(resp.body)
expected = v3_VERSION_RESPONSE
self._paste_in_port(expected['version'],
@@ -809,7 +809,7 @@ class VersionTestCase(unit.TestCase):
for app in (self.public_app, self.admin_app):
client = TestClient(app)
resp = client.get('/v3/')
- self.assertEqual(http_client.OK, resp.status_int)
+ self.assertEqual(200, resp.status_int)
data = jsonutils.loads(resp.body)
expected = v3_VERSION_RESPONSE
self._paste_in_port(expected['version'], 'http://localhost/v3/')
@@ -824,7 +824,7 @@ class VersionTestCase(unit.TestCase):
# request to /v3 should pass
resp = client.get('/v3/')
- self.assertEqual(http_client.OK, resp.status_int)
+ self.assertEqual(200, resp.status_int)
data = jsonutils.loads(resp.body)
expected = v3_VERSION_RESPONSE
self._paste_in_port(expected['version'],
@@ -857,7 +857,7 @@ class VersionTestCase(unit.TestCase):
# request to /v2.0 should pass
resp = client.get('/v2.0/')
- self.assertEqual(http_client.OK, resp.status_int)
+ self.assertEqual(200, resp.status_int)
data = jsonutils.loads(resp.body)
expected = v2_VERSION_RESPONSE
self._paste_in_port(expected['version'],
diff --git a/keystone-moon/keystone/tests/unit/test_wsgi.py b/keystone-moon/keystone/tests/unit/test_wsgi.py
index 2a5cb386..ed4c67d6 100644
--- a/keystone-moon/keystone/tests/unit/test_wsgi.py
+++ b/keystone-moon/keystone/tests/unit/test_wsgi.py
@@ -112,16 +112,15 @@ class ApplicationTest(BaseWSGITest):
resp = wsgi.render_response(body=data)
self.assertEqual('200 OK', resp.status)
- self.assertEqual(http_client.OK, resp.status_int)
+ self.assertEqual(200, resp.status_int)
self.assertEqual(body, resp.body)
self.assertEqual('X-Auth-Token', resp.headers.get('Vary'))
self.assertEqual(str(len(body)), resp.headers.get('Content-Length'))
def test_render_response_custom_status(self):
- resp = wsgi.render_response(
- status=(http_client.NOT_IMPLEMENTED, 'Not Implemented'))
+ resp = wsgi.render_response(status=(501, 'Not Implemented'))
self.assertEqual('501 Not Implemented', resp.status)
- self.assertEqual(http_client.NOT_IMPLEMENTED, resp.status_int)
+ self.assertEqual(501, resp.status_int)
def test_successful_require_attribute(self):
app = FakeAttributeCheckerApp()
@@ -173,14 +172,14 @@ class ApplicationTest(BaseWSGITest):
def test_render_response_no_body(self):
resp = wsgi.render_response()
self.assertEqual('204 No Content', resp.status)
- self.assertEqual(http_client.NO_CONTENT, resp.status_int)
+ self.assertEqual(204, resp.status_int)
self.assertEqual(b'', resp.body)
self.assertEqual('0', resp.headers.get('Content-Length'))
self.assertIsNone(resp.headers.get('Content-Type'))
def test_render_response_head_with_body(self):
resp = wsgi.render_response({'id': uuid.uuid4().hex}, method='HEAD')
- self.assertEqual(http_client.OK, resp.status_int)
+ self.assertEqual(200, resp.status_int)
self.assertEqual(b'', resp.body)
self.assertNotEqual(resp.headers.get('Content-Length'), '0')
self.assertEqual('application/json', resp.headers.get('Content-Type'))
diff --git a/keystone-moon/keystone/tests/unit/token/test_fernet_provider.py b/keystone-moon/keystone/tests/unit/token/test_fernet_provider.py
index 5f74b430..bfb590db 100644
--- a/keystone-moon/keystone/tests/unit/token/test_fernet_provider.py
+++ b/keystone-moon/keystone/tests/unit/token/test_fernet_provider.py
@@ -16,13 +16,17 @@ import hashlib
import os
import uuid
+import msgpack
from oslo_utils import timeutils
+from six.moves import urllib
from keystone.common import config
from keystone.common import utils
+from keystone.contrib.federation import constants as federation_constants
from keystone import exception
from keystone.tests import unit
from keystone.tests.unit import ksfixtures
+from keystone.tests.unit.ksfixtures import database
from keystone.token import provider
from keystone.token.providers import fernet
from keystone.token.providers.fernet import token_formatters
@@ -57,7 +61,156 @@ class TestFernetTokenProvider(unit.TestCase):
uuid.uuid4().hex)
+class TestValidate(unit.TestCase):
+ def setUp(self):
+ super(TestValidate, self).setUp()
+ self.useFixture(ksfixtures.KeyRepository(self.config_fixture))
+ self.useFixture(database.Database())
+ self.load_backends()
+
+ def config_overrides(self):
+ super(TestValidate, self).config_overrides()
+ self.config_fixture.config(group='token', provider='fernet')
+
+ def test_validate_v3_token_simple(self):
+ # Check the fields in the token result when use validate_v3_token
+ # with a simple token.
+
+ domain_ref = unit.new_domain_ref()
+ domain_ref = self.resource_api.create_domain(domain_ref['id'],
+ domain_ref)
+
+ user_ref = unit.new_user_ref(domain_ref['id'])
+ user_ref = self.identity_api.create_user(user_ref)
+
+ method_names = ['password']
+ token_id, token_data_ = self.token_provider_api.issue_v3_token(
+ user_ref['id'], method_names)
+
+ token_data = self.token_provider_api.validate_v3_token(token_id)
+ token = token_data['token']
+ self.assertIsInstance(token['audit_ids'], list)
+ self.assertIsInstance(token['expires_at'], str)
+ self.assertEqual({}, token['extras'])
+ self.assertIsInstance(token['issued_at'], str)
+ self.assertEqual(method_names, token['methods'])
+ exp_user_info = {
+ 'id': user_ref['id'],
+ 'name': user_ref['name'],
+ 'domain': {
+ 'id': domain_ref['id'],
+ 'name': domain_ref['name'],
+ },
+ }
+ self.assertEqual(exp_user_info, token['user'])
+
+ def test_validate_v3_token_federated_info(self):
+ # Check the user fields in the token result when use validate_v3_token
+ # when the token has federated info.
+
+ domain_ref = unit.new_domain_ref()
+ domain_ref = self.resource_api.create_domain(domain_ref['id'],
+ domain_ref)
+
+ user_ref = unit.new_user_ref(domain_ref['id'])
+ user_ref = self.identity_api.create_user(user_ref)
+
+ method_names = ['mapped']
+
+ group_ids = [uuid.uuid4().hex, ]
+ identity_provider = uuid.uuid4().hex
+ protocol = uuid.uuid4().hex
+ auth_context = {
+ 'user_id': user_ref['id'],
+ 'group_ids': group_ids,
+ federation_constants.IDENTITY_PROVIDER: identity_provider,
+ federation_constants.PROTOCOL: protocol,
+ }
+ token_id, token_data_ = self.token_provider_api.issue_v3_token(
+ user_ref['id'], method_names, auth_context=auth_context)
+
+ token_data = self.token_provider_api.validate_v3_token(token_id)
+ token = token_data['token']
+ exp_user_info = {
+ 'id': user_ref['id'],
+ 'name': user_ref['id'],
+ 'domain': {'id': CONF.federation.federated_domain_name,
+ 'name': CONF.federation.federated_domain_name, },
+ federation_constants.FEDERATION: {
+ 'groups': [{'id': group_id} for group_id in group_ids],
+ 'identity_provider': {'id': identity_provider, },
+ 'protocol': {'id': protocol, },
+ },
+ }
+ self.assertEqual(exp_user_info, token['user'])
+
+ def test_validate_v3_token_trust(self):
+ # Check the trust fields in the token result when use validate_v3_token
+ # when the token has trust info.
+
+ domain_ref = unit.new_domain_ref()
+ domain_ref = self.resource_api.create_domain(domain_ref['id'],
+ domain_ref)
+
+ user_ref = unit.new_user_ref(domain_ref['id'])
+ user_ref = self.identity_api.create_user(user_ref)
+
+ trustor_user_ref = unit.new_user_ref(domain_ref['id'])
+ trustor_user_ref = self.identity_api.create_user(trustor_user_ref)
+
+ project_ref = unit.new_project_ref(domain_id=domain_ref['id'])
+ project_ref = self.resource_api.create_project(project_ref['id'],
+ project_ref)
+
+ role_ref = unit.new_role_ref()
+ role_ref = self.role_api.create_role(role_ref['id'], role_ref)
+
+ self.assignment_api.create_grant(
+ role_ref['id'], user_id=user_ref['id'],
+ project_id=project_ref['id'])
+
+ self.assignment_api.create_grant(
+ role_ref['id'], user_id=trustor_user_ref['id'],
+ project_id=project_ref['id'])
+
+ trustor_user_id = trustor_user_ref['id']
+ trustee_user_id = user_ref['id']
+ trust_ref = unit.new_trust_ref(
+ trustor_user_id, trustee_user_id, project_id=project_ref['id'],
+ role_ids=[role_ref['id'], ])
+ trust_ref = self.trust_api.create_trust(trust_ref['id'], trust_ref,
+ trust_ref['roles'])
+
+ method_names = ['password']
+
+ token_id, token_data_ = self.token_provider_api.issue_v3_token(
+ user_ref['id'], method_names, project_id=project_ref['id'],
+ trust=trust_ref)
+
+ token_data = self.token_provider_api.validate_v3_token(token_id)
+ token = token_data['token']
+ exp_trust_info = {
+ 'id': trust_ref['id'],
+ 'impersonation': False,
+ 'trustee_user': {'id': user_ref['id'], },
+ 'trustor_user': {'id': trustor_user_ref['id'], },
+ }
+ self.assertEqual(exp_trust_info, token['OS-TRUST:trust'])
+
+ def test_validate_v3_token_validation_error_exc(self):
+ # When the token format isn't recognized, TokenNotFound is raised.
+
+ # A uuid string isn't a valid fernet token.
+ token_id = uuid.uuid4().hex
+ self.assertRaises(exception.TokenNotFound,
+ self.token_provider_api.validate_v3_token, token_id)
+
+
class TestTokenFormatter(unit.TestCase):
+ def setUp(self):
+ super(TestTokenFormatter, self).setUp()
+ self.useFixture(ksfixtures.KeyRepository(self.config_fixture))
+
def test_restore_padding(self):
# 'a' will result in '==' padding, 'aa' will result in '=' padding, and
# 'aaa' will result in no padding.
@@ -73,6 +226,39 @@ class TestTokenFormatter(unit.TestCase):
)
self.assertEqual(encoded_string, encoded_str_with_padding_restored)
+ def test_legacy_padding_validation(self):
+ first_value = uuid.uuid4().hex
+ second_value = uuid.uuid4().hex
+ payload = (first_value, second_value)
+ msgpack_payload = msgpack.packb(payload)
+
+ # NOTE(lbragstad): This method perserves the way that keystone used to
+ # percent encode the tokens, prior to bug #1491926.
+ def legacy_pack(payload):
+ tf = token_formatters.TokenFormatter()
+ encrypted_payload = tf.crypto.encrypt(payload)
+
+ # the encrypted_payload is returned with padding appended
+ self.assertTrue(encrypted_payload.endswith('='))
+
+ # using urllib.parse.quote will percent encode the padding, like
+ # keystone did in Kilo.
+ percent_encoded_payload = urllib.parse.quote(encrypted_payload)
+
+ # ensure that the padding was actaully percent encoded
+ self.assertTrue(percent_encoded_payload.endswith('%3D'))
+ return percent_encoded_payload
+
+ token_with_legacy_padding = legacy_pack(msgpack_payload)
+ tf = token_formatters.TokenFormatter()
+
+ # demonstrate the we can validate a payload that has been percent
+ # encoded with the Fernet logic that existed in Kilo
+ serialized_payload = tf.unpack(token_with_legacy_padding)
+ returned_payload = msgpack.unpackb(serialized_payload)
+ self.assertEqual(first_value, returned_payload[0])
+ self.assertEqual(second_value, returned_payload[1])
+
class TestPayloads(unit.TestCase):
def test_uuid_hex_to_byte_conversions(self):
@@ -204,8 +390,7 @@ class TestPayloads(unit.TestCase):
self.assertEqual(exp_audit_ids, audit_ids)
self.assertEqual(exp_trust_id, trust_id)
- def test_unscoped_payload_with_non_uuid_user_id(self):
- exp_user_id = 'someNonUuidUserId'
+ def _test_unscoped_payload_with_user_id(self, exp_user_id):
exp_methods = ['password']
exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True)
exp_audit_ids = [provider.random_urlsafe_str()]
@@ -221,30 +406,15 @@ class TestPayloads(unit.TestCase):
self.assertEqual(exp_expires_at, expires_at)
self.assertEqual(exp_audit_ids, audit_ids)
- def test_project_scoped_payload_with_non_uuid_user_id(self):
- exp_user_id = 'someNonUuidUserId'
- exp_methods = ['password']
- exp_project_id = uuid.uuid4().hex
- exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True)
- exp_audit_ids = [provider.random_urlsafe_str()]
-
- payload = token_formatters.ProjectScopedPayload.assemble(
- exp_user_id, exp_methods, exp_project_id, exp_expires_at,
- exp_audit_ids)
-
- (user_id, methods, project_id, expires_at, audit_ids) = (
- token_formatters.ProjectScopedPayload.disassemble(payload))
+ def test_unscoped_payload_with_non_uuid_user_id(self):
+ self._test_unscoped_payload_with_user_id('someNonUuidUserId')
- self.assertEqual(exp_user_id, user_id)
- self.assertEqual(exp_methods, methods)
- self.assertEqual(exp_project_id, project_id)
- self.assertEqual(exp_expires_at, expires_at)
- self.assertEqual(exp_audit_ids, audit_ids)
+ def test_unscoped_payload_with_16_char_non_uuid_user_id(self):
+ self._test_unscoped_payload_with_user_id('0123456789abcdef')
- def test_project_scoped_payload_with_non_uuid_project_id(self):
- exp_user_id = uuid.uuid4().hex
+ def _test_project_scoped_payload_with_ids(self, exp_user_id,
+ exp_project_id):
exp_methods = ['password']
- exp_project_id = 'someNonUuidProjectId'
exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True)
exp_audit_ids = [provider.random_urlsafe_str()]
@@ -261,8 +431,15 @@ class TestPayloads(unit.TestCase):
self.assertEqual(exp_expires_at, expires_at)
self.assertEqual(exp_audit_ids, audit_ids)
- def test_domain_scoped_payload_with_non_uuid_user_id(self):
- exp_user_id = 'someNonUuidUserId'
+ def test_project_scoped_payload_with_non_uuid_user_id(self):
+ self._test_project_scoped_payload_with_ids('someNonUuidUserId',
+ 'someNonUuidProjectId')
+
+ def test_project_scoped_payload_with_16_char_non_uuid_user_id(self):
+ self._test_project_scoped_payload_with_ids('0123456789abcdef',
+ '0123456789abcdef')
+
+ def _test_domain_scoped_payload_with_user_id(self, exp_user_id):
exp_methods = ['password']
exp_domain_id = uuid.uuid4().hex
exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True)
@@ -281,32 +458,14 @@ class TestPayloads(unit.TestCase):
self.assertEqual(exp_expires_at, expires_at)
self.assertEqual(exp_audit_ids, audit_ids)
- def test_trust_scoped_payload_with_non_uuid_user_id(self):
- exp_user_id = 'someNonUuidUserId'
- exp_methods = ['password']
- exp_project_id = uuid.uuid4().hex
- exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True)
- exp_audit_ids = [provider.random_urlsafe_str()]
- exp_trust_id = uuid.uuid4().hex
-
- payload = token_formatters.TrustScopedPayload.assemble(
- exp_user_id, exp_methods, exp_project_id, exp_expires_at,
- exp_audit_ids, exp_trust_id)
-
- (user_id, methods, project_id, expires_at, audit_ids, trust_id) = (
- token_formatters.TrustScopedPayload.disassemble(payload))
+ def test_domain_scoped_payload_with_non_uuid_user_id(self):
+ self._test_domain_scoped_payload_with_user_id('nonUuidUserId')
- self.assertEqual(exp_user_id, user_id)
- self.assertEqual(exp_methods, methods)
- self.assertEqual(exp_project_id, project_id)
- self.assertEqual(exp_expires_at, expires_at)
- self.assertEqual(exp_audit_ids, audit_ids)
- self.assertEqual(exp_trust_id, trust_id)
+ def test_domain_scoped_payload_with_16_char_non_uuid_user_id(self):
+ self._test_domain_scoped_payload_with_user_id('0123456789abcdef')
- def test_trust_scoped_payload_with_non_uuid_project_id(self):
- exp_user_id = uuid.uuid4().hex
+ def _test_trust_scoped_payload_with_ids(self, exp_user_id, exp_project_id):
exp_methods = ['password']
- exp_project_id = 'someNonUuidProjectId'
exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True)
exp_audit_ids = [provider.random_urlsafe_str()]
exp_trust_id = uuid.uuid4().hex
@@ -325,12 +484,19 @@ class TestPayloads(unit.TestCase):
self.assertEqual(exp_audit_ids, audit_ids)
self.assertEqual(exp_trust_id, trust_id)
- def test_federated_payload_with_non_uuid_ids(self):
- exp_user_id = 'someNonUuidUserId'
+ def test_trust_scoped_payload_with_non_uuid_user_id(self):
+ self._test_trust_scoped_payload_with_ids('someNonUuidUserId',
+ 'someNonUuidProjectId')
+
+ def test_trust_scoped_payload_with_16_char_non_uuid_user_id(self):
+ self._test_trust_scoped_payload_with_ids('0123456789abcdef',
+ '0123456789abcdef')
+
+ def _test_federated_payload_with_ids(self, exp_user_id, exp_group_id):
exp_methods = ['password']
exp_expires_at = utils.isotime(timeutils.utcnow(), subsecond=True)
exp_audit_ids = [provider.random_urlsafe_str()]
- exp_federated_info = {'group_ids': [{'id': 'someNonUuidGroupId'}],
+ exp_federated_info = {'group_ids': [{'id': exp_group_id}],
'idp_id': uuid.uuid4().hex,
'protocol_id': uuid.uuid4().hex}
@@ -352,6 +518,14 @@ class TestPayloads(unit.TestCase):
self.assertEqual(exp_federated_info['protocol_id'],
federated_info['protocol_id'])
+ def test_federated_payload_with_non_uuid_ids(self):
+ self._test_federated_payload_with_ids('someNonUuidUserId',
+ 'someNonUuidGroupId')
+
+ def test_federated_payload_with_16_char_non_uuid_ids(self):
+ self._test_federated_payload_with_ids('0123456789abcdef',
+ '0123456789abcdef')
+
def test_federated_project_scoped_payload(self):
exp_user_id = 'someNonUuidUserId'
exp_methods = ['token']
diff --git a/keystone-moon/keystone/token/providers/fernet/core.py b/keystone-moon/keystone/token/providers/fernet/core.py
index 1bbacb03..a71c375b 100644
--- a/keystone-moon/keystone/token/providers/fernet/core.py
+++ b/keystone-moon/keystone/token/providers/fernet/core.py
@@ -167,7 +167,9 @@ class Provider(common.BaseProvider):
'user': {
federation_constants.FEDERATION: federated_info,
'id': user_id,
- 'name': user_id
+ 'name': user_id,
+ 'domain': {'id': CONF.federation.federated_domain_name,
+ 'name': CONF.federation.federated_domain_name, },
}
}
diff --git a/keystone-moon/keystone/token/providers/fernet/token_formatters.py b/keystone-moon/keystone/token/providers/fernet/token_formatters.py
index f0b6271d..dbfee6dd 100644
--- a/keystone-moon/keystone/token/providers/fernet/token_formatters.py
+++ b/keystone-moon/keystone/token/providers/fernet/token_formatters.py
@@ -22,6 +22,7 @@ from oslo_log import log
from oslo_utils import timeutils
import six
from six.moves import map
+from six.moves import urllib
from keystone.auth import plugins as auth_plugins
from keystone.common import utils as ks_utils
@@ -73,8 +74,19 @@ class TokenFormatter(object):
"""Unpack a token, and validate the payload."""
token = six.binary_type(token)
- # Restore padding on token before decoding it
- token = TokenFormatter.restore_padding(token)
+ # TODO(lbragstad): Restore padding on token before decoding it.
+ # Initially in Kilo, Fernet tokens were returned to the user with
+ # padding appended to the token. Later in Liberty this padding was
+ # removed and restored in the Fernet provider. The following if
+ # statement ensures that we can validate tokens with and without token
+ # padding, in the event of an upgrade and the tokens that are issued
+ # throughout the upgrade. Remove this if statement when Mitaka opens
+ # for development and exclusively use the restore_padding() class
+ # method.
+ if token.endswith('%3D'):
+ token = urllib.parse.unquote(token)
+ else:
+ token = TokenFormatter.restore_padding(token)
try:
return self.crypto.decrypt(token)
@@ -338,15 +350,16 @@ class BasePayload(object):
"""Attempt to convert value to bytes or return value.
:param value: value to attempt to convert to bytes
- :returns: uuid value in bytes or value
+ :returns: tuple containing boolean indicating whether user_id was
+ stored as bytes and uuid value as bytes or the original value
"""
try:
- return cls.convert_uuid_hex_to_bytes(value)
+ return (True, cls.convert_uuid_hex_to_bytes(value))
except ValueError:
# this might not be a UUID, depending on the situation (i.e.
# federation)
- return value
+ return (False, value)
@classmethod
def attempt_convert_uuid_bytes_to_hex(cls, value):
@@ -392,7 +405,9 @@ class UnscopedPayload(BasePayload):
audit_ids
"""
- user_id = cls.attempt_convert_uuid_bytes_to_hex(payload[0])
+ (is_stored_as_bytes, user_id) = payload[0]
+ if is_stored_as_bytes:
+ user_id = cls.attempt_convert_uuid_bytes_to_hex(user_id)
methods = auth_plugins.convert_integer_to_method_list(payload[1])
expires_at_str = cls._convert_int_to_time_string(payload[2])
audit_ids = list(map(provider.base64_encode, payload[3]))
@@ -438,7 +453,9 @@ class DomainScopedPayload(BasePayload):
expires_at_str, and audit_ids
"""
- user_id = cls.attempt_convert_uuid_bytes_to_hex(payload[0])
+ (is_stored_as_bytes, user_id) = payload[0]
+ if is_stored_as_bytes:
+ user_id = cls.attempt_convert_uuid_bytes_to_hex(user_id)
methods = auth_plugins.convert_integer_to_method_list(payload[1])
try:
domain_id = cls.convert_uuid_bytes_to_hex(payload[2])
@@ -486,9 +503,13 @@ class ProjectScopedPayload(BasePayload):
expires_at_str, and audit_ids
"""
- user_id = cls.attempt_convert_uuid_bytes_to_hex(payload[0])
+ (is_stored_as_bytes, user_id) = payload[0]
+ if is_stored_as_bytes:
+ user_id = cls.attempt_convert_uuid_bytes_to_hex(user_id)
methods = auth_plugins.convert_integer_to_method_list(payload[1])
- project_id = cls.attempt_convert_uuid_bytes_to_hex(payload[2])
+ (is_stored_as_bytes, project_id) = payload[2]
+ if is_stored_as_bytes:
+ project_id = cls.attempt_convert_uuid_bytes_to_hex(project_id)
expires_at_str = cls._convert_int_to_time_string(payload[3])
audit_ids = list(map(provider.base64_encode, payload[4]))
@@ -532,9 +553,13 @@ class TrustScopedPayload(BasePayload):
expires_at_str, audit_ids, and trust_id
"""
- user_id = cls.attempt_convert_uuid_bytes_to_hex(payload[0])
+ (is_stored_as_bytes, user_id) = payload[0]
+ if is_stored_as_bytes:
+ user_id = cls.attempt_convert_uuid_bytes_to_hex(user_id)
methods = auth_plugins.convert_integer_to_method_list(payload[1])
- project_id = cls.attempt_convert_uuid_bytes_to_hex(payload[2])
+ (is_stored_as_bytes, project_id) = payload[2]
+ if is_stored_as_bytes:
+ project_id = cls.attempt_convert_uuid_bytes_to_hex(project_id)
expires_at_str = cls._convert_int_to_time_string(payload[3])
audit_ids = list(map(provider.base64_encode, payload[4]))
trust_id = cls.convert_uuid_bytes_to_hex(payload[5])
@@ -552,7 +577,9 @@ class FederatedUnscopedPayload(BasePayload):
@classmethod
def unpack_group_id(cls, group_id_in_bytes):
- group_id = cls.attempt_convert_uuid_bytes_to_hex(group_id_in_bytes)
+ (is_stored_as_bytes, group_id) = group_id_in_bytes
+ if is_stored_as_bytes:
+ group_id = cls.attempt_convert_uuid_bytes_to_hex(group_id)
return {'id': group_id}
@classmethod
@@ -596,10 +623,14 @@ class FederatedUnscopedPayload(BasePayload):
"""
- user_id = cls.attempt_convert_uuid_bytes_to_hex(payload[0])
+ (is_stored_as_bytes, user_id) = payload[0]
+ if is_stored_as_bytes:
+ user_id = cls.attempt_convert_uuid_bytes_to_hex(user_id)
methods = auth_plugins.convert_integer_to_method_list(payload[1])
group_ids = list(map(cls.unpack_group_id, payload[2]))
- idp_id = cls.attempt_convert_uuid_bytes_to_hex(payload[3])
+ (is_stored_as_bytes, idp_id) = payload[3]
+ if is_stored_as_bytes:
+ idp_id = cls.attempt_convert_uuid_bytes_to_hex(idp_id)
protocol_id = payload[4]
expires_at_str = cls._convert_int_to_time_string(payload[5])
audit_ids = list(map(provider.base64_encode, payload[6]))
@@ -653,11 +684,17 @@ class FederatedScopedPayload(FederatedUnscopedPayload):
group IDs
"""
- user_id = cls.attempt_convert_uuid_bytes_to_hex(payload[0])
+ (is_stored_as_bytes, user_id) = payload[0]
+ if is_stored_as_bytes:
+ user_id = cls.attempt_convert_uuid_bytes_to_hex(user_id)
methods = auth_plugins.convert_integer_to_method_list(payload[1])
- scope_id = cls.attempt_convert_uuid_bytes_to_hex(payload[2])
+ (is_stored_as_bytes, scope_id) = payload[2]
+ if is_stored_as_bytes:
+ scope_id = cls.attempt_convert_uuid_bytes_to_hex(scope_id)
group_ids = list(map(cls.unpack_group_id, payload[3]))
- idp_id = cls.attempt_convert_uuid_bytes_to_hex(payload[4])
+ (is_stored_as_bytes, idp_id) = payload[4]
+ if is_stored_as_bytes:
+ idp_id = cls.attempt_convert_uuid_bytes_to_hex(idp_id)
protocol_id = payload[5]
expires_at_str = cls._convert_int_to_time_string(payload[6])
audit_ids = list(map(provider.base64_encode, payload[7]))
diff --git a/keystone-moon/releasenotes/notes/.placeholder b/keystone-moon/releasenotes/notes/.placeholder
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/keystone-moon/releasenotes/notes/.placeholder
diff --git a/keystone-moon/releasenotes/notes/deprecations-c4afc19dc5324b9c.yaml b/keystone-moon/releasenotes/notes/deprecations-c4afc19dc5324b9c.yaml
new file mode 100644
index 00000000..0c1c4f11
--- /dev/null
+++ b/keystone-moon/releasenotes/notes/deprecations-c4afc19dc5324b9c.yaml
@@ -0,0 +1,19 @@
+---
+other:
+ - Running keystone in eventlet remains deprecated and will be removed in the
+ Mitaka release.
+ - Using LDAP as the resource backend, i.e for projects and domains, is now
+ deprecated and will be removed in the Mitaka release.
+ - Using the full path to the driver class is deprecated in favor of using
+ the entrypoint. In the Mitaka release, the entrypoint must be used.
+ - In the [resource] and [role] sections of the ``keystone.conf`` file, not
+ specifying the driver and using the assignment driver is deprecated. In
+ the Mitaka release, the resource and role drivers will default to the SQL
+ driver.
+ - In ``keystone-paste.ini``, using ``paste.filter_factory`` is deprecated in
+ favor of the "use" directive, specifying an entrypoint.
+ - Not specifying a domain during a create user, group or project call, which
+ relied on falling back to the default domain, is now deprecated and will
+ be removed in the N release.
+ - Certain deprecated methods from the assignment manager were removed in
+ favor of the same methods in the [resource] and [role] manager.
diff --git a/keystone-moon/releasenotes/notes/new_features-e33d793d8a5ca76a.yaml b/keystone-moon/releasenotes/notes/new_features-e33d793d8a5ca76a.yaml
new file mode 100644
index 00000000..06e1db2c
--- /dev/null
+++ b/keystone-moon/releasenotes/notes/new_features-e33d793d8a5ca76a.yaml
@@ -0,0 +1,21 @@
+---
+features:
+ - >
+ **Experimental** - Domain specific configuration options can be stored in
+ SQL instead of configuration files, using the new REST APIs.
+ - >
+ **Experimental** - Keystone now supports tokenless authorization with
+ X.509 SSL client certificate.
+ - Configuring per-Identity Provider WebSSO is now supported.
+ - >
+ ``openstack_user_domain`` and ``openstack_project_domain`` attributes were
+ added to SAML assertion in order to map user and project domains,
+ respectively.
+ - The credentials list call can now have its results filtered by credential
+ type.
+ - Support was improved for out-of-tree drivers by defining stable driver
+ interfaces.
+ - Several features were hardened, including Fernet tokens, federation,
+ domain specific configurations from database and role assignments.
+ - Certain variables in ``keystone.conf`` now have options, which determine
+ if the user's setting is valid.
diff --git a/keystone-moon/releasenotes/notes/upgrade_notes-ca81f5d531ab3522.yaml b/keystone-moon/releasenotes/notes/upgrade_notes-ca81f5d531ab3522.yaml
new file mode 100644
index 00000000..be8282ce
--- /dev/null
+++ b/keystone-moon/releasenotes/notes/upgrade_notes-ca81f5d531ab3522.yaml
@@ -0,0 +1,31 @@
+---
+upgrade:
+ - The EC2 token middleware, deprecated in Juno, is no longer available in
+ keystone. It has been moved to the keystonemiddleware package.
+ - The ``compute_port`` configuration option, deprecated in Juno, is no longer
+ available.
+ - The XML middleware stub has been removed, so references to it must be
+ removed from the ``keystone-paste.ini`` configuration file.
+ - stats_monitoring and stats_reporting paste filters have been removed, so
+ references to it must be removed from the ``keystone-paste.ini``
+ configuration file.
+ - The external authentication plugins ExternalDefault, ExternalDomain,
+ LegacyDefaultDomain, and LegacyDomain, deprecated in Icehouse, are no
+ longer available.
+ - The ``keystone.conf`` file now references entrypoint names for drivers.
+ For example, the drivers are now specified as "sql", "ldap", "uuid",
+ rather than the full module path. See the sample configuration file for
+ other examples.
+ - We now expose entrypoints for the ``keystone-manage`` command instead of a
+ file.
+ - Schema downgrades via ``keystone-manage db_sync`` are no longer supported.
+ Only upgrades are supported.
+ - Features that were "extensions" in previous releases (OAuth delegation,
+ Federated Identity support, Endpoint Policy, etc) are now enabled by
+ default.
+ - A new ``secure_proxy_ssl_header`` configuration option is available when
+ running keystone behind a proxy.
+ - Several configuration options have been deprecated, renamed, or moved to
+ new sections in the ``keystone.conf`` file.
+ - Domain name information can now be used in policy rules with the attribute
+ ``domain_name``.
diff --git a/keystone-moon/releasenotes/source/_static/.placeholder b/keystone-moon/releasenotes/source/_static/.placeholder
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/keystone-moon/releasenotes/source/_static/.placeholder
diff --git a/keystone-moon/releasenotes/source/_templates/.placeholder b/keystone-moon/releasenotes/source/_templates/.placeholder
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/keystone-moon/releasenotes/source/_templates/.placeholder
diff --git a/keystone-moon/releasenotes/source/conf.py b/keystone-moon/releasenotes/source/conf.py
new file mode 100644
index 00000000..6df2e041
--- /dev/null
+++ b/keystone-moon/releasenotes/source/conf.py
@@ -0,0 +1,275 @@
+# -*- coding: utf-8 -*-
+# 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.
+
+# Keystone Release Notes documentation build configuration file, created by
+# sphinx-quickstart on Tue Nov 3 17:40:50 2015.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+# sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'oslosphinx',
+ 'reno.sphinxext',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+# source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Keystone Release Notes'
+copyright = u'2015, Keystone Developers'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+import pbr.version
+keystone_version = pbr.version.VersionInfo('keystone')
+# The full version, including alpha/beta/rc tags.
+release = keystone_version.version_string_with_vcs()
+# The short X.Y version.
+version = keystone_version.canonical_version_string()
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+# language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+# today = ''
+# Else, today_fmt is used as the format for a strftime call.
+# today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = []
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+# default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+# add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+# add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+# show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+# modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+# keep_warnings = False
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+# html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+# html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+# html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+# html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+# html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+# html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+# html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+# html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+# html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+# html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+# html_additional_pages = {}
+
+# If false, no module index is generated.
+# html_domain_indices = True
+
+# If false, no index is generated.
+# html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+# html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+# html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+# html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+# html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+# html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+# html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'KeystoneReleaseNotesdoc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+ # The paper size ('letterpaper' or 'a4paper').
+ # 'papersize': 'letterpaper',
+
+ # The font size ('10pt', '11pt' or '12pt').
+ # 'pointsize': '10pt',
+
+ # Additional stuff for the LaTeX preamble.
+ # 'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ ('index', 'KeystoneReleaseNotes.tex',
+ u'Keystone Release Notes Documentation',
+ u'Keystone Developers', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+# latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+# latex_use_parts = False
+
+# If true, show page references after internal links.
+# latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+# latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+# latex_appendices = []
+
+# If false, no module index is generated.
+# latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'keystonereleasenotes', u'Keystone Release Notes Documentation',
+ [u'Keystone Developers'], 1)
+]
+
+# If true, show URL addresses after external links.
+# man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'KeystoneReleaseNotes', u'Keystone Release Notes Documentation',
+ u'Keystone Developers', 'KeystoneReleaseNotes',
+ 'Identity, Authentication and Access Management for OpenStack.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+# texinfo_appendices = []
+
+# If false, no module index is generated.
+# texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+# texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+# texinfo_no_detailmenu = False
diff --git a/keystone-moon/releasenotes/source/index.rst b/keystone-moon/releasenotes/source/index.rst
new file mode 100644
index 00000000..9139d688
--- /dev/null
+++ b/keystone-moon/releasenotes/source/index.rst
@@ -0,0 +1,9 @@
+========================
+ Keystone Release Notes
+========================
+
+.. toctree::
+ :maxdepth: 1
+
+ liberty
+ unreleased
diff --git a/keystone-moon/releasenotes/source/liberty.rst b/keystone-moon/releasenotes/source/liberty.rst
new file mode 100644
index 00000000..36217be8
--- /dev/null
+++ b/keystone-moon/releasenotes/source/liberty.rst
@@ -0,0 +1,6 @@
+==============================
+ Liberty Series Release Notes
+==============================
+
+.. release-notes::
+ :branch: origin/stable/liberty
diff --git a/keystone-moon/releasenotes/source/unreleased.rst b/keystone-moon/releasenotes/source/unreleased.rst
new file mode 100644
index 00000000..cd22aabc
--- /dev/null
+++ b/keystone-moon/releasenotes/source/unreleased.rst
@@ -0,0 +1,5 @@
+==============================
+ Current Series Release Notes
+==============================
+
+.. release-notes::
diff --git a/keystone-moon/requirements.txt b/keystone-moon/requirements.txt
index 555a148f..8bc177b1 100644
--- a/keystone-moon/requirements.txt
+++ b/keystone-moon/requirements.txt
@@ -16,12 +16,12 @@ SQLAlchemy<1.1.0,>=0.9.9
sqlalchemy-migrate>=0.9.6
stevedore>=1.5.0 # Apache-2.0
passlib>=1.6
-python-keystoneclient>=1.6.0
-keystonemiddleware>=2.0.0
+python-keystoneclient!=1.8.0,>=1.6.0
+keystonemiddleware!=2.4.0,>=2.0.0
oslo.concurrency>=2.3.0 # Apache-2.0
oslo.config>=2.3.0 # Apache-2.0
oslo.context>=0.2.0 # Apache-2.0
-oslo.messaging!=1.17.0,!=1.17.1,>=1.16.0 # Apache-2.0
+oslo.messaging!=1.17.0,!=1.17.1,!=2.6.0,!=2.6.1,!=2.7.0,!=2.8.0,!=2.8.1,!=2.9.0,>=1.16.0 # Apache-2.0
oslo.db>=2.4.1 # Apache-2.0
oslo.i18n>=1.5.0 # Apache-2.0
oslo.log>=1.8.0 # Apache-2.0
@@ -29,7 +29,7 @@ oslo.middleware>=2.8.0 # Apache-2.0
oslo.policy>=0.5.0 # Apache-2.0
oslo.serialization>=1.4.0 # Apache-2.0
oslo.service>=0.7.0 # Apache-2.0
-oslo.utils>=2.0.0 # Apache-2.0
+oslo.utils!=2.6.0,>=2.0.0 # Apache-2.0
oauthlib>=0.6
pysaml2>=2.4.0
dogpile.cache>=0.5.4
diff --git a/keystone-moon/setup.cfg b/keystone-moon/setup.cfg
index c40aa3b8..7788537e 100644
--- a/keystone-moon/setup.cfg
+++ b/keystone-moon/setup.cfg
@@ -1,6 +1,5 @@
[metadata]
name = keystone
-version = 9.0.0
summary = OpenStack Identity
description-file =
README.rst
@@ -171,18 +170,6 @@ keystone.revoke =
kvs = keystone.contrib.revoke.backends.kvs:Revoke
sql = keystone.contrib.revoke.backends.sql:Revoke
-keystone.moon.configuration =
- ram = keystone.contrib.moon.backends.memory:ConfigurationConnector
-
-keystone.moon.intraextension =
- sql = keystone.contrib.moon.backends.sql:IntraExtensionConnector
-
-keystone.moon.log =
- flat = keystone.contrib.moon.backends.flat:LogConnector
-
-keystone.moon.tenant =
- sql = keystone.contrib.moon.backends.sql:TenantConnector
-
oslo.config.opts =
keystone = keystone.common.config:list_opts
keystone.notifications = keystone.notifications:list_opts
@@ -196,7 +183,6 @@ paste.filter_factory =
ec2_extension = keystone.contrib.ec2:Ec2Extension.factory
ec2_extension_v3 = keystone.contrib.ec2:Ec2ExtensionV3.factory
federation_extension = keystone.contrib.federation.routers:FederationExtension.factory
- moon_extension = keystone.contrib.moon.routers:Routers.factory
json_body = keystone.middleware:JsonBodyMiddleware.factory
oauth1_extension = keystone.contrib.oauth1.routers:OAuth1Extension.factory
request_id = oslo_middleware:RequestId.factory
diff --git a/keystone-moon/test-requirements.txt b/keystone-moon/test-requirements.txt
index a027613f..f10b9929 100644
--- a/keystone-moon/test-requirements.txt
+++ b/keystone-moon/test-requirements.txt
@@ -29,8 +29,9 @@ testtools>=1.4.0
# For documentation
oslosphinx>=2.5.0 # Apache-2.0
+reno>=0.1.1 # Apache2
tempest-lib>=0.8.0
# Functional tests.
-requests>=2.5.2
+requests!=2.8.0,>=2.5.2
diff --git a/keystone-moon/tox.ini b/keystone-moon/tox.ini
index 0d249105..af1d9b82 100644
--- a/keystone-moon/tox.ini
+++ b/keystone-moon/tox.ini
@@ -1,7 +1,7 @@
[tox]
minversion = 1.6
skipsdist = True
-envlist = py27,py34,pep8,docs,genconfig
+envlist = py27,py34,pep8,docs,genconfig,releasenotes
[testenv]
usedevelop = True
@@ -97,6 +97,9 @@ commands=
bash -c "rm -rf doc/source/api"
python setup.py build_sphinx
+[testenv:releasenotes]
+commands = sphinx-build -a -E -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
+
[testenv:genconfig]
commands = oslo-config-generator --config-file=config-generator/keystone.conf