Skip to content

Commit

Permalink
Add support for OPENSEARCH_INITIAL_ADMIN_PASSWORD that is required by…
Browse files Browse the repository at this point in the history
… OpenSearch 2.12.0 or later (#176)

* Add support for OPENSEARCH_INITIAL_ADMIN_PASSWORD that is required by OpenSearch 2.12.0 or later

Signed-off-by: Andriy Redko <andriy.redko@aiven.io>

* Add support for -SNAPSHOT OpenSearch versions

Signed-off-by: Andriy Redko <andriy.redko@aiven.io>

* Address code review comments

Signed-off-by: Andriy Redko <andriy.redko@aiven.io>

---------

Signed-off-by: Andriy Redko <andriy.redko@aiven.io>
  • Loading branch information
reta authored Sep 24, 2024
1 parent 297fe15 commit bbdf7e6
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main_and_pr_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
java-version: [ 11, 17, 21 ]
java-version: [ 11, 17, 21, 23 ]
runs-on: [ubuntu-latest]
name: Build on ${{ matrix.runs-on }} with jdk ${{ matrix.java-version }}
runs-on: ${{ matrix.runs-on }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import java.net.InetSocketAddress;
import java.time.Duration;
import java.util.regex.Pattern;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
import org.testcontainers.containers.wait.strategy.WaitStrategy;
Expand All @@ -21,10 +22,16 @@
* (http/https) and 9300 (tcp, deprecated).
*/
public class OpensearchContainer<SELF extends OpensearchContainer<SELF>> extends GenericContainer<SELF> {
// The initial password is required starting from OpenSearch 2.12.0
private static final Pattern OPENSEARCH_INITIAL_PASSWORD_VERSION = Pattern.compile(
"^(([3-9][.]\\d+[.]\\d+|[2][.][1][2-9]+[.]\\d+|[2][.][2-9]\\d+[.]\\d+)(-SNAPSHOT)?|latest)$");

// Default username to connect to Opensearch instance
private static final String DEFAULT_USER = "admin";
// Default password to connect to Opensearch instance
private static final String DEFAULT_PASSWORD = "admin";
// Default initial password to connect to Opensearch instance
private static final String DEFAULT_INITIAL_PASSWORD = "_ad0m#Ns_";

// Default HTTP port.
private static final int DEFAULT_HTTP_PORT = 9200;
Expand All @@ -39,6 +46,8 @@ public class OpensearchContainer<SELF extends OpensearchContainer<SELF>> extends
// HTTPs,
// along with Basic Auth being used.
private boolean disableSecurity = true;
private boolean requireInitialPassword = false;
private String password = DEFAULT_PASSWORD;

/**
* Create an Opensearch Container by passing the full docker image name.
Expand All @@ -65,6 +74,14 @@ public OpensearchContainer(String dockerImageName) {
public OpensearchContainer(final DockerImageName dockerImageName) {
super(dockerImageName);
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);

final String version = dockerImageName.getVersionPart();
if (version == null || version.isBlank()) {
requireInitialPassword = false; /* we don't know the version */
} else {
requireInitialPassword =
OPENSEARCH_INITIAL_PASSWORD_VERSION.matcher(version).matches();
}
}

/**
Expand All @@ -85,6 +102,13 @@ protected void configure() {
withEnv("discovery.type", "single-node");
if (disableSecurity) {
withEnv("DISABLE_SECURITY_PLUGIN", Boolean.toString(disableSecurity));
} else if (requireInitialPassword) {
// Check if the OPENSEARCH_INITIAL_ADMIN_PASSWORD is already provided
password = getEnvMap().get("OPENSEARCH_INITIAL_ADMIN_PASSWORD");
if (password == null || password.isBlank()) {
withEnv("OPENSEARCH_INITIAL_ADMIN_PASSWORD", DEFAULT_INITIAL_PASSWORD);
password = DEFAULT_INITIAL_PASSWORD;
}
}
addExposedPorts(DEFAULT_HTTP_PORT, DEFAULT_TCP_PORT);

Expand All @@ -96,7 +120,7 @@ protected void configure() {
.usingTls()
.allowInsecure()
.forPort(DEFAULT_HTTP_PORT)
.withBasicCredentials(DEFAULT_USER, DEFAULT_PASSWORD)
.withBasicCredentials(DEFAULT_USER, password)
.forStatusCodeMatching(response -> response == HTTP_OK || response == HTTP_UNAUTHORIZED)
.withReadTimeout(Duration.ofSeconds(10))
.withStartupTimeout(Duration.ofMinutes(5));
Expand Down Expand Up @@ -153,6 +177,6 @@ public String getUsername() {
* @return password to connect to Opensearch container
*/
public String getPassword() {
return DEFAULT_PASSWORD;
return password;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
import javax.net.ssl.SSLContext;
Expand All @@ -38,8 +39,10 @@ class OpensearchContainerTest {
@DisplayName("Create default OpensearchContainer with security enabled")
@ParameterizedTest(name = "Running Opensearch version={0} (security enabled)")
@MethodSource("containers")
public void defaultWithSecurity(final String version, final DockerImageName image) throws Exception {
try (OpensearchContainer<?> container = new OpensearchContainer<>(image).withSecurityEnabled()) {
public void defaultWithSecurity(final String version, final Map<String, String> env, final DockerImageName image)
throws Exception {
try (OpensearchContainer<?> container =
new OpensearchContainer<>(image).withEnv(env).withSecurityEnabled()) {
container.start();

try (RestClient client = getClient(container)) {
Expand All @@ -59,8 +62,9 @@ public void defaultWithSecurity(final String version, final DockerImageName imag
@DisplayName("Create OpensearchContainer with security disabled")
@ParameterizedTest(name = "Running Opensearch version={0} (security disabled)")
@MethodSource("containers")
public void defaultNoSecurity(final String version, final DockerImageName image) throws Exception {
try (OpensearchContainer<?> container = new OpensearchContainer<>(image)) {
public void defaultNoSecurity(final String version, final Map<String, String> env, final DockerImageName image)
throws Exception {
try (OpensearchContainer<?> container = new OpensearchContainer<>(image).withEnv(env)) {
container.start();

try (RestClient client = getClient(container)) {
Expand All @@ -81,16 +85,28 @@ private static Stream<Arguments> containers() {
return Stream.of(
Arguments.of(
"1.3.4",
Map.of(), /* empty env */
DockerImageName.parse("opensearchproject/opensearch").withTag("1.3.4")),
Arguments.of(
"2.0.1",
Map.of(), /* empty env */
DockerImageName.parse("opensearchproject/opensearch").withTag("2.0.1")),
Arguments.of(
"2.1.0",
Map.of(), /* empty env */
DockerImageName.parse("opensearchproject/opensearch").withTag("2.1.0")),
Arguments.of(
"2.11.0",
DockerImageName.parse("opensearchproject/opensearch").withTag("2.11.0")));
Map.of(), /* empty env */
DockerImageName.parse("opensearchproject/opensearch").withTag("2.11.0")),
Arguments.of(
"2.15.0",
Map.of("OPENSEARCH_INITIAL_ADMIN_PASSWORD", "_oop0m#NsR_"),
DockerImageName.parse("opensearchproject/opensearch").withTag("2.15.0")),
Arguments.of(
"2.17.0",
Map.of(), /* empty env */
DockerImageName.parse("opensearchproject/opensearch").withTag("2.17.0")));
}

private RestClient getClient(OpensearchContainer<?> container)
Expand Down

0 comments on commit bbdf7e6

Please sign in to comment.