def test_bulk_index_error_handling(self): """Check that 404 and 409 errors are appropriately ignored""" from elasticsearch import helpers mock_engine = mock.Mock() plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) indexing_helper = helper.IndexingHelper(plugin) bulk_name = 'searchlight.elasticsearch.plugins.helper.helpers.bulk' with mock.patch(bulk_name) as mock_bulk: mock_bulk.side_effect = helpers.BulkIndexError( "1 document(s) failed to index", [{ 'delete': { "_id": "1", "error": "Some error", "status": 404, "exception": helpers.TransportError() } }]) indexing_helper.delete_documents([{'_id': '1'}]) self.assertEqual(1, mock_bulk.call_count) with mock.patch(bulk_name) as mock_bulk: mock_bulk.side_effect = helpers.BulkIndexError( "1 document(s) failed to index", [{ 'index': { "_id": "1", "error": "VersionConflict", "status": 409 } }]) indexing_helper.save_documents([{'id': '1'}]) self.assertEqual(1, mock_bulk.call_count)
def test_region_mapping(self, service_credentials_conf, resource_plugin_conf, mock_bulk): mock_engine = mock.Mock() plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) resource_plugin_conf.include_region_name = True service_credentials_conf.os_region_name = 'test-region' indexing_helper = helper.IndexingHelper(plugin) _, mapping = six.next(plugin.get_full_mapping()) self.assertIn('region_name', mapping['properties']) count = len(plugin.get_objects()) fake_versions = range(1, count + 1) indexing_helper.save_documents(plugin.get_objects(), fake_versions) self.assertEqual(1, len(mock_bulk.call_args_list)) actions = list(mock_bulk.call_args_list[0][1]['actions']) self.assertEqual(['test-region'], actions[0]['_source']['region_name']) # Test without a region resource_plugin_conf.include_region_name = False mock_bulk.reset_mock() _, mapping = six.next(plugin.get_full_mapping()) self.assertNotIn('region_name', mapping['properties']) indexing_helper.save_documents(plugin.get_objects(), fake_versions) actions = list(mock_bulk.call_args_list[0][1]['actions']) self.assertNotIn('region_name', actions[0]['_source'])
def test_with_region(self, resource_plugin_conf, service_cred_conf): # Now test with a region resource_plugin_conf.include_region_name = True service_cred_conf.os_region_name = 'test-region' index_name = self.role_plugin.alias_name_listener simple_plugin = fake_plugins.FakeSimplePlugin(self.elastic_connection) non_role = fake_plugins.NonRoleSeparatedPlugin(self.elastic_connection) # Override region name for non-role non_role.options.override_region_name = ['region1', 'region2'] non_role.index_initial_data() simple_plugin.index_initial_data() self._flush_elasticsearch(index_name) es_results = self._get_all_elasticsearch_docs() simple_res = list( filter(lambda r: r['_type'] == simple_plugin.get_document_type(), es_results['hits']['hits'])) non_role_res = list( filter(lambda r: r['_type'] == non_role.get_document_type(), es_results['hits']['hits'])) self.assertEqual(['test-region'], simple_res[0]['_source']['region_name']) self.assertEqual(['region1', 'region2'], non_role_res[0]['_source']['region_name'])
def test_set_child_plugin_group(self): """Test setting child plugin's resource_group_name while loading plugins """ mock_engine = mock.Mock() parent_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) child_plugin = fake_plugins.FakeWrongGroupChildPlugin( es_engine=mock_engine) grandchild_plugin = fake_plugins.FakeWrongGroupGrandchildPlugin( es_engine=mock_engine) mock_stevedore_parent = mock.Mock() mock_stevedore_parent.obj = parent_plugin mock_stevedore_child = mock.Mock() mock_stevedore_child.obj = child_plugin mock_stevedore_grandchild = mock.Mock() mock_stevedore_grandchild.obj = grandchild_plugin with mock.patch('stevedore.extension.ExtensionManager') as mock_stev: manager = mock.Mock() manager.extensions = [ mock_stevedore_parent, mock_stevedore_child, mock_stevedore_grandchild ] mock_stev.return_value = manager searchlight_utils.get_search_plugins() self.assertEqual(grandchild_plugin.resource_group_name, child_plugin.resource_group_name) self.assertEqual(child_plugin.resource_group_name, parent_plugin.resource_group_name)
def test_rbac_field_mapping(self, mock_use_doc_vals): mock_use_doc_vals.return_value = False mock_engine = mock.Mock() simple_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) simple_plugin.setup_index_mapping(index_name='fake') mock_engine.indices.put_mapping.assert_called_once_with( index='fake', doc_type='fake-simple', body={ 'properties': { 'updated_at': { 'type': 'date' }, 'id': { 'type': 'string', 'index': 'not_analyzed' }, ROLE_USER_FIELD: { 'include_in_all': False, 'type': 'string', 'index': 'not_analyzed' } } })
def test_parent_child_mapping(self, mock_use_doc_vals): mock_use_doc_vals.return_value = False mock_engine = mock.Mock() parent_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) child_plugin = fake_plugins.FakeChildPlugin(es_engine=mock_engine) child_plugin.register_parent(parent_plugin) parent_plugin.setup_index_mapping(index_name='fake') # Testing a couple of things; that expected_calls = [ mock.call( index='fake', doc_type='fake-child', body={ '_parent': {'type': 'fake-simple'}, 'properties': { 'updated_at': {'type': 'date'}, 'id': {'type': 'string', 'index': 'not_analyzed'}, 'parent_id': {'type': 'string', 'index': 'not_analyzed'}, ROLE_USER_FIELD: {'include_in_all': False, 'type': 'string', 'index': 'not_analyzed'} } }), mock.call( index='fake', doc_type='fake-simple', body={ 'properties': { 'updated_at': {'type': 'date'}, 'id': {'type': 'string', 'index': 'not_analyzed'}, ROLE_USER_FIELD: {'include_in_all': False, 'type': 'string', 'index': 'not_analyzed'} } }) ] mock_engine.indices.put_mapping.assert_has_calls(expected_calls) # Also test explicitly setting _parent on the child, which should # result in the same mapping mock_engine.reset_mock() mock_engine.indices.put_mapping.assert_not_called() child_mapping = child_plugin.get_mapping() # This mapping matches what would be assigned automatically def explicit_parent_mapping(_self): child_mapping['_parent'] = {'type': 'fake-simple'} return child_mapping child_plugin.get_mapping = types.MethodType(explicit_parent_mapping, child_plugin) parent_plugin.setup_index_mapping(index_name='fake') mock_engine.indices.put_mapping.assert_has_calls(expected_calls)
def test_nested_object_facets(self): """Check 'nested' and 'object' types are treated the same for facets""" mock_engine = mock.Mock() plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) fake_request = unit_test_utils.get_fake_request( 'a', 'b', '/v1/search/facets', is_admin=True ) mock_engine.search.return_value = { "hits": {"total": 1} } fake_mapping = { "properties": { "nested": { "type": "nested", "properties": {"inner": {"type": "string"}} }, "object": { "type": "object", "properties": {"inner": {"type": "string"}} } } } with mock.patch.object(plugin, 'get_mapping', return_value=fake_mapping): facets, _ = plugin.get_facets(fake_request.context) facets = sorted(facets, key=operator.itemgetter("name")) expected = [ {"name": "nested.inner", "type": "string", "nested": True}, {"name": "object.inner", "type": "string", "nested": False}, ] self.assertEqual(expected, facets)
def test_child_only_separated(self, mock_role_separated): """Test where the child (and not the parent) is separated. Expect two documents with the same parent """ mock_role_separated.return_value = True mock_engine = mock.Mock() plugin = fake_plugins.FakeChildPlugin(es_engine=mock_engine) parent_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) plugin.register_parent(parent_plugin) indexing_helper = helper.IndexingHelper(plugin) bulk_name = 'searchlight.elasticsearch.plugins.helper.helpers.bulk' child_docs = copy.deepcopy(fake_plugins.CHILD_DATA) with mock.patch(bulk_name) as mock_bulk: indexing_helper.save_documents(child_docs) self.assertEqual(1, len(mock_bulk.call_args_list)) actions = list(mock_bulk.call_args_list[0][1]['actions']) expected_admin_doc = copy.deepcopy(child_docs[0]) expected_admin_doc[ROLE_USER_FIELD] = 'admin' expected_user_doc = copy.deepcopy(child_docs[0]) expected_user_doc[ROLE_USER_FIELD] = 'user' expected_actions = [ {'_op_type': 'index', '_id': 'child1_ADMIN', '_source': expected_admin_doc, '_parent': 'simple1'}, {'_op_type': 'index', '_id': 'child1_USER', '_source': expected_user_doc, '_parent': 'simple1'} ] self.assertEqual(expected_actions, list(actions))
def test_filter_result(self): """Verify that any highlighted query results will filter out the ROLE_USER_FIELD field. """ request = unit_test_utils.get_fake_request(is_admin=True) mock_engine = mock.Mock() simple_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) # Verify with ROLE_USER_FIELD hit = { "_source": { "owner": "<em>admin</em>" }, "highlight": { "owner": "<em>admin</em>", "__searchlight-user-role": "<em>admin</em>" } } simple_plugin.filter_result(hit, request.context) self.assertNotIn('__searchlight-user-role', hit['highlight']) # Verify without ROLE_USER_FIELD hit = { "_source": { "owner": "<em>admin</em>" }, "highlight": { "owner": "<em>admin</em>" } } original_hit = copy.deepcopy(hit) simple_plugin.filter_result(hit, request.context) self.assertEqual(original_hit, hit)
def test_prepare_index(self, mock_mapping): """Verify Indexbase.prepare_index(). The method will verify that all non-analyzed mapping fields that are raw, are truly marked as raw. This applies to any children plugins. There should not be any exceptions raised. In addition, the index mappings and settings are created at this time. Since we have separate unit tests for verifying the index mappings and index settings functionality, we will verify only that these methods are called. """ mock_engine = mock.Mock() # Test #1: Plugin with no children, good "raw" mapping field. plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) with mock.patch.object(plugin, 'get_mapping') as mock_map: mock_map.return_value = {"properties": { "id": {"type": "string", "index": "not_analyzed"}, "name": {"type": "string", "fields": { "raw": {"type": "string", "index": "not_analyzed"} }}}} plugin.prepare_index('fake') mock_mapping.assert_called_once_with(index_name='fake') # Test #2: Plugin with no children, bad "raw" mapping field. mock_mapping.reset_mock() plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) with mock.patch.object(plugin, 'get_mapping') as mock_map: mock_map.return_value = {"properties": { "id": {"type": "string", "index": "not_analyzed"}, "name": {"type": "string"}}} message = ("Field 'name' for searchlight-listener/fake-simple " "must contain a subfield whose name is 'raw' for " "sorting.") self.assertRaisesRegex(Exception, message, plugin.prepare_index, index_name='fake') mock_mapping.assert_not_called() # Test #3: Plugin with two children. No "raw" mapping fields. mock_mapping.reset_mock() parent_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) child1_plugin = fake_plugins.FakeChildPlugin(es_engine=mock_engine) child1_plugin.register_parent(parent_plugin) child2_plugin = fake_plugins.FakeChildPlugin(es_engine=mock_engine) child2_plugin.register_parent(parent_plugin) parent_plugin.prepare_index('fake') mock_mapping.assert_called_once_with(index_name='fake')
def test_without_region(self, resource_plugin_conf, service_cred_conf): # Test that region isn't indexed unless explicitly enabled resource_plugin_conf.include_region_name = False service_cred_conf.os_region_name = 'test-region' index_name = self.role_plugin.alias_name_listener simple_plugin = fake_plugins.FakeSimplePlugin(self.elastic_connection) simple_plugin.index_initial_data() self._flush_elasticsearch(index_name) es_results = self._get_all_elasticsearch_docs() self.assertNotIn('region_name', es_results['hits']['hits'][0]['_source'])
def test_doc_values_property(self): mock_engine = mock.Mock() plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) doc_type, mapping = six.next(plugin.get_full_mapping()) self.assertEqual(True, mapping['properties']['id']['doc_values']) # Test the same but disabling doc values for the plugin with mock.patch.object(plugin.__class__, 'mapping_use_doc_values', new_callable=mock.PropertyMock) as conf_mock: conf_mock.return_value = False doc_type, mapping = six.next(plugin.get_full_mapping()) self.assertNotIn('doc_values', mapping['properties']['id'])
def test_delete_children_non_role_separated(self): mock_engine = mock.Mock() plugin = fake_plugins.FakeChildPlugin(es_engine=mock_engine) parent_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) plugin.register_parent(parent_plugin) indexing_helper = helper.IndexingHelper(plugin) scan_name = 'searchlight.elasticsearch.plugins.helper.helpers.scan' bulk_name = 'searchlight.elasticsearch.plugins.helper.helpers.bulk' mock_scan_data = [ { '_id': '1', 'fields': { '_parent': 'p1' } }, ] with mock.patch(scan_name, return_value=mock_scan_data) as mock_scan: with mock.patch(bulk_name) as mock_bulk: indexing_helper.delete_documents_with_parent('p1') parent_type = plugin.parent_plugin_type() expected_scan_query = { 'fields': ['_parent', '_routing'], 'query': { 'term': { '_parent': '%s#%s' % (parent_type, 'p1') } } } mock_scan.assert_called_with(client=plugin.engine, index=plugin.alias_name_listener, doc_type=plugin.document_type, query=expected_scan_query) expected_delete_actions = [{ '_op_type': 'delete', '_id': '1', '_parent': 'p1' }] mock_bulk.assert_called_with(client=plugin.engine, index=plugin.alias_name_listener, doc_type=plugin.document_type, actions=expected_delete_actions)
def test_manage_type_glob(self, mock_get_plugins, mock_utcnow): mock_utcnow.return_value = datetime.datetime(year=2016, month=3, day=3) expected_index_name = 'searchlight-2016_03_03_00_00_00' simple_plugin = fake_plugins.FakeSimplePlugin(self.elastic_connection) child_plugin = fake_plugins.FakeChildPlugin(self.elastic_connection) non_role_plugin = fake_plugins.NonRoleSeparatedPlugin( self.elastic_connection) child_plugin.register_parent(simple_plugin) mock_get_plugins.return_value = { plugin.get_document_type(): test_utils.StevedoreMock(plugin) for plugin in (simple_plugin, child_plugin, non_role_plugin) } index_command = manage.IndexCommands() # Expect this to match simple plugin and child plugin, but not # non_role_plugin. Patch the index->index function call since it won't # find any data, and we want to check it's called correctly with mock.patch.object(index_command, '_es_reindex_worker') as patch_es_reindex: try: # Use two wildcard matches index_command.sync(_type='fake-sim*,fake-chi*', force=True) es_results = self._get_all_elasticsearch_docs() es_hits = self._get_hit_source(es_results) finally: es_utils.delete_index(expected_index_name) patch_es_reindex.assert_called_with( {non_role_plugin.get_document_type(): non_role_plugin}, [('searchlight', 'searchlight-search', 'searchlight-listener')], {'searchlight': expected_index_name} ) expected = ['simple1', 'child1'] self.assertEqual(len(expected), len(es_hits)) self.assertEqual( set(expected), set(hit['_id'] for hit in es_results['hits']['hits']))
def test_facets(self): """If you have a weak constitution, we may want to avert your eyes now. We want to verify that the "exclude_options" parameter for facets will not result in any aggregation in the Elasticsearch query. The actual ES query is buried in the bowels of Searchlight. Instead of trying to call it directly through the searchcontroller and mock mutliple levels of Servers/Requests/Catalogs/etc we will go directly to the IndexBase call. """ request = unit_test_utils.get_fake_request(is_admin=True) mock_engine = mock.Mock() simple_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) mock_engine.search.return_value = {"hits": {"total": 0}} simple_plugin._get_facet_terms(fields={}, request_context=request.context, all_projects=False, limit_terms=False, exclude_options=True) # Verify there is no aggregation when searching Elasticsearch. body = { 'query': { 'bool': { 'filter': { 'bool': { 'must': { 'term': { '__searchlight-user-role': 'admin' } } } } } } } mock_engine.search.assert_called_with(body=body, doc_type='fake-simple', ignore_unavailable=True, index='searchlight-search', size=0)
def test_invalid_parent_mapping(self): mock_engine = mock.Mock() parent_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) child_plugin = fake_plugins.FakeChildPlugin(es_engine=mock_engine) child_plugin.register_parent(parent_plugin) child_mapping = child_plugin.get_mapping() def bad_parent_mapping(_self): child_mapping['_parent'] = {'type': 'this is not my parent'} return child_mapping # Now have the child's mapping include a bad _parent value child_plugin.get_mapping = types.MethodType(bad_parent_mapping, child_plugin) expected_error = ("Mapping for 'fake-child' contains a _parent 'this " "is not my parent' that doesn't match 'fake-simple'") self.assertRaisesRegexp(exception.IndexingException, expected_error, parent_plugin.setup_index_mapping, index_name='fake')
def test_manage(self, mock_get_plugins, mock_utcnow): """Test that manage index sync works from end to end. Uses fake plugins because it avoids having to fake service data and is less dependent on functional tests for each service plugin. """ mock_utcnow.return_value = datetime.datetime(year=2016, month=1, day=1) expected_index_name = 'searchlight-2016_01_01_00_00_00' simple_plugin = fake_plugins.FakeSimplePlugin(self.elastic_connection) child_plugin = fake_plugins.FakeChildPlugin(self.elastic_connection) non_role_plugin = fake_plugins.NonRoleSeparatedPlugin( self.elastic_connection) child_plugin.register_parent(simple_plugin) mock_get_plugins.return_value = { plugin.get_document_type(): test_utils.StevedoreMock(plugin) for plugin in (simple_plugin, child_plugin, non_role_plugin) } index_command = manage.IndexCommands() # The fake plugins all have hardcoded data for get_objects that will # be indexed. Use force=True to avoid the 'are you sure?' prompt try: index_command.sync(force=True) es_results = self._get_all_elasticsearch_docs() es_hits = self._get_hit_source(es_results) finally: es_utils.delete_index(expected_index_name) self.assertEqual(expected_index_name, es_results['hits']['hits'][0]['_index']) expected = ['simple1', 'child1', 'non-role-fake1', 'non-role-fake2'] self.assertEqual(len(expected), len(es_hits)) self.assertEqual( set(expected), set(hit['_id'] for hit in es_results['hits']['hits']))
def test_raw_subfield_facets(self): mock_engine = mock.Mock() simple_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) simple_plugin.engine = mock_engine mock_engine.search.return_value = { 'aggregations': { 'name': { 'buckets': [{ 'key': 'klopp', 'doc_count': 1 }, { 'key': 'bob', 'doc_count': 2 }] } }, 'hits': { 'total': 2 } } fake_request = unit_test_utils.get_fake_request(USER1, TENANT1, '/v1/search/facets', is_admin=True) raw_field_mapping = { 'properties': { # not analyzed string field 'id': { 'type': 'string', 'index': 'not_analyzed' }, # analyzed string field with a raw subfield 'name': { 'type': 'string', 'fields': { 'raw': { 'type': 'string', 'index': 'not_analyzed' } } }, # non-string field with a raw subfield 'non_string_field': { 'type': 'date', 'fields': { 'raw': { 'type': 'string' } } } } } with mock.patch.object(simple_plugin, 'get_mapping', return_value=raw_field_mapping): with mock.patch.object(simple_plugin.__class__, 'facets_with_options', new_callable=mock.PropertyMock, return_value=('name', )): facets, doc_count = simple_plugin.get_facets( fake_request.context, all_projects=True) expected = [{ 'type': 'string', 'name': 'id' }, { 'type': 'string', 'name': 'name', 'facet_field': 'name.raw', 'options': [{ 'key': 'klopp', 'doc_count': 1 }, { 'key': 'bob', 'doc_count': 2 }] }, { 'type': 'date', 'name': 'non_string_field' }] facets = sorted(facets, key=lambda facet: facet['name']) # Test if facets query result is as expected self.assertEqual(expected, facets) expected_body = { 'query': { 'filtered': { 'filter': { 'and': [{ 'term': { ROLE_USER_FIELD: 'admin' } }] } } }, 'aggs': { 'name': { 'terms': { 'field': 'name.raw', 'size': 0 } } } } # Test if engine gets called with right search query mock_engine.search.assert_called_with( index=simple_plugin.alias_name_search, doc_type=simple_plugin.get_document_type(), body=expected_body, ignore_unavailable=True, size=0)
def test_get_facets(self): mock_engine = mock.Mock() simple_plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) simple_plugin.engine = mock_engine child_plugin = fake_plugins.FakeChildPlugin(es_engine=mock_engine) child_plugin.engine = mock_engine mock_engine.search.return_value = { 'aggregations': {}, 'hits': { 'total': 1 } } fake_request = unit_test_utils.get_fake_request() meta_mapping = { 'properties': { 'reference_id_1': { 'type': 'string', 'index': 'not_analyzed' }, 'some_key': { 'type': 'integer' }, 'nested': { 'type': 'nested', 'properties': { "some_key": { 'type': 'string' }, 'reference_id_2': { 'type': 'string', 'index': 'not_analyzed' } } } }, "_meta": { "reference_id_1": { "resource_type": "OS::Glance::Image" }, "nested.reference_id_2": { "resource_type": "OS::Cinder::Snapshot" } } } # Test resource_types without parent with mock.patch.object(simple_plugin, 'get_mapping', return_value=meta_mapping): facets, doc_count = simple_plugin.get_facets(fake_request.context) expected = [{ "type": "string", "name": "reference_id_1", "resource_type": "OS::Glance::Image" }, { "type": "string", "name": "nested.reference_id_2", "resource_type": "OS::Cinder::Snapshot", "nested": True, }, { "type": "string", "name": "nested.some_key", "nested": True }, { "type": "integer", "name": "some_key", }] expected_list = sorted(expected, key=lambda k: k['name']) actual_list = sorted(facets, key=lambda k: k['name']) self.assertEqual(expected_list, actual_list) # Test resource_types with parent meta_mapping = { 'properties': { 'parent_id': { 'type': 'string', 'index': 'not_analyzed' } }, "_meta": { "parent_id": { "resource_type": child_plugin.parent_plugin_type() } } } with mock.patch.object(child_plugin, 'get_mapping', return_value=meta_mapping): facets, doc_count = child_plugin.get_facets(fake_request.context) expected = [{ "type": "string", "name": "parent_id", "resource_type": child_plugin.parent_plugin_type(), "parent": True }] self.assertEqual(expected, facets) # Test resource_types with parent and no explicit meta info meta_mapping.pop('_meta') with mock.patch.object(child_plugin, 'get_mapping', return_value=meta_mapping): facets, doc_count = child_plugin.get_facets(fake_request.context) expected = [{ "type": "string", "name": "parent_id", "resource_type": child_plugin.parent_plugin_type(), "parent": True }] self.assertEqual(expected, facets)
def test_rbac_field_doc_values(self): mock_engine = mock.Mock() plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) doc_Type, mapping = six.next(plugin.get_full_mapping()) props = mapping['properties'] self.assertEqual(True, props[ROLE_USER_FIELD]['doc_values'])
def test_doc_values(self): mock_engine = mock.Mock() plugin = fake_plugins.FakeSimplePlugin(es_engine=mock_engine) test_doc_value_mapping = { 'dynamic_templates': [{ 'test': { "path_match": "test.*", 'mapping': { 'type': 'integer' } } }], 'properties': { 'not_analyzed_string': { 'type': 'string', 'index': 'not_analyzed' }, 'analyzed_string': { 'type': 'string' }, 'sortable_string': { 'type': 'string', 'fields': { 'raw': { 'type': 'string', 'index': 'not_analyzed' } } }, 'no_doc_values': { 'type': 'string', 'index': 'not_analyzed', 'doc_values': False }, 'inttype': { 'type': 'integer' }, 'datetype': { 'type': 'date' }, 'booltype': { 'type': 'boolean' }, 'shorttype': { 'type': 'short' }, 'longtype': { 'type': 'long' }, 'iptype': { 'type': 'ip' }, 'nested': { 'type': 'nested', 'properties': { 'booltype': { 'type': 'boolean' }, 'analyzed_string': { 'type': 'string' }, 'not_analyzed_string': { 'type': 'string', 'index': 'not_analyzed' } } } } } with mock.patch.object(plugin, 'get_mapping', return_value=test_doc_value_mapping): # get_full_mapping is a generator doc_type, mapping = six.next(plugin.get_full_mapping()) props = mapping['properties'] # These fields should all have doc_values. Explicitly testing # for 'true' here rather than assertTrue for field in ('not_analyzed_string', 'inttype', 'datetype', 'booltype', 'shorttype', 'longtype'): self.assertEqual(True, props[field]['doc_values']) self.assertEqual( True, props['sortable_string']['fields']['raw']['doc_values']) # Check nested for field in ('booltype', 'not_analyzed_string'): self.assertEqual( True, props['nested']['properties'][field]['doc_values']) # Check dynamic templates dyn_mapping = mapping['dynamic_templates'][0]['test']['mapping'] self.assertEqual(True, dyn_mapping['doc_values']) # These should not have doc_values self.assertNotIn('doc_values', props['analyzed_string']) self.assertNotIn('doc_values', props['nested']['properties']['analyzed_string']) # Test explicit setting of doc_values self.assertEqual(False, props['no_doc_values']['doc_values'])