diff --git a/data-node/src/main/java/org/graylog/datanode/Configuration.java b/data-node/src/main/java/org/graylog/datanode/Configuration.java index 4f0ab5f047..8de87164cc 100644 --- a/data-node/src/main/java/org/graylog/datanode/Configuration.java +++ b/data-node/src/main/java/org/graylog/datanode/Configuration.java @@ -30,6 +30,7 @@ import com.github.joschi.jadconfig.validators.URIAbsoluteValidator; import com.google.common.annotations.VisibleForTesting; import com.google.common.net.InetAddresses; import org.graylog.datanode.configuration.BaseConfiguration; +import org.graylog.datanode.configuration.OpensearchDistributionProvider; import org.graylog2.plugin.Tools; import org.graylog2.shared.SuppressForbidden; import org.joda.time.DateTimeZone; @@ -274,16 +275,6 @@ public class Configuration extends BaseConfiguration { } } - @ValidatorMethod - @SuppressWarnings("unused") - public void validateOpenSearchDistribution() throws ValidationException { - try { - OpensearchDistribution.detectInDirectory(Path.of(getOpensearchDistributionRoot())); - } catch (RuntimeException | IOException e) { - throw new ValidationException("Could not detect OpenSearch in " + getOpensearchDistributionRoot() + ", please check your installation. Error was: " + e.getMessage()); - } - } - public String getNodeIdFile() { return nodeIdFile; } diff --git a/data-node/src/main/java/org/graylog/datanode/OpensearchDistribution.java b/data-node/src/main/java/org/graylog/datanode/OpensearchDistribution.java index 1e108feaf1..72633ef022 100644 --- a/data-node/src/main/java/org/graylog/datanode/OpensearchDistribution.java +++ b/data-node/src/main/java/org/graylog/datanode/OpensearchDistribution.java @@ -16,116 +16,16 @@ */ package org.graylog.datanode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.graylog.datanode.configuration.OpensearchArchitecture; import javax.annotation.Nullable; -import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; -import java.util.Locale; -import java.util.Objects; -import java.util.Optional; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public record OpensearchDistribution(Path directory, String version, @Nullable String platform, - @Nullable String architecture) { - - private static final Logger LOG = LoggerFactory.getLogger(OpensearchDistribution.class); - public static final Pattern FULL_NAME_PATTERN = Pattern.compile("opensearch-(.*)-(.+)-(.+)"); - public static final Pattern SHORT_NAME_PATTERN = Pattern.compile("opensearch-(.*)"); + @Nullable OpensearchArchitecture architecture) { public OpensearchDistribution(Path path, String version) { this(path, version, null, null); } - public static OpensearchDistribution detectInDirectory(Path directory) throws IOException { - final var osArch = System.getProperty("os.arch"); - return detectInDirectory(directory, osArch); - } - - static OpensearchDistribution detectInDirectory(Path rootDistDirectory, String osArch) throws IOException { - Objects.requireNonNull(rootDistDirectory, "Dist directory needs to be provided"); - - // if the base directory points directly to one opensearch distribution, we should return it directly. - // If the format doesn't fit, we'll look for opensearch distributions in this root directory. - final Optional distDirectory = parse(rootDistDirectory); - return distDirectory.orElseGet(() -> detectInSubdirectory(rootDistDirectory, osArch)); - - } - - private static OpensearchDistribution detectInSubdirectory(Path directory, String osArch) { - - final var archCode = archCode(osArch); - - final List opensearchDistributions; - try ( - var files = Files.list(directory); - ) { - opensearchDistributions = files - .filter(Files::isDirectory) - .flatMap(f -> parse(f).stream()) - .toList(); - } catch (IOException e) { - throw createErrorMessage(directory, archCode, "Failed to list content of provided directory", e); - } - - if (opensearchDistributions.isEmpty()) { - throw createErrorMessage(directory, archCode, "Could not detect any opensearch distribution"); - } - - LOG.info("Found following opensearch distributions: " + opensearchDistributions.stream().map(d -> d.directory().toAbsolutePath()).toList()); - - return findByArchitecture(opensearchDistributions, archCode) - .orElseGet(() -> findWithoutArchitecture(opensearchDistributions) - .orElseThrow(() -> createErrorMessage(directory, archCode, "No Opensearch distribution found for your system architecture"))); - } - - private static IllegalArgumentException createErrorMessage(Path directory, String osArch, String message) { - return createErrorMessage(directory, osArch, message, null); - } - - - private static IllegalArgumentException createErrorMessage(Path directory, String archCode, String errorMessage, Exception cause) { - final String message = String.format(Locale.ROOT, "%s. Directory used for Opensearch detection: %s. Please configure opensearch_location to a directory that contains an opensearch distribution for your architecture %s. You can download Opensearch from https://opensearch.org/downloads.html . Please extract the downloaded distribution and point opensearch_location configuration option to that directory.", errorMessage, directory.toAbsolutePath(), archCode); - return new IllegalArgumentException(message, cause); - } - - public static String archCode(final String osArch) { - return switch (osArch) { - case "amd64" -> "x64"; - case "x86_64" -> "x64"; - case "aarch64" -> "aarch64"; - case "arm64" -> "aarch64"; - default -> - throw new UnsupportedOperationException("Unsupported OpenSearch distribution architecture: " + osArch); - }; - } - - private static Optional findByArchitecture(List available, String archCode) { - return available.stream() - .filter(d -> archCode.equals(d.architecture())) - .findAny(); - } - - private static Optional findWithoutArchitecture(List available) { - return available.stream().filter(d -> d.architecture() == null).findFirst(); - } - - private static Optional parse(Path path) { - final String filename = path.getFileName().toString(); - final Matcher matcher = FULL_NAME_PATTERN.matcher(filename); - if (matcher.matches()) { - return Optional.of(new OpensearchDistribution(path, matcher.group(1), matcher.group(2), matcher.group(3))); - } else { - final Matcher shortMatcher = SHORT_NAME_PATTERN.matcher(filename); - if (shortMatcher.matches()) { - return Optional.of(new OpensearchDistribution(path, shortMatcher.group(1))); - } else { - return Optional.empty(); - } - } - } } diff --git a/data-node/src/main/java/org/graylog/datanode/bindings/DatanodeConfigurationBindings.java b/data-node/src/main/java/org/graylog/datanode/bindings/DatanodeConfigurationBindings.java index 474abc9946..ae440e6a14 100644 --- a/data-node/src/main/java/org/graylog/datanode/bindings/DatanodeConfigurationBindings.java +++ b/data-node/src/main/java/org/graylog/datanode/bindings/DatanodeConfigurationBindings.java @@ -17,12 +17,15 @@ package org.graylog.datanode.bindings; import com.google.inject.AbstractModule; +import org.graylog.datanode.OpensearchDistribution; import org.graylog.datanode.configuration.DatanodeConfiguration; import org.graylog.datanode.configuration.DatanodeConfigurationProvider; +import org.graylog.datanode.configuration.OpensearchDistributionProvider; public class DatanodeConfigurationBindings extends AbstractModule { @Override protected void configure() { bind(DatanodeConfiguration.class).toProvider(DatanodeConfigurationProvider.class); + bind(OpensearchDistribution.class).toProvider(OpensearchDistributionProvider.class); } } diff --git a/data-node/src/main/java/org/graylog/datanode/bindings/GenericInitializerBindings.java b/data-node/src/main/java/org/graylog/datanode/bindings/GenericInitializerBindings.java index c945dab2a4..48b0acb678 100644 --- a/data-node/src/main/java/org/graylog/datanode/bindings/GenericInitializerBindings.java +++ b/data-node/src/main/java/org/graylog/datanode/bindings/GenericInitializerBindings.java @@ -20,7 +20,6 @@ import com.google.common.util.concurrent.Service; import com.google.inject.AbstractModule; import com.google.inject.multibindings.Multibinder; import org.graylog.datanode.configuration.OpensearchConfigurationProvider; -import org.graylog.datanode.initializers.JerseyService; import org.graylog.datanode.initializers.PeriodicalsService; import org.graylog.datanode.management.OpensearchProcess; import org.graylog.datanode.management.OpensearchProcessService; diff --git a/data-node/src/main/java/org/graylog/datanode/bootstrap/preflight/OpensearchBinPreflightCheck.java b/data-node/src/main/java/org/graylog/datanode/bootstrap/preflight/OpensearchBinPreflightCheck.java index 68aa047009..eb9f7282c8 100644 --- a/data-node/src/main/java/org/graylog/datanode/bootstrap/preflight/OpensearchBinPreflightCheck.java +++ b/data-node/src/main/java/org/graylog/datanode/bootstrap/preflight/OpensearchBinPreflightCheck.java @@ -28,25 +28,27 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Optional; +import java.util.function.Supplier; import java.util.stream.Collectors; public class OpensearchBinPreflightCheck implements PreflightCheck { - private final Path opensearchDir; + private final Supplier opensearchDirSupplier; private static final Logger LOG = LoggerFactory.getLogger(OpensearchBinPreflightCheck.class); @Inject public OpensearchBinPreflightCheck(DatanodeConfiguration datanodeConfiguration) { - this(datanodeConfiguration.opensearchDistribution().directory()); + this(() -> datanodeConfiguration.opensearchDistributionProvider().get().directory()); } - public OpensearchBinPreflightCheck(Path opensearchBaseDirectory) { - this.opensearchDir = opensearchBaseDirectory; + public OpensearchBinPreflightCheck(Supplier opensearchBaseDirectory) { + this.opensearchDirSupplier = opensearchBaseDirectory; } @Override public void runCheck() throws PreflightCheckException { + final Path opensearchDir = opensearchDirSupplier.get(); if (!Files.isDirectory(opensearchDir)) { throw new PreflightCheckException("Opensearch base directory " + opensearchDir + " doesn't exist!"); } diff --git a/data-node/src/main/java/org/graylog/datanode/configuration/DatanodeConfiguration.java b/data-node/src/main/java/org/graylog/datanode/configuration/DatanodeConfiguration.java index 2744fe5d5c..40f726fd60 100644 --- a/data-node/src/main/java/org/graylog/datanode/configuration/DatanodeConfiguration.java +++ b/data-node/src/main/java/org/graylog/datanode/configuration/DatanodeConfiguration.java @@ -24,7 +24,7 @@ import org.graylog2.security.IndexerJwtAuthTokenProvider; * config file or from the ENV properties. */ public record DatanodeConfiguration( - OpensearchDistribution opensearchDistribution, + OpensearchDistributionProvider opensearchDistributionProvider, String nodeName, int processLogsBufferSize, IndexerJwtAuthTokenProvider indexerJwtAuthTokenProvider diff --git a/data-node/src/main/java/org/graylog/datanode/configuration/DatanodeConfigurationProvider.java b/data-node/src/main/java/org/graylog/datanode/configuration/DatanodeConfigurationProvider.java index 790401b586..86be67536d 100644 --- a/data-node/src/main/java/org/graylog/datanode/configuration/DatanodeConfigurationProvider.java +++ b/data-node/src/main/java/org/graylog/datanode/configuration/DatanodeConfigurationProvider.java @@ -18,14 +18,24 @@ package org.graylog.datanode.configuration; import org.graylog.datanode.Configuration; import org.graylog.datanode.OpensearchDistribution; +import org.graylog.datanode.process.OpensearchConfiguration; import org.graylog2.plugin.Tools; import org.graylog2.security.IndexerJwtAuthTokenProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.inject.Provider; import javax.inject.Singleton; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Singleton public class DatanodeConfigurationProvider implements Provider { @@ -33,8 +43,7 @@ public class DatanodeConfigurationProvider implements Provider. + */ +package org.graylog.datanode.configuration; + +public enum OpensearchArchitecture { + x64, + aarch64; + + public static OpensearchArchitecture fromOperatingSystem() { + final var osArch = System.getProperty("os.arch"); + return fromCode(osArch); + } + + public static OpensearchArchitecture fromCode(String osArch) { + return switch (osArch) { + case "amd64" -> x64; + case "x86_64" -> x64; + case "x64" -> x64; + case "aarch64" -> aarch64; + case "arm64" -> aarch64; + default -> + throw new UnsupportedOperationException("Unsupported OpenSearch distribution architecture: " + osArch); + }; + } +} diff --git a/data-node/src/main/java/org/graylog/datanode/configuration/OpensearchConfigurationProvider.java b/data-node/src/main/java/org/graylog/datanode/configuration/OpensearchConfigurationProvider.java index f0aeecc2d6..b6a02b16d2 100644 --- a/data-node/src/main/java/org/graylog/datanode/configuration/OpensearchConfigurationProvider.java +++ b/data-node/src/main/java/org/graylog/datanode/configuration/OpensearchConfigurationProvider.java @@ -117,7 +117,7 @@ public class OpensearchConfigurationProvider implements Provider. + */ +package org.graylog.datanode.configuration; + +import com.google.common.base.Suppliers; +import org.graylog.datanode.Configuration; +import org.graylog.datanode.OpensearchDistribution; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Singleton +public class OpensearchDistributionProvider implements Provider { + + private static final Logger LOG = LoggerFactory.getLogger(OpensearchDistributionProvider.class); + public static final Pattern FULL_NAME_PATTERN = Pattern.compile("opensearch-(.*)-(.+)-(.+)"); + public static final Pattern SHORT_NAME_PATTERN = Pattern.compile("opensearch-(.*)"); + + private final Supplier distribution; + + @Inject + public OpensearchDistributionProvider(final Configuration localConfiguration) { + this(Path.of(localConfiguration.getOpensearchDistributionRoot()), OpensearchArchitecture.fromOperatingSystem()); + } + + OpensearchDistributionProvider(final Path opensearchDistributionRoot, OpensearchArchitecture architecture) { + this.distribution = Suppliers.memoize(() -> detectInDirectory(opensearchDistributionRoot, architecture)); + } + + @Override + public OpensearchDistribution get() { + return distribution.get(); + } + + private static OpensearchDistribution detectInDirectory(Path rootDistDirectory, OpensearchArchitecture osArch) { + Objects.requireNonNull(rootDistDirectory, "Dist directory needs to be provided"); + + // if the base directory points directly to one opensearch distribution, we should return it directly. + // If the format doesn't fit, we'll look for opensearch distributions in this root directory. + final Optional distDirectory = parse(rootDistDirectory); + return distDirectory.orElseGet(() -> detectInSubdirectory(rootDistDirectory, osArch)); + + } + + private static OpensearchDistribution detectInSubdirectory(Path directory, OpensearchArchitecture arch) { + final List opensearchDistributions; + try ( + var files = Files.list(directory); + ) { + opensearchDistributions = files + .filter(Files::isDirectory) + .flatMap(f -> parse(f).stream()) + .toList(); + } catch (IOException e) { + throw createErrorMessage(directory, arch, "Failed to list content of provided directory", e); + } + + if (opensearchDistributions.isEmpty()) { + throw createErrorMessage(directory, arch, "Could not detect any opensearch distribution"); + } + + LOG.info("Found following opensearch distributions: " + opensearchDistributions.stream().map(d -> d.directory().toAbsolutePath()).toList()); + + return findByArchitecture(opensearchDistributions, arch) + .orElseGet(() -> findWithoutArchitecture(opensearchDistributions) + .orElseThrow(() -> createErrorMessage(directory, arch, "No Opensearch distribution found for your system architecture"))); + } + + private static IllegalArgumentException createErrorMessage(Path directory, OpensearchArchitecture arch, String message) { + return createErrorMessage(directory, arch, message, null); + } + + + private static IllegalArgumentException createErrorMessage(Path directory, OpensearchArchitecture arch, String errorMessage, Exception cause) { + final String message = String.format(Locale.ROOT, "%s. Directory used for Opensearch detection: %s. Please configure opensearch_location to a directory that contains an opensearch distribution for your architecture %s. You can download Opensearch from https://opensearch.org/downloads.html . Please extract the downloaded distribution and point opensearch_location configuration option to that directory.", errorMessage, directory.toAbsolutePath(), arch); + return new IllegalArgumentException(message, cause); + } + + public static String archCode(final String osArch) { + return switch (osArch) { + case "amd64" -> "x64"; + case "x86_64" -> "x64"; + case "aarch64" -> "aarch64"; + case "arm64" -> "aarch64"; + default -> + throw new UnsupportedOperationException("Unsupported OpenSearch distribution architecture: " + osArch); + }; + } + + private static Optional findByArchitecture(List available, OpensearchArchitecture arch) { + return available.stream() + .filter(d -> arch.equals(d.architecture())) + .findAny(); + } + + private static Optional findWithoutArchitecture(List available) { + return available.stream().filter(d -> d.architecture() == null).findFirst(); + } + + private static Optional parse(Path path) { + final String filename = path.getFileName().toString(); + final Matcher matcher = FULL_NAME_PATTERN.matcher(filename); + if (matcher.matches()) { + return Optional.of(new OpensearchDistribution(path, matcher.group(1), matcher.group(2), OpensearchArchitecture.fromCode(matcher.group(3)))); + } else { + final Matcher shortMatcher = SHORT_NAME_PATTERN.matcher(filename); + if (shortMatcher.matches()) { + return Optional.of(new OpensearchDistribution(path, shortMatcher.group(1))); + } else { + return Optional.empty(); + } + } + } +} diff --git a/data-node/src/main/java/org/graylog/datanode/rest/StatusController.java b/data-node/src/main/java/org/graylog/datanode/rest/StatusController.java index 668a521007..5bbfc127d9 100644 --- a/data-node/src/main/java/org/graylog/datanode/rest/StatusController.java +++ b/data-node/src/main/java/org/graylog/datanode/rest/StatusController.java @@ -45,7 +45,7 @@ public class StatusController { public DataNodeStatus status() { return new DataNodeStatus( version, - new StatusResponse(datanodeConfiguration.opensearchDistribution().version(), openSearch.processInfo()) + new StatusResponse(datanodeConfiguration.opensearchDistributionProvider().get().version(), openSearch.processInfo()) ); } } diff --git a/data-node/src/test/java/org/graylog/datanode/bootstrap/OpensearchBinPreflightCheckTest.java b/data-node/src/test/java/org/graylog/datanode/bootstrap/OpensearchBinPreflightCheckTest.java index 4e289bcba2..8c35b42127 100644 --- a/data-node/src/test/java/org/graylog/datanode/bootstrap/OpensearchBinPreflightCheckTest.java +++ b/data-node/src/test/java/org/graylog/datanode/bootstrap/OpensearchBinPreflightCheckTest.java @@ -37,7 +37,7 @@ public class OpensearchBinPreflightCheckTest { @Test void testNonexistentDirectory() { final Path baseDirectory = tempDir.resolve("nonexistent"); - final OpensearchBinPreflightCheck check = new OpensearchBinPreflightCheck(baseDirectory); + final OpensearchBinPreflightCheck check = new OpensearchBinPreflightCheck(() -> baseDirectory); Assertions.assertThatThrownBy(check::runCheck) .isInstanceOf(PreflightCheckException.class) .hasMessage("Opensearch base directory %s doesn't exist!", baseDirectory.toAbsolutePath()); @@ -53,7 +53,7 @@ public class OpensearchBinPreflightCheckTest { // nonexistent! final Path executable = binDir.resolve("opensearch"); - final OpensearchBinPreflightCheck check = new OpensearchBinPreflightCheck(baseDir); + final OpensearchBinPreflightCheck check = new OpensearchBinPreflightCheck(() -> baseDir); Assertions.assertThatThrownBy(check::runCheck) .isInstanceOf(PreflightCheckException.class) @@ -68,7 +68,7 @@ public class OpensearchBinPreflightCheckTest { final Path executable = binDir.resolve("opensearch"); Files.createFile(executable); - final OpensearchBinPreflightCheck check = new OpensearchBinPreflightCheck(baseDir); + final OpensearchBinPreflightCheck check = new OpensearchBinPreflightCheck(() -> baseDir); Assertions.assertThatThrownBy(check::runCheck) .isInstanceOf(PreflightCheckException.class) .hasMessageStartingWith(StringUtils.f("Opensearch binary %s is not executable!", executable.toAbsolutePath())); @@ -85,7 +85,7 @@ public class OpensearchBinPreflightCheckTest { Files.setPosixFilePermissions(executable, Collections.singleton(PosixFilePermission.OWNER_EXECUTE)); - final OpensearchBinPreflightCheck check = new OpensearchBinPreflightCheck(baseDir); + final OpensearchBinPreflightCheck check = new OpensearchBinPreflightCheck(() -> baseDir); Assertions.assertThatCode(check::runCheck) .doesNotThrowAnyException(); } diff --git a/data-node/src/test/java/org/graylog/datanode/configuration/OpensearchArchitectureTest.java b/data-node/src/test/java/org/graylog/datanode/configuration/OpensearchArchitectureTest.java new file mode 100644 index 0000000000..ab3fd2f82e --- /dev/null +++ b/data-node/src/test/java/org/graylog/datanode/configuration/OpensearchArchitectureTest.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 Graylog, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * . + */ +package org.graylog.datanode.configuration; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +class OpensearchArchitectureTest { + + @Test + void nameKnown() { + final OpensearchArchitecture amd64 = OpensearchArchitecture.fromCode("amd64"); + final OpensearchArchitecture x8664 = OpensearchArchitecture.fromCode("x86_64"); + final OpensearchArchitecture x64 = OpensearchArchitecture.fromCode("x64"); + Assertions.assertThat(amd64).isEqualTo(OpensearchArchitecture.x64); + Assertions.assertThat(x8664).isEqualTo(OpensearchArchitecture.x64); + Assertions.assertThat(x64).isEqualTo(OpensearchArchitecture.x64); + } + + @Test + void fromCodeUnknown() { + Assertions.assertThatThrownBy(() -> OpensearchArchitecture.fromCode("nonsense")) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessage("Unsupported OpenSearch distribution architecture: nonsense"); + } +} diff --git a/data-node/src/test/java/org/graylog/datanode/OpensearchDistributionTest.java b/data-node/src/test/java/org/graylog/datanode/configuration/OpensearchDistributionProviderTest.java similarity index 64% rename from data-node/src/test/java/org/graylog/datanode/OpensearchDistributionTest.java rename to data-node/src/test/java/org/graylog/datanode/configuration/OpensearchDistributionProviderTest.java index 226c600eb2..1d911bc841 100644 --- a/data-node/src/test/java/org/graylog/datanode/OpensearchDistributionTest.java +++ b/data-node/src/test/java/org/graylog/datanode/configuration/OpensearchDistributionProviderTest.java @@ -14,9 +14,11 @@ * along with this program. If not, see * . */ -package org.graylog.datanode; +package org.graylog.datanode.configuration; import org.assertj.core.api.Assertions; +import org.graylog.datanode.OpensearchDistribution; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -25,7 +27,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -class OpensearchDistributionTest { +class OpensearchDistributionProviderTest { @TempDir private Path tempDir; @@ -48,54 +50,53 @@ class OpensearchDistributionTest { @Test void testFailedDetectionInDirectory() { - Assertions.assertThatThrownBy(() -> OpensearchDistribution.detectInDirectory(emptyTempDir.resolve("nonexistent"), "amd64")) + Assertions.assertThatThrownBy(() -> + provider(emptyTempDir.resolve("nonexistent"), OpensearchArchitecture.x64).get()) .hasMessageStartingWith("Failed to list content of provided directory"); - Assertions.assertThatThrownBy(() -> OpensearchDistribution.detectInDirectory(emptyTempDir, "amd64")) + Assertions.assertThatThrownBy(() -> provider(emptyTempDir, OpensearchArchitecture.x64).get()) .hasMessageStartingWith("Could not detect any opensearch distribution"); } @Test - void testDetection() throws IOException { - final OpensearchDistribution x64 = OpensearchDistribution.detectInDirectory(tempDir, "amd64"); + void testDetection() { + final OpensearchDistribution x64 = provider(tempDir, OpensearchArchitecture.x64).get(); Assertions.assertThat(x64.version()).isEqualTo("2.5.0"); Assertions.assertThat(x64.platform()).isEqualTo("linux"); - Assertions.assertThat(x64.architecture()).isEqualTo("x64"); + Assertions.assertThat(x64.architecture()).isEqualTo(OpensearchArchitecture.x64); - final OpensearchDistribution mac = OpensearchDistribution.detectInDirectory(tempDir, "x86_64"); + final OpensearchDistribution mac = provider(tempDir, OpensearchArchitecture.x64).get(); Assertions.assertThat(mac.version()).isEqualTo("2.5.0"); Assertions.assertThat(mac.platform()).isEqualTo("linux"); - Assertions.assertThat(mac.architecture()).isEqualTo("x64"); + Assertions.assertThat(mac.architecture()).isEqualTo(OpensearchArchitecture.x64); - final OpensearchDistribution aarch64 = OpensearchDistribution.detectInDirectory(tempDir, "aarch64"); + final OpensearchDistribution aarch64 = provider(tempDir, OpensearchArchitecture.aarch64).get(); Assertions.assertThat(aarch64.version()).isEqualTo("2.5.0"); Assertions.assertThat(aarch64.platform()).isEqualTo("linux"); - Assertions.assertThat(aarch64.architecture()).isEqualTo("aarch64"); + Assertions.assertThat(aarch64.architecture()).isEqualTo(OpensearchArchitecture.aarch64); } @Test - void testDetectionUnknownArch() { - Assertions.assertThatThrownBy(() -> OpensearchDistribution.detectInDirectory(tempDir, "nonsense")) - .isInstanceOf(UnsupportedOperationException.class) - .hasMessage("Unsupported OpenSearch distribution architecture: nonsense"); - } - - @Test - void testDetectionWithoutArch() throws IOException { - final OpensearchDistribution dist = OpensearchDistribution.detectInDirectory(tempDirWithoutArch, "amd64"); + void testDetectionWithoutArch() { + final OpensearchDistribution dist = provider(tempDirWithoutArch, OpensearchArchitecture.x64).get(); Assertions.assertThat(dist.version()).isEqualTo("2.4.1"); Assertions.assertThat(dist.architecture()).isNull(); Assertions.assertThat(dist.platform()).isNull(); } @Test - void testBackwardsCompatibility() throws IOException { + void testBackwardsCompatibility() { // we are not pointing to the root directory which should contain different OS distributions but rather directly to one // specific distribution. - final OpensearchDistribution dist = OpensearchDistribution.detectInDirectory(tempDir.resolve("opensearch-2.5.0-linux-x64"), "amd64"); + final OpensearchDistribution dist = provider(tempDir.resolve("opensearch-2.5.0-linux-x64"), OpensearchArchitecture.x64).get(); Assertions.assertThat(dist.version()).isEqualTo("2.5.0"); Assertions.assertThat(dist.platform()).isEqualTo("linux"); - Assertions.assertThat(dist.architecture()).isEqualTo("x64"); + Assertions.assertThat(dist.architecture()).isEqualTo(OpensearchArchitecture.x64); + } + + @NotNull + private OpensearchDistributionProvider provider(Path dir, OpensearchArchitecture arch) { + return new OpensearchDistributionProvider(dir, arch); } } diff --git a/data-node/src/test/java/org/graylog/datanode/testinfra/DatanodeDevContainerBuilder.java b/data-node/src/test/java/org/graylog/datanode/testinfra/DatanodeDevContainerBuilder.java index 96d0bfeacd..4819c1cc70 100644 --- a/data-node/src/test/java/org/graylog/datanode/testinfra/DatanodeDevContainerBuilder.java +++ b/data-node/src/test/java/org/graylog/datanode/testinfra/DatanodeDevContainerBuilder.java @@ -18,6 +18,8 @@ package org.graylog.datanode.testinfra; import com.google.common.base.Suppliers; import org.graylog.datanode.OpensearchDistribution; +import org.graylog.datanode.configuration.OpensearchArchitecture; +import org.graylog.datanode.configuration.OpensearchDistributionProvider; import org.graylog.testing.datanode.DatanodeDockerHooks; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -187,7 +189,7 @@ public class DatanodeDevContainerBuilder implements org.graylog.testing.datanode } private static ImageFromDockerfile createImage() { - final String opensearchTarArchive = "opensearch-" + getOpensearchVersion() + "-linux-" + OpensearchDistribution.archCode(System.getProperty("os.arch")) + ".tar.gz"; + final String opensearchTarArchive = "opensearch-" + getOpensearchVersion() + "-linux-" + OpensearchArchitecture.fromOperatingSystem() + ".tar.gz"; final Path downloadedOpensearch = getPath().resolve(Path.of("downloads", opensearchTarArchive)); if(!Files.exists(downloadedOpensearch)) {