Skip to content

Commit

Permalink
Add imagePushed field to jib-image.json (#3641)
Browse files Browse the repository at this point in the history
* Add imagePushed field to jib-image.json to note registry push when jib.skipExistingImages option is in use.

Co-authored-by: Mridula Peddada <mpeddada@google.com>
  • Loading branch information
wwadge and mpeddada1 committed May 26, 2022
1 parent 6df635e commit 7cdc78c
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 27 deletions.
Expand Up @@ -270,6 +270,10 @@ public void testSteps_forBuildToDockerRegistry_skipExistingDigest()
// Test that both images have the same properties.
Assert.assertEquals(image1.getDigest(), image2.getDigest());
Assert.assertEquals(image1.getImageId(), image2.getImageId());

// Test that the first image was pushed while the second one was skipped
Assert.assertTrue(image1.isImagePushed());
Assert.assertFalse(image2.isImagePushed());
}

@Test
Expand Down
Expand Up @@ -29,25 +29,28 @@ public class JibContainer {
private final DescriptorDigest imageDigest;
private final DescriptorDigest imageId;
private final Set<String> tags;
private final boolean imagePushed;

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

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);
return new JibContainer(targetImage, imageDigest, imageId, tags, buildResult.isImagePushed());
}

/**
Expand All @@ -59,6 +62,15 @@ public ImageReference getTargetImage() {
return targetImage;
}

/**
* Returns true if we pushed this image all the way to a registry.
*
* @return true if pushed.
*/
public boolean isImagePushed() {
return imagePushed;
}

