Limit description support

This patch added description support for registered
limit and project limit.

Closes-Bug: #1754185
Change-Id: Ia2023ca809b8c2f58af648cb7377f41cd220725b
This commit is contained in:
wangxiyuan 2018-03-15 10:56:51 +08:00
parent 403917cef9
commit 9d7ffbc89e
21 changed files with 249 additions and 49 deletions

View File

@ -626,6 +626,18 @@ default_project_id_update_body:
in: body
required: false
type: string
description_limit_request_body:
description: |
The limit description.
in: body
required: false
type: string
description_limit_response_body:
description: |
The limit description.
in: body
required: true
type: string
description_region_request_body:
description: |
The region description.
@ -638,6 +650,18 @@ description_region_response_body:
in: body
required: true
type: string
description_registered_limit_request_body:
description: |
The registered limit description.
in: body
required: false
type: string
description_registered_limit_response_body:
description: |
The registered limit description.
in: body
required: true
type: string
domain:
description: |
A ``domain`` object, containing:

View File

@ -8,6 +8,7 @@
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"project_id": "3a705b9f56bb439381b43c4fe59dccce",
"id": "25a04c7a065c430590881c646cdcdd58",
"resource_limit": 11
"resource_limit": 11,
"description": ""
}
}

View File

@ -11,7 +11,8 @@
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"project_id": "3a705b9f56bb439381b43c4fe59dccce",
"resource_name": "volume",
"resource_limit": 10
"resource_limit": 10,
"description": "Number of volumes for project 3a705b9f56bb439381b43c4fe59dccce"
}
]
}

View File

@ -9,7 +9,8 @@
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"project_id": "3a705b9f56bb439381b43c4fe59dccce",
"id": "25a04c7a065c430590881c646cdcdd58",
"resource_limit": 10
"resource_limit": 10,
"description": "Number of volumes for project 3a705b9f56bb439381b43c4fe59dccce"
},
{
"resource_name": "snapshot",
@ -20,7 +21,8 @@
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"project_id": "3a705b9f56bb439381b43c4fe59dccce",
"id": "3229b3849f584faea483d6851f7aab05",
"resource_limit": 5
"resource_limit": 5,
"description": ""
}
]
}

View File

@ -14,7 +14,8 @@
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"project_id": "3a705b9f56bb439381b43c4fe59dccce",
"id": "25a04c7a065c430590881c646cdcdd58",
"resource_limit": 11
"resource_limit": 11,
"description": "Number of volumes for project 3a705b9f56bb439381b43c4fe59dccce"
},
{
"resource_name": "snapshot",
@ -25,7 +26,8 @@
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"project_id": "3a705b9f56bb439381b43c4fe59dccce",
"id": "3229b3849f584faea483d6851f7aab05",
"resource_limit": 5
"resource_limit": 5,
"description": ""
}
]
}

View File

@ -6,7 +6,8 @@
},
{
"id": "3229b3849f584faea483d6851f7aab05",
"resource_limit": 5
"resource_limit": 5,
"description": "Number of snapshots for project 3a705b9f56bb439381b43c4fe59dccce"
}
]
}

View File

@ -9,7 +9,8 @@
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"project_id": "3a705b9f56bb439381b43c4fe59dccce",
"id": "25a04c7a065c430590881c646cdcdd58",
"resource_limit": 11
"resource_limit": 11,
"description": ""
},
{
"resource_name": "snapshot",
@ -20,7 +21,8 @@
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"project_id": "3a705b9f56bb439381b43c4fe59dccce",
"id": "3229b3849f584faea483d6851f7aab05",
"resource_limit": 5
"resource_limit": 5,
"description": "Number of snapshots for project 3a705b9f56bb439381b43c4fe59dccce"
}
]
}

View File

@ -7,6 +7,7 @@
},
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"default_limit": 10,
"id": "773147dd53cd4a17b921d555cf17c633"
"id": "773147dd53cd4a17b921d555cf17c633",
"description": "Number of volumes"
}
}

View File

@ -9,7 +9,8 @@
{
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"resource_name": "volume",
"default_limit": 10
"default_limit": 10,
"description": "Number of volumes"
}
]
}

View File

