diff --git a/.baseline/findbugs/excludeFilter.xml b/.baseline/findbugs/excludeFilter.xml
index 1887223f2..d96c8a012 100644
--- a/.baseline/findbugs/excludeFilter.xml
+++ b/.baseline/findbugs/excludeFilter.xml
@@ -9,13 +9,14 @@
-
+
+
diff --git a/docker-compose-rule-core/build.gradle b/docker-compose-rule-core/build.gradle
index 7159dad63..660c561be 100644
--- a/docker-compose-rule-core/build.gradle
+++ b/docker-compose-rule-core/build.gradle
@@ -5,6 +5,7 @@ dependencies {
compile "com.google.guava:guava:$guavaVersion"
compile "joda-time:joda-time:$jodaVersion"
compile "com.github.zafarkhaja:java-semver:$javaSemverVersion"
+ compile "com.google.code.findbugs:jsr305:3.0.0"
compile 'com.jayway.awaitility:awaitility:1.6.5'
@@ -18,7 +19,6 @@ dependencies {
testCompile "org.hamcrest:hamcrest-all:$hamcrestVersion"
testCompile "org.mockito:mockito-core:$mockitoVersion"
testCompile "com.github.tomakehurst:wiremock:2.0.6-beta"
- testCompile "com.google.code.findbugs:jsr305:3.0.0"
testCompile "com.github.stefanbirkner:system-rules:1.16.1"
}
diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCommandLocations.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCommandLocations.java
deleted file mode 100644
index a1e0c0a06..000000000
--- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCommandLocations.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2016 Palantir Technologies, Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.palantir.docker.compose.execution;
-
-import static java.util.Arrays.asList;
-
-import java.io.File;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Predicate;
-
-public class DockerCommandLocations {
- private static final Predicate IS_NOT_NULL = path -> path != null;
- private static final Predicate FILE_EXISTS = path -> new File(path).exists();
-
- private final List possiblePaths;
-
- public DockerCommandLocations(String... possiblePaths) {
- this.possiblePaths = asList(possiblePaths);
- }
-
- public Optional preferredLocation() {
-
- return possiblePaths.stream()
- .filter(IS_NOT_NULL)
- .filter(FILE_EXISTS)
- .findFirst();
- }
-
- @Override
- public String toString() {
- return "DockerCommandLocations{possiblePaths=" + possiblePaths + "}";
- }
-}
diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCommandLocator.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCommandLocator.java
new file mode 100644
index 000000000..402d9c8a2
--- /dev/null
+++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCommandLocator.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016 Palantir Technologies, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.palantir.docker.compose.execution;
+
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.apache.commons.lang3.SystemUtils;
+import org.immutables.value.Value;
+
+@Value.Immutable
+public abstract class DockerCommandLocator {
+
+ private static final List MAC_SEARCH_LOCATIONS = ImmutableList.of("/usr/local/bin", "/usr/bin");
+
+ protected abstract String command();
+
+ @Value.Default
+ protected boolean isWindows() {
+ return SystemUtils.IS_OS_WINDOWS;
+ }
+
+ @Value.Default
+ protected List macSearchLocations() {
+ return MAC_SEARCH_LOCATIONS;
+ }
+
+ @Value.Derived
+ protected String executableName() {
+ if (isWindows()) {
+ return command() + ".exe";
+ }
+ return command();
+ }
+
+ @Nullable
+ protected abstract String locationOverride();
+
+ public String getLocation() {
+ if (locationOverride() != null) {
+ return locationOverride();
+ }
+ return macSearchLocations()
+ .stream()
+ .map(p -> Paths.get(p, executableName()))
+ .filter(Files::exists)
+ .findFirst()
+ .map(Path::toString)
+ .orElse(executableName());
+ }
+
+ public static ImmutableDockerCommandLocator.Builder forCommand(String command) {
+ return ImmutableDockerCommandLocator.builder()
+ .command(command);
+ }
+
+}
diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerComposeExecutable.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerComposeExecutable.java
index 9c2daed21..48a54697e 100644
--- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerComposeExecutable.java
+++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerComposeExecutable.java
@@ -29,19 +29,12 @@
public abstract class DockerComposeExecutable implements Executable {
private static final Logger log = LoggerFactory.getLogger(DockerComposeExecutable.class);
- private static final DockerCommandLocations DOCKER_COMPOSE_LOCATIONS = new DockerCommandLocations(
- System.getenv("DOCKER_COMPOSE_LOCATION"),
- "/usr/local/bin/docker-compose",
- "/usr/bin/docker-compose"
- );
-
private static String defaultDockerComposePath() {
- String pathToUse = DOCKER_COMPOSE_LOCATIONS.preferredLocation()
- .orElseThrow(() -> new IllegalStateException(
- "Could not find docker-compose, looked in: " + DOCKER_COMPOSE_LOCATIONS));
-
+ DockerCommandLocator commandLocator = DockerCommandLocator.forCommand("docker-compose")
+ .locationOverride(System.getenv("DOCKER_COMPOSE_LOCATION"))
+ .build();
+ String pathToUse = commandLocator.getLocation();
log.debug("Using docker-compose found at " + pathToUse);
-
return pathToUse;
}
diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerExecutable.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerExecutable.java
index 1ff5cf01e..5dc9cf755 100644
--- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerExecutable.java
+++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerExecutable.java
@@ -26,12 +26,6 @@
public abstract class DockerExecutable implements Executable {
private static final Logger log = LoggerFactory.getLogger(DockerExecutable.class);
- private static final DockerCommandLocations DOCKER_LOCATIONS = new DockerCommandLocations(
- System.getenv("DOCKER_LOCATION"),
- "/usr/local/bin/docker",
- "/usr/bin/docker"
- );
-
@Value.Parameter protected abstract DockerConfiguration dockerConfiguration();
@Override
@@ -41,12 +35,11 @@ public final String commandName() {
@Value.Derived
protected String dockerPath() {
- String pathToUse = DOCKER_LOCATIONS.preferredLocation()
- .orElseThrow(() -> new IllegalStateException(
- "Could not find docker, looked in: " + DOCKER_LOCATIONS));
-
+ DockerCommandLocator commandLocator = DockerCommandLocator.forCommand("docker")
+ .locationOverride(System.getenv("DOCKER_LOCATION"))
+ .build();
+ String pathToUse = commandLocator.getLocation();
log.debug("Using docker found at " + pathToUse);
-
return pathToUse;
}
@@ -66,4 +59,5 @@ public Process execute(String... commands) throws IOException {
public static ImmutableDockerExecutable.Builder builder() {
return ImmutableDockerExecutable.builder();
}
+
}
diff --git a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerCommandLocationsShould.java b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerCommandLocationsShould.java
deleted file mode 100644
index f5b2e44eb..000000000
--- a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerCommandLocationsShould.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2016 Palantir Technologies, Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.palantir.docker.compose.execution;
-
-import static java.util.Optional.empty;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.core.Is.is;
-
-import java.io.IOException;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
-public class DockerCommandLocationsShould {
- private static final String badLocation = "file/that/does/not/exist";
- private static final String otherBadLocation = "another/file/that/does/not/exist";
-
- @Rule public TemporaryFolder folder = new TemporaryFolder();
-
- private String goodLocation;
-
- @Before
- public void setup() throws IOException {
- goodLocation = folder.newFile("docker-compose.yml").getAbsolutePath();
- }
-
- @Test public void
- provide_the_first_docker_command_location_if_it_exists() {
- DockerCommandLocations dockerCommandLocations = new DockerCommandLocations(
- badLocation,
- goodLocation,
- otherBadLocation);
-
- assertThat(dockerCommandLocations.preferredLocation().get(),
- is(goodLocation));
- }
-
- @Test public void
- skip_paths_from_environment_variables_that_are_unset() {
- DockerCommandLocations dockerCommandLocations = new DockerCommandLocations(
- System.getenv("AN_UNSET_DOCKER_COMPOSE_PATH"),
- goodLocation);
-
- assertThat(dockerCommandLocations.preferredLocation().get(),
- is(goodLocation));
- }
-
- @Test public void
- have_no_preferred_path_when_all_possible_paths_are_all_invalid() {
- DockerCommandLocations dockerCommandLocations = new DockerCommandLocations(
- badLocation);
-
- assertThat(dockerCommandLocations.preferredLocation(),
- is(empty()));
- }
-}
diff --git a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerCommandLocatorShould.java b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerCommandLocatorShould.java
new file mode 100644
index 000000000..d32348db3
--- /dev/null
+++ b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerCommandLocatorShould.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016 Palantir Technologies, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.palantir.docker.compose.execution;
+
+import static java.util.Collections.singletonList;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+public class DockerCommandLocatorShould {
+ private static final String command = "not-a-real-command!";
+ private static final String windowsCommand = command + ".exe";
+
+ @Rule public TemporaryFolder folder = new TemporaryFolder();
+
+ @Rule public ExpectedException exception = ExpectedException.none();
+
+ @Test public void
+ returns_the_command_name_when_no_other_paths_contain_command() {
+ DockerCommandLocator locator = DockerCommandLocator.forCommand(command)
+ .isWindows(false)
+ .build();
+
+ assertThat(locator.getLocation(), is(command));
+ }
+
+ @Test public void
+ returns_the_command_name_with_exe_on_windows_when_no_other_paths_contain_command() {
+ DockerCommandLocator locator = DockerCommandLocator.forCommand(command)
+ .isWindows(true)
+ .build();
+
+ assertThat(locator.getLocation(), is(windowsCommand));
+ }
+
+ @Test public void
+ allow_the_path_to_be_overriden() throws IOException {
+ Path overrideFolder = folder.newFolder("override").toPath();
+ String overridenCommand = Files.createFile(overrideFolder.resolve(command)).toString();
+
+ DockerCommandLocator locator = DockerCommandLocator.forCommand(command)
+ .locationOverride(overridenCommand)
+ .isWindows(false)
+ .build();
+
+ assertThat(locator.getLocation(), is(overridenCommand));
+ }
+
+ @Test public void
+ search_in_known_mac_install_locations_for_the_command() throws IOException {
+ Path macSearchFolder = folder.newFolder("override").toPath();
+ String commandLocation = Files.createFile(macSearchFolder.resolve(command)).toString();
+
+ DockerCommandLocator locator = DockerCommandLocator.forCommand(command)
+ .macSearchLocations(singletonList(macSearchFolder.toString()))
+ .isWindows(false)
+ .build();
+
+ assertThat(locator.getLocation(), is(commandLocation));
+ }
+
+}