Skip to content

Commit

Permalink
container: Add history struct to oci writing, tweak history description
Browse files Browse the repository at this point in the history
Prep for ostreedev#69
where we'll split up the input ostree commit into content-addressed
blobs.

We want to inject something useful into the the `history` in the
config git that describes each chunk, so add support for that
into our OCI writer.

Change the default description for the (currently single) layer
to include the commit subject, if present; otherwise the
commit hash.

The description of the layer shouldn't change as this tool changes,
just as the input changes.

(Side note; today rpm-ostree isn't adding a subject description,
 but hey, maybe someone else is)
  • Loading branch information
cgwalters committed Dec 10, 2021
1 parent 896fd4b commit 4ea6846
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 24 deletions.
14 changes: 13 additions & 1 deletion lib/src/container/encapsulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ fn build_oci(
let commit = repo.resolve_rev(rev, false)?.unwrap();
let commit = commit.as_str();
let (commit_v, _) = repo.load_commit(commit)?;
let commit_subject = commit_v.child_value(3);
let commit_subject = commit_subject.str().ok_or_else(|| {
anyhow::anyhow!(
"Corrupted commit {}; expecting string value for subject",
commit
)
})?;
let commit_meta = &commit_v.child_value(0);
let commit_meta = glib::VariantDict::new(Some(commit_meta));

Expand Down Expand Up @@ -85,9 +92,14 @@ fn build_oci(
};

let rootfs_blob = export_ostree_ref(repo, commit, &mut writer, Some(compression))?;
let description = if commit_subject.is_empty() {
Cow::Owned(format!("ostree export of commit {}", commit))
} else {
Cow::Borrowed(commit_subject)
};
let mut annos = HashMap::new();
annos.insert(BLOB_OSTREE_ANNOTATION.to_string(), "true".to_string());
writer.push_layer_annotated(rootfs_blob, Some(annos));
writer.push_layer_annotated(rootfs_blob, Some(annos), &description);
writer.complete()?;

Ok(ImageReference {
Expand Down
43 changes: 20 additions & 23 deletions lib/src/container/ociwriter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub(crate) struct OciWriter<'a> {
cmd: Option<Vec<String>>,

layers: Vec<(oci_image::Descriptor, String)>,
history: Vec<String>,
}

/// Write a serializable data (JSON) as an OCI blob
Expand All @@ -102,6 +103,7 @@ impl<'a> OciWriter<'a> {
config_annotations: Default::default(),
manifest_annotations: Default::default(),
layers: Vec::new(),
history: Vec::new(),
cmd: None,
})
}
Expand All @@ -123,20 +125,11 @@ impl<'a> OciWriter<'a> {
Ok(tar::Builder::new(self.create_raw_layer(c)?))
}

/// Add a layer to the top of the image stack. The firsh pushed layer becomes the root.
#[allow(dead_code)]
/// Finish all I/O for a layer writer, and add it to the layers in the image.
pub(crate) fn finish_and_push_layer(&mut self, w: RawLayerWriter) -> Result<()> {
let w = w.complete()?;
self.push_layer(w);
Ok(())
}

/// Add a layer to the top of the image stack.
///
/// The first pushed layer becomes the root.
pub(crate) fn push_layer(&mut self, layer: Layer) {
let v: Option<HashMap<String, String>> = None;
self.push_layer_annotated(layer, v);
pub(crate) fn push_layer(&mut self, layer: Layer, description: &str) {
let annotations: Option<HashMap<String, String>> = None;
self.push_layer_annotated(layer, annotations, description);
}

/// Add a layer to the top of the image stack with optional annotations.
Expand All @@ -146,13 +139,15 @@ impl<'a> OciWriter<'a> {
&mut self,
layer: Layer,
annotations: Option<impl Into<HashMap<String, String>>>,
description: &str,
) {
let mut builder = layer.descriptor().media_type(MediaType::ImageLayerGzip);
if let Some(annotations) = annotations {
builder = builder.annotations(annotations);
}
self.layers
.push((builder.build().unwrap(), layer.uncompressed_sha256));
self.history.push(description.to_string());
}

pub(crate) fn set_cmd(&mut self, e: &[&str]) {
Expand Down Expand Up @@ -201,20 +196,22 @@ impl<'a> OciWriter<'a> {
}
.build()
.unwrap();
let history = oci_image::HistoryBuilder::default()
.created_by(format!(
"created by {} {}",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION")
))
.build()
.unwrap();
let history: Vec<_> = self
.history
.into_iter()
.map(|h| {
oci_image::HistoryBuilder::default()
.created_by(h)
.build()
.unwrap()
})
.collect();
let config = oci_image::ImageConfigurationBuilder::default()
.architecture(arch.clone())
.os(oci_image::Os::Linux)
.config(ctrconfig)
.rootfs(rootfs)
.history(vec![history])
.history(history)
.build()
.unwrap();
let config_blob = write_json_blob(self.dir, &config, MediaType::ImageConfig)?;
Expand Down Expand Up @@ -380,7 +377,7 @@ mod tests {
root_layer.uncompressed_sha256,
"349438e5faf763e8875b43de4d7101540ef4d865190336c2cc549a11f33f8d7c"
);
w.push_layer(root_layer);
w.push_layer(root_layer, "root");
w.complete()?;
Ok(())
}
Expand Down

0 comments on commit 4ea6846

Please sign in to comment.