@ -8,7 +8,8 @@
},
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"default_limit": 10,
"id": "773147dd53cd4a17b921d555cf17c633"
"id": "773147dd53cd4a17b921d555cf17c633",
"description": "Number of volumes"
},
{
"resource_name": "snapshot",
@ -18,7 +19,8 @@
},
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"default_limit": 5,
"id": "e35a965b2b244209bb0c2b193c55955f"
"id": "e35a965b2b244209bb0c2b193c55955f",
"description": ""
}
]
}

View File

@ -13,7 +13,8 @@
},
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"default_limit": 10,
"id": "195acb8a093e43e9afb23d6628361e7c"
"id": "195acb8a093e43e9afb23d6628361e7c",
"description": ""
},
{
"resource_name": "volume",
@ -23,7 +24,8 @@
},
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"default_limit": 5,
"id": "ea7f74f15cba4c6db1406fe52532f98d"
"id": "ea7f74f15cba4c6db1406fe52532f98d",
"description": "Number of volumes"
}
]
}

View File

@ -5,13 +5,15 @@
"id": "e35a965b2b244209bb0c2b193c55955f",
"region_id": "RegionOne",
"resource_name": "snapshot",
"default_limit": 5
"default_limit": 5,
"description": "Number of snapshots"
},
{
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"id": "773147dd53cd4a17b921d555cf17c633",
"resource_name": "volume",
"default_limit": 10
"default_limit": 10,
"description": ""
}
]
}

View File

@ -8,7 +8,8 @@
},
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"default_limit": 10,
"id": "773147dd53cd4a17b921d555cf17c633"
"id": "773147dd53cd4a17b921d555cf17c633",
"description": ""
},
{
"resource_name": "snapshot",
@ -18,7 +19,8 @@
},
"service_id": "9408080f1970482aa0e38bc2d4ea34b7",
"default_limit": 5,
"id": "e35a965b2b244209bb0c2b193c55955f"
"id": "e35a965b2b244209bb0c2b193c55955f",
"description": "Number of snapshots"
}
]
}

View File

@ -48,6 +48,7 @@ Parameters
- region_id: region_id_response_body
- resource_name: resource_name
- default_limit: default_limit
- description: description_registered_limit_response_body
- links: link_response_body
@ -93,6 +94,7 @@ Parameters
- region_id: region_id_request_body
- resource_name: resource_name
- default_limit: default_limit
- description: description_registered_limit_request_body
Examples
~~~~~~~~
@ -116,6 +118,7 @@ Parameters
- region_id: region_id_response_body
- resource_name: resource_name
- default_limit: default_limit
- description: description_registered_limit_response_body
- links: link_response_body
Status Codes
@ -164,6 +167,7 @@ Parameters
- region_id: region_id_request_body
- resource_name: resource_name
- default_limit: default_limit
- description: description_registered_limit_request_body
Example
~~~~~~~
@ -185,6 +189,7 @@ Parameters
- region_id: region_id_response_body
- resource_name: resource_name
- default_limit: default_limit
- description: description_registered_limit_response_body
- links: link_response_body
@ -243,6 +248,7 @@ Parameters
- region_id: region_id_response_body
- resource_name: resource_name
- default_limit: default_limit
- description: description_registered_limit_response_body
- links: link_response_body
Status Codes
@ -339,6 +345,7 @@ Parameters
- region_id: region_id_response_body
- resource_name: resource_name
- resource_limit: resource_limit
- description: description_limit_response_body
- links: link_response_body
@ -383,6 +390,7 @@ Parameters
- region_id: region_id_request_body
- resource_name: resource_name
- resource_limit: resource_limit
- description: description_limit_request_body
Examples
~~~~~~~~
@ -406,6 +414,7 @@ Parameters
- region_id: region_id_response_body
- resource_name: resource_name
- resource_limit: resource_limit
- description: description_limit_response_body
- links: link_response_body
Status Codes
@ -451,6 +460,7 @@ Parameters
- limits: limits
- resource_limit: resource_limit
- description: description_limit_request_body
Example
~~~~~~~
@ -472,6 +482,7 @@ Parameters
- region_id: region_id_response_body
- resource_name: resource_name
- resource_limit: resource_limit
- description: description_limit_response_body
- links: link_response_body
@ -531,6 +542,7 @@ Parameters
- region_id: region_id_response_body
- resource_name: resource_name
- resource_limit: resource_limit
- description: description_limit_response_body
- links: link_response_body
Status Codes

View File

