Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -147,6 +147,15 @@ public Image call() throws LayerPropertyNotFoundException {
imageBuilder.setWorkingDirectory(containerConfiguration.getWorkingDirectory().toString());
}

// Set base image reference and digest for OCI annotations.
if (buildContext.getBaseImageConfiguration() != null
&& buildContext.getBaseImageConfiguration().getImage() != null
&& !buildContext.getBaseImageConfiguration().getImage().isScratch()) {
imageBuilder.setBaseImageName(
buildContext.getBaseImageConfiguration().getImage().toString());
imageBuilder.setBaseImageDigest(baseImage.getBaseImageDigest());
}

// Gets the container configuration content descriptor.
return imageBuilder.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,11 +297,16 @@ private List<Image> pullBaseImages(
ProgressEventDispatcher.Factory childProgressDispatcherFactory =
progressDispatcher1.newChildProducer();

String baseImageDigest =
manifestAndDigest.getDigest() != null ? manifestAndDigest.getDigest().toString() : null;

ManifestTemplate manifestTemplate = manifestAndDigest.getManifest();
if (manifestTemplate instanceof V21ManifestTemplate) {
V21ManifestTemplate v21Manifest = (V21ManifestTemplate) manifestTemplate;
cache.writeMetadata(baseImageConfig.getImage(), v21Manifest);
return Collections.singletonList(JsonToImageTranslator.toImage(v21Manifest));
Image image = JsonToImageTranslator.toImage(v21Manifest);
image.setBaseImageDigest(baseImageDigest);
return Collections.singletonList(image);

} else if (manifestTemplate instanceof BuildableManifestTemplate) {
// V22ManifestTemplate or OciManifestTemplate
Expand All @@ -311,8 +316,9 @@ private List<Image> pullBaseImages(
manifestAndDigest, registryClient, childProgressDispatcherFactory);
PlatformChecker.checkManifestPlatform(buildContext, containerConfig);
cache.writeMetadata(baseImageConfig.getImage(), imageManifest, containerConfig);
return Collections.singletonList(
JsonToImageTranslator.toImage(imageManifest, containerConfig));
Image image = JsonToImageTranslator.toImage(imageManifest, containerConfig);
image.setBaseImageDigest(baseImageDigest);
return Collections.singletonList(image);
}

Verify.verify(manifestTemplate instanceof ManifestListTemplate);
Expand Down Expand Up @@ -344,7 +350,9 @@ private List<Image> pullBaseImages(

manifestsAndConfigs.add(
new ManifestAndConfigTemplate(imageManifest, containerConfig, manifestDigest));
images.add(JsonToImageTranslator.toImage(imageManifest, containerConfig));
Image image = JsonToImageTranslator.toImage(imageManifest, containerConfig);
image.setBaseImageDigest(manifestDigest);
images.add(image);
}
}

