Repository: opensearch-project/opensearch-testcontainers
Pull request #221: [Breaking] Rename OpensearchContainer to OpenSearchContainer
Author: login: andrross
Created: 2025-03-12T16:37:58Z | Merged: 2025-03-14T01:13:08Z

There are no logical changes here only a rename of the existing class.

### Check List
- [x] New functionality includes testing.
  - [x] All tests pass
- [x] New functionality has been documented.
  - [x] New functionality has javadoc added
- [x] Commits are signed per the DCO using --signoff

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check [here](https://github.com/opensearch-project/OpenSearch/blob/main/CONTRIBUTING.md#developer-certificate-of-origin).



Diff:
diff --git a/.gitignore b/.gitignore
index bb95c66..ad80fea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,6 @@
 .classpath
 .project
 .gradle
+.idea/
 build/
 bin/
-
diff --git a/README.md b/README.md
index 3574852..f295d29 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@ The [opensearch-testcontainers](https://github.com/opensearch-project/opensearch
 
 |opensearch-testcontainers|OpenSearch|testcontainers|JDK|
 |---|---|---|---|
+|3.0.0-SNAPSHOT|2.0.0+|1.20.0+|21+|
 |2.1.4-SNAPSHOT|2.0.0+|1.20.0+|11+|
 |2.1.3|2.0.0+|1.20.0+|11+|
 |2.1.2|2.0.0+|1.20.0+|11+|
@@ -41,7 +42,7 @@ Follow the [JUnit 4 Quickstart](https://www.testcontainers.org/quickstart/junit_
 
 ```java
 @Rule
-public OpensearchContainer<?> opensearch = new OpensearchContainer<>(DockerImageName.parse("opensearchproject/opensearch:2.11.0"));
+public OpenSearchContainer<?> opensearch = new OpenSearchContainer<>(DockerImageName.parse("opensearchproject/opensearch:2.11.0"));
 
 ```
 
@@ -51,7 +52,7 @@ Follow the [JUnit 5 Quickstart](https://www.testcontainers.org/quickstart/junit_
 
 ```java
 @Container
-public OpensearchContainer<?> opensearch = new OpensearchContainer<>(DockerImageName.parse("opensearchproject/opensearch:2.11.0"));
+public OpenSearchContainer<?> opensearch = new OpenSearchContainer<>(DockerImageName.parse("opensearchproject/opensearch:2.11.0"));
 
 ```
 
@@ -59,7 +60,7 @@ Please note that at the moment [testcontainers](https://www.testcontainers.org/)
 
 ## Usage Examples
 
-By default, [OpenSearch](https://opensearch.org/) Docker containers run with [security plugin](https://github.com/opensearch-project/security) activated, however `OpensearchContainer` deactivates it. Use `withSecurityEnabled()` to enable security, please notice that in this case in order to connect to the running container the HTTPS protocol should be used along with username / password credentials.
+By default, [OpenSearch](https://opensearch.org/) Docker containers run with [security plugin](https://github.com/opensearch-project/security) activated, however `OpenSearchContainer` deactivates it. Use `withSecurityEnabled()` to enable security, please notice that in this case in order to connect to the running container the HTTPS protocol should be used along with username / password credentials.
 
 ```java
 
@@ -78,7 +79,7 @@ import org.opensearch.client.RestClient;
 private static final DockerImageName OPENSEARCH_IMAGE = DockerImageName.parse("opensearchproject/opensearch:2.11.0");
 
 // Create the Opensearch container.
-try (OpensearchContainer<?> container = new OpensearchContainer<>(OPENSEARCH_IMAGE).withSecurityEnabled()) {
+try (OpenSearchContainer<?> container = new OpenSearchContainer<>(OPENSEARCH_IMAGE).withSecurityEnabled()) {
     // Start the container. This step might take some time...
     container.start();
 
@@ -109,7 +110,7 @@ try (OpensearchContainer<?> container = new OpensearchContainer<>(OPENSEARCH_IMA
 }
 ```
 
-When [security plugin](https://github.com/opensearch-project/security) is not required (not recommended for production), just use `OpensearchContainer` default constructor.
+When [security plugin](https://github.com/opensearch-project/security) is not required (not recommended for production), just use `OpenSearchContainer` default constructor.
 
 ```java
 
@@ -121,7 +122,7 @@ import org.opensearch.client.RestClient;
 private static final DockerImageName OPENSEARCH_IMAGE = DockerImageName.parse("opensearchproject/opensearch:2.11.0");
 
 // Create the OpenSearch container.
-try (OpensearchContainer<?> container = new OpensearchContainer<>(OPENSEARCH_IMAGE)) {
+try (OpenSearchContainer<?> container = new OpenSearchContainer<>(OPENSEARCH_IMAGE)) {
     // Start the container. This step might take some time...
     container.start();
 
diff --git a/src/main/java/org/opensearch/testcontainers/OpensearchContainer.java b/src/main/java/org/opensearch/testcontainers/OpenSearchContainer.java
similarity index 85%
rename from src/main/java/org/opensearch/testcontainers/OpensearchContainer.java
rename to src/main/java/org/opensearch/testcontainers/OpenSearchContainer.java
index aa38b00..92e795e 100644
--- a/src/main/java/org/opensearch/testcontainers/OpensearchContainer.java
+++ b/src/main/java/org/opensearch/testcontainers/OpenSearchContainer.java
@@ -18,19 +18,19 @@
 import org.testcontainers.utility.DockerImageName;
 
 /**
- * The Opensearch Docker container (single node cluster) which exposes by default ports 9200
+ * The OpenSearch Docker container (single node cluster) which exposes by default ports 9200
  * (http/https) and 9300 (tcp, deprecated).
  */
-public class OpensearchContainer<SELF extends OpensearchContainer<SELF>> extends GenericContainer<SELF> {
+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
+    // Default username to connect to OpenSearch instance
     private static final String DEFAULT_USER = "admin";
-    // Default password to connect to Opensearch instance
+    // Default password to connect to OpenSearch instance
     private static final String DEFAULT_PASSWORD = "admin";
-    // Default initial password to connect to Opensearch instance
+    // Default initial password to connect to OpenSearch instance
     private static final String DEFAULT_INITIAL_PASSWORD = "_ad0m#Ns_";
 
     // Default HTTP port.
@@ -39,7 +39,7 @@ public class OpensearchContainer<SELF extends OpensearchContainer<SELF>> extends
     // Default TCP port (deprecated and may be removed in future versions).
     private static final int DEFAULT_TCP_PORT = 9300;
 
-    // Opensearch Docker base image.
+    // OpenSearch Docker base image.
     private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("opensearchproject/opensearch");
 
     // Disables (or enables) security plugin. If security is enabled, the communication protocol switches from HTTP to
@@ -50,18 +50,18 @@ public class OpensearchContainer<SELF extends OpensearchContainer<SELF>> extends
     private String password = DEFAULT_PASSWORD;
 
     /**
-     * Create an Opensearch Container by passing the full docker image name.
+     * Create an OpenSearch Container by passing the full docker image name.
      *
      * @param dockerImageName Full docker image name as a {@link String}, like:
      *     opensearchproject/opensearch:1.2.4 opensearchproject/opensearch:1.3.1
      *     opensearchproject/opensearch:2.0.0
      */
-    public OpensearchContainer(String dockerImageName) {
+    public OpenSearchContainer(String dockerImageName) {
         this(DockerImageName.parse(dockerImageName));
     }
 
     /**
-     * Create an Opensearch Container (with security plugin enabled) by passing the full docker image
+     * Create an OpenSearch Container (with security plugin enabled) by passing the full docker image
      * name.
      *
      * @param dockerImageName Full docker image name as a {@link DockerImageName}, like:
@@ -71,7 +71,7 @@ public OpensearchContainer(String dockerImageName) {
      *      DockerImageName.parse("opensearchproject/opensearch:2.0.0")
      *
      */
-    public OpensearchContainer(final DockerImageName dockerImageName) {
+    public OpenSearchContainer(final DockerImageName dockerImageName) {
         super(dockerImageName);
         dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME);
 
@@ -114,7 +114,7 @@ protected void configure() {
 
         final WaitStrategy waitStrategy;
         if (!disableSecurity) {
-            // By default, Opensearch uses self-signed certificates for HTTPS, allowing insecure
+            // By default, OpenSearch uses self-signed certificates for HTTPS, allowing insecure
             // connection in order to skip the certificate validation checks.
             waitStrategy = new HttpWaitStrategy()
                     .usingTls()
@@ -136,7 +136,7 @@ protected void configure() {
     }
 
     /**
-     * Return HTTP(s) host and port to connect to Opensearch container.
+     * Return HTTP(s) host and port to connect to OpenSearch container.
      *
      * @return HTTP(s) host and port (in a form of "host:port")
      */
@@ -154,7 +154,7 @@ public boolean isSecurityEnabled() {
     }
 
     /**
-     * Return socket address to connect to Opensearch over TCP. The TransportClient will is deprecated
+     * Return socket address to connect to OpenSearch over TCP. The TransportClient will is deprecated
      * and may be removed in future versions.
      *
      * @return TCP socket address
@@ -165,16 +165,16 @@ public InetSocketAddress getTcpHost() {
     }
 
     /**
-     * Return user name to connect to Opensearch container (if security plugin is enabled)
-     * @return user name to connect to Opensearch container
+     * Return user name to connect to OpenSearch container (if security plugin is enabled)
+     * @return user name to connect to OpenSearch container
      */
     public String getUsername() {
         return DEFAULT_USER;
     }
 
     /**
-     * Return password to connect to Opensearch container (if security plugin is enabled)
-     * @return password to connect to Opensearch container
+     * Return password to connect to OpenSearch container (if security plugin is enabled)
+     * @return password to connect to OpenSearch container
      */
     public String getPassword() {
         return password;
diff --git a/src/test/java/org/opensearch/testcontainers/OpensearchContainerTest.java b/src/test/java/org/opensearch/testcontainers/OpenSearchContainerTest.java
similarity index 87%
rename from src/test/java/org/opensearch/testcontainers/OpensearchContainerTest.java
rename to src/test/java/org/opensearch/testcontainers/OpenSearchContainerTest.java
index 1a027e3..508e73d 100644
--- a/src/test/java/org/opensearch/testcontainers/OpensearchContainerTest.java
+++ b/src/test/java/org/opensearch/testcontainers/OpenSearchContainerTest.java
@@ -35,14 +35,14 @@
 import org.opensearch.client.RestClient;
 import org.testcontainers.utility.DockerImageName;
 
-class OpensearchContainerTest {
-    @DisplayName("Create default OpensearchContainer with security enabled")
-    @ParameterizedTest(name = "Running Opensearch version={0} (security enabled)")
+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 Map<String, String> env, final DockerImageName image)
             throws Exception {
-        try (OpensearchContainer<?> container =
-                new OpensearchContainer<>(image).withEnv(env).withSecurityEnabled()) {
+        try (OpenSearchContainer<?> container =
+                new OpenSearchContainer<>(image).withEnv(env).withSecurityEnabled()) {
             container.start();
 
             try (RestClient client = getClient(container)) {
@@ -59,12 +59,12 @@ public void defaultWithSecurity(final String version, final Map<String, String>
         }
     }
 
-    @DisplayName("Create OpensearchContainer with security disabled")
-    @ParameterizedTest(name = "Running Opensearch version={0} (security disabled)")
+    @DisplayName("Create OpenSearchContainer with security disabled")
+    @ParameterizedTest(name = "Running OpenSearch version={0} (security disabled)")
     @MethodSource("containers")
     public void defaultNoSecurity(final String version, final Map<String, String> env, final DockerImageName image)
             throws Exception {
-        try (OpensearchContainer<?> container = new OpensearchContainer<>(image).withEnv(env)) {
+        try (OpenSearchContainer<?> container = new OpenSearchContainer<>(image).withEnv(env)) {
             container.start();
 
             try (RestClient client = getClient(container)) {
@@ -106,10 +106,14 @@ private static Stream<Arguments> containers() {
                 Arguments.of(
                         "2.17.0",
                         Map.of(), /* empty env */
-                        DockerImageName.parse("opensearchproject/opensearch").withTag("2.17.0")));
+                        DockerImageName.parse("opensearchproject/opensearch").withTag("2.17.0")),
+                Arguments.of(
+                        "2.19.1",
+                        Map.of(), /* empty env */
+                        DockerImageName.parse("opensearchproject/opensearch").withTag("2.19.1")));
     }
 
-    private RestClient getClient(OpensearchContainer<?> container)
+    private RestClient getClient(OpenSearchContainer<?> container)
             throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
         final CredentialsProvider credentialsProvider =
                 getCredentialsProvider(container).orElse(null);
@@ -127,7 +131,7 @@ private RestClient getClient(OpensearchContainer<?> container)
                 .build();
     }
 
-    private Optional<CredentialsProvider> getCredentialsProvider(OpensearchContainer<?> container) {
+    private Optional<CredentialsProvider> getCredentialsProvider(OpenSearchContainer<?> container) {
         if (!container.isSecurityEnabled()) {
             return Optional.empty();
         }
diff --git a/version.properties b/version.properties
index c2ae59d..4950f0d 100644
--- a/version.properties
+++ b/version.properties
@@ -1 +1 @@
-version=2.1.4
+version=3.0.0


Reviews:
user: login: andrross
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-12T17:04:24Z
user: login: reta
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-12T17:08:01Z
user: login: reta
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-12T17:10:17Z
user: login: reta
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-12T17:14:28Z
user: login: andrross
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-12T17:44:16Z
user: login: reta
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-12T17:53:45Z
user: login: dblock
state: DISMISSED
author_association: MEMBER
submitted_at: 2025-03-12T20:21:58Z
user: login: andrross
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-12T20:55:16Z
user: login: reta
state: DISMISSED
author_association: COLLABORATOR
submitted_at: 2025-03-13T01:25:39Z
user: login: reta
state: DISMISSED
author_association: COLLABORATOR
submitted_at: 2025-03-14T00:52:31Z
user: login: reta
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-14T01:13:01Z

Review comments:
diff_hunk: @@ -0,0 +1,182 @@
+/*
path: src/main/java/org/opensearch/testcontainers/OpenSearchContainer.java
user: login: andrross
body: Honestly my biggest concern here is that things will go very badly for people with a case-insensitive file system (which I think is the default on MacOS?) since the file and class names only differ in the case of a single letter.
created_at: 2025-03-12T17:04:23Z
author_association: MEMBER
diff_hunk: @@ -59,11 +59,33 @@ public void defaultWithSecurity(final String version, final Map<String, String>
         }
     }
 
-    @DisplayName("Create OpensearchContainer with security disabled")
-    @ParameterizedTest(name = "Running Opensearch version={0} (security disabled)")
+    @DisplayName("Create OpenSearchContainer with security disabled")
+    @ParameterizedTest(name = "Running OpenSearch version={0} (security disabled)")
     @MethodSource("containers")
     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)) {
+                Response response = client.performRequest(new Request("GET", "/"));
+
+                assertThat(response.getStatusLine().getStatusCode(), is(200));
+                assertThat(EntityUtils.toString(response.getEntity()), containsString(version));
+
+                // No such handler should be thrown by the server
+                assertThrows(
+                        ResponseException.class,
+                        () -> client.performRequest(new Request("GET", "/_plugins/_security/health")));
+            }
+        }
+    }
+
+    @DisplayName("Create OpensearchContainer (deprecated)")
+    @ParameterizedTest(name = "Running OpenSearch version={0}")
+    @MethodSource("containers")
+    public void defaultDeprecatedName(final String version, final Map<String, String> env, final DockerImageName image)
path: src/test/java/org/opensearch/testcontainers/OpenSearchContainerTest.java
user: login: reta
body: You may extract it into `OpensearchContainerTest` so when we remove it, we won't be touching this class anymore
created_at: 2025-03-12T17:08:01Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,182 @@
+/*
path: src/main/java/org/opensearch/testcontainers/OpenSearchContainer.java
user: login: reta
body: It will backfire for sure :(
created_at: 2025-03-12T17:10:17Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,182 @@
+/*
path: src/main/java/org/opensearch/testcontainers/OpenSearchContainer.java
user: login: reta
body: As expected, it messes things on Windows, I believe we should change the approach here :(
created_at: 2025-03-12T17:14:28Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,182 @@
+/*
path: src/main/java/org/opensearch/testcontainers/OpenSearchContainer.java
user: login: andrross
body: Maybe "OpenSearchContainer" could be in the `org.opensearch.test` package, so `org.opensearch.test.testcontainers.OpenSearchContainer`. What do you think?
created_at: 2025-03-12T17:44:16Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,182 @@
+/*
path: src/main/java/org/opensearch/testcontainers/OpenSearchContainer.java
user: login: reta
body: This is by convention, I think we could postpone this change to next major version release (along with 3.0.0) and just rename as one breaking change.
created_at: 2025-03-12T17:53:45Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,182 @@
+/*
path: src/main/java/org/opensearch/testcontainers/OpenSearchContainer.java
user: login: andrross
body: Sure, the major version makes sense. It'll be a trivial change for anyone who upgrades.
created_at: 2025-03-12T20:55:16Z
author_association: MEMBER

PR comments:
user: login: andrross
created_at: 2025-03-12T16:39:07Z
body: @reta I _think_ this will be fully backward compatible. I don't know testcontainers really at all so let me know if I'm missing something.

@dblock FYI, you may want to come out of retirement just for this one.
author_association: MEMBER
user: login: dblock
created_at: 2025-03-12T20:22:41Z
body: > @dblock FYI, you may want to come out of retirement just for this one.

I love me a good rename.
author_association: MEMBER
user: login: reta
created_at: 2025-03-13T01:26:16Z
body: Thanks @andrross ! I will create a branch for 2.1.x and merge this one shortly
author_association: COLLABORATOR