Skip to content
This repository has been archived by the owner on May 18, 2020. It is now read-only.

Support elastic search7 travis fix - support platforms. #98

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
language: java
script:
dist: trusty
script:
- ./gradlew clean check --info
jdk:
- oraclejdk8
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Build Status](https://travis-ci.org/allegro/embedded-elasticsearch.svg?branch=master)](https://travis-ci.org/allegro/embedded-elasticsearch)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/pl.allegro.tech/embedded-elasticsearch/badge.svg)](http://central.maven.org/maven2/pl/allegro/tech/embedded-elasticsearch)

Small utility for creating integration tests that use Elasticsearch. Instead of using `Node` it downloads Elasticsearch in specified version and starts it in a separate process. It also allows you to install required plugins which is not possible when using `NodeBuilder`. Utility was tested with 1.x, 2.x, 5.x and 6.x versions of Elasticsearch.
Small utility for creating integration tests that use Elasticsearch. Instead of using `Node` it downloads Elasticsearch in specified version and starts it in a separate process. It also allows you to install required plugins which is not possible when using `NodeBuilder`. Utility was tested with 1.x, 2.x, 5.x, 6.x and 7.x versions of Elasticsearch.

## Introduction

Expand Down Expand Up @@ -63,6 +63,7 @@ Available `IndexSettings.Builder` options
| Method | Description |
| ------------- | ------------- |
| `withType(String type, String mapping)` | specify type and it's mappings |
| `withMapping(String mapping)` | starting from Elasticseatch 7, there is no more types, so when using an ES version 7.0 and above this method should be used insted of withType method |
| `withSettings(String settings)` | specify index settings |


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,13 @@ private String indexMetadataJson(String indexName, String indexType, String id,
joiner.add("\"_id\": \"" + id + "\"");
}

if(routing != null) {
joiner.add("\"_routing\": \"" + routing + "\"");
if (routing != null) {
if (newESVersion()) {
joiner.add("\"routing\": \"" + routing + "\"");
} else {
joiner.add("\"_routing\": \"" + routing + "\"");
}
}

return "{ \"index\": {" + joiner.toString() + "} }";
}

Expand All @@ -180,6 +183,20 @@ void refresh() {
}
}

private boolean newESVersion() {
HttpGet request = new HttpGet(url("/"));
return httpClient.execute(request, response -> {
JsonNode jsonNode;
try {
jsonNode = OBJECT_MAPPER.readTree(readBodySafely(response));
} catch (IOException e) {
return false;
}
String esV = jsonNode.get("version").get("number").asText();
return Integer.parseInt(esV.substring(0,1)) >= 7; //if version is 7 and above
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens with elasticsearch version above 9? Can we use split with '.' sign to use the structure of the version number?

});
}

