/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.beam.sdk.io.elasticsearch; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest; import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse; import org.elasticsearch.action.admin.indices.upgrade.post.UpgradeRequest; import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.Client; import org.elasticsearch.client.IndicesAdminClient; import org.elasticsearch.client.Requests; import org.elasticsearch.index.IndexNotFoundException; /** Test utilities to use with {@link ElasticsearchIO}. */ class ElasticSearchIOTestUtils { /** Enumeration that specifies whether to insert malformed documents. */ enum InjectionMode { INJECT_SOME_INVALID_DOCS, DO_NOT_INJECT_INVALID_DOCS } /** Deletes the given index synchronously. */ static void deleteIndex(String index, Client client) throws Exception { IndicesAdminClient indices = client.admin().indices(); IndicesExistsResponse indicesExistsResponse = indices.exists(new IndicesExistsRequest(index)).get(); if (indicesExistsResponse.isExists()) { indices.prepareClose(index).get(); indices.delete(Requests.deleteIndexRequest(index)).get(); } } /** Inserts the given number of test documents into Elasticsearch. */ static void insertTestDocuments(String index, String type, long numDocs, Client client) throws Exception { final BulkRequestBuilder bulkRequestBuilder = client.prepareBulk().setRefresh(true); List<String> data = ElasticSearchIOTestUtils.createDocuments( numDocs, ElasticSearchIOTestUtils.InjectionMode.DO_NOT_INJECT_INVALID_DOCS); for (String document : data) { bulkRequestBuilder.add(client.prepareIndex(index, type, null).setSource(document)); } final BulkResponse bulkResponse = bulkRequestBuilder.execute().actionGet(); if (bulkResponse.hasFailures()) { throw new IOException( String.format( "Cannot insert test documents in index %s : %s", index, bulkResponse.buildFailureMessage())); } } /** * Forces an upgrade of the given index to make recently inserted documents available for search. * * @return The number of docs in the index */ static long upgradeIndexAndGetCurrentNumDocs(String index, String type, Client client) { try { client.admin().indices().upgrade(new UpgradeRequest(index)).actionGet(); SearchResponse response = client.prepareSearch(index).setTypes(type).execute().actionGet(5000); return response.getHits().getTotalHits(); // it is fine to ignore bellow exceptions because in testWriteWithBatchSize* sometimes, // we call upgrade before any doc have been written // (when there are fewer docs processed than batchSize). // In that cases index/type has not been created (created upon first doc insertion) } catch (IndexNotFoundException e) { } catch (java.lang.IllegalArgumentException e) { if (!e.getMessage().contains("No search type")) { throw e; } } return 0; } /** * Generates a list of test documents for insertion. * * @param numDocs Number of docs to generate * @param injectionMode {@link InjectionMode} that specifies whether to insert malformed documents * @return the list of json String representing the documents */ static List<String> createDocuments(long numDocs, InjectionMode injectionMode) { String[] scientists = { "Einstein", "Darwin", "Copernicus", "Pasteur", "Curie", "Faraday", "Newton", "Bohr", "Galilei", "Maxwell" }; ArrayList<String> data = new ArrayList<>(); for (int i = 0; i < numDocs; i++) { int index = i % scientists.length; // insert 2 malformed documents if (InjectionMode.INJECT_SOME_INVALID_DOCS.equals(injectionMode) && (i == 6 || i == 7)) { data.add(String.format("{\"scientist\";\"%s\", \"id\":%d}", scientists[index], i)); } else { data.add(String.format("{\"scientist\":\"%s\", \"id\":%d}", scientists[index], i)); } } return data; } }