@ -32,7 +32,8 @@ class RegisteredLimitModel(sql.ModelBase, sql.ModelDictMixin):
'service_id',
'region_id',
'resource_name',
'default_limit'
'default_limit',
'description'
]
id = sql.Column(sql.String(length=64), primary_key=True)
@ -42,6 +43,7 @@ class RegisteredLimitModel(sql.ModelBase, sql.ModelDictMixin):
sql.ForeignKey('region.id'), nullable=True)
resource_name = sql.Column(sql.String(255))
default_limit = sql.Column(sql.Integer, nullable=False)
description = sql.Column(sql.Text())
__table_args__ = (
sqlalchemy.UniqueConstraint('service_id',
@ -57,7 +59,8 @@ class LimitModel(sql.ModelBase, sql.ModelDictMixin):
'service_id',
'region_id',
'resource_name',
'resource_limit'
'resource_limit',
'description'
]
id = sql.Column(sql.String(length=64), primary_key=True)
@ -67,6 +70,7 @@ class LimitModel(sql.ModelBase, sql.ModelDictMixin):
region_id = sql.Column(sql.String(64), nullable=True)
resource_name = sql.Column(sql.String(255))
resource_limit = sql.Column(sql.Integer, nullable=False)
description = sql.Column(sql.Text())
__table_args__ = (
sqlalchemy.ForeignKeyConstraint(['service_id',
@ -227,9 +231,10 @@ class UnifiedLimit(base.UnifiedLimitDriverBase):
for limit in limits:
ref = self._get_limit(session, limit['id'])
old_dict = ref.to_dict()
old_dict['resource_limit'] = limit['resource_limit']
old_dict.update(limit)
new_limit = LimitModel.from_dict(old_dict)
ref.resource_limit = new_limit.resource_limit
ref.description = new_limit.description
@driver_hints.truncated
def list_limits(self, hints):

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from keystone.common import validation
from keystone.common.validation import parameter_types
_registered_limit_create_properties = {
@ -24,7 +25,8 @@ _registered_limit_create_properties = {
},
'default_limit': {
'type': 'integer'
}
},
'description': validation.nullable(parameter_types.description)
}
_registered_limit_create = {
@ -51,7 +53,8 @@ _registered_limit_update_properties = {
},
'default_limit': {
'type': 'integer'
}
},
'description': validation.nullable(parameter_types.description)
}
_registered_limit_update = {
@ -78,7 +81,8 @@ _limit_create_properties = {
},
'resource_limit': {
'type': 'integer'
}
},
'description': validation.nullable(parameter_types.description)
}
@ -99,14 +103,15 @@ _limit_update_properties = {
'id': parameter_types.id_string,
'resource_limit': {
'type': 'integer'
}
},
'description': validation.nullable(parameter_types.description)
}
_limit_update = {
'type': 'object',
'properties': _limit_update_properties,
'additionalProperties': False,
'required': ['id', 'resource_limit']
'required': ['id', ]
}
limit_update = {

View File

@ -467,7 +467,8 @@ def new_registered_limit_ref(**kwargs):
ref = {
'service_id': uuid.uuid4().hex,
'resource_name': uuid.uuid4().hex,
'default_limit': 10
'default_limit': 10,
'description': uuid.uuid4().hex
}
ref.update(kwargs)
@ -479,7 +480,8 @@ def new_limit_ref(**kwargs):
'project_id': uuid.uuid4().hex,
'service_id': uuid.uuid4().hex,
'resource_name': uuid.uuid4().hex,
'resource_limit': 10
'resource_limit': 10,
'description': uuid.uuid4().hex
}
ref.update(kwargs)

View File

