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
This commit is contained in:
Moritz Halbritter 2023-10-23 10:38:55 +02:00
parent 955c2bfcdf
commit 09821feb75
3 changed files with 36 additions and 3 deletions

View File

@ -21,10 +21,12 @@ import java.util.ArrayList;
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 @@ class DefaultDockerCompose implements DockerCompose {
List<RunningService> result = new ArrayList<>();
Map<String, DockerCliInspectResponse> 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 @@ class DefaultDockerCompose implements DockerCompose {
return inspectResponses.stream().collect(Collectors.toMap(DockerCliInspectResponse::id, Function.identity()));
}
private DockerCliInspectResponse inspectContainer(String id, Map<String, DockerCliInspectResponse> 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<String, DockerCliInspectResponse> entry : inspected.entrySet()) {
if (entry.getKey().startsWith(id)) {
return entry.getValue();
}
}
return null;
}
private List<DockerCliComposePsResponse> runComposePs() {
return this.cli.run(new DockerCliCommand.ComposePs());
}

View File

@ -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 @@ class DefaultDockerComposeTests {
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<RunningService> runningServices = compose.getRunningServices();
assertThat(runningServices).hasSize(1);
}
}

View File

@ -84,7 +84,7 @@ class DockerCliIntegrationTests {
String id = ps.get(0).id();
List<DockerCliInspectResponse> 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());