Skip to content

Instantly share code, notes, and snippets.

@ChristopherMacGown
Created February 2, 2012 19:31
Show Gist options
  • Save ChristopherMacGown/1725271 to your computer and use it in GitHub Desktop.
Save ChristopherMacGown/1725271 to your computer and use it in GitHub Desktop.
diff --git a/glance/api/v1/filters.py b/glance/api/v1/filters.py
new file mode 100644
index 0000000..20bbbb8
--- /dev/null
+++ b/glance/api/v1/filters.py
@@ -0,0 +1,57 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012, Piston Cloud Computing, Inc.
+# All Rights Reserved.
+#
+# 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.
+
+
+FILTER_FUNCTIONS = {}
+
+
+def register(*names):
+ def _(fn, *args, **kw):
+ for name in names:
+ FILTER_FUNCTIONS[name] = fn
+ return _
+
+
+def validate(filter, value):
+ return FILTER_FUNCTIONS.get(filter, lambda v: True)(value)
+
+
+@register('size_max')
+def size_max_filter(v):
+ try:
+ return int(v) > 0
+ except ValueError:
+ return False
+
+
+@register('size_min')
+def size_min_filter(v):
+ try:
+ return int(v) > 0
+ except ValueError:
+ return False
+
+
+@register('min_ram')
+def min_ram_filter(v):
+ return int(v) > 0
+
+
+@register('protected', 'is_public')
+def boolean(v):
+ v = v.lower()
+ return v in ('none', 'true', 'false', '1', '0')
diff --git a/glance/api/v1/images.py b/glance/api/v1/images.py
index 03b44d6..58f809d 100644
--- a/glance/api/v1/images.py
+++ b/glance/api/v1/images.py
@@ -35,6 +35,7 @@ from webob.exc import (HTTPError,
from glance.api import policy
import glance.api.v1
from glance.api.v1 import controller
+from glance.api.v1 import filters
from glance.common import cfg
from glance.common import exception
from glance.common import wsgi
@@ -182,6 +183,7 @@ class Controller(controller.BaseController):
:retval dict of parameters that can be used by registry client
"""
params = {'filters': self._get_filters(req)}
+
for PARAM in SUPPORTED_PARAMS:
if PARAM in req.str_params:
params[PARAM] = req.str_params.get(PARAM)
@@ -194,12 +196,15 @@ class Controller(controller.BaseController):
:param req: the Request object coming from the wsgi layer
:retval a dict of key/value filters
"""
- filters = {}
+ query_filters = {}
for param in req.str_params:
if param in SUPPORTED_FILTERS or param.startswith('property-'):
- filters[param] = req.str_params.get(param)
-
- return filters
+ query_filters[param] = req.str_params.get(param)
+ if not filters.validate(param, query_filters[param]):
+ raise HTTPBadRequest('Bad value passed to filter %s '
+ 'got %s' % (param,
+ query_filters[param]))
+ return query_filters
def meta(self, req, id):
"""
diff --git a/glance/tests/functional/test_api.py b/glance/tests/functional/test_api.py
index 75297ba..1a36524 100644
--- a/glance/tests/functional/test_api.py
+++ b/glance/tests/functional/test_api.py
@@ -925,6 +925,51 @@ class TestApi(functional.FunctionalTest):
data = json.loads(content)
self.assertEqual(len(data['images']), 0)
+ # 18. GET /images with size_min filter
+ # Verify correct images returned with size >= expected
+ params = "size_min=-1"
+ path = "http://%s:%d/v1/images?%s" % (
+ "0.0.0.0", self.api_port, params)
+ response, content = http.request(path, 'GET')
+ self.assertEqual(response.status, 400)
+ self.assertTrue("filter size_min got -1" in content)
+
+ # 19. GET /images with size_min filter
+ # Verify correct images returned with size >= expected
+ params = "size_max=-1"
+ path = "http://%s:%d/v1/images?%s" % (
+ "0.0.0.0", self.api_port, params)
+ response, content = http.request(path, 'GET')
+ self.assertEqual(response.status, 400)
+ self.assertTrue("filter size_max got -1" in content)
+
+ # 20. GET /images with size_min filter
+ # Verify correct images returned with size >= expected
+ params = "min_ram=-1"
+ path = "http://%s:%d/v1/images?%s" % (
+ "0.0.0.0", self.api_port, params)
+ response, content = http.request(path, 'GET')
+ self.assertEqual(response.status, 400)
+ self.assertTrue("Bad value passed to filter min_ram got -1" in content)
+
+ # 21. GET /images with size_min filter
+ # Verify correct images returned with size >= expected
+ params = "protected=imalittleteapot"
+ path = "http://%s:%d/v1/images?%s" % (
+ "0.0.0.0", self.api_port, params)
+ response, content = http.request(path, 'GET')
+ self.assertEqual(response.status, 400)
+ self.assertTrue("protected got imalittleteapot" in content)
+
+ # 22. GET /images with size_min filter
+ # Verify correct images returned with size >= expected
+ params = "is_public=imalittleteapot"
+ path = "http://%s:%d/v1/images?%s" % (
+ "0.0.0.0", self.api_port, params)
+ response, content = http.request(path, 'GET')
+ self.assertEqual(response.status, 400)
+ self.assertTrue("is_public got imalittleteapot" in content)
+
self.stop_servers()
@skip_if_disabled
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment