diff --git a/docker-compose-rule-core/src/integrationTest/java/com/palantir/docker/compose/DockerComposeManagerNativeHealthcheckIntegrationTest.java b/docker-compose-rule-core/src/integrationTest/java/com/palantir/docker/compose/DockerComposeManagerNativeHealthcheckIntegrationTest.java index ba177612f..ca33a305c 100644 --- a/docker-compose-rule-core/src/integrationTest/java/com/palantir/docker/compose/DockerComposeManagerNativeHealthcheckIntegrationTest.java +++ b/docker-compose-rule-core/src/integrationTest/java/com/palantir/docker/compose/DockerComposeManagerNativeHealthcheckIntegrationTest.java @@ -20,14 +20,13 @@ import static com.jayway.awaitility.Awaitility.await; import static com.palantir.docker.compose.execution.DockerComposeExecArgument.arguments; import static com.palantir.docker.compose.execution.DockerComposeExecOption.noOptions; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.junit.Assert.fail; import static org.junit.Assume.assumeThat; import com.github.zafarkhaja.semver.Version; import com.palantir.docker.compose.connection.Container; import com.palantir.docker.compose.connection.State; -import com.palantir.docker.compose.execution.Docker; -import com.palantir.docker.compose.execution.DockerCompose; import java.io.IOException; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -38,7 +37,6 @@ import org.hamcrest.Matchers; import org.junit.After; import org.junit.Test; -import org.mockito.internal.matchers.GreaterOrEqual; public class DockerComposeManagerNativeHealthcheckIntegrationTest { @@ -61,12 +59,13 @@ public void shutdownPool() { @Test public void dockerComposeManagerWaitsUntilHealthcheckPasses() throws ExecutionException, IOException, InterruptedException, TimeoutException { - assumeThat("docker version", Docker.version(), new GreaterOrEqual<>(Version.forIntegers(1, 12, 0))); - assumeThat("docker-compose version", DockerCompose.version(), new GreaterOrEqual<>(Version.forIntegers(1, 10, 0))); - docker = new DockerComposeManager.Builder() .file("src/test/resources/native-healthcheck.yaml") .build(); + + assumeThat(docker.docker().version(), greaterThanOrEqualTo(Version.valueOf("1.12.0"))); + assumeThat(docker.dockerCompose().version(), greaterThanOrEqualTo(Version.valueOf("1.10.0"))); + Future beforeFuture = pool.submit(() -> { docker.before(); return null; diff --git a/docker-compose-rule-core/src/integrationTest/java/com/palantir/docker/compose/connection/ContainerIntegrationTests.java b/docker-compose-rule-core/src/integrationTest/java/com/palantir/docker/compose/connection/ContainerIntegrationTests.java index 27832bd66..eea53c567 100644 --- a/docker-compose-rule-core/src/integrationTest/java/com/palantir/docker/compose/connection/ContainerIntegrationTests.java +++ b/docker-compose-rule-core/src/integrationTest/java/com/palantir/docker/compose/connection/ContainerIntegrationTests.java @@ -20,6 +20,7 @@ import static com.palantir.docker.compose.execution.DockerComposeExecArgument.arguments; import static com.palantir.docker.compose.execution.DockerComposeExecOption.noOptions; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.junit.Assert.assertEquals; import static org.junit.Assume.assumeThat; @@ -35,7 +36,6 @@ import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.junit.Test; -import org.mockito.internal.matchers.GreaterOrEqual; public class ContainerIntegrationTests { @@ -69,14 +69,14 @@ public void testStateChanges_withoutHealthCheck() throws IOException, Interrupte */ @Test public void testStateChanges_withHealthCheck() throws IOException, InterruptedException { - assumeThat("docker version", Docker.version(), new GreaterOrEqual<>(Version.forIntegers(1, 12, 0))); - assumeThat("docker-compose version", DockerCompose.version(), new GreaterOrEqual<>(Version.forIntegers(1, 10, 0))); - DockerCompose dockerCompose = new DefaultDockerCompose( DockerComposeFiles.from("src/test/resources/native-healthcheck.yaml"), dockerMachine, ProjectName.random()); + assumeThat(docker.version(), greaterThanOrEqualTo(Version.valueOf("1.12.0"))); + assumeThat(dockerCompose.version(), greaterThanOrEqualTo(Version.valueOf("1.10.0"))); + // The withHealthcheck service's healthcheck checks every 100ms whether the file "healthy" exists Container container = new Container("withHealthcheck", docker, dockerCompose); assertEquals(State.DOWN, container.state()); diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DefaultDockerCompose.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DefaultDockerCompose.java index c450f351a..c489afaf0 100644 --- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DefaultDockerCompose.java +++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DefaultDockerCompose.java @@ -28,6 +28,7 @@ import com.palantir.docker.compose.connection.ContainerNames; import com.palantir.docker.compose.connection.DockerMachine; import com.palantir.docker.compose.connection.Ports; +import com.palantir.docker.compose.helpers.VersionHelper; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; @@ -64,6 +65,12 @@ public DefaultDockerCompose(DockerComposeExecutable rawExecutable, DockerMachine this.dockerMachine = dockerMachine; } + @Override + public Version version() throws IOException, InterruptedException { + String version = command.execute(Command.throwingOnError(), "version", "--short"); + return VersionHelper.toSemVer(version); + } + @Override public void pull() throws IOException, InterruptedException { command.execute(Command.throwingOnError(), "pull"); @@ -139,11 +146,6 @@ private void verifyDockerComposeVersionAtLeast(Version targetVersion, String mes validState(version().greaterThanOrEqualTo(targetVersion), message); } - private Version version() throws IOException, InterruptedException { - String versionOutput = command.execute(Command.throwingOnError(), "-v"); - return DockerComposeVersion.parseFromDockerComposeVersion(versionOutput); - } - private static String[] constructFullDockerComposeExecArguments(DockerComposeExecOption dockerComposeExecOption, String containerName, DockerComposeExecArgument dockerComposeExecArgument) { // The "-T" option here disables pseudo-TTY allocation, which is not useful here since we are not using diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DelegatingDockerCompose.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DelegatingDockerCompose.java index 3ef32f5e3..04c34bea8 100644 --- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DelegatingDockerCompose.java +++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DelegatingDockerCompose.java @@ -15,6 +15,7 @@ */ package com.palantir.docker.compose.execution; +import com.github.zafarkhaja.semver.Version; import com.palantir.docker.compose.connection.Container; import com.palantir.docker.compose.connection.ContainerName; import com.palantir.docker.compose.connection.Ports; @@ -30,6 +31,11 @@ protected DelegatingDockerCompose(DockerCompose dockerCompose) { this.dockerCompose = dockerCompose; } + @Override + public Version version() throws IOException, InterruptedException { + return dockerCompose.version(); + } + @Override public void pull() throws IOException, InterruptedException { dockerCompose.pull(); diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/Docker.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/Docker.java index be742a215..738507916 100644 --- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/Docker.java +++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/Docker.java @@ -15,16 +15,13 @@ */ package com.palantir.docker.compose.execution; -import static com.google.common.base.Preconditions.checkState; import com.github.zafarkhaja.semver.Version; import com.google.common.collect.ObjectArrays; -import com.palantir.docker.compose.connection.DockerMachine; import com.palantir.docker.compose.connection.State; +import com.palantir.docker.compose.helpers.VersionHelper; import java.io.IOException; import java.util.Collection; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.apache.commons.lang3.SystemUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,8 +30,6 @@ public class Docker { private static final Logger log = LoggerFactory.getLogger(Docker.class); - // Without java escape characters: ^(\d+)\.(\d+)\.(\d+)(?:-.*)?$ - private static final Pattern VERSION_PATTERN = Pattern.compile("^Docker version (\\d+)\\.(\\d+)\\.(\\d+)(?:-.*)?$"); private static final String HEALTH_STATUS_FORMAT = "--format=" + "{{if not .State.Running}}DOWN" @@ -45,26 +40,17 @@ public class Docker { + "{{else}}HEALTHY{{end}}"; private static final String HEALTH_STATUS_FORMAT_WINDOWS = HEALTH_STATUS_FORMAT.replaceAll("\"", "`\""); - public static Version version() throws IOException, InterruptedException { - return new Docker(DockerExecutable.builder().dockerConfiguration(DockerMachine.localMachine().build()).build()) - .configuredVersion(); - } - - public Version configuredVersion() throws IOException, InterruptedException { - String versionString = command.execute(Command.throwingOnError(), "-v"); - Matcher matcher = VERSION_PATTERN.matcher(versionString); - checkState(matcher.matches(), "Unexpected output of docker -v: %s", versionString); - return Version.forIntegers(Integer.parseInt(matcher.group(1)), - Integer.parseInt(matcher.group(2)), - Integer.parseInt(matcher.group(3))); - } - private final Command command; public Docker(DockerExecutable rawExecutable) { this.command = new Command(rawExecutable, log::trace); } + public Version version() throws IOException, InterruptedException { + String clientVersionString = command.execute(Command.throwingOnError(), "version", "--format", "{{.Client.Version}}"); + return VersionHelper.toSemVer(clientVersionString); + } + public State state(String containerId) throws IOException, InterruptedException { String formatString = SystemUtils.IS_OS_WINDOWS ? HEALTH_STATUS_FORMAT_WINDOWS : HEALTH_STATUS_FORMAT; String stateString = command.execute(Command.throwingOnError(), "inspect", formatString, containerId); diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCompose.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCompose.java index f9b9112ba..2ae8bea95 100644 --- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCompose.java +++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerCompose.java @@ -25,9 +25,7 @@ import java.util.Optional; public interface DockerCompose { - static Version version() throws IOException, InterruptedException { - return DockerComposeExecutable.version(); - } + Version version() throws IOException, InterruptedException; void pull() throws IOException, InterruptedException; void build() throws IOException, InterruptedException; void up() throws IOException, InterruptedException; 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 6a71fe293..5525f40f5 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 @@ -15,7 +15,6 @@ */ package com.palantir.docker.compose.execution; -import com.github.zafarkhaja.semver.Version; import com.google.common.collect.ImmutableList; import com.palantir.docker.compose.configuration.DockerComposeFiles; import com.palantir.docker.compose.configuration.ProjectName; @@ -45,27 +44,6 @@ private static String defaultDockerComposePath() { return pathToUse; } - static Version version() throws IOException, InterruptedException { - Command dockerCompose = new Command(new Executable() { - @Override - public String commandName() { - return "docker-compose"; - } - - @Override - public Process execute(String... commands) throws IOException { - List args = ImmutableList.builder() - .add(defaultDockerComposePath()) - .add(commands) - .build(); - return new ProcessBuilder(args).redirectErrorStream(true).start(); - } - }, log::trace); - - String versionOutput = dockerCompose.execute(Command.throwingOnError(), "-v"); - return DockerComposeVersion.parseFromDockerComposeVersion(versionOutput); - } - @Value.Parameter protected abstract DockerComposeFiles dockerComposeFiles(); @Value.Parameter protected abstract DockerConfiguration dockerConfiguration(); diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerComposeVersion.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerComposeVersion.java deleted file mode 100644 index 07790b53e..000000000 --- a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/execution/DockerComposeVersion.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * (c) 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.github.zafarkhaja.semver.Version; -import com.google.common.base.Splitter; -import java.util.List; - -public final class DockerComposeVersion { - - private DockerComposeVersion() {} - - //docker-compose version format is like 1.7.0rc1, which can't be parsed by java-semver - //here we only pass 1.7.0 to java-semver - public static Version parseFromDockerComposeVersion(String versionOutput) { - List splitOnSeparator = Splitter.on(' ').splitToList(versionOutput); - String version = splitOnSeparator.get(2); - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < version.length(); i++) { - if ((version.charAt(i) >= '0' && version.charAt(i) <= '9') || version.charAt(i) == '.') { - builder.append(version.charAt(i)); - } else { - return Version.valueOf(builder.toString()); - } - } - return Version.valueOf(builder.toString()); - } -} diff --git a/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/helpers/VersionHelper.java b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/helpers/VersionHelper.java new file mode 100644 index 000000000..9ebe4ba2b --- /dev/null +++ b/docker-compose-rule-core/src/main/java/com/palantir/docker/compose/helpers/VersionHelper.java @@ -0,0 +1,58 @@ +/* + * (c) Copyright 2019 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.helpers; + +import static com.google.common.base.Preconditions.checkState; + +import com.github.zafarkhaja.semver.Version; +import com.google.common.base.Joiner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * We depend on semantic versioning (https://semver.org/) and use Java SemVer within + * this library to handle versions (https://github.com/zafarkhaja/jsemver). + * Docker however doesn't use exact semantic versioning so this helper does + * some light processing to get simple, useable versions + */ +public enum VersionHelper { + INSTANCE; + + // Semantic versions have a structure of ..-+ + // This regex groups pre-release and build metadata into the "rest" group + // Regex without escape characters: ^(?\d+)\.(?\d+)\.(?\d+)(?.*)$ + private static final Pattern BASIC_SEM_VER_PATTERN = + Pattern.compile("^(?\\d+)\\.(?\\d+)\\.(?\\d+)(?.*)$"); + + public static Version toSemVer(String version) { + Matcher matcher = BASIC_SEM_VER_PATTERN.matcher(version); + + checkState(matcher.matches(), "Unexpected version structure: %s", version); + + String major = dropLeadingZeroes(matcher.group("major")); + String minor = dropLeadingZeroes(matcher.group("minor")); + String patch = dropLeadingZeroes(matcher.group("patch")); + + String versionCore = Joiner.on(".").join(major, minor, patch); + + return Version.valueOf(versionCore); + } + + private static String dropLeadingZeroes(String numericString) { + return String.valueOf(Integer.parseInt(numericString)); + } +} diff --git a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerComposeShould.java b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerComposeShould.java index 054576209..2494c9d6a 100644 --- a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerComposeShould.java +++ b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerComposeShould.java @@ -99,7 +99,7 @@ public void parse_and_returns_container_names_on_ps() throws IOException, Interr @Test public void call_docker_compose_with_no_colour_flag_on_logs() throws IOException { when(executedProcess.getInputStream()).thenReturn( - toInputStream("docker-compose version 1.7.0, build 1ad8866"), + toInputStream("1.7.0"), toInputStream("logs")); ByteArrayOutputStream output = new ByteArrayOutputStream(); @@ -116,8 +116,8 @@ public void call_docker_compose_with_no_container_on_logs() throws IOException { final Process mockVersionProcess = mock(Process.class); when(mockVersionProcess.exitValue()).thenReturn(0); - when(mockVersionProcess.getInputStream()).thenReturn(toInputStream("docker-compose version 1.7.0, build 1ad8866")); - when(executor.execute("-v")).thenReturn(mockVersionProcess); + when(mockVersionProcess.getInputStream()).thenReturn(toInputStream("1.7.0")); + when(executor.execute("version", "--short")).thenReturn(mockVersionProcess); when(executor.execute("logs", "--no-color", "db")).thenReturn(executedProcess); when(executedProcess.getInputStream()).thenReturn(toInputStream("logs")); ByteArrayOutputStream output = new ByteArrayOutputStream(); @@ -130,7 +130,7 @@ public void call_docker_compose_with_no_container_on_logs() throws IOException { @Test public void fail_if_docker_compose_version_is_prior_1_7_on_logs() throws IOException, InterruptedException { - when(executedProcess.getInputStream()).thenReturn(toInputStream("docker-compose version 1.5.6, build 1ad8866")); + when(executedProcess.getInputStream()).thenReturn(toInputStream("1.5.6")); exception.expect(IllegalStateException.class); exception.expectMessage("You need at least docker-compose 1.7 to run docker-compose exec"); compose.exec(options("-d"), "container_1", arguments("ls")); @@ -188,7 +188,7 @@ public void throw_illegal_state_exception_when_there_is_no_container_found_for_p @Test public void pass_concatenated_arguments_to_executor_on_docker_compose_exec() throws IOException, InterruptedException { - when(executedProcess.getInputStream()).thenReturn(toInputStream("docker-compose version 1.7.0rc1, build 1ad8866")); + when(executedProcess.getInputStream()).thenReturn(toInputStream("1.7.0-rc1")); compose.exec(options("-d"), "container_1", arguments("ls")); verify(executor, times(1)).execute("exec", "-T", "-d", "container_1", "ls"); } @@ -196,7 +196,7 @@ public void pass_concatenated_arguments_to_executor_on_docker_compose_exec() @Test public void fail_if_docker_compose_version_is_prior_1_7_on_docker_compose_exec() throws IOException, InterruptedException { - when(executedProcess.getInputStream()).thenReturn(toInputStream("docker-compose version 1.5.6, build 1ad8866")); + when(executedProcess.getInputStream()).thenReturn(toInputStream("1.5.6")); exception.expect(IllegalStateException.class); exception.expectMessage("You need at least docker-compose 1.7 to run docker-compose exec"); compose.exec(options("-d"), "container_1", arguments("ls")); @@ -214,11 +214,11 @@ public void return_the_output_from_the_executed_process_on_docker_compose_exec() String lsString = String.format("-rw-r--r-- 1 user 1318458867 11326 Mar 9 17:47 LICENSE%n" + "-rw-r--r-- 1 user 1318458867 12570 May 12 14:51 README.md"); - String versionString = "docker-compose version 1.7.0rc1, build 1ad8866"; + String versionString = "1.7.0-rc1"; DockerComposeExecutable processExecutor = mock(DockerComposeExecutable.class); - addProcessToExecutor(processExecutor, processWithOutput(versionString), "-v"); + addProcessToExecutor(processExecutor, processWithOutput(versionString), "version", "--short"); addProcessToExecutor(processExecutor, processWithOutput(lsString), "exec", "-T", "container_1", "ls", "-l"); DockerCompose processCompose = new DefaultDockerCompose(processExecutor, dockerMachine); diff --git a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerComposeVersionShould.java b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerComposeVersionShould.java deleted file mode 100644 index 9e20a3b87..000000000 --- a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerComposeVersionShould.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * (c) 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 org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.lessThan; - -import com.github.zafarkhaja.semver.Version; -import org.junit.Test; - - -public class DockerComposeVersionShould { - - @Test - public void compare_major_versions_first() { - assertThat(Version.valueOf("2.1.0").compareTo(Version.valueOf("1.2.1")), greaterThan(0)); - } - - @Test - public void compare_minor_versions_when_major_versions_are_the_same() { - assertThat(Version.valueOf("2.1.7").compareTo(Version.valueOf("2.3.2")), lessThan(0)); - } - - @Test - public void return_equals_for_the_same_version_strings() { - assertThat(Version.valueOf("2.1.2").compareTo(Version.valueOf("2.1.2")), is(0)); - } - - @Test - public void remove_non_digits_when_passing_version_string() { - assertThat( - DockerComposeVersion.parseFromDockerComposeVersion("docker-compose version 1.7.0rc1, build 1ad8866"), - is(Version.valueOf("1.7.0"))); - } -} diff --git a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerShould.java b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerShould.java index 89ee99b49..efcd3868c 100644 --- a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerShould.java +++ b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/execution/DockerShould.java @@ -71,18 +71,12 @@ public void call_docker_network_prune() throws IOException, InterruptedException } @Test - public void understand_old_version_format() throws IOException, InterruptedException { - when(executedProcess.getInputStream()).thenReturn(toInputStream("Docker version 1.7.2")); + public void call_docker_version() throws IOException, InterruptedException { + when(executedProcess.getInputStream()).thenReturn(toInputStream("19.03.5")); - Version version = docker.configuredVersion(); - assertThat(version, is(Version.valueOf("1.7.2"))); - } - - @Test - public void understand_new_version_format() throws IOException, InterruptedException { - when(executedProcess.getInputStream()).thenReturn(toInputStream("Docker version 17.03.1-ce")); + Version version = docker.version(); + assertThat(version, is(Version.valueOf("19.3.5"))); - Version version = docker.configuredVersion(); - assertThat(version, is(Version.valueOf("17.3.1"))); + verify(executor).execute("version", "--format", "{{.Client.Version}}"); } } diff --git a/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/helpers/VersionHelperShould.java b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/helpers/VersionHelperShould.java new file mode 100644 index 000000000..929a3594a --- /dev/null +++ b/docker-compose-rule-core/src/test/java/com/palantir/docker/compose/helpers/VersionHelperShould.java @@ -0,0 +1,57 @@ +/* + * (c) Copyright 2019 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.helpers; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +import com.github.zafarkhaja.semver.Version; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class VersionHelperShould { + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Test + public void satisfactory_version_core_remains_unchanged() { + String version = "1.2.3"; + assertThat(VersionHelper.toSemVer(version), is(Version.valueOf("1.2.3"))); + } + + @Test + public void satisfactory_full_version_gets_simplified() { + String version = "1.2.3-rc4+build5"; + assertThat(VersionHelper.toSemVer(version), is(Version.valueOf("1.2.3"))); + } + + @Test + public void leading_zeroes_are_removed_from_version_core() { + String version = "01.02.03-rc4+build5"; + assertThat(VersionHelper.toSemVer(version), is(Version.valueOf("1.2.3"))); + } + + @Test + public void unexpected_version_structure_throws_exception() { + String version = "totally_a_version"; + exception.expect(IllegalStateException.class); + exception.expectMessage("Unexpected version structure: totally_a_version"); + VersionHelper.toSemVer(version); + } +}