summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMorgan Fainberg <morgan.fainberg@gmail.com>2018-04-13 13:34:31 -0700
committerLance Bragstad <lbragstad@gmail.com>2018-04-19 13:25:02 +0000
commit22af1d9f35c86e9c5bca288c2996be5c19e3cd61 (patch)
tree2bb2ed378134a342ccfcfe73bbb9bcee17caa07d
parent6de0a147d68042af79ddc6d700cec3fd71b9d03c (diff)
Fix json schema nullable to add None to ENUMstable/pike
The JSON Schema validation implementation of nullable(), which makes values possible to be null was not adding None to the enum if it exists. This causes validation to fail on ``None`` especially in the case of keystone's boolean parameter_type implementation. ``nullable()`` now adds ``None`` to the enum if the enum exists. Closes-Bug: #1763824 Change-Id: I176fa90df63049661413c445554dba9b7d87272a (cherry picked from commit 78adf4b40fb88e371101ed065ac1d15063d8d86e)
Notes
Notes (review): Code-Review+1: Lance Bragstad <lbragstad@gmail.com> Code-Review+1: Gage Hugo <gagehugo@gmail.com> Code-Review+2: Morgan Fainberg <morgan.fainberg@gmail.com> Workflow+1: Morgan Fainberg <morgan.fainberg@gmail.com> Verified+2: Zuul Submitted-by: Zuul Submitted-at: Sat, 21 Apr 2018 03:53:07 +0000 Reviewed-on: https://review.openstack.org/561354 Project: openstack/keystone Branch: refs/heads/stable/pike
-rw-r--r--keystone/common/validation/__init__.py8
-rw-r--r--keystone/tests/unit/test_validation.py42
-rw-r--r--releasenotes/notes/bug-1763824-3d2f5169af9d42f.yaml6
3 files changed, 53 insertions, 3 deletions
diff --git a/keystone/common/validation/__init__.py b/keystone/common/validation/__init__.py
index 8284bac..0311de5 100644
--- a/keystone/common/validation/__init__.py
+++ b/keystone/common/validation/__init__.py
@@ -40,6 +40,14 @@ def nullable(property_schema):
40 # do that yet so I'm not wasting time on it 40 # do that yet so I'm not wasting time on it
41 new_schema = property_schema.copy() 41 new_schema = property_schema.copy()
42 new_schema['type'] = [property_schema['type'], 'null'] 42 new_schema['type'] = [property_schema['type'], 'null']
43 # NOTE(kmalloc): If enum is specified (such as our boolean case) ensure we
44 # add null to the enum as well so that null can be passed/validated as
45 # expected. Without adding to the enum, null will not validate as enum is
46 # explicitly listing valid values. According to the JSON Schema
47 # specification, the values must be unique in the enum array.
48 if 'enum' in new_schema and None not in new_schema['enum']:
49 # In the enum the 'null' is NoneType
50 new_schema['enum'].append(None)
43 return new_schema 51 return new_schema
44 52
45 53
diff --git a/keystone/tests/unit/test_validation.py b/keystone/tests/unit/test_validation.py
index 0602e56..73135cb 100644
--- a/keystone/tests/unit/test_validation.py
+++ b/keystone/tests/unit/test_validation.py
@@ -11,6 +11,7 @@
11# License for the specific language governing permissions and limitations 11# License for the specific language governing permissions and limitations
12# under the License. 12# under the License.
13 13
14import copy
14import uuid 15import uuid
15 16
16from keystone.assignment import schema as assignment_schema 17from keystone.assignment import schema as assignment_schema
@@ -107,6 +108,43 @@ _INVALID_FILTERS = ['some string', 1, 0, True, False]
107_INVALID_NAMES = [True, 24, ' ', ''] 108_INVALID_NAMES = [True, 24, ' ', '']
108 109
109 110
111class CommonValidationTestCase(unit.BaseTestCase):
112
113 def test_nullable_type_only(self):
114 bool_without_enum = copy.deepcopy(parameter_types.boolean)
115 bool_without_enum.pop('enum')
116 schema_type_only = {
117 'type': 'object',
118 'properties': {'test': validation.nullable(bool_without_enum)},
119 'additionalProperties': False,
120 'required': ['test']}
121
122 # Null should be in the types
123 self.assertIn('null', schema_type_only['properties']['test']['type'])
124 # No Enum, and nullable should not have added it.
125 self.assertNotIn('enum', schema_type_only['properties']['test'].keys())
126 validator = validators.SchemaValidator(schema_type_only)
127 reqs_to_validate = [{'test': val} for val in [True, False, None]]
128 for req in reqs_to_validate:
129 validator.validate(req)
130
131 def test_nullable_with_enum(self):
132 schema_with_enum = {
133 'type': 'object',
134 'properties': {
135 'test': validation.nullable(parameter_types.boolean)},
136 'additionalProperties': False,
137 'required': ['test']}
138
139 # Null should be in enum and type
140 self.assertIn('null', schema_with_enum['properties']['test']['type'])
141 self.assertIn(None, schema_with_enum['properties']['test']['enum'])
142 validator = validators.SchemaValidator(schema_with_enum)
143 reqs_to_validate = [{'test': val} for val in [True, False, None]]
144 for req in reqs_to_validate:
145 validator.validate(req)
146
147
110class EntityValidationTestCase(unit.BaseTestCase): 148class EntityValidationTestCase(unit.BaseTestCase):
111 149
112 def setUp(self): 150 def setUp(self):
@@ -1814,9 +1852,7 @@ class UserValidationTestCase(unit.BaseTestCase):
1814 ro.IGNORE_CHANGE_PASSWORD_OPT.option_name: None 1852 ro.IGNORE_CHANGE_PASSWORD_OPT.option_name: None
1815 } 1853 }
1816 } 1854 }
1817 self.assertRaises(exception.SchemaValidationError, 1855 self.create_user_validator.validate(request_to_validate)
1818 self.create_user_validator.validate,
1819 request_to_validate)
1820 1856
1821 def test_user_update_with_options_change_password_required(self): 1857 def test_user_update_with_options_change_password_required(self):
1822 request_to_validate = { 1858 request_to_validate = {
diff --git a/releasenotes/notes/bug-1763824-3d2f5169af9d42f.yaml b/releasenotes/notes/bug-1763824-3d2f5169af9d42f.yaml
new file mode 100644
index 0000000..7fb8be5
--- /dev/null
+++ b/releasenotes/notes/bug-1763824-3d2f5169af9d42f.yaml
@@ -0,0 +1,6 @@
1---
2fixes:
3 - |
4 [`bug 1763824 <https://bugs.launchpad.net/keystone/+bug/1763824>`_]
5 JSON Schema implementation ``nullable`` in keystone.common.validation now
6 properly adds ``None`` to the enum if the enum exists.