Support podman for building images
Closes gh-30196
This commit is contained in:
@@ -187,7 +187,7 @@ public class DockerApi {
|
||||
listener.onUpdate(event);
|
||||
});
|
||||
}
|
||||
return inspect(reference.withDigest(digestCapture.getCapturedDigest()));
|
||||
return inspect(reference);
|
||||
}
|
||||
finally {
|
||||
listener.onFinish();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -61,6 +61,8 @@ public class ImageArchive implements TarArchive {
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ISO_ZONED_DATE_TIME
|
||||
.withZone(ZoneOffset.UTC);
|
||||
|
||||
private static final String EMPTY_LAYER_NAME_PREFIX = "blank_";
|
||||
|
||||
private static final IOConsumer<Update> NO_UPDATES = (update) -> {
|
||||
};
|
||||
|
||||
@@ -125,6 +127,9 @@ public class ImageArchive implements TarArchive {
|
||||
}
|
||||
|
||||
private List<LayerId> writeLayers(Layout writer) throws IOException {
|
||||
for (int i = 0; i < this.existingLayers.size(); i++) {
|
||||
writeEmptyLayer(writer, EMPTY_LAYER_NAME_PREFIX + i);
|
||||
}
|
||||
List<LayerId> writtenLayers = new ArrayList<>();
|
||||
for (Layer layer : this.newLayers) {
|
||||
writtenLayers.add(writeLayer(writer, layer));
|
||||
@@ -132,9 +137,13 @@ public class ImageArchive implements TarArchive {
|
||||
return Collections.unmodifiableList(writtenLayers);
|
||||
}
|
||||
|
||||
private void writeEmptyLayer(Layout writer, String name) throws IOException {
|
||||
writer.file(name, Owner.ROOT, Content.of(""));
|
||||
}
|
||||
|
||||
private LayerId writeLayer(Layout writer, Layer layer) throws IOException {
|
||||
LayerId id = layer.getId();
|
||||
writer.file("/" + id.getHash() + ".tar", Owner.ROOT, layer);
|
||||
writer.file(id.getHash() + ".tar", Owner.ROOT, layer);
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -144,7 +153,7 @@ public class ImageArchive implements TarArchive {
|
||||
String json = this.objectMapper.writeValueAsString(config).replace("\r\n", "\n");
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
InspectedContent content = InspectedContent.of(Content.of(json), digest::update);
|
||||
String name = "/" + LayerId.ofSha256Digest(digest.digest()).getHash() + ".json";
|
||||
String name = LayerId.ofSha256Digest(digest.digest()).getHash() + ".json";
|
||||
writer.file(name, Owner.ROOT, content);
|
||||
return name;
|
||||
}
|
||||
@@ -187,7 +196,7 @@ public class ImageArchive implements TarArchive {
|
||||
private void writeManifest(Layout writer, String config, List<LayerId> writtenLayers) throws IOException {
|
||||
ArrayNode manifest = createManifest(config, writtenLayers);
|
||||
String manifestJson = this.objectMapper.writeValueAsString(manifest);
|
||||
writer.file("/manifest.json", Owner.ROOT, Content.of(manifestJson));
|
||||
writer.file("manifest.json", Owner.ROOT, Content.of(manifestJson));
|
||||
}
|
||||
|
||||
private ArrayNode createManifest(String config, List<LayerId> writtenLayers) {
|
||||
@@ -204,7 +213,7 @@ public class ImageArchive implements TarArchive {
|
||||
private ArrayNode getManifestLayers(List<LayerId> writtenLayers) {
|
||||
ArrayNode layers = this.objectMapper.createArrayNode();
|
||||
for (int i = 0; i < this.existingLayers.size(); i++) {
|
||||
layers.add("");
|
||||
layers.add(EMPTY_LAYER_NAME_PREFIX + i);
|
||||
}
|
||||
writtenLayers.stream().map((id) -> id.getHash() + ".tar").forEach(layers::add);
|
||||
return layers;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -58,6 +58,8 @@ import static org.assertj.core.api.Assertions.entry;
|
||||
*/
|
||||
class EphemeralBuilderTests extends AbstractJsonTests {
|
||||
|
||||
private static final int EXISTING_IMAGE_LAYER_COUNT = 43;
|
||||
|
||||
@TempDir
|
||||
File temp;
|
||||
|
||||
@@ -131,7 +133,7 @@ class EphemeralBuilderTests extends AbstractJsonTests {
|
||||
void getArchiveContainsEnvLayer() throws Exception {
|
||||
EphemeralBuilder builder = new EphemeralBuilder(this.owner, this.image, this.targetImage, this.metadata,
|
||||
this.creator, this.env, this.buildpacks);
|
||||
File directory = unpack(getLayer(builder.getArchive(), 0), "env");
|
||||
File directory = unpack(getLayer(builder.getArchive(), EXISTING_IMAGE_LAYER_COUNT), "env");
|
||||
assertThat(new File(directory, "platform/env/spring")).usingCharset(StandardCharsets.UTF_8).hasContent("boot");
|
||||
assertThat(new File(directory, "platform/env/empty")).usingCharset(StandardCharsets.UTF_8).hasContent("");
|
||||
}
|
||||
@@ -154,10 +156,13 @@ class EphemeralBuilderTests extends AbstractJsonTests {
|
||||
this.buildpacks = Buildpacks.of(buildpackList);
|
||||
EphemeralBuilder builder = new EphemeralBuilder(this.owner, this.image, this.targetImage, this.metadata,
|
||||
this.creator, null, this.buildpacks);
|
||||
assertBuildpackLayerContent(builder, 0, "/cnb/buildpacks/example_buildpack1/0.0.1/buildpack.toml");
|
||||
assertBuildpackLayerContent(builder, 1, "/cnb/buildpacks/example_buildpack2/0.0.2/buildpack.toml");
|
||||
assertBuildpackLayerContent(builder, 2, "/cnb/buildpacks/example_buildpack3/0.0.3/buildpack.toml");
|
||||
File orderDirectory = unpack(getLayer(builder.getArchive(), 3), "order");
|
||||
assertBuildpackLayerContent(builder, EXISTING_IMAGE_LAYER_COUNT,
|
||||
"/cnb/buildpacks/example_buildpack1/0.0.1/buildpack.toml");
|
||||
assertBuildpackLayerContent(builder, EXISTING_IMAGE_LAYER_COUNT + 1,
|
||||
"/cnb/buildpacks/example_buildpack2/0.0.2/buildpack.toml");
|
||||
assertBuildpackLayerContent(builder, EXISTING_IMAGE_LAYER_COUNT + 2,
|
||||
"/cnb/buildpacks/example_buildpack3/0.0.3/buildpack.toml");
|
||||
File orderDirectory = unpack(getLayer(builder.getArchive(), EXISTING_IMAGE_LAYER_COUNT + 3), "order");
|
||||
assertThat(new File(orderDirectory, "cnb/order.toml")).usingCharset(StandardCharsets.UTF_8)
|
||||
.hasContent(content("order.toml"));
|
||||
}
|
||||
|
||||
@@ -164,8 +164,7 @@ class DockerApiTests {
|
||||
void pullPullsImageAndProducesEvents() throws Exception {
|
||||
ImageReference reference = ImageReference.of("gcr.io/paketo-buildpacks/builder:base");
|
||||
URI createUri = new URI(IMAGES_URL + "/create?fromImage=gcr.io%2Fpaketo-buildpacks%2Fbuilder%3Abase");
|
||||
String imageHash = "4acb6bfd6c4f0cabaf7f3690e444afe51f1c7de54d51da7e63fac709c56f1c30";
|
||||
URI imageUri = new URI(IMAGES_URL + "/gcr.io/paketo-buildpacks/builder@sha256:" + imageHash + "/json");
|
||||
URI imageUri = new URI(IMAGES_URL + "/gcr.io/paketo-buildpacks/builder:base/json");
|
||||
given(http().post(eq(createUri), isNull())).willReturn(responseOf("pull-stream.json"));
|
||||
given(http().get(imageUri)).willReturn(responseOf("type/image.json"));
|
||||
Image image = this.api.pull(reference, this.pullListener);
|
||||
@@ -180,8 +179,7 @@ class DockerApiTests {
|
||||
void pullWithRegistryAuthPullsImageAndProducesEvents() throws Exception {
|
||||
ImageReference reference = ImageReference.of("gcr.io/paketo-buildpacks/builder:base");
|
||||
URI createUri = new URI(IMAGES_URL + "/create?fromImage=gcr.io%2Fpaketo-buildpacks%2Fbuilder%3Abase");
|
||||
String imageHash = "4acb6bfd6c4f0cabaf7f3690e444afe51f1c7de54d51da7e63fac709c56f1c30";
|
||||
URI imageUri = new URI(IMAGES_URL + "/gcr.io/paketo-buildpacks/builder@sha256:" + imageHash + "/json");
|
||||
URI imageUri = new URI(IMAGES_URL + "/gcr.io/paketo-buildpacks/builder:base/json");
|
||||
given(http().post(eq(createUri), eq("auth token"))).willReturn(responseOf("pull-stream.json"));
|
||||
given(http().get(imageUri)).willReturn(responseOf("type/image.json"));
|
||||
Image image = this.api.pull(reference, this.pullListener, "auth token");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,6 +40,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class ImageArchiveTests extends AbstractJsonTests {
|
||||
|
||||
private static final int EXISTING_IMAGE_LAYER_COUNT = 46;
|
||||
|
||||
@Test
|
||||
void fromImageWritesToValidArchiveTar() throws Exception {
|
||||
Image image = Image.of(getContent("image.json"));
|
||||
@@ -51,13 +53,16 @@ class ImageArchiveTests extends AbstractJsonTests {
|
||||
archive.writeTo(outputStream);
|
||||
try (TarArchiveInputStream tar = new TarArchiveInputStream(
|
||||
new ByteArrayInputStream(outputStream.toByteArray()))) {
|
||||
for (int i = 0; i < EXISTING_IMAGE_LAYER_COUNT; i++) {
|
||||
TarArchiveEntry blankEntry = tar.getNextTarEntry();
|
||||
assertThat(blankEntry.getName()).isEqualTo("blank_" + i);
|
||||
}
|
||||
TarArchiveEntry layerEntry = tar.getNextTarEntry();
|
||||
byte[] layerContent = read(tar, layerEntry.getSize());
|
||||
TarArchiveEntry configEntry = tar.getNextTarEntry();
|
||||
byte[] configContent = read(tar, configEntry.getSize());
|
||||
TarArchiveEntry manifestEntry = tar.getNextTarEntry();
|
||||
byte[] manifestContent = read(tar, manifestEntry.getSize());
|
||||
assertThat(tar.getNextTarEntry()).isNull();
|
||||
assertExpectedLayer(layerEntry, layerContent);
|
||||
assertExpectedConfig(configEntry, configContent);
|
||||
assertExpectedManifest(manifestEntry, manifestContent);
|
||||
@@ -65,7 +70,7 @@ class ImageArchiveTests extends AbstractJsonTests {
|
||||
}
|
||||
|
||||
private void assertExpectedLayer(TarArchiveEntry entry, byte[] content) throws Exception {
|
||||
assertThat(entry.getName()).isEqualTo("/bb09e17fd1bd2ee47155f1349645fcd9fff31e1247c7ed99cad469f1c16a4216.tar");
|
||||
assertThat(entry.getName()).isEqualTo("bb09e17fd1bd2ee47155f1349645fcd9fff31e1247c7ed99cad469f1c16a4216.tar");
|
||||
try (TarArchiveInputStream tar = new TarArchiveInputStream(new ByteArrayInputStream(content))) {
|
||||
TarArchiveEntry contentEntry = tar.getNextTarEntry();
|
||||
assertThat(contentEntry.getName()).isEqualTo("/spring/");
|
||||
@@ -73,14 +78,14 @@ class ImageArchiveTests extends AbstractJsonTests {
|
||||
}
|
||||
|
||||
private void assertExpectedConfig(TarArchiveEntry entry, byte[] content) throws Exception {
|
||||
assertThat(entry.getName()).isEqualTo("/682f8d24b9d9c313d1190a0e955dcb5e65ec9beea40420999839c6f0cbb38382.json");
|
||||
assertThat(entry.getName()).isEqualTo("682f8d24b9d9c313d1190a0e955dcb5e65ec9beea40420999839c6f0cbb38382.json");
|
||||
String actualJson = new String(content, StandardCharsets.UTF_8);
|
||||
String expectedJson = StreamUtils.copyToString(getContent("image-archive-config.json"), StandardCharsets.UTF_8);
|
||||
JSONAssert.assertEquals(expectedJson, actualJson, false);
|
||||
}
|
||||
|
||||
private void assertExpectedManifest(TarArchiveEntry entry, byte[] content) throws Exception {
|
||||
assertThat(entry.getName()).isEqualTo("/manifest.json");
|
||||
assertThat(entry.getName()).isEqualTo("manifest.json");
|
||||
String actualJson = new String(content, StandardCharsets.UTF_8);
|
||||
String expectedJson = StreamUtils.copyToString(getContent("image-archive-manifest.json"),
|
||||
StandardCharsets.UTF_8);
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
[
|
||||
{
|
||||
"Config": "/682f8d24b9d9c313d1190a0e955dcb5e65ec9beea40420999839c6f0cbb38382.json",
|
||||
"Config": "682f8d24b9d9c313d1190a0e955dcb5e65ec9beea40420999839c6f0cbb38382.json",
|
||||
"Layers": [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"blank_0",
|
||||
"blank_1",
|
||||
"blank_2",
|
||||
"blank_3",
|
||||
"blank_4",
|
||||
"blank_5",
|
||||
"blank_6",
|
||||
"blank_7",
|
||||
"blank_8",
|
||||
"blank_9",
|
||||
"blank_10",
|
||||
"blank_11",
|
||||
"blank_12",
|
||||
"blank_13",
|
||||
"blank_14",
|
||||
"blank_15",
|
||||
"blank_16",
|
||||
"blank_17",
|
||||
"blank_18",
|
||||
"blank_19",
|
||||
"blank_20",
|
||||
"blank_21",
|
||||
"blank_22",
|
||||
"blank_23",
|
||||
"blank_24",
|
||||
"blank_25",
|
||||
"blank_26",
|
||||
"blank_27",
|
||||
"blank_28",
|
||||
"blank_29",
|
||||
"blank_30",
|
||||
"blank_31",
|
||||
"blank_32",
|
||||
"blank_33",
|
||||
"blank_34",
|
||||
"blank_35",
|
||||
"blank_36",
|
||||
"blank_37",
|
||||
"blank_38",
|
||||
"blank_39",
|
||||
"blank_40",
|
||||
"blank_41",
|
||||
"blank_42",
|
||||
"blank_43",
|
||||
"blank_44",
|
||||
"blank_45",
|
||||
"bb09e17fd1bd2ee47155f1349645fcd9fff31e1247c7ed99cad469f1c16a4216.tar"
|
||||
],
|
||||
"RepoTags": [
|
||||
|
||||
Reference in New Issue
Block a user