Skip to content

Commit

Permalink
spec: Add cached update metadata
Browse files Browse the repository at this point in the history
In ostreedev/ostree-rs-ext#537 we
added a facility to cache metadata (manifest+config) for
container image updates with an eye for use in rpm-ostree.

The `bootc update --check` code here in bootc was also
updated to use it; but we didn't really expose it back in
the status.

This closes the gap, just bridging the cached update metadata
into status.  We want to do this as opposed to having
`bootc update --check` grow its own API for example.

Signed-off-by: Colin Walters <[email protected]>
  • Loading branch information
cgwalters committed Jan 2, 2024
1 parent d2a2326 commit 2ad49ae
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 23 deletions.
2 changes: 2 additions & 0 deletions lib/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ pub struct BootEntryOstree {
pub struct BootEntry {
/// The image reference
pub image: Option<ImageStatus>,
/// The last fetched cached update metadata
pub cached_update: Option<ImageStatus>,
/// Whether this boot entry is not compatible (has origin changes bootc does not understand)
pub incompatible: bool,
/// Whether this entry will be subject to garbage collection
Expand Down
68 changes: 45 additions & 23 deletions lib/src/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use ostree_container::OstreeImageReference;
use ostree_ext::container as ostree_container;
use ostree_ext::keyfileext::KeyFileExt;
use ostree_ext::oci_spec;
use ostree_ext::oci_spec::image::ImageConfiguration;
use ostree_ext::ostree;
use ostree_ext::sysroot::SysrootLock;

Expand Down Expand Up @@ -112,48 +113,69 @@ pub(crate) fn labels_of_config(
config.config().as_ref().and_then(|c| c.labels().as_ref())
}

/// Convert between a subset of ostree-ext metadata and the exposed spec API.
pub(crate) fn create_imagestatus(
image: ImageReference,
manifest_digest: &str,
config: Option<&ImageConfiguration>,
) -> ImageStatus {
let labels = config.and_then(labels_of_config);
let timestamp = labels
.and_then(|l| {
l.get(oci_spec::image::ANNOTATION_CREATED)
.map(|s| s.as_str())
})
.and_then(try_deserialize_timestamp);

let version = config
.and_then(ostree_container::version_for_config)
.map(ToOwned::to_owned);
ImageStatus {
image,
version,
timestamp,
image_digest: manifest_digest.to_owned(),
}
}

/// Given an OSTree deployment, parse out metadata into our spec.
#[context("Reading deployment metadata")]
fn boot_entry_from_deployment(
sysroot: &SysrootLock,
deployment: &ostree::Deployment,
) -> Result<BootEntry> {
let repo = &sysroot.repo();
let (image, incompatible) = if let Some(origin) = deployment.origin().as_ref() {
let (image, cached_update, incompatible) = if let Some(origin) = deployment.origin().as_ref() {
let incompatible = crate::utils::origin_has_rpmostree_stuff(origin);
let image = if incompatible {
let (image, cached) = if incompatible {
// If there are local changes, we can't represent it as a bootc compatible image.
None
(None, None)
} else if let Some(image) = get_image_origin(origin)? {
let image = ImageReference::from(image);
let csum = deployment.csum();
let imgstate = ostree_container::store::query_image_commit(repo, &csum)?;
let config = imgstate.configuration.as_ref();
let labels = config.and_then(labels_of_config);
let timestamp = labels
.and_then(|l| {
l.get(oci_spec::image::ANNOTATION_CREATED)
.map(|s| s.as_str())
})
.and_then(try_deserialize_timestamp);

let version = config
.and_then(ostree_container::version_for_config)
.map(ToOwned::to_owned);
Some(ImageStatus {
let cached = imgstate.cached_update.map(|cached| {
create_imagestatus(image.clone(), &cached.manifest_digest, Some(&cached.config))
});
let imagestatus = create_imagestatus(
image,
version,
timestamp,
image_digest: imgstate.manifest_digest,
})
&imgstate.manifest_digest,
imgstate.configuration.as_ref(),
);
// We found a container-image based deployment
(Some(imagestatus), cached)
} else {
None
// The deployment isn't using a container image
(None, None)
};
(image, incompatible)
(image, cached, incompatible)
} else {
(None, false)
// The deployment has no origin at all (this generally shouldn't happen)
(None, None, false)
};
let r = BootEntry {
image,
cached_update,
incompatible,
pinned: deployment.is_pinned(),
ostree: Some(crate::spec::BootEntryOstree {
Expand Down

0 comments on commit 2ad49ae

Please sign in to comment.