/**
* Gets the digest of the registry image manifest built by Jib. This digest can be used to fetch a
* specific image from the registry in the form {@code myregistry/myimage@digest}.
Expand Down Expand Up @@ -89,7 +101,7 @@ public Set<String> getTags() {

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

@Override
Expand All @@ -104,6 +116,7 @@ public boolean equals(Object other) {
return targetImage.equals(otherContainer.targetImage)
&& imageDigest.equals(otherContainer.imageDigest)
&& imageId.equals(otherContainer.imageId)
&& tags.equals(otherContainer.tags);
&& tags.equals(otherContainer.tags)
&& imagePushed == otherContainer.imagePushed;
}
}
Expand Up @@ -46,15 +46,17 @@ static BuildResult fromImage(Image image, Class<? extends BuildableManifestTempl
targetFormat, containerConfigurationBlobDescriptor);
DescriptorDigest imageDigest = Digests.computeJsonDigest(manifestTemplate);
DescriptorDigest imageId = containerConfigurationBlobDescriptor.getDigest();
return new BuildResult(imageDigest, imageId);
return new BuildResult(imageDigest, imageId, false);
}

private final DescriptorDigest imageDigest;
private final DescriptorDigest imageId;
private final Boolean imagePushed;

BuildResult(DescriptorDigest imageDigest, DescriptorDigest imageId) {
BuildResult(DescriptorDigest imageDigest, DescriptorDigest imageId, boolean imagePushed) {
this.imageDigest = imageDigest;
this.imageId = imageId;
this.imagePushed = imagePushed;
}

public DescriptorDigest getImageDigest() {
Expand All @@ -65,6 +67,10 @@ public DescriptorDigest getImageId() {
return imageId;
}

public boolean isImagePushed() {
return imagePushed;
}

@Override
public int hashCode() {
return Objects.hash(imageDigest, imageId);
Expand All @@ -80,6 +86,7 @@ public boolean equals(Object other) {
}
BuildResult otherBuildResult = (BuildResult) other;
return imageDigest.equals(otherBuildResult.imageDigest)
&& imageId.equals(otherBuildResult.imageId);
&& imageId.equals(otherBuildResult.imageId)
&& imagePushed.equals(otherBuildResult.imagePushed);
}
}
Expand Up @@ -180,7 +180,7 @@ public BuildResult call() throws IOException, RegistryException {
eventHandlers.dispatch(LogEvent.info("Pushing manifest for " + imageQualifier + "..."));

registryClient.pushManifest(manifestTemplate, imageQualifier);
return new BuildResult(imageDigest, imageId);
return new BuildResult(imageDigest, imageId, true);
}
}
}
Expand Up @@ -573,15 +573,23 @@ private Future<BuildResult> pushImage(
results.manifestCheckResult.get().isPresent()));

realizeFutures(manifestPushResults);

return manifestPushResults.isEmpty()
? new BuildResult(
results.manifestCheckResult.get().get().getDigest(),
Verify.verifyNotNull(containerConfigPushResult).get().getDigest())
Verify.verifyNotNull(containerConfigPushResult).get().getDigest(),
isImagePushed(results.manifestCheckResult.get()))
// Manifest pushers return the same BuildResult.
: manifestPushResults.get(0).get();
});
}

@VisibleForTesting
boolean isImagePushed(Optional<ManifestAndDigest<ManifestTemplate>> manifestResult) {

return !(JibSystemProperties.skipExistingImages() && manifestResult.isPresent());
}

private void pushManifestList(ProgressEventDispatcher.Factory progressDispatcherFactory) {
results.buildResult =
executorService.submit(
Expand Down
Expand Up @@ -16,6 +16,11 @@

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

import static org.mockito.Mockito.when;

import com.google.cloud.tools.jib.builder.steps.BuildResult;
import com.google.cloud.tools.jib.configuration.BuildContext;
import com.google.cloud.tools.jib.configuration.ImageConfiguration;
import com.google.common.collect.ImmutableSet;
import java.security.DigestException;
import java.util.Set;
Expand All @@ -24,6 +29,7 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.Mockito;

/** Tests for {@link JibContainer}. */
public class JibContainerTest {
Expand Down Expand Up @@ -53,56 +59,87 @@ public void setUp() throws DigestException, InvalidImageReferenceException {

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

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

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

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

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

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);
JibContainer container1 = new JibContainer(targetImage1, digest1, digest2, tags1, true);
JibContainer container2 = new JibContainer(targetImage1, digest2, digest2, tags1, true);

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);
JibContainer container1 = new JibContainer(targetImage1, digest1, digest1, tags1, true);
JibContainer container2 = new JibContainer(targetImage1, digest1, digest2, tags1, true);

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);
JibContainer container1 = new JibContainer(targetImage1, digest1, digest1, tags1, true);
JibContainer container2 = new JibContainer(targetImage1, digest1, digest1, tags2, true);

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

