-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Write history as part of layer metadata #877
Changes from 13 commits
318071e
8b2aada
23ee777
f7f83d4
b7d38d0
3530ec6
352c011
aa063f1
9ab0d43
260cf4d
f8f48c2
e4ce5a9
0c6cceb
bf2b25f
b93594d
247814e
3fe3597
aed225b
80c588a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* Copyright 2018 Google LLC. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy of | ||
* the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations under | ||
* the License. | ||
*/ | ||
|
||
package com.google.cloud.tools.jib.image; | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnore; | ||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.google.cloud.tools.jib.json.JsonTemplate; | ||
import java.util.Objects; | ||
import javax.annotation.Nullable; | ||
|
||
/** Represents an item in the container configuration's {@code history} list. */ | ||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
public class HistoryEntry implements JsonTemplate { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this might better belong under the I'm thinking it might make more sense to call this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll move it to the package, but I'm just going to make an issue for the second point for now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
/** The timestamp at which the image was created. */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A comment about this needing to be formatted according to RFC 3339, section 5.6 |
||
private String created; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to be making the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was referencing this and it didn't seem optional (no "omitempty"). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, interesting - okay, let's match that behavior then since we don't want to break compatibility with Docker. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But on the flip side we may error out reading an OCI-conformant image that has no There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can name this in code style and use |
||
|
||
/** The name of the author specified when committing the image. */ | ||
@Nullable private String author; | ||
|
||
/** The command used while building the image. */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s/while building/to build/? |
||
@JsonProperty("created_by") | ||
@Nullable | ||
private String createdBy; | ||
|
||
/** Whether or not the layer is empty ({@code @Nullable Boolean} to make field optional). */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This field is actually about whether or not this history entry corresponds to an actual layer in the container. |
||
@JsonProperty("empty_layer") | ||
@Nullable | ||
private Boolean emptyLayer; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could be named like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that naming is too different from the field it corresponds to and could get confusing. |
||
|
||
public HistoryEntry() { | ||
this("1970-01-01T00:00:00Z", null, null, null); | ||
} | ||
|
||
public HistoryEntry( | ||
String created, | ||
@Nullable String author, | ||
@Nullable String createdBy, | ||
@Nullable Boolean emptyLayer) { | ||
this.author = author; | ||
this.created = created; | ||
this.createdBy = createdBy; | ||
this.emptyLayer = emptyLayer; | ||
} | ||
|
||
/** | ||
* Returns whether or not the history object corresponds to an empty layer. | ||
* | ||
* @return {@code true} if the history object corresponds to an empty layer | ||
*/ | ||
@JsonIgnore | ||
public boolean isEmptyLayer() { | ||
return emptyLayer == null ? false : emptyLayer; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object other) { | ||
if (this == other) { | ||
return true; | ||
} | ||
if (other instanceof HistoryEntry) { | ||
HistoryEntry otherHistory = (HistoryEntry) other; | ||
return otherHistory.created.equals(created) | ||
&& Objects.equals(otherHistory.author, author) | ||
&& Objects.equals(otherHistory.createdBy, createdBy) | ||
&& Objects.equals(otherHistory.emptyLayer, emptyLayer); | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(author, created, createdBy, emptyLayer); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ | |
|
||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
import com.google.cloud.tools.jib.image.DescriptorDigest; | ||
import com.google.cloud.tools.jib.image.HistoryEntry; | ||
import com.google.cloud.tools.jib.json.JsonTemplate; | ||
import com.google.common.annotations.VisibleForTesting; | ||
import java.util.ArrayList; | ||
|
@@ -42,6 +43,18 @@ | |
* "ExposedPorts": { "6000/tcp":{}, "8000/tcp":{}, "9000/tcp":{} } | ||
* "Labels": { "com.example.label": "value" } | ||
* }, | ||
* "history": [ | ||
* { | ||
* "author": "Jib", | ||
* "created": "1970-01-01T00:00:00Z", | ||
* "created_by": "jib" | ||
* }, | ||
* { | ||
* "author": "Jib", | ||
* "created": "1970-01-01T00:00:00Z", | ||
* "created_by": "jib" | ||
* } | ||
* ] | ||
* "rootfs": { | ||
* "diff_ids": [ | ||
* "sha256:2aebd096e0e237b447781353379722157e6c2d434b9ec5a0d63f2a6f07cf90c2", | ||
|
@@ -70,6 +83,9 @@ public class ContainerConfigurationTemplate implements JsonTemplate { | |
/** Execution parameters that should be used as a base when running the container. */ | ||
private final ConfigurationObjectTemplate config = new ConfigurationObjectTemplate(); | ||
|
||
/** Build commands used to create the image. */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Describes the history of each layer"? |
||
private final List<HistoryEntry> history = new ArrayList<>(); | ||
|
||
/** Layer content digests that are used to build the container filesystem. */ | ||
private final RootFilesystemObjectTemplate rootfs = new RootFilesystemObjectTemplate(); | ||
|
||
|
@@ -137,10 +153,18 @@ public void addLayerDiffId(DescriptorDigest diffId) { | |
rootfs.diff_ids.add(diffId); | ||
} | ||
|
||
public void addHistory(HistoryEntry historyEntry) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: since |
||
history.add(historyEntry); | ||
} | ||
|
||
List<DescriptorDigest> getDiffIds() { | ||
return rootfs.diff_ids; | ||
} | ||
|
||
List<HistoryEntry> getHistory() { | ||
return history; | ||
} | ||
|
||
@Nullable | ||
String getCreated() { | ||
return created; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a link to https://github.com/opencontainers/image-spec/blob/master/config.md#properties and pointing specifically to the
history
field.