Support podman for building images

Closes gh-30196
This commit is contained in:
Scott Frederick
2022-03-11 16:39:07 -06:00
parent 7ad538cd84
commit de321b00b7
15 changed files with 227 additions and 84 deletions

View File

@@ -187,7 +187,7 @@ public class DockerApi {
listener.onUpdate(event);
});
}
return inspect(reference.withDigest(digestCapture.getCapturedDigest()));
return inspect(reference);
}
finally {
listener.onFinish();

View File

@@ -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;

View File

@@ -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"));
}

View File

@@ -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");

View File

@@ -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);

View File

@@ -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": [