From 09821feb7559ab15433bf01f6eda86db208dc198 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Mon, 23 Oct 2023 10:38:55 +0200 Subject: [PATCH] Fix container inspection for Docker Compose >= 2.23.0 Docker Compose starting with 2.23.0 returns truncated ids in the docker compose ps call. We now do a prefix search if an exact match isn't found in the docker inspect response. Closes gh-37982 --- .../compose/core/DefaultDockerCompose.java | 19 ++++++++++++++++++- .../core/DefaultDockerComposeTests.java | 18 +++++++++++++++++- .../core/DockerCliIntegrationTests.java | 2 +- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/DefaultDockerCompose.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/DefaultDockerCompose.java index c969cf440585..ff13762364ff 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/DefaultDockerCompose.java +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/core/DefaultDockerCompose.java @@ -21,10 +21,12 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.function.Function; import java.util.stream.Collectors; import org.springframework.boot.logging.LogLevel; +import org.springframework.util.Assert; /** * Default {@link DockerCompose} implementation backed by {@link DockerCli}. @@ -79,7 +81,8 @@ public List getRunningServices() { List result = new ArrayList<>(); Map inspected = inspect(runningPsResponses); for (DockerCliComposePsResponse psResponse : runningPsResponses) { - DockerCliInspectResponse inspectResponse = inspected.get(psResponse.id()); + DockerCliInspectResponse inspectResponse = inspectContainer(psResponse.id(), inspected); + Assert.notNull(inspectResponse, () -> "Failed to inspect container '%s'".formatted(psResponse.id())); result.add(new DefaultRunningService(this.hostname, dockerComposeFile, psResponse, inspectResponse)); } return Collections.unmodifiableList(result); @@ -91,6 +94,20 @@ private Map inspect(List inspected) { + DockerCliInspectResponse inspect = inspected.get(id); + if (inspect != null) { + return inspect; + } + // Docker Compose v2.23.0 returns truncated ids, so we have to do a prefix match + for (Entry entry : inspected.entrySet()) { + if (entry.getKey().startsWith(id)) { + return entry.getValue(); + } + } + return null; + } + private List runComposePs() { return this.cli.run(new DockerCliCommand.ComposePs()); } diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DefaultDockerComposeTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DefaultDockerComposeTests.java index c6c297d3a9b2..cb1bbf13d219 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DefaultDockerComposeTests.java +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DefaultDockerComposeTests.java @@ -46,7 +46,7 @@ class DefaultDockerComposeTests { private static final String HOST = "192.168.1.1"; - private DockerCli cli = mock(DockerCli.class); + private final DockerCli cli = mock(DockerCli.class); @Test void upRunsUpCommand() { @@ -141,4 +141,20 @@ void getRunningServicesWhenNoHostUsesHostFromContext() { assertThat(runningService.host()).isEqualTo("192.168.1.1"); } + @Test + void worksWithTruncatedIds() { + String shortId = "123"; + String longId = "123456"; + DockerCliComposePsResponse psResponse = new DockerCliComposePsResponse(shortId, "name", "redis", "running"); + Config config = new Config("redis", Collections.emptyMap(), Collections.emptyMap(), Collections.emptyList()); + DockerCliInspectResponse inspectResponse = new DockerCliInspectResponse(longId, config, null, null); + willReturn(List.of(new DockerCliContextResponse("test", true, "https://192.168.1.1"))).given(this.cli) + .run(new DockerCliCommand.Context()); + willReturn(List.of(psResponse)).given(this.cli).run(new DockerCliCommand.ComposePs()); + willReturn(List.of(inspectResponse)).given(this.cli).run(new DockerCliCommand.Inspect(List.of(shortId))); + DefaultDockerCompose compose = new DefaultDockerCompose(this.cli, null); + List runningServices = compose.getRunningServices(); + assertThat(runningServices).hasSize(1); + } + } diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliIntegrationTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliIntegrationTests.java index b405ff587eb8..fe00279095b9 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliIntegrationTests.java +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/core/DockerCliIntegrationTests.java @@ -84,7 +84,7 @@ void runLifecycle() throws IOException { String id = ps.get(0).id(); List inspect = cli.run(new Inspect(List.of(id))); assertThat(inspect).isNotEmpty(); - assertThat(inspect.get(0).id()).isEqualTo(id); + assertThat(inspect.get(0).id()).startsWith(id); // Run stop, then run ps and verify the services are stopped cli.run(new ComposeStop(Duration.ofSeconds(10))); ps = cli.run(new ComposePs());