mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-17 12:09:16 +00:00
Merge branch '3.5.x'
Closes gh-48128
This commit is contained in:
+1
-1
@@ -391,7 +391,7 @@ public class Builder {
|
||||
@Override
|
||||
public void exportImageLayers(ImageReference reference, IOBiConsumer<String, TarArchive> exports)
|
||||
throws IOException {
|
||||
Builder.this.docker.image().exportLayers(reference, exports);
|
||||
Builder.this.docker.image().exportLayers(reference, this.platform, exports);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+35
-16
@@ -124,6 +124,13 @@ public class DockerApi {
|
||||
return this.jsonStream;
|
||||
}
|
||||
|
||||
URI buildPlatformJsonUrl(Feature feature, @Nullable ImagePlatform platform, String path) {
|
||||
if (platform != null && getApiVersion().supports(feature.minimumVersion())) {
|
||||
return buildUrl(feature, path, "platform", platform.toJson());
|
||||
}
|
||||
return buildUrl(path);
|
||||
}
|
||||
|
||||
private URI buildUrl(String path, @Nullable Collection<?> params) {
|
||||
return buildUrl(Feature.BASELINE, path, (params != null) ? params.toArray() : null);
|
||||
}
|
||||
@@ -229,9 +236,8 @@ public class DockerApi {
|
||||
UpdateListener<PullImageUpdateEvent> listener, @Nullable String registryAuth) throws IOException {
|
||||
Assert.notNull(reference, "'reference' must not be null");
|
||||
Assert.notNull(listener, "'listener' must not be null");
|
||||
URI createUri = (platform != null)
|
||||
? buildUrl(Feature.PLATFORM, "/images/create", "fromImage", reference, "platform", platform)
|
||||
: buildUrl("/images/create", "fromImage", reference);
|
||||
URI createUri = (platform != null) ? buildUrl(Feature.PLATFORM_IMAGE_PULL, "/images/create", "fromImage",
|
||||
reference, "platform", platform) : buildUrl("/images/create", "fromImage", reference);
|
||||
DigestCaptureUpdateListener digestCapture = new DigestCaptureUpdateListener();
|
||||
listener.onStart();
|
||||
try {
|
||||
@@ -313,9 +319,24 @@ public class DockerApi {
|
||||
*/
|
||||
public void exportLayers(ImageReference reference, IOBiConsumer<String, TarArchive> exports)
|
||||
throws IOException {
|
||||
exportLayers(reference, null, exports);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export the layers of an image as {@link TarArchive TarArchives}.
|
||||
* @param reference the reference to export
|
||||
* @param platform the platform (os/architecture/variant) of the image to export.
|
||||
* Ignored on older versions of Docker.
|
||||
* @param exports a consumer to receive the layers (contents can only be accessed
|
||||
* during the callback)
|
||||
* @throws IOException on IO error
|
||||
* @since 3.4.12
|
||||
*/
|
||||
public void exportLayers(ImageReference reference, @Nullable ImagePlatform platform,
|
||||
IOBiConsumer<String, TarArchive> exports) throws IOException {
|
||||
Assert.notNull(reference, "'reference' must not be null");
|
||||
Assert.notNull(exports, "'exports' must not be null");
|
||||
URI uri = buildUrl("/images/" + reference + "/get");
|
||||
URI uri = buildPlatformJsonUrl(Feature.PLATFORM_IMAGE_EXPORT, platform, "/images/" + reference + "/get");
|
||||
try (Response response = http().get(uri)) {
|
||||
try (ExportedImageTar exportedImageTar = new ExportedImageTar(reference, response.getContent())) {
|
||||
exportedImageTar.exportLayers(exports);
|
||||
@@ -359,20 +380,13 @@ public class DockerApi {
|
||||
// The Docker documentation is incomplete but platform parameters
|
||||
// are supported since 1.49 (see https://github.com/moby/moby/pull/49586)
|
||||
Assert.notNull(reference, "'reference' must not be null");
|
||||
URI inspectUrl = inspectUrl(reference, platform);
|
||||
URI inspectUrl = buildPlatformJsonUrl(Feature.PLATFORM_IMAGE_INSPECT, platform,
|
||||
"/images/" + reference + "/json");
|
||||
try (Response response = http().get(inspectUrl)) {
|
||||
return Image.of(response.getContent());
|
||||
}
|
||||
}
|
||||
|
||||
private URI inspectUrl(ImageReference reference, @Nullable ImagePlatform platform) {
|
||||
String path = "/images/" + reference + "/json";
|
||||
if (platform != null && getApiVersion().supports(Feature.PLATFORM_INSPECT.minimumVersion())) {
|
||||
return buildUrl(Feature.PLATFORM_INSPECT, path, "platform", platform.toJson());
|
||||
}
|
||||
return buildUrl(path);
|
||||
}
|
||||
|
||||
public void tag(ImageReference sourceReference, ImageReference targetReference) throws IOException {
|
||||
Assert.notNull(sourceReference, "'sourceReference' must not be null");
|
||||
Assert.notNull(targetReference, "'targetReference' must not be null");
|
||||
@@ -415,7 +429,8 @@ public class DockerApi {
|
||||
|
||||
private ContainerReference createContainer(ContainerConfig config, @Nullable ImagePlatform platform)
|
||||
throws IOException {
|
||||
URI createUri = (platform != null) ? buildUrl(Feature.PLATFORM, "/containers/create", "platform", platform)
|
||||
URI createUri = (platform != null)
|
||||
? buildUrl(Feature.PLATFORM_CONTAINER_CREATE, "/containers/create", "platform", platform)
|
||||
: buildUrl("/containers/create");
|
||||
try (Response response = http().post(createUri, "application/json", config::writeTo)) {
|
||||
return ContainerReference
|
||||
@@ -624,9 +639,13 @@ public class DockerApi {
|
||||
|
||||
BASELINE(ApiVersion.of(1, 24)),
|
||||
|
||||
PLATFORM(ApiVersion.of(1, 41)),
|
||||
PLATFORM_IMAGE_PULL(ApiVersion.of(1, 41)),
|
||||
|
||||
PLATFORM_INSPECT(ApiVersion.of(1, 49));
|
||||
PLATFORM_CONTAINER_CREATE(ApiVersion.of(1, 41)),
|
||||
|
||||
PLATFORM_IMAGE_INSPECT(ApiVersion.of(1, 49)),
|
||||
|
||||
PLATFORM_IMAGE_EXPORT(ApiVersion.of(1, 48));
|
||||
|
||||
private final ApiVersion minimumVersion;
|
||||
|
||||
|
||||
+59
@@ -501,6 +501,65 @@ class DockerApiTests {
|
||||
.containsExactly("/cnb/stack.toml");
|
||||
}
|
||||
|
||||
@Test
|
||||
void exportLayersExportsLayerTarsWithPlatformWhenSupportedVersion() throws Exception {
|
||||
setVersion("1.48");
|
||||
ImageReference reference = ImageReference.of("docker.io/paketobuildpacks/builder:base");
|
||||
URI exportUri = new URI("/v1.48/images/docker.io/paketobuildpacks/builder:base/get?platform="
|
||||
+ ENCODED_LINUX_ARM64_PLATFORM_JSON);
|
||||
given(DockerApiTests.this.http.get(exportUri)).willReturn(responseOf("export.tar"));
|
||||
MultiValueMap<String, String> contents = new LinkedMultiValueMap<>();
|
||||
this.api.exportLayers(reference, LINUX_ARM64_PLATFORM, (name, archive) -> {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
archive.writeTo(out);
|
||||
try (TarArchiveInputStream in = new TarArchiveInputStream(
|
||||
new ByteArrayInputStream(out.toByteArray()))) {
|
||||
TarArchiveEntry entry = in.getNextEntry();
|
||||
while (entry != null) {
|
||||
contents.add(name, entry.getName());
|
||||
entry = in.getNextEntry();
|
||||
}
|
||||
}
|
||||
});
|
||||
assertThat(contents).hasSize(3)
|
||||
.containsKeys("70bb7a3115f3d5c01099852112c7e05bf593789e510468edb06b6a9a11fa3b73/layer.tar",
|
||||
"74a9a50ece13c025cf10e9110d9ddc86c995079c34e2a22a28d1a3d523222c6e/layer.tar",
|
||||
"a69532b5b92bb891fbd9fa1a6b3af9087ea7050255f59ba61a796f8555ecd783/layer.tar");
|
||||
assertThat(contents.get("70bb7a3115f3d5c01099852112c7e05bf593789e510468edb06b6a9a11fa3b73/layer.tar"))
|
||||
.containsExactly("/cnb/order.toml");
|
||||
assertThat(contents.get("74a9a50ece13c025cf10e9110d9ddc86c995079c34e2a22a28d1a3d523222c6e/layer.tar"))
|
||||
.containsExactly("/cnb/stack.toml");
|
||||
}
|
||||
|
||||
@Test
|
||||
void exportLayersExportsLayerTarsWithPlatformWhenOldVersionInspectImage() throws Exception {
|
||||
setVersion("1.47");
|
||||
ImageReference reference = ImageReference.of("docker.io/paketobuildpacks/builder:base");
|
||||
URI exportUri = new URI("/v1.47/images/docker.io/paketobuildpacks/builder:base/get");
|
||||
given(DockerApiTests.this.http.get(exportUri)).willReturn(responseOf("export.tar"));
|
||||
MultiValueMap<String, String> contents = new LinkedMultiValueMap<>();
|
||||
this.api.exportLayers(reference, LINUX_ARM64_PLATFORM, (name, archive) -> {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
archive.writeTo(out);
|
||||
try (TarArchiveInputStream in = new TarArchiveInputStream(
|
||||
new ByteArrayInputStream(out.toByteArray()))) {
|
||||
TarArchiveEntry entry = in.getNextEntry();
|
||||
while (entry != null) {
|
||||
contents.add(name, entry.getName());
|
||||
entry = in.getNextEntry();
|
||||
}
|
||||
}
|
||||
});
|
||||
assertThat(contents).hasSize(3)
|
||||
.containsKeys("70bb7a3115f3d5c01099852112c7e05bf593789e510468edb06b6a9a11fa3b73/layer.tar",
|
||||
"74a9a50ece13c025cf10e9110d9ddc86c995079c34e2a22a28d1a3d523222c6e/layer.tar",
|
||||
"a69532b5b92bb891fbd9fa1a6b3af9087ea7050255f59ba61a796f8555ecd783/layer.tar");
|
||||
assertThat(contents.get("70bb7a3115f3d5c01099852112c7e05bf593789e510468edb06b6a9a11fa3b73/layer.tar"))
|
||||
.containsExactly("/cnb/order.toml");
|
||||
assertThat(contents.get("74a9a50ece13c025cf10e9110d9ddc86c995079c34e2a22a28d1a3d523222c6e/layer.tar"))
|
||||
.containsExactly("/cnb/stack.toml");
|
||||
}
|
||||
|
||||
@Test
|
||||
void exportLayersWithSymlinksExportsLayerTars() throws Exception {
|
||||
ImageReference reference = ImageReference.of("docker.io/paketobuildpacks/builder:base");
|
||||
|
||||
Reference in New Issue
Block a user