Procházet zdrojové kódy

api: more permissive boolean checks

At the moment, we strictly enforce boolean values to be one of
the JSON defined "false" or "true".

However, our Python client passes Python values such as "True" or
"False". The API won't throw an error, it will simply reject the
value and default to "False", which can lead to misleading behavior.

Similarly to Openstack Nova [1], we'll accept a broader set of values
that can be converted to boolean, such as "True", "T", "Y", "yes", "1".
To do so, we'll reuse the strutils.bool_from_string helper [2].

[1] https://github.com/openstack/nova/blob/9e1434d255f59f10c0fdf75c3fe6bebfa315df10/nova/api/validation/parameter_types.py#L206-L212
[2] https://github.com/openstack/oslo.utils/blob/2efc66aeedf27c1a51345d377ddd4407d7db489c/oslo_utils/strutils.py#L187-L204
Lucian Petrut před 1 měsícem
rodič
revize
c587e4cde4
2 změnil soubory, kde provedl 14 přidání a 12 odebrání
  1. 6 6
      coriolis/api/v1/utils.py
  2. 8 6
      coriolis/tests/api/v1/test_utils.py

+ 6 - 6
coriolis/api/v1/utils.py

@@ -2,9 +2,9 @@
 # All Rights Reserved.
 
 import functools
-import json
 
 from oslo_log import log as logging
+from oslo_utils import strutils
 from webob import exc
 
 from coriolis import constants
@@ -18,12 +18,12 @@ LOG = logging.getLogger(__name__)
 def get_bool_url_arg(req, arg_name, default=False):
     val = req.GET.get(arg_name, default)
     try:
-        parsed_val = json.loads(val)
-        if type(parsed_val) is bool:
-            return parsed_val
-    except Exception as err:
+        return strutils.bool_from_string(
+            str(val), strict=True)
+    except ValueError as err:
         LOG.warn(
-            "failed to parse %s: %s" % (arg_name, err))
+            "failed to parse %s: %s, defaulting to %s" % (
+                arg_name, err, default))
     return default
 
 

+ 8 - 6
coriolis/tests/api/v1/test_utils.py

@@ -16,11 +16,12 @@ from coriolis.tests import test_base
 class UtilsTestCase(test_base.CoriolisBaseTestCase):
     """Test suite for the Coriolis Utils v1 API"""
 
-    def test_get_bool_url_arg_(
-        self
+    @ddt.data(True, "True", "true", "t", "1", "yes", "y", "on", "1")
+    def test_get_bool_url_arg_true(
+        self, value
     ):
         mock_req = mock.Mock()
-        mock_req.GET.get.return_value = "true"
+        mock_req.GET.get.return_value = value
         arg_name = "show_deleted"
 
         result = utils.get_bool_url_arg(mock_req, arg_name, default=False)
@@ -31,11 +32,12 @@ class UtilsTestCase(test_base.CoriolisBaseTestCase):
         )
         mock_req.GET.get.assert_called_once_with(arg_name, False)
 
+    @ddt.data(False, "False", "false", "f", "0", "no", "n", "off", "0")
     def test_get_bool_url_arg_false(
-        self
+        self, value
     ):
         mock_req = mock.Mock()
-        mock_req.GET.get.return_value = False
+        mock_req.GET.get.return_value = value
         arg_name = "show_deleted"
 
         result = utils.get_bool_url_arg(mock_req, arg_name, False)
@@ -46,7 +48,7 @@ class UtilsTestCase(test_base.CoriolisBaseTestCase):
         )
         mock_req.GET.get.assert_called_once_with(arg_name, False)
 
-    def test_get_bool_url_arg_invalid_json(
+    def test_get_bool_url_arg_invalid(
         self
     ):
         mock_req = mock.MagicMock()