@ -28,7 +28,8 @@ class RegisteredLimitTests(object):
registered_limit_1 = unit.new_registered_limit_ref(
service_id=self.service_one['id'],
region_id=self.region_one['id'],
resource_name='volume', default_limit=10, id=uuid.uuid4().hex)
resource_name='volume', default_limit=10, id=uuid.uuid4().hex,
description='test description')
reg_limits = PROVIDERS.unified_limit_api.create_registered_limits(
[registered_limit_1])
self.assertDictEqual(registered_limit_1, reg_limits[0])
@ -111,6 +112,26 @@ class RegisteredLimitTests(object):
PROVIDERS.unified_limit_api.create_registered_limits,
[registered_limit_1])
def test_create_registered_limit_description_none(self):
registered_limit = unit.new_registered_limit_ref(
service_id=self.service_one['id'],
region_id=self.region_one['id'],
resource_name='volume', default_limit=10, id=uuid.uuid4().hex,
description=None)
res = PROVIDERS.unified_limit_api.create_registered_limits(
[registered_limit])
self.assertIsNone(res[0]['description'])
def test_create_registered_limit_without_description(self):
registered_limit = unit.new_registered_limit_ref(
service_id=self.service_one['id'],
region_id=self.region_one['id'],
resource_name='volume', default_limit=10, id=uuid.uuid4().hex)
registered_limit.pop('description')
res = PROVIDERS.unified_limit_api.create_registered_limits(
[registered_limit])
self.assertIsNone(res[0]['description'])
def test_update_registered_limit(self):
# create two registered limits
registered_limit_1 = unit.new_registered_limit_ref(
@ -380,7 +401,8 @@ class LimitTests(object):
project_id=self.tenant_bar['id'],
service_id=self.service_one['id'],
region_id=self.region_one['id'],
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex)
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex,
description='test description')
limits = PROVIDERS.unified_limit_api.create_limits([limit_1])
self.assertDictEqual(limit_1, limits[0])
@ -452,6 +474,26 @@ class LimitTests(object):
PROVIDERS.unified_limit_api.create_limits,
[limit_1])
def test_create_limit_description_none(self):
limit = unit.new_limit_ref(
project_id=self.tenant_bar['id'],
service_id=self.service_one['id'],
region_id=self.region_one['id'],
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex,
description=None)
res = PROVIDERS.unified_limit_api.create_limits([limit])
self.assertIsNone(res[0]['description'])
def test_create_limit_without_description(self):
limit = unit.new_limit_ref(
project_id=self.tenant_bar['id'],
service_id=self.service_one['id'],
region_id=self.region_one['id'],
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex)
limit.pop('description')
res = PROVIDERS.unified_limit_api.create_limits([limit])
self.assertIsNone(res[0]['description'])
def test_update_limits(self):
# create two limits
limit_1 = unit.new_limit_ref(

View File

@ -53,7 +53,7 @@ class RegisteredLimitsTestCase(test_v3.RestfulTestCase):
expected_status=http_client.CREATED)
registered_limits = r.result['registered_limits']
for key in ['service_id', 'region_id', 'resource_name',
'default_limit']:
'default_limit', 'description']:
self.assertEqual(registered_limits[0][key], ref[key])
def test_create_registered_limit_without_region(self):
@ -67,6 +67,20 @@ class RegisteredLimitsTestCase(test_v3.RestfulTestCase):
self.assertEqual(registered_limits[0][key], ref[key])
self.assertIsNone(registered_limits[0].get('region_id'))
def test_create_registered_without_description(self):
ref = unit.new_registered_limit_ref(service_id=self.service_id,
region_id=self.region_id)
ref.pop('description')
r = self.post(
'/registered_limits',
body={'registered_limits': [ref]},
expected_status=http_client.CREATED)
registered_limits = r.result['registered_limits']
for key in ['service_id', 'region_id', 'resource_name',
'default_limit']:
self.assertEqual(registered_limits[0][key], ref[key])
self.assertIsNone(registered_limits[0]['description'])
def test_create_multi_registered_limit(self):
ref1 = unit.new_registered_limit_ref(service_id=self.service_id,
region_id=self.region_id,
@ -141,7 +155,8 @@ class RegisteredLimitsTestCase(test_v3.RestfulTestCase):
'service_id': self.service_id2,
'region_id': self.region_id2,
'resource_name': 'snapshot',
'default_limit': 5
'default_limit': 5,
'description': 'test description'
}
r = self.put(
'/registered_limits',
@ -153,6 +168,37 @@ class RegisteredLimitsTestCase(test_v3.RestfulTestCase):
self.assertEqual(new_registered_limits['region_id'], self.region_id2)
self.assertEqual(new_registered_limits['resource_name'], 'snapshot')
self.assertEqual(new_registered_limits['default_limit'], 5)
self.assertEqual(new_registered_limits['description'],
'test description')
def test_update_registered_limit_description(self):
ref = unit.new_registered_limit_ref(service_id=self.service_id,
region_id=self.region_id,
resource_name='volume',
default_limit=10)
r = self.post(
'/registered_limits',
body={'registered_limits': [ref]},
expected_status=http_client.CREATED)
update_ref = {
'id': r.result['registered_limits'][0]['id'],
'description': 'test description'
}
r = self.put(
'/registered_limits',
body={'registered_limits': [update_ref]},
expected_status=http_client.OK)
new_registered_limits = r.result['registered_limits'][0]
self.assertEqual(new_registered_limits['description'],
'test description')
update_ref['description'] = ''
r = self.put(
'/registered_limits',
body={'registered_limits': [update_ref]},
expected_status=http_client.OK)
new_registered_limits = r.result['registered_limits'][0]
self.assertEqual(new_registered_limits['description'], '')
def test_update_multi_registered_limit(self):
ref = unit.new_registered_limit_ref(service_id=self.service_id,
@ -213,8 +259,10 @@ class RegisteredLimitsTestCase(test_v3.RestfulTestCase):
resource_name=123)
update_ref4 = unit.new_registered_limit_ref(id=uuid.uuid4().hex,
region_id='fake_region')
update_ref5 = unit.new_registered_limit_ref(id=uuid.uuid4().hex,
description=123)
for input_limit in [update_ref1, update_ref2, update_ref3,
update_ref4]:
update_ref4, update_ref5]:
self.put(
'/registered_limits',
body={'registered_limits': [input_limit]},
@ -325,7 +373,7 @@ class RegisteredLimitsTestCase(test_v3.RestfulTestCase):
expected_status=http_client.OK)
registered_limit = r.result['registered_limit']
for key in ['service_id', 'region_id', 'resource_name',
'default_limit']:
'default_limit', 'description']:
self.assertEqual(registered_limit[key], ref1[key])
def test_delete_registered_limit(self):
@ -420,7 +468,7 @@ class LimitsTestCase(test_v3.RestfulTestCase):
self. assertIsNotNone(limits[0]['id'])
self. assertIsNotNone(limits[0]['project_id'])
for key in ['service_id', 'region_id', 'resource_name',
'resource_limit']:
'resource_limit', 'description']:
self.assertEqual(limits[0][key], ref[key])
def test_create_limit_without_region(self):
@ -439,6 +487,25 @@ class LimitsTestCase(test_v3.RestfulTestCase):
self.assertEqual(limits[0][key], ref[key])
self.assertIsNone(limits[0].get('region_id'))
def test_create_limit_without_description(self):
ref = unit.new_limit_ref(project_id=self.project_id,
service_id=self.service_id,
region_id=self.region_id,
resource_name='volume')
ref.pop('description')
r = self.post(
'/limits',
body={'limits': [ref]},
expected_status=http_client.CREATED)
limits = r.result['limits']
self. assertIsNotNone(limits[0]['id'])
self. assertIsNotNone(limits[0]['project_id'])
for key in ['service_id', 'region_id', 'resource_name',
'resource_limit']:
self.assertEqual(limits[0][key], ref[key])
self.assertIsNone(limits[0]['description'])
def test_create_multi_limit(self):
ref1 = unit.new_limit_ref(project_id=self.project_id,
service_id=self.service_id,
@ -535,7 +602,8 @@ class LimitsTestCase(test_v3.RestfulTestCase):
expected_status=http_client.CREATED)
update_ref = {
'id': r.result['limits'][0]['id'],
'resource_limit': 5
'resource_limit': 5,
'description': 'test description'
}
r = self.put(
'/limits',
@ -544,6 +612,7 @@ class LimitsTestCase(test_v3.RestfulTestCase):
new_limits = r.result['limits'][0]
self.assertEqual(new_limits['resource_limit'], 5)
self.assertEqual(new_limits['description'], 'test description')
def test_update_multi_limit(self):
ref = unit.new_limit_ref(project_id=self.project_id,
@ -687,7 +756,7 @@ class LimitsTestCase(test_v3.RestfulTestCase):
expected_status=http_client.OK)
limit = r.result['limit']
for key in ['service_id', 'region_id', 'resource_name',
'resource_limit']:
'resource_limit', 'description']:
self.assertEqual(limit[key], ref1[key])
def test_delete_limit(self):

