Skip to content

Commit

Permalink
Write out the image metadata to a file after build (#2227)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbruggmann authored and briandealwis committed Jan 21, 2020
1 parent eeddc9e commit 9b194da
Show file tree
Hide file tree
Showing 20 changed files with 417 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.google.cloud.tools.jib.registry.RegistryAliasGroup;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -347,4 +348,23 @@ public String toString() {
public String toStringWithTag() {
return toString() + (usesDefaultTag() ? ":" + DEFAULT_TAG : "");
}

@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof ImageReference)) {
return false;
}
ImageReference otherImageReference = (ImageReference) other;
return registry.equals(otherImageReference.registry)
&& repository.equals(otherImageReference.repository)
&& tag.equals(otherImageReference.tag);
}

@Override
public int hashCode() {
return Objects.hash(registry, repository, tag);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,47 @@

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

import com.google.cloud.tools.jib.builder.steps.BuildResult;
import com.google.cloud.tools.jib.configuration.BuildContext;
import com.google.common.annotations.VisibleForTesting;
import java.util.Objects;
import java.util.Set;

/** The container built by Jib. */
public class JibContainer {

private final ImageReference targetImage;
private final DescriptorDigest imageDigest;
private final DescriptorDigest imageId;
private final Set<String> tags;

JibContainer(DescriptorDigest imageDigest, DescriptorDigest imageId) {
@VisibleForTesting
JibContainer(
ImageReference targetImage,
DescriptorDigest imageDigest,
DescriptorDigest imageId,
Set<String> tags) {
this.targetImage = targetImage;
this.imageDigest = imageDigest;
this.imageId = imageId;
this.tags = tags;
}

static JibContainer from(BuildContext buildContext, BuildResult buildResult) {
ImageReference targetImage = buildContext.getTargetImageConfiguration().getImage();
DescriptorDigest imageDigest = buildResult.getImageDigest();
DescriptorDigest imageId = buildResult.getImageId();
Set<String> tags = buildContext.getAllTargetImageTags();
return new JibContainer(targetImage, imageDigest, imageId, tags);
}

/**
* Get the target image that was built.
*
* @return the target image reference.
*/
public ImageReference getTargetImage() {
return targetImage;
}

/**
Expand All @@ -48,9 +78,18 @@ public DescriptorDigest getImageId() {
return imageId;
}

/**
* Get the tags applied to the container.
*
* @return the set of all tags
*/
public Set<String> getTags() {
return tags;
}

@Override
public int hashCode() {
return Objects.hash(imageDigest, imageId);
return Objects.hash(targetImage, imageDigest, imageId, tags);
}

@Override
Expand All @@ -62,6 +101,9 @@ public boolean equals(Object other) {
return false;
}
JibContainer otherContainer = (JibContainer) other;
return imageDigest.equals(otherContainer.imageDigest) && imageId.equals(otherContainer.imageId);
return targetImage.equals(otherContainer.targetImage)
&& imageDigest.equals(otherContainer.imageDigest)
&& imageId.equals(otherContainer.imageId)
&& tags.equals(otherContainer.tags);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,8 @@ public JibContainer containerize(Containerizer containerizer)
buildContext.getEventHandlers(), containerizer.getDescription())) {
logSources(buildContext.getEventHandlers());

BuildResult result = containerizer.run(buildContext);
return new JibContainer(result.getImageDigest(), result.getImageId());
BuildResult buildResult = containerizer.run(buildContext);
return JibContainer.from(buildContext, buildResult);

} catch (ExecutionException ex) {
// If an ExecutionException occurs, re-throw the cause to be more easily handled by the user
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,42 @@ public void testGetRegistry() {
Assert.assertEquals("gcr.io", ImageReference.of("gcr.io", "someimage", null).getRegistry());
}

@Test
public void testEquality() throws InvalidImageReferenceException {
ImageReference image1 = ImageReference.parse("gcr.io/project/image:tag");
ImageReference image2 = ImageReference.parse("gcr.io/project/image:tag");

Assert.assertEquals(image1, image2);
Assert.assertEquals(image1.hashCode(), image2.hashCode());
}

@Test
public void testEquality_differentRegistry() throws InvalidImageReferenceException {
ImageReference image1 = ImageReference.parse("gcr.io/project/image:tag");
ImageReference image2 = ImageReference.parse("registry-1.docker.io/project/image:tag");

Assert.assertNotEquals(image1, image2);
Assert.assertNotEquals(image1.hashCode(), image2.hashCode());
}

@Test
public void testEquality_differentRepository() throws InvalidImageReferenceException {
ImageReference image1 = ImageReference.parse("gcr.io/project/image:tag");
ImageReference image2 = ImageReference.parse("gcr.io/project2/image:tag");

Assert.assertNotEquals(image1, image2);
Assert.assertNotEquals(image1.hashCode(), image2.hashCode());
}

@Test
public void testEquality_differentTag() throws InvalidImageReferenceException {
ImageReference image1 = ImageReference.parse("gcr.io/project/image:tag1");
ImageReference image2 = ImageReference.parse("gcr.io/project/image:tag2");

Assert.assertNotEquals(image1, image2);
Assert.assertNotEquals(image1.hashCode(), image2.hashCode());
}

private void verifyParse(String registry, String repository, String tagSeparator, String tag)
throws InvalidImageReferenceException {
// Gets the expected parsed components.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

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

import com.google.common.collect.ImmutableSet;
import java.security.DigestException;
import java.util.Set;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
Expand All @@ -28,39 +30,79 @@ public class JibContainerTest {

@Rule public TemporaryFolder temporaryDirectory = new TemporaryFolder();

private ImageReference targetImage1;
private ImageReference targetImage2;
private DescriptorDigest digest1;
private DescriptorDigest digest2;
private DescriptorDigest digest3;
private Set<String> tags1;
private Set<String> tags2;

@Before
public void setUp() throws DigestException {
public void setUp() throws DigestException, InvalidImageReferenceException {
targetImage1 = ImageReference.parse("gcr.io/project/image:tag");
targetImage2 = ImageReference.parse("gcr.io/project/image:tag2");
digest1 =
DescriptorDigest.fromDigest(
"sha256:abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789");
digest2 =
DescriptorDigest.fromDigest(
"sha256:9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba");
digest3 =
DescriptorDigest.fromDigest(
"sha256:fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210");
tags1 = ImmutableSet.of("latest", "custom-tag");
tags2 = ImmutableSet.of("latest");
}

@Test
public void testCreation() {
JibContainer container = new JibContainer(digest1, digest2);
JibContainer container = new JibContainer(targetImage1, digest1, digest2, tags1);

Assert.assertEquals(targetImage1, container.getTargetImage());
Assert.assertEquals(digest1, container.getDigest());
Assert.assertEquals(digest2, container.getImageId());
Assert.assertEquals(tags1, container.getTags());
}

@Test
public void testEquality() {
JibContainer container1 = new JibContainer(digest1, digest2);
JibContainer container2 = new JibContainer(digest1, digest2);
JibContainer container3 = new JibContainer(digest2, digest3);
JibContainer container1 = new JibContainer(targetImage1, digest1, digest2, tags1);
JibContainer container2 = new JibContainer(targetImage1, digest1, digest2, tags1);

Assert.assertEquals(container1, container2);
Assert.assertEquals(container1.hashCode(), container2.hashCode());
Assert.assertNotEquals(container1, container3);
}

@Test
public void testEquality_differentTargetImage() {
JibContainer container1 = new JibContainer(targetImage1, digest1, digest2, tags1);
JibContainer container2 = new JibContainer(targetImage2, digest1, digest2, tags1);

Assert.assertNotEquals(container1, container2);
Assert.assertNotEquals(container1.hashCode(), container2.hashCode());
}

@Test
public void testEquality_differentImageDigest() {
JibContainer container1 = new JibContainer(targetImage1, digest1, digest2, tags1);
JibContainer container2 = new JibContainer(targetImage1, digest2, digest2, tags1);

Assert.assertNotEquals(container1, container2);
Assert.assertNotEquals(container1.hashCode(), container2.hashCode());
}

@Test
public void testEquality_differentImageId() {
JibContainer container1 = new JibContainer(targetImage1, digest1, digest1, tags1);
JibContainer container2 = new JibContainer(targetImage1, digest1, digest2, tags1);

Assert.assertNotEquals(container1, container2);
Assert.assertNotEquals(container1.hashCode(), container2.hashCode());
}

@Test
public void testEquality_differentTags() {
JibContainer container1 = new JibContainer(targetImage1, digest1, digest1, tags1);
JibContainer container2 = new JibContainer(targetImage1, digest1, digest1, tags2);

Assert.assertNotEquals(container1, container2);
Assert.assertNotEquals(container1.hashCode(), container2.hashCode());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,9 @@ public Path getDigestOutputPath() {
public Path getImageIdOutputPath() {
return jibExtension.getOutputPaths().getImageIdPath();
}

@Override
public Path getImageJsonOutputPath() {
return jibExtension.getOutputPaths().getImageJsonPath();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ public class OutputPathsParameters {
private Path digest;
private Path tar;
private Path imageId;
private Path imageJson;

@Inject
public OutputPathsParameters(Project project) {
this.project = project;
digest = project.getBuildDir().toPath().resolve("jib-image.digest");
imageId = project.getBuildDir().toPath().resolve("jib-image.id");
imageJson = project.getBuildDir().toPath().resolve("jib-image.json");
tar = project.getBuildDir().toPath().resolve("jib-image.tar");
}

Expand Down Expand Up @@ -69,6 +71,20 @@ public void setImageId(String id) {
this.imageId = Paths.get(id);
}

@Input
public String getImageJson() {
return getRelativeToProjectRoot(imageJson, PropertyNames.OUTPUT_PATHS_IMAGE_JSON).toString();
}

@Internal
Path getImageJsonPath() {
return getRelativeToProjectRoot(imageJson, PropertyNames.OUTPUT_PATHS_IMAGE_JSON);
}

public void setImageJson(String imageJson) {
this.imageJson = Paths.get(imageJson);
}

@Input
public String getTar() {
return getRelativeToProjectRoot(tar, PropertyNames.OUTPUT_PATHS_TAR).toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public void testGetters() {

Mockito.when(outputPathsParameters.getDigestPath()).thenReturn(Paths.get("digest/path"));
Mockito.when(outputPathsParameters.getImageIdPath()).thenReturn(Paths.get("id/path"));
Mockito.when(outputPathsParameters.getImageJsonPath()).thenReturn(Paths.get("json/path"));
Mockito.when(outputPathsParameters.getTarPath()).thenReturn(Paths.get("tar/path"));

GradleRawConfiguration rawConfiguration = new GradleRawConfiguration(jibExtension);
Expand Down Expand Up @@ -115,6 +116,7 @@ public void testGetters() {
rawConfiguration.getDockerEnvironment());
Assert.assertEquals(Paths.get("digest/path"), rawConfiguration.getDigestOutputPath());
Assert.assertEquals(Paths.get("id/path"), rawConfiguration.getImageIdOutputPath());
Assert.assertEquals(Paths.get("json/path"), rawConfiguration.getImageJsonOutputPath());
Assert.assertEquals(Paths.get("tar/path"), rawConfiguration.getTarOutputPath());
}
}
1 change: 1 addition & 0 deletions jib-maven-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ Property | Type | Default | Description
`tar` | string | `(project-dir)/target/jib-image.tar` | The path of the tarball generated by `jib:buildTar`. Relative paths are resolved relative to the project root.
`digest` | string | `(project-dir)/target/jib-image.digest` | The path of the image digest written out during the build. Relative paths are resolved relative to the project root.
`imageId` | string | `(project-dir)/target/jib-image.id` | The path of the image ID written out during the build. Relative paths are resolved relative to the project root.
`imageJson` | string | `(project-dir)/target/jib-image.json` | The path of the image metadata json file written out during the build. Relative paths are resolved relative to the project root.

<a name="dockerclient-object"></a>`dockerClient` is an object used to configure Docker when building to/from the Docker daemon. It has the following properties:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ public static class OutputPathsParameters {
@Nullable @Parameter private File digest;

@Nullable @Parameter private File imageId;

@Nullable @Parameter private File imageJson;
}

@Nullable
Expand Down Expand Up @@ -625,6 +627,14 @@ Path getImageIdOutputPath() {
return getRelativeToProjectRoot(configuredPath, PropertyNames.OUTPUT_PATHS_IMAGE_ID);
}

Path getImageJsonOutputPath() {
Path configuredPath =
outputPaths.imageJson == null
? Paths.get(getProject().getBuild().getDirectory()).resolve("jib-image.json")
: outputPaths.imageJson.toPath();
return getRelativeToProjectRoot(configuredPath, PropertyNames.OUTPUT_PATHS_IMAGE_JSON);
}

private Path getRelativeToProjectRoot(Path configuration, String propertyName) {
String property = getProperty(propertyName);
Path path = property != null ? Paths.get(property) : configuration;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,9 @@ public Path getDigestOutputPath() {
public Path getImageIdOutputPath() {
return jibPluginConfiguration.getImageIdOutputPath();
}

@Override
public Path getImageJsonOutputPath() {
return jibPluginConfiguration.getImageJsonOutputPath();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ public void testSystemProperties() {
sessionProperties.put("jib.outputPaths.imageId", "id/path");
Assert.assertEquals(
Paths.get("/repository/project/id/path"), testPluginConfiguration.getImageIdOutputPath());
sessionProperties.put("jib.outputPaths.imageJson", "json/path");
Assert.assertEquals(
Paths.get("/repository/project/json/path"),
testPluginConfiguration.getImageJsonOutputPath());
sessionProperties.put("jib.outputPaths.tar", "tar/path");
Assert.assertEquals(
Paths.get("/repository/project/tar/path"), testPluginConfiguration.getTarOutputPath());
Expand Down Expand Up @@ -258,6 +262,8 @@ public void testPomProperties() {
Assert.assertEquals(Paths.get("/digest/path"), testPluginConfiguration.getDigestOutputPath());
project.getProperties().setProperty("jib.outputPaths.imageId", "/id/path");
Assert.assertEquals(Paths.get("/id/path"), testPluginConfiguration.getImageIdOutputPath());
project.getProperties().setProperty("jib.outputPaths.imageJson", "/json/path");
Assert.assertEquals(Paths.get("/json/path"), testPluginConfiguration.getImageJsonOutputPath());
project.getProperties().setProperty("jib.outputPaths.tar", "tar/path");
Assert.assertEquals(
Paths.get("/repository/project/tar/path"), testPluginConfiguration.getTarOutputPath());
Expand Down
Loading

0 comments on commit 9b194da

Please sign in to comment.