@Test
public void testEquality_differentImagePushed() {
JibContainer container1 = new JibContainer(targetImage1, digest1, digest1, tags1, true);
JibContainer container2 = new JibContainer(targetImage1, digest1, digest1, tags1, false);

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

@Test
public void testCreation_withBuildContextAndBuildResult() {
BuildResult buildResult = Mockito.mock(BuildResult.class);
BuildContext buildContext = Mockito.mock(BuildContext.class);
ImageConfiguration mockTargetConfiguration = Mockito.mock(ImageConfiguration.class);

when(buildResult.getImageDigest()).thenReturn(digest1);
when(buildResult.getImageId()).thenReturn(digest1);
when(buildResult.isImagePushed()).thenReturn(true);
when(mockTargetConfiguration.getImage()).thenReturn(targetImage1);
when(buildContext.getTargetImageConfiguration()).thenReturn(mockTargetConfiguration);
when(buildContext.getAllTargetImageTags()).thenReturn(ImmutableSet.copyOf(tags1));

JibContainer container = JibContainer.from(buildContext, buildResult);
Assert.assertEquals(targetImage1, container.getTargetImage());
Assert.assertEquals(digest1, container.getDigest());
Assert.assertEquals(digest1, container.getImageId());
Assert.assertEquals(tags1, container.getTags());
Assert.assertTrue(container.isImagePushed());
}
}
Expand Up @@ -31,6 +31,7 @@ public class BuildResultTest {
private DescriptorDigest digest1;
private DescriptorDigest digest2;
private DescriptorDigest id;
private DescriptorDigest id2;

@Before
public void setUp() throws DigestException {
Expand All @@ -43,24 +44,37 @@ public void setUp() throws DigestException {
id =
DescriptorDigest.fromDigest(
"sha256:9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba");

id2 =
DescriptorDigest.fromDigest(
"sha256:1234543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba");
}

@Test
public void testCreated() {
BuildResult container = new BuildResult(digest1, id);
BuildResult container = new BuildResult(digest1, id, true);
Assert.assertEquals(digest1, container.getImageDigest());
Assert.assertEquals(id, container.getImageId());
Assert.assertTrue(container.isImagePushed());
}

@Test
public void testEquality() {
BuildResult container1 = new BuildResult(digest1, id);
BuildResult container2 = new BuildResult(digest1, id);
BuildResult container3 = new BuildResult(digest2, id);
BuildResult container1 = new BuildResult(digest1, id, true);
BuildResult container2 = new BuildResult(digest1, id, true);
BuildResult container3 = new BuildResult(digest2, id, true);
BuildResult container4 = new BuildResult(digest1, id, false);
BuildResult container5 = new BuildResult(digest1, id2, false);

Assert.assertEquals(container1, container2);
Assert.assertEquals(container1, container1);
Assert.assertNotEquals(container1, container5);
Assert.assertNotEquals(container1, new Object());

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

@Test
Expand Down
Expand Up @@ -20,8 +20,11 @@
import com.google.cloud.tools.jib.builder.ProgressEventDispatcher;
import com.google.cloud.tools.jib.builder.steps.PullBaseImageStep.ImagesAndRegistryClient;
import com.google.cloud.tools.jib.configuration.BuildContext;
import com.google.cloud.tools.jib.global.JibSystemProperties;
import com.google.cloud.tools.jib.image.DigestOnlyLayer;
import com.google.cloud.tools.jib.image.Image;
import com.google.cloud.tools.jib.image.json.ManifestTemplate;
import com.google.cloud.tools.jib.registry.ManifestAndDigest;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ForwardingExecutorService;
import com.google.common.util.concurrent.Futures;
Expand All @@ -30,6 +33,7 @@
import java.security.DigestException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
Expand Down Expand Up @@ -148,4 +152,30 @@ public void testObtainBaseImageLayers_skipObtainingDuplicateLayers()
Mockito.verify(executorService, Mockito.times(3))
.submit(Mockito.any(ObtainBaseImageLayerStep.class));
}

@Test
public void testIsImagePushed_skipExistingEnabledAndManifestPresent() {
Optional<ManifestAndDigest<ManifestTemplate>> manifestResult = Mockito.mock(Optional.class);
Mockito.when(manifestResult.isPresent()).thenReturn(true);
System.setProperty(JibSystemProperties.SKIP_EXISTING_IMAGES, "true");

Assert.assertFalse(stepsRunner.isImagePushed(manifestResult));
}

@Test
public void testIsImagePushed_skipExistingImageDisabledAndManifestPresent() {
Optional<ManifestAndDigest<ManifestTemplate>> manifestResult = Mockito.mock(Optional.class);
System.setProperty(JibSystemProperties.SKIP_EXISTING_IMAGES, "false");

Assert.assertTrue(stepsRunner.isImagePushed(manifestResult));
}

@Test
public void testIsImagePushed_skipExistingImageEnabledAndManifestNotPresent() {
Optional<ManifestAndDigest<ManifestTemplate>> manifestResult = Mockito.mock(Optional.class);
System.setProperty(JibSystemProperties.SKIP_EXISTING_IMAGES, "true");
Mockito.when(manifestResult.isPresent()).thenReturn(false);

Assert.assertTrue(stepsRunner.isImagePushed(manifestResult));
}
}

0 comments on commit 7cdc78c

Please sign in to comment.