Expand Down
70 changes: 68 additions & 2 deletions jib-core/src/main/java/com/google/cloud/tools/jib/image/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public static class Builder {
@Nullable private DockerHealthCheck healthCheck;
@Nullable private String workingDirectory;
@Nullable private String user;
@Nullable private String baseImageName;
@Nullable private String baseImageDigest;

private Builder(Class<? extends ManifestTemplate> imageFormat) {
this.imageFormat = imageFormat;
Expand Down Expand Up @@ -250,6 +252,28 @@ public Builder addHistory(HistoryEntry history) {
return this;
}

/**
* Sets the base image name (reference) used to build this image.
*
* @param baseImageName the base image reference string
* @return this
*/
public Builder setBaseImageName(@Nullable String baseImageName) {
this.baseImageName = baseImageName;
return this;
}

/**
* Sets the base image digest.
*
* @param baseImageDigest the base image digest string
* @return this
*/
public Builder setBaseImageDigest(@Nullable String baseImageDigest) {
this.baseImageDigest = baseImageDigest;
return this;
}

/**
* Create an {@link Image} instance.
*
Expand All @@ -271,7 +295,9 @@ public Image build() {
ImmutableSet.copyOf(volumesBuilder),
ImmutableMap.copyOf(labelsBuilder),
workingDirectory,
user);
user,
baseImageName,
baseImageDigest);
}
}

Expand Down Expand Up @@ -324,6 +350,12 @@ public static Builder builder(Class<? extends ManifestTemplate> imageFormat) {
/** User on the container configuration. */
@Nullable private final String user;

/** The base image name (reference) used to build this image. */
@Nullable private final String baseImageName;

/** The base image digest. */
@Nullable private String baseImageDigest;

private Image(
Class<? extends ManifestTemplate> imageFormat,
@Nullable Instant created,
Expand All @@ -339,7 +371,9 @@ private Image(
@Nullable ImmutableSet<AbsoluteUnixPath> volumes,
@Nullable ImmutableMap<String, String> labels,
@Nullable String workingDirectory,
@Nullable String user) {
@Nullable String user,
@Nullable String baseImageName,
@Nullable String baseImageDigest) {
this.imageFormat = imageFormat;
this.created = created;
this.architecture = architecture;
Expand All @@ -355,6 +389,8 @@ private Image(
this.labels = labels;
this.workingDirectory = workingDirectory;
this.user = user;
this.baseImageName = baseImageName;
this.baseImageDigest = baseImageDigest;
}

public Class<? extends ManifestTemplate> getImageFormat() {
Expand Down Expand Up @@ -426,4 +462,34 @@ public ImmutableList<Layer> getLayers() {
public ImmutableList<HistoryEntry> getHistory() {
return history;
}

/**
* Returns the base image name (reference) used to build this image.
*
* @return the base image name, or {@code null} if not set
*/
@Nullable
public String getBaseImageName() {
return baseImageName;
}

/**
* Returns the base image digest.
*
* @return the base image digest, or {@code null} if not set
*/
@Nullable
public String getBaseImageDigest() {
return baseImageDigest;
}

/**
* Sets the base image digest. This is set after image construction when the digest becomes
* available from the registry pull.
*
* @param baseImageDigest the base image digest string
*/
public void setBaseImageDigest(@Nullable String baseImageDigest) {
this.baseImageDigest = baseImageDigest;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,18 @@ public <T extends BuildableManifestTemplate> T getManifestTemplate(
layer.getBlobDescriptor().getSize(), layer.getBlobDescriptor().getDigest());
}

// Adds OCI base image annotations if the target format is OCI.
if (template instanceof OciManifestTemplate) {
OciManifestTemplate ociTemplate = (OciManifestTemplate) template;
if (image.getBaseImageName() != null) {
ociTemplate.addAnnotation("org.opencontainers.image.base.name", image.getBaseImageName());
}
if (image.getBaseImageDigest() != null) {
ociTemplate.addAnnotation(
"org.opencontainers.image.base.digest", image.getBaseImageDigest());
}
}

return template;

} catch (InstantiationException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
package com.google.cloud.tools.jib.image.json;

import com.google.cloud.tools.jib.api.DescriptorDigest;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/**
Expand Down Expand Up @@ -77,6 +80,9 @@ public class OciManifestTemplate implements BuildableManifestTemplate {
/** The list of layer references. */
private final List<ContentDescriptorTemplate> layers = new ArrayList<>();

/** The manifest-level annotations. */
@Nullable private Map<String, String> annotations;

@Override
public int getSchemaVersion() {
return schemaVersion;
Expand Down Expand Up @@ -107,4 +113,27 @@ public void setContainerConfiguration(long size, DescriptorDigest digest) {
public void addLayer(long size, DescriptorDigest digest) {
layers.add(new ContentDescriptorTemplate(LAYER_MEDIA_TYPE, size, digest));
}

/**
* Returns the manifest-level annotations.
*
* @return the annotations map, or {@code null} if not set
*/
@Nullable
public Map<String, String> getAnnotations() {
return annotations == null ? null : ImmutableMap.copyOf(annotations);
}

/**
* Adds a manifest-level annotation.
*
* @param key the annotation key
* @param value the annotation value
*/
public void addAnnotation(String key, String value) {
if (annotations == null) {
annotations = new LinkedHashMap<>();
}
annotations.put(key, value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,31 @@ public void testOsArch() {
Assert.assertEquals("wasm", image.getArchitecture());
Assert.assertEquals("js", image.getOs());
}

@Test
public void testBaseImageInfo() {
Image image =
Image.builder(V22ManifestTemplate.class)
.setBaseImageName("alpine:3.18")
.setBaseImageDigest("sha256:abc123")
.build();
Assert.assertEquals("alpine:3.18", image.getBaseImageName());
Assert.assertEquals("sha256:abc123", image.getBaseImageDigest());
}

@Test
public void testBaseImageInfo_defaults() {
Image image = Image.builder(V22ManifestTemplate.class).build();
Assert.assertNull(image.getBaseImageName());
Assert.assertNull(image.getBaseImageDigest());
}

@Test
public void testBaseImageDigest_mutableSetter() {
Image image = Image.builder(V22ManifestTemplate.class).build();
Assert.assertNull(image.getBaseImageDigest());

image.setBaseImageDigest("sha256:def456");
Assert.assertEquals("sha256:def456", image.getBaseImageDigest());
}
}
Loading