summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-04-24 08:32:10 +0000
committerGerrit Code Review <review@openstack.org>2015-04-24 08:32:10 +0000
commit9a2bab8b53054af433c7f17cd534ef230e42a8d5 (patch)
treecbd6cfa4d7e9f08801e1f6b93c877ea06c566f94
parent061a7557980223022d0ef2dd2c329eca4b04e262 (diff)
parente1e3c76392245da912f14b26cf2a585b37c5feb1 (diff)
downloadglance-9a2bab8b53054af433c7f17cd534ef230e42a8d5.tar.gz
Merge "Plugin types are not exposed to the client." into stable/kilo
-rw-r--r--etc/search-policy.json3
-rwxr-xr-xglance/api/policy.py4
-rw-r--r--glance/common/utils.py8
-rw-r--r--glance/search/__init__.py17
-rwxr-xr-xglance/search/api/v0_1/router.py11
-rwxr-xr-xglance/search/api/v0_1/search.py27
-rwxr-xr-xglance/tests/unit/v0_1/test_search.py80
7 files changed, 138 insertions, 12 deletions
diff --git a/etc/search-policy.json b/etc/search-policy.json
index abef5b3b0..dc324e259 100644
--- a/etc/search-policy.json
+++ b/etc/search-policy.json
@@ -3,5 +3,6 @@
"default": "",
"catalog_index": "role:admin",
- "catalog_search": ""
+ "catalog_search": "",
+ "catalog_plugins": ""
}
diff --git a/glance/api/policy.py b/glance/api/policy.py
index e3c4d5710..f7939cb24 100755
--- a/glance/api/policy.py
+++ b/glance/api/policy.py
@@ -690,6 +690,10 @@ class CatalogSearchRepoProxy(object):
self.policy.enforce(self.context, 'catalog_search', {})
return self.search_repo.search(*args, **kwargs)
+ def plugins_info(self, *args, **kwargs):
+ self.policy.enforce(self.context, 'catalog_plugins', {})
+ return self.search_repo.plugins_info(*args, **kwargs)
+
def index(self, *args, **kwargs):
self.policy.enforce(self.context, 'catalog_index', {})
return self.search_repo.index(*args, **kwargs)
diff --git a/glance/common/utils.py b/glance/common/utils.py
index 868235e48..1923be411 100644
--- a/glance/common/utils.py
+++ b/glance/common/utils.py
@@ -32,6 +32,7 @@ import functools
import os
import platform
import re
+import stevedore
import subprocess
import sys
import uuid
@@ -729,3 +730,10 @@ def stash_conf_values():
conf['cert_file'] = CONF.cert_file
return conf
+
+
+def get_search_plugins():
+ namespace = 'glance.search.index_backend'
+ ext_manager = stevedore.extension.ExtensionManager(
+ namespace, invoke_on_load=True)
+ return ext_manager.extensions
diff --git a/glance/search/__init__.py b/glance/search/__init__.py
index 5b36d7d57..e1cacf01f 100644
--- a/glance/search/__init__.py
+++ b/glance/search/__init__.py
@@ -17,6 +17,8 @@ import elasticsearch
from elasticsearch import helpers
from oslo_config import cfg
+from glance.common import utils
+
search_opts = [
cfg.ListOpt('hosts', default=['127.0.0.1:9200'],
@@ -40,6 +42,8 @@ class CatalogSearchRepo(object):
def __init__(self, context, es_api):
self.context = context
self.es_api = es_api
+ self.plugins = utils.get_search_plugins() or []
+ self.plugins_info_dict = self._get_plugin_info()
def search(self, index, doc_type, query, fields, offset, limit,
ignore_unavailable=True):
@@ -58,3 +62,16 @@ class CatalogSearchRepo(object):
index=default_index,
doc_type=default_type,
actions=actions)
+
+ def plugins_info(self):
+ return self.plugins_info_dict
+
+ def _get_plugin_info(self):
+ plugin_info = dict()
+ plugin_info['plugins'] = []
+ for plugin in self.plugins:
+ info = dict()
+ info['type'] = plugin.obj.get_document_type()
+ info['index'] = plugin.obj.get_index_name()
+ plugin_info['plugins'].append(info)
+ return plugin_info
diff --git a/glance/search/api/v0_1/router.py b/glance/search/api/v0_1/router.py
index ad0462a6f..1f08b33b4 100755
--- a/glance/search/api/v0_1/router.py
+++ b/glance/search/api/v0_1/router.py
@@ -41,6 +41,17 @@ class API(wsgi.Router):
conditions={'method': ['PUT', 'DELETE',
'PATCH', 'HEAD']})
+ mapper.connect('/search/plugins',
+ controller=search_catalog_resource,
+ action='plugins_info',
+ conditions={'method': ['GET']})
+ mapper.connect('/search/plugins',
+ controller=reject_method_resource,
+ action='reject',
+ allowed_methods='GET',
+ conditions={'method': ['POST', 'PUT', 'DELETE',
+ 'PATCH', 'HEAD']})
+
mapper.connect('/index',
controller=search_catalog_resource,
action='index',
diff --git a/glance/search/api/v0_1/search.py b/glance/search/api/v0_1/search.py
index 64ca7ba41..f6aa4bf55 100755
--- a/glance/search/api/v0_1/search.py
+++ b/glance/search/api/v0_1/search.py
@@ -18,7 +18,6 @@ import json
from oslo.config import cfg
from oslo_log import log as logging
import six
-import stevedore
import webob.exc
from glance.api import policy
@@ -76,6 +75,18 @@ class SearchController(object):
LOG.error(utils.exception_to_str(e))
raise webob.exc.HTTPInternalServerError()
+ def plugins_info(self, req):
+ try:
+ search_repo = self.gateway.get_catalog_search_repo(req.context)
+ return search_repo.plugins_info()
+ except exception.Forbidden as e:
+ raise webob.exc.HTTPForbidden(explanation=e.msg)
+ except exception.NotFound as e:
+ raise webob.exc.HTTPNotFound(explanation=e.msg)
+ except Exception as e:
+ LOG.error(utils.exception_to_str(e))
+ raise webob.exc.HTTPInternalServerError()
+
def index(self, req, actions, default_index=None, default_type=None):
try:
search_repo = self.gateway.get_catalog_search_repo(req.context)
@@ -351,22 +362,20 @@ class ResponseSerializer(wsgi.JSONResponseSerializer):
response.unicode_body = six.text_type(body)
response.content_type = 'application/json'
- def index(self, response, query_result):
+ def plugins_info(self, response, query_result):
body = json.dumps(query_result, ensure_ascii=False)
response.unicode_body = six.text_type(body)
response.content_type = 'application/json'
-
-def get_plugins():
- namespace = 'glance.search.index_backend'
- ext_manager = stevedore.extension.ExtensionManager(
- namespace, invoke_on_load=True)
- return ext_manager.extensions
+ def index(self, response, query_result):
+ body = json.dumps(query_result, ensure_ascii=False)
+ response.unicode_body = six.text_type(body)
+ response.content_type = 'application/json'
def create_resource():
"""Search resource factory method"""
- plugins = get_plugins()
+ plugins = utils.get_search_plugins()
deserializer = RequestDeserializer(plugins)
serializer = ResponseSerializer()
controller = SearchController(plugins)
diff --git a/glance/tests/unit/v0_1/test_search.py b/glance/tests/unit/v0_1/test_search.py
index d5782a966..09a083cf6 100755
--- a/glance/tests/unit/v0_1/test_search.py
+++ b/glance/tests/unit/v0_1/test_search.py
@@ -18,6 +18,7 @@ from oslo.serialization import jsonutils
import webob.exc
from glance.common import exception
+from glance.common import utils
import glance.gateway
import glance.search
from glance.search.api.v0_1 import search as search
@@ -234,12 +235,52 @@ class TestSearchController(base.IsolatedUnitTest):
webob.exc.HTTPInternalServerError, self.search_controller.index,
request, actions)
+ def test_plugins_info(self):
+ request = unit_test_utils.get_fake_request()
+ self.search_controller.plugins_info = mock.Mock(return_value="{}")
+ self.search_controller.plugins_info(request)
+ self.search_controller.plugins_info.assert_called_once_with(request)
+
+ def test_plugins_info_repo(self):
+ request = unit_test_utils.get_fake_request()
+ repo = glance.search.CatalogSearchRepo
+ repo.plugins_info = mock.Mock(return_value="{}")
+ self.search_controller.plugins_info(request)
+ repo.plugins_info.assert_called_once_with()
+
+ def test_plugins_info_forbidden(self):
+ request = unit_test_utils.get_fake_request()
+ repo = glance.search.CatalogSearchRepo
+ repo.plugins_info = mock.Mock(side_effect=exception.Forbidden)
+
+ self.assertRaises(
+ webob.exc.HTTPForbidden, self.search_controller.plugins_info,
+ request)
+
+ def test_plugins_info_not_found(self):
+ request = unit_test_utils.get_fake_request()
+ repo = glance.search.CatalogSearchRepo
+ repo.plugins_info = mock.Mock(side_effect=exception.NotFound)
+
+ self.assertRaises(webob.exc.HTTPNotFound,
+ self.search_controller.plugins_info, request)
+
+ def test_plugins_info_internal_server_error(self):
+ request = unit_test_utils.get_fake_request()
+ repo = glance.search.CatalogSearchRepo
+ repo.plugins_info = mock.Mock(side_effect=Exception)
+
+ self.assertRaises(webob.exc.HTTPInternalServerError,
+ self.search_controller.plugins_info, request)
+
class TestSearchDeserializer(test_utils.BaseTestCase):
def setUp(self):
super(TestSearchDeserializer, self).setUp()
- self.deserializer = search.RequestDeserializer(search.get_plugins())
+ self.deserializer = search.RequestDeserializer(
+ utils.get_search_plugins()
+ )
def test_single_index(self):
request = unit_test_utils.get_fake_request()
@@ -411,7 +452,9 @@ class TestIndexDeserializer(test_utils.BaseTestCase):
def setUp(self):
super(TestIndexDeserializer, self).setUp()
- self.deserializer = search.RequestDeserializer(search.get_plugins())
+ self.deserializer = search.RequestDeserializer(
+ utils.get_search_plugins()
+ )
def test_empty_request(self):
request = unit_test_utils.get_fake_request()
@@ -874,6 +917,39 @@ class TestResponseSerializer(test_utils.BaseTestCase):
super(TestResponseSerializer, self).setUp()
self.serializer = search.ResponseSerializer()
+ def test_plugins_info(self):
+ expected = {
+ "plugins": [
+ {
+ "index": "glance",
+ "type": "image"
+ },
+ {
+ "index": "glance",
+ "type": "metadef"
+ }
+ ]
+ }
+
+ request = webob.Request.blank('/v0.1/search')
+ response = webob.Response(request=request)
+ result = {
+ "plugins": [
+ {
+ "index": "glance",
+ "type": "image"
+ },
+ {
+ "index": "glance",
+ "type": "metadef"
+ }
+ ]
+ }
+ self.serializer.search(response, result)
+ actual = jsonutils.loads(response.body)
+ self.assertEqual(expected, actual)
+ self.assertEqual('application/json', response.content_type)
+
def test_search(self):
expected = [{
'id': '1',