Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Blob conversion from ImageToTarballTranslator and TarStreamBuilder #1647

Merged
merged 7 commits into from
Apr 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import com.google.cloud.tools.jib.builder.ProgressEventDispatcher;
import com.google.cloud.tools.jib.configuration.BuildConfiguration;
import com.google.cloud.tools.jib.docker.DockerClient;
import com.google.cloud.tools.jib.docker.ImageToTarballTranslator;
import com.google.cloud.tools.jib.docker.ImageTarball;
import com.google.cloud.tools.jib.event.events.LogEvent;
import com.google.cloud.tools.jib.image.Image;
import com.google.cloud.tools.jib.image.ImageReference;
Expand Down Expand Up @@ -105,9 +105,7 @@ private BuildResult afterPushBaseImageLayerFuturesFuture()
buildConfiguration
.getEventDispatcher()
.dispatch(
LogEvent.debug(
dockerClient.load(
new ImageToTarballTranslator(image).toTarballBlob(targetImageReference))));
LogEvent.debug(dockerClient.load(new ImageTarball(image, targetImageReference))));

// Tags the image with all the additional tags, skipping the one 'docker load' already loaded.
for (String tag : buildConfiguration.getAllTargetImageTags()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import com.google.cloud.tools.jib.builder.BuildStepType;
import com.google.cloud.tools.jib.builder.ProgressEventDispatcher;
import com.google.cloud.tools.jib.configuration.BuildConfiguration;
import com.google.cloud.tools.jib.docker.ImageToTarballTranslator;
import com.google.cloud.tools.jib.docker.ImageTarball;
import com.google.cloud.tools.jib.event.events.LogEvent;
import com.google.cloud.tools.jib.filesystem.FileOperations;
import com.google.cloud.tools.jib.image.Image;
Expand Down Expand Up @@ -103,8 +103,7 @@ private BuildResult writeTarFile() throws ExecutionException, IOException {
Files.createDirectories(outputPath.getParent());
try (OutputStream outputStream =
new BufferedOutputStream(FileOperations.newLockingOutputStream(outputPath))) {
new ImageToTarballTranslator(image)
.toTarballBlob(buildConfiguration.getTargetImageConfiguration().getImage())
new ImageTarball(image, buildConfiguration.getTargetImageConfiguration().getImage())
.writeTo(outputStream);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.google.cloud.tools.jib.docker;

import com.google.cloud.tools.jib.blob.Blob;
import com.google.cloud.tools.jib.image.ImageReference;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
Expand Down Expand Up @@ -164,18 +163,18 @@ public static boolean isDockerInstalled(Path dockerExecutable) {
*
* @see <a
* href="https://docs.docker.com/engine/reference/commandline/load/">https://docs.docker.com/engine/reference/commandline/load</a>
* @param imageTarballBlob the built container tarball.
* @param imageTarball the built container tarball.
* @return stdout from {@code docker}.
* @throws InterruptedException if the 'docker load' process is interrupted.
* @throws IOException if streaming the blob to 'docker load' fails.
*/
public String load(Blob imageTarballBlob) throws InterruptedException, IOException {
public String load(ImageTarball imageTarball) throws InterruptedException, IOException {
// Runs 'docker load'.
Process dockerProcess = docker("load");

try (OutputStream stdin = dockerProcess.getOutputStream()) {
try {
imageTarballBlob.writeTo(stdin);
imageTarball.writeTo(stdin);

} catch (IOException ex) {
// Tries to read from stderr.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@
import com.google.cloud.tools.jib.json.JsonTemplateMapper;
import com.google.cloud.tools.jib.tar.TarStreamBuilder;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;

/** Translates an {@link Image} to a tarball that can be loaded into Docker. */
public class ImageToTarballTranslator {
public class ImageTarball {

/** File name for the container configuration in the tarball. */
private static final String CONTAINER_CONFIGURATION_JSON_FILE_NAME = "config.json";
Expand All @@ -42,16 +43,20 @@ public class ImageToTarballTranslator {

private final Image<Layer> image;

private final ImageReference imageReference;

/**
* Instantiate with an {@link Image}.
*
* @param image the image to convert into a tarball
* @param imageReference image reference to set in the manifest
*/
public ImageToTarballTranslator(Image<Layer> image) {
public ImageTarball(Image<Layer> image, ImageReference imageReference) {
this.image = image;
this.imageReference = imageReference;
}

public Blob toTarballBlob(ImageReference imageReference) throws IOException {
public void writeTo(OutputStream out) throws IOException {
TarStreamBuilder tarStreamBuilder = new TarStreamBuilder();
DockerLoadManifestEntryTemplate manifestTemplate = new DockerLoadManifestEntryTemplate();

Expand All @@ -77,6 +82,6 @@ public Blob toTarballBlob(ImageReference imageReference) throws IOException {
JsonTemplateMapper.toBlob(Collections.singletonList(manifestTemplate))),
MANIFEST_JSON_FILE_NAME);

return tarStreamBuilder.toBlob();
tarStreamBuilder.writeAsTarArchiveTo(out);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.google.cloud.tools.jib.image;

import com.google.cloud.tools.jib.blob.Blob;
import com.google.cloud.tools.jib.blob.Blobs;
import com.google.cloud.tools.jib.tar.TarStreamBuilder;
import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList;
Expand Down Expand Up @@ -132,6 +133,6 @@ public Blob build() {
tarStreamBuilder.addTarArchiveEntry(entry);
}

return tarStreamBuilder.toBlob();
return Blobs.from(outputStream -> tarStreamBuilder.writeAsTarArchiveTo(outputStream));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ public class TarStreamBuilder {
/**
* Writes each entry in the filesystem to the tarball archive stream.
*
* @param tarByteStream the stream to write to.
* @param out the stream to write to.
* @throws IOException if building the tarball fails.
*/
private void writeEntriesAsTarArchive(OutputStream tarByteStream) throws IOException {
public void writeAsTarArchiveTo(OutputStream out) throws IOException {
try (TarArchiveOutputStream tarArchiveOutputStream =
new TarArchiveOutputStream(tarByteStream, StandardCharsets.UTF_8.name())) {
new TarArchiveOutputStream(out, StandardCharsets.UTF_8.name())) {
// Enables PAX extended headers to support long file names.
tarArchiveOutputStream.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
for (Map.Entry<TarArchiveEntry, Blob> entry : archiveMap.entrySet()) {
Expand Down Expand Up @@ -90,9 +90,4 @@ public void addBlobEntry(Blob blob, long size, String name) {
entry.setSize(size);
archiveMap.put(entry, blob);
}

/** @return a new {@link Blob} that can stream the uncompressed tarball archive BLOB. */
public Blob toBlob() {
return Blobs.from(this::writeEntriesAsTarArchive);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.google.cloud.tools.jib.docker;

import com.google.cloud.tools.jib.blob.Blobs;
import com.google.cloud.tools.jib.image.ImageReference;
import com.google.cloud.tools.jib.image.InvalidImageReferenceException;
import com.google.common.collect.ImmutableMap;
Expand All @@ -38,22 +37,32 @@
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.AdditionalAnswers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.VoidAnswer1;

/** Tests for {@link DockerClient}. */
@RunWith(MockitoJUnitRunner.class)
public class DockerClientTest {

@Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
@Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder();

@Mock private ProcessBuilder mockProcessBuilder;
@Mock private Process mockProcess;
@Mock private ImageTarball imageTarball;

@Before
public void setUp() throws IOException {
Mockito.when(mockProcessBuilder.start()).thenReturn(mockProcess);

Mockito.doAnswer(
AdditionalAnswers.answerVoid(
(VoidAnswer1<OutputStream>)
out -> out.write("jib".getBytes(StandardCharsets.UTF_8))))
.when(imageTarball)
.writeTo(Mockito.any(OutputStream.class));
}

@Test
Expand All @@ -79,7 +88,7 @@ public void testLoad() throws IOException, InterruptedException {
Mockito.when(mockProcess.getInputStream())
.thenReturn(new ByteArrayInputStream("output".getBytes(StandardCharsets.UTF_8)));

String output = testDockerClient.load(Blobs.from("jib"));
String output = testDockerClient.load(imageTarball);

Assert.assertEquals(
"jib", new String(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8));
Expand All @@ -103,7 +112,7 @@ public void write(int b) throws IOException {
.thenReturn(new ByteArrayInputStream("error".getBytes(StandardCharsets.UTF_8)));

try {
testDockerClient.load(Blobs.from("jib"));
testDockerClient.load(imageTarball);
Assert.fail("Write should have failed");

} catch (IOException ex) {
Expand Down Expand Up @@ -136,7 +145,7 @@ public int read() throws IOException {
});

try {
testDockerClient.load(Blobs.from("jib"));
testDockerClient.load(imageTarball);
Assert.fail("Write should have failed");

} catch (IOException ex) {
Expand All @@ -156,7 +165,7 @@ public void testLoad_stdoutFail() throws InterruptedException {
.thenReturn(new ByteArrayInputStream("error".getBytes(StandardCharsets.UTF_8)));

try {
testDockerClient.load(Blobs.from("jib"));
testDockerClient.load(imageTarball);
Assert.fail("Process should have failed");

} catch (IOException ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.google.cloud.tools.jib.docker;

import com.google.cloud.tools.jib.blob.Blob;
import com.google.cloud.tools.jib.blob.BlobDescriptor;
import com.google.cloud.tools.jib.blob.Blobs;
import com.google.cloud.tools.jib.docker.json.DockerLoadManifestEntryTemplate;
Expand All @@ -32,6 +31,7 @@
import com.google.common.io.CharStreams;
import com.google.common.io.Resources;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
Expand All @@ -49,15 +49,15 @@
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

/** Tests for {@link ImageToTarballTranslator}. */
/** Tests for {@link ImageTarball}. */
@RunWith(MockitoJUnitRunner.class)
public class ImageToTarballTranslatorTest {
public class ImageTarballTest {

@Mock private Layer mockLayer1;
@Mock private Layer mockLayer2;

@Test
public void testToTarballBlob()
public void testWriteTo()
throws InvalidImageReferenceException, IOException, URISyntaxException,
LayerPropertyNotFoundException, DigestException {
Path fileA = Paths.get(Resources.getResource("core/fileA").toURI());
Expand All @@ -83,13 +83,13 @@ public void testToTarballBlob()
Image<Layer> testImage =
Image.builder(V22ManifestTemplate.class).addLayer(mockLayer1).addLayer(mockLayer2).build();

Blob tarballBlob =
new ImageToTarballTranslator(testImage).toTarballBlob(ImageReference.parse("my/image:tag"));
ImageTarball imageToTarball = new ImageTarball(testImage, ImageReference.parse("my/image:tag"));

ByteArrayOutputStream out = new ByteArrayOutputStream();
imageToTarball.writeTo(out);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
try (TarArchiveInputStream tarArchiveInputStream = new TarArchiveInputStream(in)) {

try (ByteArrayInputStream tarballBytesStream =
new ByteArrayInputStream(Blobs.writeToByteArray(tarballBlob));
TarArchiveInputStream tarArchiveInputStream =
new TarArchiveInputStream(tarballBytesStream)) {
// Verifies layer with fileA was added.
TarArchiveEntry headerFileALayer = tarArchiveInputStream.getNextTarEntry();
Assert.assertEquals(fakeDigestA.getHash() + ".tar.gz", headerFileALayer.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.google.cloud.tools.jib.tar;

import com.google.cloud.tools.jib.blob.Blob;
import com.google.cloud.tools.jib.blob.Blobs;
import com.google.common.io.ByteStreams;
import com.google.common.io.Resources;
Expand Down Expand Up @@ -101,12 +100,11 @@ public void testToBlob_multiByte() throws IOException {
testTarStreamBuilder.addByteEntry("asdf".getBytes(StandardCharsets.UTF_8), "crepecake");
testTarStreamBuilder.addBlobEntry(
Blobs.from("jib"), "jib".getBytes(StandardCharsets.UTF_8).length, "jib");
Blob blob = testTarStreamBuilder.toBlob();

// Writes the BLOB and captures the output.
ByteArrayOutputStream tarByteOutputStream = new ByteArrayOutputStream();
OutputStream compressorStream = new GZIPOutputStream(tarByteOutputStream);
blob.writeTo(compressorStream);
testTarStreamBuilder.writeAsTarArchiveTo(compressorStream);

// Rearrange the output into input for verification.
ByteArrayInputStream byteArrayInputStream =
Expand Down Expand Up @@ -173,12 +171,10 @@ private void setUpWithStringsAndTarEntries() {

/** Creates a compressed blob from the TarStreamBuilder and verifies it. */
private void verifyBlobWithCompression() throws IOException {
Blob blob = testTarStreamBuilder.toBlob();

// Writes the BLOB and captures the output.
ByteArrayOutputStream tarByteOutputStream = new ByteArrayOutputStream();
OutputStream compressorStream = new GZIPOutputStream(tarByteOutputStream);
blob.writeTo(compressorStream);
testTarStreamBuilder.writeAsTarArchiveTo(compressorStream);

// Rearrange the output into input for verification.
ByteArrayInputStream byteArrayInputStream =
Expand All @@ -190,11 +186,9 @@ private void verifyBlobWithCompression() throws IOException {

/** Creates an uncompressed blob from the TarStreamBuilder and verifies it. */
private void verifyBlobWithoutCompression() throws IOException {
Blob blob = testTarStreamBuilder.toBlob();

// Writes the BLOB and captures the output.
ByteArrayOutputStream tarByteOutputStream = new ByteArrayOutputStream();
blob.writeTo(tarByteOutputStream);
testTarStreamBuilder.writeAsTarArchiveTo(tarByteOutputStream);

// Rearrange the output into input for verification.
ByteArrayInputStream byteArrayInputStream =
Expand Down