private void performBulkRequest(String requestUrl, String bulkRequestBody) {
HttpPost request = new HttpPost(requestUrl);
request.setHeader(new BasicHeader(HttpHeaders.CONTENT_TYPE, "application/json"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,21 @@
import org.slf4j.LoggerFactory;
import pl.allegro.tech.embeddedelasticsearch.InstallationDescription.Plugin;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ProcessBuilder.Redirect;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.GZIPInputStream;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.commons.io.FileUtils.forceMkdir;
Expand Down Expand Up @@ -64,16 +69,37 @@ private void installElastic(Path downloadedTo) throws IOException {
logger.info("Installing Elasticsearch" + " into " + destination + "...");
try {
unzip(downloadedTo, destination);
makeExecutable("bin", "elasticsearch");
makeExecutable("bin", "plugin");
makeExecutable("bin", "elasticsearch-plugin");
makeExecutable("modules", "x-pack", "x-pack-ml", "platform", "linux-x86_64", "bin", "controller");
logger.info("Done");
} catch (IOException e) {
logger.info("Failure : " + e);
throw new EmbeddedElasticsearchStartupException(e);
}
}

private void makeExecutable(String... names) {
File executable = getFile(getInstallationDirectory(), names);
if (!executable.canExecute()) {
executable.setExecutable(true);
}
}

private void unzip(Path downloadedTo, File destination) throws IOException {
Archiver archiver = ArchiverFactory.createArchiver("zip");
archiver.extract(downloadedTo.toFile(), destination);
Archiver archiver = ArchiverFactory.createArchiver(downloadedTo.endsWith("zip") ? "zip" : "tar");
try (InputStream is = toStream(downloadedTo)) {
archiver.extract(is, destination);
}
}

private InputStream toStream(Path downloadedTo) throws IOException {
InputStream result = new FileInputStream(downloadedTo.toFile());
if (downloadedTo.toFile().getName().endsWith(".gz")) {
result = new GZIPInputStream(result);
}
return new BufferedInputStream(result);
}

private void configureElastic() throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,65 @@ public class IndexSettings {

private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

private final Optional<JsonNode> mappings;
private final List<TypeWithMapping> types;
private final Optional<JsonNode> settings;
private final Optional<JsonNode> aliases;

private boolean includeTypeName=false;
public static Builder builder() {
return new Builder();
}

public IndexSettings(List<TypeWithMapping> types, Optional<String> settings) {
private IndexSettings(List<TypeWithMapping> types, Optional<String> settings, Optional<String> aliases) {
this.mappings = rawToJson(Optional.of("{}"));
this.types = types;
this.settings = rawToJson(settings);
this.aliases = Optional.empty();
}

private IndexSettings(List<TypeWithMapping> types, Optional<String> settings, Optional<String> aliases) {
this.types = types;
public IndexSettings(Optional<String> mapping, Optional<String> settings) {
includeTypeName = true;
this.mappings = rawToJson(mapping);
this.settings = rawToJson(settings);
this.aliases = Optional.empty();
this.types = new ArrayList<>();
}

private IndexSettings(Optional<String> mapping, Optional<String> settings, Optional<String> aliases) {
this.mappings = rawToJson(mapping);
includeTypeName = true;
this.settings = rawToJson(settings);
this.aliases = rawToJson(aliases);
this.types = new ArrayList<>();
}

public static class Builder {

private final List<TypeWithMapping> types = new ArrayList<>();
private Optional<String> mapping = Optional.empty();
private Optional<String> settings = Optional.empty();
private Optional<String> aliases = Optional.empty();
private final List<TypeWithMapping> types = new ArrayList<>();

/**
* Type with mappings to create with index
*
* @param mapping mappings for created type
*/
public Builder withMapping(Object mapping) throws IOException {
String mappingString;
if (mapping == null) {
return this;
}
else if (mapping instanceof InputStream) {
InputStream mappingStream = (InputStream) mapping;
mappingString = IOUtils.toString(mappingStream, UTF_8);
}
else {
mappingString = (String) mapping;
}
this.mapping = Optional.of(mappingString);
return this;
}

/**
* Specify type inside created index
Expand All @@ -53,6 +87,7 @@ public Builder withType(String type, InputStream mapping) throws IOException {
return withType(type, IOUtils.toString(mapping, UTF_8));
}


/**
* Type with mappings to create with index
*
Expand Down Expand Up @@ -106,16 +141,23 @@ public Builder withAliases(String aliases) {
* @return IndexSettings with specified parameters
*/
public IndexSettings build() {
return new IndexSettings(types, settings, aliases);
return new IndexSettings(mapping, settings, aliases);
}
}

public ObjectNode toJson() {
ObjectNode objectNode = new ObjectMapper().createObjectNode();
objectNode.set("settings", settings.orElse(OBJECT_MAPPER.createObjectNode()));
objectNode.set("aliases", aliases.orElse(OBJECT_MAPPER.createObjectNode()));
ObjectNode mappingsObject = prepareMappingsObject();
objectNode.set("mappings", mappingsObject);

if (includeTypeName){
objectNode.set("mappings",mappings.orElse(OBJECT_MAPPER.createObjectNode()));
}
else {
ObjectNode mappingsObject = prepareMappingsObject();
objectNode.set("mappings", mappingsObject);
}

return objectNode;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package pl.allegro.tech.embeddedelasticsearch;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;

import java.net.MalformedURLException;
import java.net.URL;
Expand Down Expand Up @@ -29,7 +30,7 @@ public URL resolveDownloadUrl() {
private URL urlFromVersion(String version) {
ElsDownloadUrl elsDownloadUrl = ElsDownloadUrl.getByVersion(version);
try {
return new URL(StringUtils.replace(elsDownloadUrl.downloadUrl, "{VERSION}", version));
return new URL(StringUtils.replace(elsDownloadUrl.getDownloadUrl(), "{VERSION}", version));
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
Expand All @@ -39,7 +40,26 @@ private enum ElsDownloadUrl {
ELS_1x("1.", "https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-{VERSION}.zip"),
ELS_2x("2.", "https://download.elasticsearch.org/elasticsearch/release/org/elasticsearch/distribution/zip/elasticsearch/{VERSION}/elasticsearch-{VERSION}.zip"),
ELS_5x("5.", "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-{VERSION}.zip"),
ELS_6x("6.", ELS_5x.downloadUrl);
ELS_6x("6.", ELS_5x.downloadUrl),
ELS_7x("7.", "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-{VERSION}-{PLATFORM}-x86_64.{EXTENSION}") {
@Override
String getDownloadUrl() {
if (SystemUtils.IS_OS_LINUX) {
String result = StringUtils.replace(downloadUrl, PLATFORM, "linux");
return StringUtils.replace(result, EXTENSION, "tar.gz");
} else if (SystemUtils.IS_OS_MAC) {
String result = StringUtils.replace(downloadUrl, PLATFORM, "darwin");
return StringUtils.replace(result, EXTENSION, "tar.gz");
} else if (SystemUtils.IS_OS_WINDOWS) {
String result = StringUtils.replace(downloadUrl, PLATFORM, "windows");
return StringUtils.replace(result, EXTENSION, "zip");
}
throw new IllegalArgumentException(("Unsupported OS version " + SystemUtils.OS_NAME));
}
};

private static final String PLATFORM = "{PLATFORM}";
private static final String EXTENSION = "{EXTENSION}";

String versionPrefix;
String downloadUrl;
Expand All @@ -53,6 +73,10 @@ boolean versionMatch(String elasticVersion) {
return elasticVersion.startsWith(versionPrefix);
}

String getDownloadUrl() {
return downloadUrl;
}

static ElsDownloadUrl getByVersion(String elasticVersion) {
return Arrays.stream(ElsDownloadUrl.values())
.filter(u -> u.versionMatch(elasticVersion))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ public String getType() {
public JsonNode getMapping() {
return mapping;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import spock.lang.Specification
import spock.lang.Unroll

class InstallationSourceSpec extends Specification {
static {
//Need to do this here since we read the value statically
System.setProperty("os.name", "Linux")
}

def "should construct valid url for version"() {
given:
Expand All @@ -14,6 +18,16 @@ class InstallationSourceSpec extends Specification {
resolvedUrl != null
}

def "should construct valid url for platform specific version"() {
given:
final installationSource = new InstallFromVersion("7.6.2")
when:
final resolvedUrl = installationSource.resolveDownloadUrl()
then:
resolvedUrl != null
resolvedUrl.toExternalForm() == "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.6.2-linux-x86_64.tar.gz"
}

def "should extract properly version from normal url"() {
given:
final expectedVersion = "2.3.4"
Expand Down
10 changes: 10 additions & 0 deletions es73-test/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
dependencies {
testCompile project(':test-base')

testCompile group: 'org.elasticsearch', name: 'elasticsearch', version: '7.3.2'
testCompile group: 'org.elasticsearch.client', name: 'elasticsearch-rest-high-level-client', version: '7.3.2'
testCompile group: 'org.elasticsearch.client', name: 'elasticsearch-rest-client', version: '7.3.2'
testCompile group: 'org.locationtech.spatial4j', name: 'spatial4j', version: '0.6'
testCompile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.6.2'
testCompile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.6.2'
}
Loading