From e3fd3649f46ea62bfcf316ebdbf8e7832334c66e Mon Sep 17 00:00:00 2001 From: Wojciech Krakowiak Date: Thu, 19 Mar 2026 14:14:32 +0100 Subject: [PATCH] Read docker location from PATH env variable on unix based systems Signed-off-by: Wojciech Krakowiak --- .../gradle/docker/DockerSupportService.java | 35 +++++++++++++++++-- .../docker/DockerSupportServiceTests.java | 29 +++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/java/org/opensearch/gradle/docker/DockerSupportService.java b/buildSrc/src/main/java/org/opensearch/gradle/docker/DockerSupportService.java index 66048e29356ab..e7b0a470e14ac 100644 --- a/buildSrc/src/main/java/org/opensearch/gradle/docker/DockerSupportService.java +++ b/buildSrc/src/main/java/org/opensearch/gradle/docker/DockerSupportService.java @@ -53,11 +53,13 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Build service for detecting available Docker installation and checking for compatibility with OpenSearch Docker image build @@ -66,8 +68,14 @@ public abstract class DockerSupportService implements BuildService { private static Logger LOGGER = Logging.getLogger(DockerSupportService.class); + + private static String[] DEFAULT_PATH_UNIX = { "/usr/bin", "/usr/local/bin" }; + + // Get unix path from PATH env variable, with fallback to DEFAUL_PATH_UNIX + private static String[] PATH_UNIX = DockerSupportService.getUnixPath(System.getenv("PATH"), DEFAULT_PATH_UNIX); + // Defines the possible locations of the Docker CLI. These will be searched in order. - private static String[] DOCKER_BINARIES_UNIX = { "/usr/bin/docker", "/usr/local/bin/docker" }; + private static String[] DOCKER_BINARIES_UNIX = Arrays.stream(PATH_UNIX).map((String path) -> path + "/docker").toArray(String[]::new); private static String[] DOCKER_BINARIES_WINDOWS = { System.getenv("PROGRAMFILES") + "\\Docker\\Docker\\resources\\bin\\docker.exe", @@ -75,7 +83,9 @@ public abstract class DockerSupportService implements BuildService path + "/docker-compose") + .toArray(String[]::new); private static String[] DOCKER_COMPOSE_BINARIES_WINDOWS = { System.getenv("PROGRAMFILES") + "\\Docker\\Docker\\resources\\bin\\docker-compose.exe" }; @@ -289,6 +299,27 @@ static Map parseOsRelease(final List osReleaseLines) { return values; } + /** + * Visible for testing + * + * If the system is of Unix family it converts the PATH string to array, combines it with fallback + * path removing duplicates and returns it as array. + * + * @return an array containing PATH locations + */ + static String[] getUnixPath(String pathEnvString, String[] fallbackPath) { + if (!Os.isFamily(Os.FAMILY_WINDOWS) && pathEnvString instanceof String) { + String[] resolvedUnixPath = pathEnvString.split(":"); + Stream filteredUnixPath = Arrays.stream(resolvedUnixPath).filter(path -> path.length() > 0); + return Stream.concat(filteredUnixPath, Arrays.stream(fallbackPath)) + // LinkedHashSet removes duplicates and keeps the order + .collect(Collectors.toCollection(LinkedHashSet::new)) + .toArray(String[]::new); + } + + return fallbackPath; + } + /** * Searches the entries in {@link #DOCKER_BINARIES} for the Docker CLI. This method does * not check whether the Docker installation appears usable, see {@link #getDockerAvailability()} diff --git a/buildSrc/src/test/java/org/opensearch/gradle/docker/DockerSupportServiceTests.java b/buildSrc/src/test/java/org/opensearch/gradle/docker/DockerSupportServiceTests.java index e2acf3c087ecc..4872a51a777ef 100644 --- a/buildSrc/src/test/java/org/opensearch/gradle/docker/DockerSupportServiceTests.java +++ b/buildSrc/src/test/java/org/opensearch/gradle/docker/DockerSupportServiceTests.java @@ -39,6 +39,7 @@ import java.util.Map; import static org.opensearch.gradle.docker.DockerSupportService.deriveId; +import static org.opensearch.gradle.docker.DockerSupportService.getUnixPath; import static org.opensearch.gradle.docker.DockerSupportService.parseOsRelease; import static org.hamcrest.CoreMatchers.equalTo; @@ -123,4 +124,32 @@ public void testDeriveIdOnOracle() { assertThat("ol-6.10", equalTo(deriveId(osRelease))); } + + public void testGetUnixPathDefault() { + final String[] fallbackPath = { "/usr/bin", "/usr/local/bin" }; + final String path = null; + + assertArrayEquals(fallbackPath, getUnixPath(path, fallbackPath)); + } + + public void testGetUnixPathEmptyString() { + final String[] fallbackPath = { "/usr/bin", "/usr/local/bin" }; + final String path = ""; + + assertArrayEquals(fallbackPath, getUnixPath(path, fallbackPath)); + } + + /** + * Tests: + * 1. Duplicates are removed. + * 2. The order is preserved, prioritizing the order from path over the order from fallback. + */ + public void testGetUnixPathWithDuplicatesAndEmptyEntries() { + final String[] fallbackPath = { "/usr/bin", "/usr/local/bin" }; + final String path = "/home/User/bin:/usr/local/bin:/bin::/home/User/bin"; + + final String[] expected = { "/home/User/bin", "/usr/local/bin", "/bin", "/usr/bin" }; + + assertArrayEquals(expected, getUnixPath(path, fallbackPath)); + } }