summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorM V P Nitesh <m.nitesh@nectechnologies.in>2017-08-07 18:41:35 +0530
committerDeepak Mourya <deepakmoriya7@gmail.com>2018-09-06 05:09:10 +0000
commit430d7f765a75830ae377545bc57195d38e44e172 (patch)
tree9315e209364c09a91fbb8806667e365719eee525
parent9e107fdd64adc0c9507d3810db9010e05ce72ba8 (diff)
downloadkeystone-430d7f765a75830ae377545bc57195d38e44e172.tar.gz
Added support for a ``description`` attribute for Identity Roles
Now user can add the description to the role when user creates the role. Added support for a ``description`` attribute for V3 Identity Roles. Co-Authored-By: wangxiyuan<wangxiyuan@huawei.com> Co-Authored-By: Deepak Mourya<deepakmoriya7@gmail.com> Change-Id: I230af9cc833af13064636b5d9a7ce6334c3f6e9a Closes-Bug: #1669080
-rw-r--r--api-ref/source/v3/parameters.yaml18
-rw-r--r--api-ref/source/v3/roles.inc6
-rw-r--r--api-ref/source/v3/samples/admin/domain-specific-role-create-request.json1
-rw-r--r--api-ref/source/v3/samples/admin/role-create-request.json1
-rw-r--r--api-ref/source/v3/samples/admin/role-create-response.json1
-rw-r--r--api-ref/source/v3/samples/admin/role-inferences-response.json6
-rw-r--r--api-ref/source/v3/samples/admin/role-show-response.json1
-rw-r--r--api-ref/source/v3/samples/admin/role-update-request.json1
-rw-r--r--api-ref/source/v3/samples/admin/role-update-response.json1
-rw-r--r--api-ref/source/v3/samples/admin/roles-list-response.json5
-rw-r--r--keystone/assignment/role_backends/sql.py4
-rw-r--r--keystone/assignment/schema.py3
-rw-r--r--keystone/common/sql/contract_repo/versions/053_contract_add_role_description_to_role_table.py15
-rw-r--r--keystone/common/sql/data_migration_repo/versions/053_migrate_add_role_description_to_role_table.py15
-rw-r--r--keystone/common/sql/expand_repo/versions/053_expand_add_role_description_to_role_table.py23
-rw-r--r--keystone/tests/unit/assignment/test_core.py25
-rw-r--r--keystone/tests/unit/core.py1
-rw-r--r--keystone/tests/unit/test_sql_upgrade.py39
-rw-r--r--keystone/tests/unit/test_v3.py1
-rw-r--r--keystone/tests/unit/test_validation.py14
-rw-r--r--releasenotes/notes/add-description-to-role-88ab5bb8a96cc002.yaml6
21 files changed, 185 insertions, 2 deletions
diff --git a/api-ref/source/v3/parameters.yaml b/api-ref/source/v3/parameters.yaml
index 6e77e51da..0b9690065 100644
--- a/api-ref/source/v3/parameters.yaml
+++ b/api-ref/source/v3/parameters.yaml
@@ -1665,6 +1665,24 @@ role_assignments:
in: body
required: true
type: array
+role_description_create_body:
+ description: |
+ Add description about the role.
+ in: body
+ required: false
+ type: string
+role_description_response_body:
+ description: |
+ The role description.
+ in: body
+ required: false
+ type: string
+role_description_update_body:
+ description: |
+ The new role description.
+ in: body
+ required: false
+ type: string
role_domain_id_request_body:
description: |
The ID of the domain of the role.
diff --git a/api-ref/source/v3/roles.inc b/api-ref/source/v3/roles.inc
index 076017717..3d9435058 100644
--- a/api-ref/source/v3/roles.inc
+++ b/api-ref/source/v3/roles.inc
@@ -133,6 +133,7 @@ Parameters
- id: role_id_response_body
- links: link_response_body
- name: role_name_response_body
+ - description: role_description_response_body
Status Codes
~~~~~~~~~~~~
@@ -174,6 +175,7 @@ Parameters
- role: role
- name: role_name_create_body
- domain_id: role_domain_id_request_body
+ - description: role_description_create_body
Example
~~~~~~~
@@ -200,6 +202,7 @@ Parameters
- id: role_id_response_body
- links: link_response_body
- name: role_name_response_body
+ - description: role_description_response_body
Status Codes
~~~~~~~~~~~~
@@ -248,6 +251,7 @@ Parameters
- id: role_id_response_body
- links: link_response_body
- name: role_name_response_body
+ - description: role_description_response_body
Status Codes
~~~~~~~~~~~~
@@ -290,6 +294,7 @@ Parameters
- role_id: role_id_path
- role: role
- name: role_name_update_body
+ - description: role_description_update_body
Example
~~~~~~~
@@ -310,6 +315,7 @@ Parameters
- id: role_id_response_body
- links: link_response_body
- name: role_name_response_body
+ - description: role_description_response_body
Status Codes
~~~~~~~~~~~~
diff --git a/api-ref/source/v3/samples/admin/domain-specific-role-create-request.json b/api-ref/source/v3/samples/admin/domain-specific-role-create-request.json
index 428022c8a..d328c14a3 100644
--- a/api-ref/source/v3/samples/admin/domain-specific-role-create-request.json
+++ b/api-ref/source/v3/samples/admin/domain-specific-role-create-request.json
@@ -1,5 +1,6 @@
{
"role": {
+ "description": "My new role"
"domain_id": "92e782c4988642d783a95f4a87c3fdd7",
"name": "developer"
}
diff --git a/api-ref/source/v3/samples/admin/role-create-request.json b/api-ref/source/v3/samples/admin/role-create-request.json
index 67e4099eb..21f1e43e3 100644
--- a/api-ref/source/v3/samples/admin/role-create-request.json
+++ b/api-ref/source/v3/samples/admin/role-create-request.json
@@ -1,5 +1,6 @@
{
"role": {
+ "description": "My new role",
"name": "developer"
}
}
diff --git a/api-ref/source/v3/samples/admin/role-create-response.json b/api-ref/source/v3/samples/admin/role-create-response.json
index 77f457d10..3a1c8ae8d 100644
--- a/api-ref/source/v3/samples/admin/role-create-response.json
+++ b/api-ref/source/v3/samples/admin/role-create-response.json
@@ -4,6 +4,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/1e443fa8cee3482a8a2b6954dd5c8f12"
},
+ "description": "My new role",
"name": "developer"
}
}
diff --git a/api-ref/source/v3/samples/admin/role-inferences-response.json b/api-ref/source/v3/samples/admin/role-inferences-response.json
index 505a6e1ea..077a7ea04 100644
--- a/api-ref/source/v3/samples/admin/role-inferences-response.json
+++ b/api-ref/source/v3/samples/admin/role-inferences-response.json
@@ -6,6 +6,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/1acd3c5aa0e246b9a7427d252160dcd1"
},
+ "description": "My new role",
"name": "prior role name"
},
"implies": [
@@ -14,6 +15,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/3602510e2e1f499589f78a0724dcf614"
},
+ "description": "My new role",
"name": "implied role1 name"
},
{
@@ -21,6 +23,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/738289aeef684e73a987f7cf2ec6d925"
},
+ "description": "My new role",
"name": "implied role2 name"
}
]
@@ -31,6 +34,7 @@
"links": {
"self" : "http://example.com/identity/v3/roles/bbf7a5098bb34407b7164eb6ff9f144e"
},
+ "description": "My new role",
"name": "prior role name"
},
"implies": [
@@ -39,6 +43,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/872b20ad124c4c1bafaef2b1aae316ab"
},
+ "description": null,
"name": "implied role1 name"
},
{
@@ -46,6 +51,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/1d865b1b2da14cb7b05254677e5f36a2"
},
+ "description": null,
"name": "implied role2 name"
}
]
diff --git a/api-ref/source/v3/samples/admin/role-show-response.json b/api-ref/source/v3/samples/admin/role-show-response.json
index e93de6da1..4cb7000c4 100644
--- a/api-ref/source/v3/samples/admin/role-show-response.json
+++ b/api-ref/source/v3/samples/admin/role-show-response.json
@@ -5,6 +5,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/1e443fa8cee3482a8a2b6954dd5c8f12"
},
+ "description": "My new role",
"name": "Developer"
}
}
diff --git a/api-ref/source/v3/samples/admin/role-update-request.json b/api-ref/source/v3/samples/admin/role-update-request.json
index 9a13ea724..b24a2bd2e 100644
--- a/api-ref/source/v3/samples/admin/role-update-request.json
+++ b/api-ref/source/v3/samples/admin/role-update-request.json
@@ -1,5 +1,6 @@
{
"role": {
+ "description": "My new role",
"name": "Developer"
}
}
diff --git a/api-ref/source/v3/samples/admin/role-update-response.json b/api-ref/source/v3/samples/admin/role-update-response.json
index b9c86efdd..1fd075f3e 100644
--- a/api-ref/source/v3/samples/admin/role-update-response.json
+++ b/api-ref/source/v3/samples/admin/role-update-response.json
@@ -5,6 +5,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/1e443fa8cee3482a8a2b6954dd5c8f12"
},
+ "description": "My new role",
"name": "Developer"
}
}
diff --git a/api-ref/source/v3/samples/admin/roles-list-response.json b/api-ref/source/v3/samples/admin/roles-list-response.json
index 1f380b370..096ea0dd7 100644
--- a/api-ref/source/v3/samples/admin/roles-list-response.json
+++ b/api-ref/source/v3/samples/admin/roles-list-response.json
@@ -10,6 +10,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/5318e65d75574c17bf5339d3df33a5a3"
},
+ "description": "My new role",
"name": "admin"
},
{
@@ -17,6 +18,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/642bcfc75c384fd181adf34d9b2df897"
},
+ "description": "My new role",
"name": "anotherrole"
},
{
@@ -24,6 +26,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/779a76d74f544224a7ef8762ca0de627"
},
+ "description": "My new role",
"name": "Member"
},
{
@@ -38,6 +41,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/ba2dfba61c934ee89e3110de36273229"
},
+ "description": "My new role",
"name": "ResellerAdmin"
},
{
@@ -45,6 +49,7 @@
"links": {
"self": "http://example.com/identity/v3/roles/f127b97616f24d3ebceb7be840210adc"
},
+ "description": null,
"name": "service"
}
]
diff --git a/keystone/assignment/role_backends/sql.py b/keystone/assignment/role_backends/sql.py
index 081e1517d..a8b7cbf7e 100644
--- a/keystone/assignment/role_backends/sql.py
+++ b/keystone/assignment/role_backends/sql.py
@@ -83,6 +83,7 @@ class Role(base.RoleDriverBase):
if attr != 'id':
setattr(ref, attr, getattr(new_role, attr))
ref.extra = new_role.extra
+ ref.description = new_role.description
return ref.to_dict()
def delete_role(self, role_id):
@@ -193,10 +194,11 @@ class RoleTable(sql.ModelBase, sql.ModelDictMixinWithExtras):
return super(RoleTable, cls).from_dict(new_dict)
__tablename__ = 'role'
- attributes = ['id', 'name', 'domain_id']
+ attributes = ['id', 'name', 'domain_id', 'description']
id = sql.Column(sql.String(64), primary_key=True)
name = sql.Column(sql.String(255), nullable=False)
domain_id = sql.Column(sql.String(64), nullable=False,
server_default=NULL_DOMAIN_ID)
+ description = sql.Column(sql.String(255), nullable=True)
extra = sql.Column(sql.JsonBlob())
__table_args__ = (sql.UniqueConstraint('name', 'domain_id'),)
diff --git a/keystone/assignment/schema.py b/keystone/assignment/schema.py
index 000c00229..564ab0aec 100644
--- a/keystone/assignment/schema.py
+++ b/keystone/assignment/schema.py
@@ -15,7 +15,8 @@ from keystone.common.validation import parameter_types
# Schema for Identity v3 API
_role_properties = {
- 'name': parameter_types.name
+ 'name': parameter_types.name,
+ 'description': parameter_types.description
}
role_create = {
diff --git a/keystone/common/sql/contract_repo/versions/053_contract_add_role_description_to_role_table.py b/keystone/common/sql/contract_repo/versions/053_contract_add_role_description_to_role_table.py
new file mode 100644
index 000000000..8aa15c1ef
--- /dev/null
+++ b/keystone/common/sql/contract_repo/versions/053_contract_add_role_description_to_role_table.py
@@ -0,0 +1,15 @@
+# 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.
+
+
+def upgrade(migrate_engine):
+ pass
diff --git a/keystone/common/sql/data_migration_repo/versions/053_migrate_add_role_description_to_role_table.py b/keystone/common/sql/data_migration_repo/versions/053_migrate_add_role_description_to_role_table.py
new file mode 100644
index 000000000..8aa15c1ef
--- /dev/null
+++ b/keystone/common/sql/data_migration_repo/versions/053_migrate_add_role_description_to_role_table.py
@@ -0,0 +1,15 @@
+# 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.
+
+
+def upgrade(migrate_engine):
+ pass
diff --git a/keystone/common/sql/expand_repo/versions/053_expand_add_role_description_to_role_table.py b/keystone/common/sql/expand_repo/versions/053_expand_add_role_description_to_role_table.py
new file mode 100644
index 000000000..99e41ff15
--- /dev/null
+++ b/keystone/common/sql/expand_repo/versions/053_expand_add_role_description_to_role_table.py
@@ -0,0 +1,23 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import sqlalchemy as sql
+
+
+def upgrade(migrate_engine):
+ meta = sql.MetaData()
+ meta.bind = migrate_engine
+
+ role_table = sql.Table('role', meta, autoload=True)
+ description = sql.Column('description', sql.String(255),
+ nullable=True)
+ role_table.create_column(description)
diff --git a/keystone/tests/unit/assignment/test_core.py b/keystone/tests/unit/assignment/test_core.py
index 1eac5ba2e..003b9b0aa 100644
--- a/keystone/tests/unit/assignment/test_core.py
+++ b/keystone/tests/unit/assignment/test_core.py
@@ -82,6 +82,31 @@ class RoleTests(object):
PROVIDERS.role_api.get_role,
role['id'])
+ def test_role_crud_without_description(self):
+ role = {
+ 'id': uuid.uuid4().hex,
+ 'name': uuid.uuid4().hex,
+ 'domain_id': None,
+ }
+ self.role_api.create_role(role['id'], role)
+ role_ref = self.role_api.get_role(role['id'])
+ role_ref_dict = {x: role_ref[x] for x in role_ref}
+ self.assertIsNone(role_ref_dict['description'])
+ role_ref_dict.pop('description')
+ self.assertDictEqual(role, role_ref_dict)
+
+ role['name'] = uuid.uuid4().hex
+ updated_role_ref = self.role_api.update_role(role['id'], role)
+ role_ref = self.role_api.get_role(role['id'])
+ role_ref_dict = {x: role_ref[x] for x in role_ref}
+ self.assertIsNone(updated_role_ref['description'])
+ self.assertDictEqual(role_ref_dict, updated_role_ref)
+
+ self.role_api.delete_role(role['id'])
+ self.assertRaises(exception.RoleNotFound,
+ self.role_api.get_role,
+ role['id'])
+
def test_update_role_returns_not_found(self):
role = unit.new_role_ref()
self.assertRaises(exception.RoleNotFound,
diff --git a/keystone/tests/unit/core.py b/keystone/tests/unit/core.py
index 2034ba5fe..1c13a776a 100644
--- a/keystone/tests/unit/core.py
+++ b/keystone/tests/unit/core.py
@@ -385,6 +385,7 @@ def new_role_ref(**kwargs):
ref = {
'id': uuid.uuid4().hex,
'name': uuid.uuid4().hex,
+ 'description': uuid.uuid4().hex,
'domain_id': None
}
ref.update(kwargs)
diff --git a/keystone/tests/unit/test_sql_upgrade.py b/keystone/tests/unit/test_sql_upgrade.py
index a1a328eb3..06477614d 100644
--- a/keystone/tests/unit/test_sql_upgrade.py
+++ b/keystone/tests/unit/test_sql_upgrade.py
@@ -3140,6 +3140,45 @@ class FullMigration(SqlMigrateBase, unit.TestCase):
)
self.assertTrue(self.does_fk_exist('limit', 'registered_limit_id'))
+ def test_migration_053_adds_description_to_role(self):
+ self.expand(52)
+ self.migrate(52)
+ self.contract(52)
+
+ role_table_name = 'role'
+ self.assertTableColumns(
+ role_table_name,
+ ['id', 'name', 'domain_id', 'extra']
+ )
+
+ self.expand(53)
+ self.migrate(53)
+ self.contract(53)
+
+ self.assertTableColumns(
+ role_table_name,
+ ['id', 'name', 'domain_id', 'extra', 'description']
+ )
+
+ role_table = sqlalchemy.Table(
+ role_table_name, self.metadata, autoload=True
+ )
+
+ role = {
+ 'id': uuid.uuid4().hex,
+ 'name': "test",
+ 'domain_id': resource_base.NULL_DOMAIN_ID,
+ 'description': "This is a string"
+ }
+ role_table.insert().values(role).execute()
+
+ role_without_description = {
+ 'id': uuid.uuid4().hex,
+ 'name': "test1",
+ 'domain_id': resource_base.NULL_DOMAIN_ID
+ }
+ role_table.insert().values(role_without_description).execute()
+
class MySQLOpportunisticFullMigration(FullMigration):
FIXTURE = db_fixtures.MySQLOpportunisticFixture
diff --git a/keystone/tests/unit/test_v3.py b/keystone/tests/unit/test_v3.py
index 447be08e1..29a5e93f5 100644
--- a/keystone/tests/unit/test_v3.py
+++ b/keystone/tests/unit/test_v3.py
@@ -53,6 +53,7 @@ class RestfulTestCase(unit.SQLDriverOverrides, rest.RestfulTestCase,
'properties': {
'id': {'type': 'string', },
'name': {'type': 'string', },
+ 'description': {'type': 'string', },
},
'required': ['id', 'name', ],
'additionalProperties': False,
diff --git a/keystone/tests/unit/test_validation.py b/keystone/tests/unit/test_validation.py
index cd34a5a27..800d0ab7d 100644
--- a/keystone/tests/unit/test_validation.py
+++ b/keystone/tests/unit/test_validation.py
@@ -755,6 +755,20 @@ class RoleValidationTestCase(unit.BaseTestCase):
self.create_role_validator.validate,
request_to_validate)
+ def test_validate_role_request_with_valid_description(self):
+ """Test we can validate`description` in create role request."""
+ request_to_validate = {'name': self.role_name,
+ 'description': 'My Role'}
+ self.create_role_validator.validate(request_to_validate)
+
+ def test_validate_role_request_fails_with_invalid_description(self):
+ """Exception is raised when `description` as a non-string value."""
+ request_to_validate = {'name': self.role_name,
+ 'description': False}
+ self.assertRaises(exception.SchemaValidationError,
+ self.create_role_validator.validate,
+ request_to_validate)
+
def test_validate_role_update_request(self):
"""Test that we validate a role update request."""
request_to_validate = {'name': 'My New Role'}
diff --git a/releasenotes/notes/add-description-to-role-88ab5bb8a96cc002.yaml b/releasenotes/notes/add-description-to-role-88ab5bb8a96cc002.yaml
new file mode 100644
index 000000000..f1d9ad17e
--- /dev/null
+++ b/releasenotes/notes/add-description-to-role-88ab5bb8a96cc002.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ [`bug 1669080 <https://bugs.launchpad.net/keystone/+bug/1669080>`_]
+ Added support for a ``description`` attribute for V3 Identity Roles, see
+ API docs for details.