Plugin types are not exposed to the client.
Glance Search clients currently don't have anyway to know what "types" are available. Search clients need to know the "type" to include in the search request for the particular resource. Change-Id: I8baed7c5183752b1f52f8050ce321aacec701f1c Closes-Bug: #1439061
This commit is contained in:
parent
503a7bb4dd
commit
d6d5c501c1
@ -3,5 +3,6 @@
|
||||
"default": "",
|
||||
|
||||
"catalog_index": "role:admin",
|
||||
"catalog_search": ""
|
||||
"catalog_search": "",
|
||||
"catalog_plugins": ""
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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 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 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 get_plugins():
|
||||
namespace = 'glance.search.index_backend'
|
||||
ext_manager = stevedore.extension.ExtensionManager(
|
||||
namespace, invoke_on_load=True)
|
||||
return ext_manager.extensions
|
||||
|
||||
|
||||
def create_resource():
|
||||
"""Search resource factory method"""
|
||||
plugins = get_plugins()
|
||||
plugins = utils.get_search_plugins()
|
||||
deserializer = RequestDeserializer(plugins)
|
||||
serializer = ResponseSerializer()
|
||||
controller = SearchController(plugins)
|
||||
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user