View File

@ -2519,16 +2519,17 @@ class LimitValidationTestCase(unit.BaseTestCase):
request_to_validate = [{'service_id': uuid.uuid4().hex,
'region_id': 'RegionOne',
'resource_name': 'volume',
'default_limit': 10}]
'default_limit': 10,
'description': 'test description'}]
self.create_registered_limits_validator.validate(request_to_validate)
def test_validate_registered_limit_create_request_without_region(self):
def test_validate_registered_limit_create_request_without_optional(self):
request_to_validate = [{'service_id': uuid.uuid4().hex,
'resource_name': 'volume',
'default_limit': 10}]
self.create_registered_limits_validator.validate(request_to_validate)
def test_validate_registered_limit_update_request_without_region(self):
def test_validate_registered_limit_update_request_without_optional(self):
request_to_validate = [{'id': uuid.uuid4().hex,
'service_id': uuid.uuid4().hex,
'resource_name': 'volume',
@ -2549,12 +2550,15 @@ class LimitValidationTestCase(unit.BaseTestCase):
_INVALID_FORMATS = [{'service_id': 'fake_id'},
{'region_id': 123},
{'resource_name': 123},
{'default_limit': 'not_int'}]
{'default_limit': 'not_int'},
{'description': 123},
{'description': True}]
for invalid_desc in _INVALID_FORMATS:
request_to_validate = [{'service_id': uuid.uuid4().hex,
'region_id': 'RegionOne',
'resource_name': 'volume',
'default_limit': 10}]
'default_limit': 10,
'description': 'test description'}]
request_to_validate[0].update(invalid_desc)
self.assertRaises(exception.SchemaValidationError,
@ -2565,13 +2569,15 @@ class LimitValidationTestCase(unit.BaseTestCase):
_INVALID_FORMATS = [{'service_id': 'fake_id'},
{'region_id': 123},
{'resource_name': 123},
{'default_limit': 'not_int'}]
{'default_limit': 'not_int'},
{'description': 123}]
for invalid_desc in _INVALID_FORMATS:
request_to_validate = [{'id': uuid.uuid4().hex,
'service_id': uuid.uuid4().hex,
'region_id': 'RegionOne',
'resource_name': 'volume',
'default_limit': 10}]
'default_limit': 10,
'description': 'test description'}]
request_to_validate[0].update(invalid_desc)
self.assertRaises(exception.SchemaValidationError,
@ -2624,10 +2630,11 @@ class LimitValidationTestCase(unit.BaseTestCase):
'service_id': uuid.uuid4().hex,
'region_id': 'RegionOne',
'resource_name': 'volume',
'resource_limit': 10}]
'resource_limit': 10,
'description': 'test description'}]
self.create_limits_validator.validate(request_to_validate)
def test_validate_limit_create_request_without_region(self):
def test_validate_limit_create_request_without_optional(self):
request_to_validate = [{'project_id': uuid.uuid4().hex,
'service_id': uuid.uuid4().hex,
'resource_name': 'volume',
@ -2635,6 +2642,12 @@ class LimitValidationTestCase(unit.BaseTestCase):
self.create_limits_validator.validate(request_to_validate)
def test_validate_limit_update_request_succeeds(self):
request_to_validate = [{'id': uuid.uuid4().hex,
'resource_limit': 10,
'description': 'test description'}]
self.update_limits_validator.validate(request_to_validate)
def test_validate_limit_update_request_without_optional(self):
request_to_validate = [{'id': uuid.uuid4().hex,
'resource_limit': 10}]
self.update_limits_validator.validate(request_to_validate)
@ -2654,13 +2667,15 @@ class LimitValidationTestCase(unit.BaseTestCase):
{'service_id': 'fake_id'},
{'region_id': 123},
{'resource_name': 123},
{'resource_limit': 'not_int'}]
{'resource_limit': 'not_int'},
{'description': 123}]
for invalid_desc in _INVALID_FORMATS:
request_to_validate = [{'project_id': uuid.uuid4().hex,
'service_id': uuid.uuid4().hex,
'region_id': 'RegionOne',
'resource_name': 'volume',
'resource_limit': 10}]
'resource_limit': 10,
'description': 'test description'}]
request_to_validate[0].update(invalid_desc)
self.assertRaises(exception.SchemaValidationError,

View File

@ -0,0 +1,7 @@
---
features:
- >
[`bug 1754185 <https://bugs.launchpad.net/keystone/+bug/1754185>`_]
Registered limits and project limits now support an optional, nullable
property called `description`. Users can create/update a registered limit
or project limit with `description` now.