commit
55471cb2f1
|
@ -91,6 +91,11 @@ class ImageIndex(base.IndexBase):
|
|||
'type': {
|
||||
'value': self.get_document_type()
|
||||
}
|
||||
},
|
||||
{
|
||||
'index': {
|
||||
'value': self.get_index_name()
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -112,6 +112,11 @@ class MetadefIndex(base.IndexBase):
|
|||
'type': {
|
||||
'value': self.get_document_type()
|
||||
}
|
||||
},
|
||||
{
|
||||
'index': {
|
||||
'value': self.get_index_name()
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import datetime
|
||||
|
||||
import mock
|
||||
|
@ -21,6 +22,7 @@ from oslo_utils import timeutils
|
|||
|
||||
from searchlight.elasticsearch.plugins.glance import images as images_plugin
|
||||
from searchlight.elasticsearch.plugins import openstack_clients
|
||||
import searchlight.tests.unit.utils as unit_test_utils
|
||||
import searchlight.tests.utils as test_utils
|
||||
|
||||
|
||||
|
@ -79,6 +81,7 @@ def _image_fixture(image_id, **kwargs):
|
|||
class TestImageLoaderPlugin(test_utils.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestImageLoaderPlugin, self).setUp()
|
||||
self.set_property_protections()
|
||||
|
||||
self._create_images()
|
||||
|
||||
|
@ -236,10 +239,13 @@ class TestImageLoaderPlugin(test_utils.BaseTestCase):
|
|||
image_member_mocks = [
|
||||
[], [], [], self.members_image_members
|
||||
]
|
||||
member_calls = [
|
||||
mock.call(i['id']) for i in self.images
|
||||
]
|
||||
with mock.patch('glanceclient.v2.images.Controller.list',
|
||||
return_value=self.images) as mock_get:
|
||||
return_value=self.images) as mock_list:
|
||||
with mock.patch('glanceclient.v2.image_members.Controller.list',
|
||||
side_effect=image_member_mocks):
|
||||
side_effect=image_member_mocks) as mock_members:
|
||||
# This is not testing the elasticsearch call, just
|
||||
# that the documents being indexed are as expected
|
||||
with mock.patch.object(
|
||||
|
@ -247,7 +253,9 @@ class TestImageLoaderPlugin(test_utils.BaseTestCase):
|
|||
'save_documents') as mock_save:
|
||||
self.plugin.setup_data()
|
||||
|
||||
mock_get.assert_called_once_with()
|
||||
mock_list.assert_called_once_with()
|
||||
mock_members.assert_has_calls(member_calls)
|
||||
|
||||
mock_save.assert_called_once_with([
|
||||
{
|
||||
'status': 'active',
|
||||
|
@ -328,3 +336,128 @@ class TestImageLoaderPlugin(test_utils.BaseTestCase):
|
|||
'updated_at': DATE1
|
||||
}
|
||||
])
|
||||
|
||||
def test_image_rbac(self):
|
||||
"""Test the image plugin RBAC query terms"""
|
||||
fake_request = unit_test_utils.get_fake_request(
|
||||
USER1, TENANT1, '/v1/search'
|
||||
)
|
||||
rbac_query_fragment = self.plugin.get_rbac_filter(fake_request.context)
|
||||
expected_fragment = [{
|
||||
"and": [
|
||||
{
|
||||
"or": [
|
||||
{"term": {"owner": TENANT1}},
|
||||
{"term": {"visibility": "public"}},
|
||||
{"term": {"members": TENANT1}}
|
||||
]
|
||||
},
|
||||
{"type": {"value": "image"}},
|
||||
{"index": {"value": "glance"}}
|
||||
]
|
||||
}]
|
||||
self.assertEqual(expected_fragment, rbac_query_fragment)
|
||||
|
||||
def test_protected_properties(self):
|
||||
extra_props = {
|
||||
'x_foo_matcher': 'this is protected',
|
||||
'x_foo_something_else': 'this is not protected',
|
||||
'z_this_has_no_rules': 'this is protected too'
|
||||
}
|
||||
image_with_properties = _image_fixture(
|
||||
UUID1, owner=TENANT1, checksum=CHECKSUM, name='simple', size=256,
|
||||
is_public=True, status='active', extra_properties=extra_props
|
||||
)
|
||||
|
||||
with mock.patch('glanceclient.v2.image_members.Controller.list',
|
||||
return_value=[]):
|
||||
serialized = self.plugin.serialize(image_with_properties)
|
||||
|
||||
elasticsearch_results = {
|
||||
'hits': {
|
||||
'hits': [{
|
||||
'_source': copy.deepcopy(serialized),
|
||||
'_type': self.plugin.get_document_type(),
|
||||
'_index': self.plugin.get_index_name()
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
# Admin context
|
||||
fake_request = unit_test_utils.get_fake_request(
|
||||
USER1, TENANT1, '/v1/search', is_admin=True
|
||||
)
|
||||
filtered_result = self.plugin.filter_result(
|
||||
elasticsearch_results, fake_request.context
|
||||
)
|
||||
|
||||
# This should contain the three properties we added
|
||||
expected = {
|
||||
'checksum': '93264c3edf5972c9f1cb309543d38a5c',
|
||||
'container_format': None,
|
||||
'disk_format': None,
|
||||
'id': 'c80a1a6c-bd1f-41c5-90ee-81afedb1d58d',
|
||||
'members': [],
|
||||
'min_disk': None,
|
||||
'min_ram': None,
|
||||
'name': 'simple',
|
||||
'owner': '6838eb7b-6ded-434a-882c-b344c77fe8df',
|
||||
'protected': False,
|
||||
'size': 256,
|
||||
'status': 'active',
|
||||
'tags': [],
|
||||
'virtual_size': None,
|
||||
'visibility': 'public',
|
||||
'created_at': DATE1,
|
||||
'updated_at': DATE1,
|
||||
'x_foo_matcher': 'this is protected',
|
||||
'x_foo_something_else': 'this is not protected',
|
||||
'z_this_has_no_rules': 'this is protected too'
|
||||
}
|
||||
|
||||
self.assertEqual(expected,
|
||||
filtered_result['hits']['hits'][0]['_source'])
|
||||
|
||||
# Non admin user. Recreate this because the filter operation modifies
|
||||
# it in place and we want a fresh copy
|
||||
elasticsearch_results = {
|
||||
'hits': {
|
||||
'hits': [{
|
||||
'_source': copy.deepcopy(serialized),
|
||||
'_type': self.plugin.get_document_type(),
|
||||
'_index': self.plugin.get_index_name()
|
||||
}]
|
||||
}
|
||||
}
|
||||
# Non admin context should miss the x_foo property
|
||||
fake_request = unit_test_utils.get_fake_request(
|
||||
USER1, TENANT1, '/v1/search', is_admin=False
|
||||
)
|
||||
filtered_result = self.plugin.filter_result(
|
||||
elasticsearch_results, fake_request.context
|
||||
)
|
||||
|
||||
# Should be missing two of the properties
|
||||
expected = {
|
||||
'checksum': '93264c3edf5972c9f1cb309543d38a5c',
|
||||
'container_format': None,
|
||||
'disk_format': None,
|
||||
'id': 'c80a1a6c-bd1f-41c5-90ee-81afedb1d58d',
|
||||
'members': [],
|
||||
'min_disk': None,
|
||||
'min_ram': None,
|
||||
'name': 'simple',
|
||||
'owner': '6838eb7b-6ded-434a-882c-b344c77fe8df',
|
||||
'protected': False,
|
||||
'size': 256,
|
||||
'status': 'active',
|
||||
'tags': [],
|
||||
'virtual_size': None,
|
||||
'visibility': 'public',
|
||||
'created_at': DATE1,
|
||||
'updated_at': DATE1,
|
||||
'x_foo_something_else': 'this is not protected'
|
||||
}
|
||||
|
||||
self.assertEqual(expected,
|
||||
filtered_result['hits']['hits'][0]['_source'])
|
||||
|
|
|
@ -18,10 +18,13 @@ import mock
|
|||
|
||||
from searchlight.elasticsearch.plugins.glance import metadefs as md_plugin
|
||||
from searchlight.elasticsearch.plugins import openstack_clients
|
||||
import searchlight.tests.unit.utils as unit_test_utils
|
||||
import searchlight.tests.utils as test_utils
|
||||
|
||||
|
||||
# Metadefinitions
|
||||
USER1 = '54492ba0-f4df-4e4e-be62-27f4d76b29cf'
|
||||
|
||||
TENANT1 = '6838eb7b-6ded-434a-882c-b344c77fe8df'
|
||||
TENANT2 = '2c014f32-55eb-467d-8fcb-4bd706012f81'
|
||||
|
||||
|
@ -419,3 +422,23 @@ class TestMetadefLoaderPlugin(test_utils.BaseTestCase):
|
|||
],
|
||||
}
|
||||
])
|
||||
|
||||
def test_metadef_rbac(self):
|
||||
"""Test metadefs RBAC query terms"""
|
||||
fake_request = unit_test_utils.get_fake_request(
|
||||
USER1, TENANT1, '/v1/search'
|
||||
)
|
||||
rbac_query_fragment = self.plugin.get_rbac_filter(fake_request.context)
|
||||
expected_fragment = [{
|
||||
"and": [
|
||||
{
|
||||
"or": [
|
||||
{"term": {"owner": TENANT1}},
|
||||
{"term": {"visibility": "public"}},
|
||||
]
|
||||
},
|
||||
{"type": {"value": "metadef"}},
|
||||
{"index": {"value": "glance"}}
|
||||
]
|
||||
}]
|
||||
self.assertEqual(expected_fragment, rbac_query_fragment)
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright 2015 Hewlett-Packard Corporation
|
||||
# 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.
|
||||
|
||||
"""Common utilities used in testing"""
|
||||
|
||||
from searchlight.common import wsgi
|
||||
import searchlight.context
|
||||
|
||||
|
||||
SOMEUSER = '54492ba0-dead-beef-be62-27f4d76b29cf'
|
||||
SOMETENANT = '6838eb7b-6ded-dead-beef-b344c77fe8df'
|
||||
|
||||
|
||||
def get_fake_request(user=SOMEUSER, tenant=SOMETENANT, path='/v1/search',
|
||||
method='GET', is_admin=False, roles=['member']):
|
||||
req = wsgi.Request.blank(path)
|
||||
req.method = method
|
||||
|
||||
if is_admin and 'admin' not in roles:
|
||||
roles = roles[:]
|
||||
roles.append('admin')
|
||||
|
||||
kwargs = {
|
||||
'user': user,
|
||||
'tenant': tenant,
|
||||
'roles': roles,
|
||||
'is_admin': is_admin,
|
||||
}
|
||||
|
||||
req.context = searchlight.context.RequestContext(**kwargs)
|
||||
return req
|
|
@ -22,7 +22,6 @@ from searchlight.common import exception
|
|||
from searchlight.common import utils
|
||||
import searchlight.elasticsearch
|
||||
import searchlight.gateway
|
||||
from searchlight.tests.unit import base
|
||||
import searchlight.tests.unit.utils as unit_test_utils
|
||||
import searchlight.tests.utils as test_utils
|
||||
|
||||
|
@ -54,7 +53,7 @@ def _image_fixture(op_type, _id=None, index='glance', doc_type='image',
|
|||
return _action_fixture(op_type, image_data, index, doc_type, _id, **kwargs)
|
||||
|
||||
|
||||
class TestSearchController(base.IsolatedUnitTest):
|
||||
class TestSearchController(test_utils.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestSearchController, self).setUp()
|
||||
|
@ -155,7 +154,7 @@ class TestSearchController(base.IsolatedUnitTest):
|
|||
request, query, index, doc_type, fields, offset, limit)
|
||||
|
||||
def test_index_complete(self):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
request = unit_test_utils.get_fake_request(is_admin=True)
|
||||
self.search_controller.index = mock.Mock(return_value="{}")
|
||||
actions = [{'action': 'create', 'index': 'myindex', 'id': 10,
|
||||
'type': 'MyTest', 'data': '{"name": "MyName"}'}]
|
||||
|
@ -168,7 +167,7 @@ class TestSearchController(base.IsolatedUnitTest):
|
|||
request, actions, default_index, default_type)
|
||||
|
||||
def test_index_repo_complete(self):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
request = unit_test_utils.get_fake_request(is_admin=True)
|
||||
repo = searchlight.elasticsearch.CatalogSearchRepo
|
||||
repo.index = mock.Mock(return_value="{}")
|
||||
actions = [{'action': 'create', 'index': 'myindex', 'id': 10,
|
||||
|
@ -182,7 +181,7 @@ class TestSearchController(base.IsolatedUnitTest):
|
|||
default_index, default_type, actions)
|
||||
|
||||
def test_index_repo_minimal(self):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
request = unit_test_utils.get_fake_request(is_admin=True)
|
||||
repo = searchlight.elasticsearch.CatalogSearchRepo
|
||||
repo.index = mock.Mock(return_value="{}")
|
||||
actions = [{'action': 'create', 'index': 'myindex', 'id': 10,
|
||||
|
@ -203,7 +202,7 @@ class TestSearchController(base.IsolatedUnitTest):
|
|||
request, actions)
|
||||
|
||||
def test_index_not_found(self):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
request = unit_test_utils.get_fake_request(is_admin=True)
|
||||
repo = searchlight.elasticsearch.CatalogSearchRepo
|
||||
repo.index = mock.Mock(side_effect=exception.NotFound)
|
||||
actions = [{'action': 'create', 'index': 'myindex', 'id': 10,
|
||||
|
@ -214,7 +213,7 @@ class TestSearchController(base.IsolatedUnitTest):
|
|||
request, actions)
|
||||
|
||||
def test_index_duplicate(self):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
request = unit_test_utils.get_fake_request(is_admin=True)
|
||||
repo = searchlight.elasticsearch.CatalogSearchRepo
|
||||
repo.index = mock.Mock(side_effect=exception.Duplicate)
|
||||
actions = [{'action': 'create', 'index': 'myindex', 'id': 10,
|
||||
|
@ -225,7 +224,7 @@ class TestSearchController(base.IsolatedUnitTest):
|
|||
request, actions)
|
||||
|
||||
def test_index_exception(self):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
request = unit_test_utils.get_fake_request(is_admin=True)
|
||||
repo = searchlight.elasticsearch.CatalogSearchRepo
|
||||
repo.index = mock.Mock(side_effect=Exception)
|
||||
actions = [{'action': 'create', 'index': 'myindex', 'id': 10,
|
||||
|
@ -236,7 +235,7 @@ class TestSearchController(base.IsolatedUnitTest):
|
|||
request, actions)
|
||||
|
||||
def test_plugins_info(self):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
request = unit_test_utils.get_fake_request(is_admin=True)
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue