From e8a7dc4b2f91fe8ff3fc13f7ebb5abd983b619eb Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 4 Mar 2026 16:28:03 +0000 Subject: [PATCH 1/2] composefs: Switch to composefs_oci::pull_image() API composefs-rs now provides pull_image() which returns a PullResult containing both the manifest and config digests/verities. Switch from the older pull() which only returned the config information. Log the full pull result (manifest+config digests and verity hashes) via structured journal fields for both install and upgrade paths. Assisted-by: OpenCode (Claude Opus 4) --- crates/lib/src/bootc_composefs/repo.rs | 60 +++++++++++++++++------- crates/lib/src/bootc_composefs/update.rs | 8 +++- crates/lib/src/install.rs | 6 +-- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/crates/lib/src/bootc_composefs/repo.rs b/crates/lib/src/bootc_composefs/repo.rs index c4479cdca..2bac9beaa 100644 --- a/crates/lib/src/bootc_composefs/repo.rs +++ b/crates/lib/src/bootc_composefs/repo.rs @@ -6,7 +6,7 @@ use anyhow::{Context, Result}; use ostree_ext::composefs::fsverity::{FsVerityHashValue, Sha512HashValue}; use ostree_ext::composefs_boot::{BootOps, bootloader::BootEntry as ComposefsBootEntry}; use ostree_ext::composefs_oci::{ - image::create_filesystem as create_composefs_filesystem, pull as composefs_oci_pull, + image::create_filesystem as create_composefs_filesystem, pull_image as composefs_oci_pull_image, }; use ostree_ext::container::ImageReference as OstreeExtImgRef; @@ -24,7 +24,7 @@ pub(crate) async fn initialize_composefs_repository( state: &State, root_setup: &RootSetup, allow_missing_fsverity: bool, -) -> Result<(String, impl FsVerityHashValue)> { +) -> Result> { const COMPOSEFS_REPO_INIT_JOURNAL_ID: &str = "5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9"; let rootfs_dir = &root_setup.physical_root; @@ -53,13 +53,25 @@ pub(crate) async fn initialize_composefs_repository( } = &state.source.imageref; // transport's display is already of type ":" - composefs_oci_pull( + let pull_result = composefs_oci_pull_image( &Arc::new(repo), &format!("{transport}{image_name}"), None, None, ) - .await + .await?; + + tracing::info!( + message_id = COMPOSEFS_REPO_INIT_JOURNAL_ID, + bootc.operation = "repository_init", + bootc.manifest_digest = pull_result.manifest_digest, + bootc.manifest_verity = pull_result.manifest_verity.to_hex(), + bootc.config_digest = pull_result.config_digest, + bootc.config_verity = pull_result.config_verity.to_hex(), + "Pulled image into composefs repository", + ); + + Ok(pull_result) } /// skopeo (in composefs-rs) doesn't understand "registry:" @@ -82,6 +94,18 @@ pub(crate) fn get_imgref(transport: &str, image: &str) -> String { } } +/// Result of pulling a composefs repository, including the OCI manifest digest +/// needed to reconstruct image metadata from the local composefs repo. +#[allow(dead_code)] +pub(crate) struct PullRepoResult { + pub(crate) repo: crate::store::ComposefsRepository, + pub(crate) entries: Vec>, + pub(crate) id: Sha512HashValue, + pub(crate) fs: crate::store::ComposefsFilesystem, + /// The OCI manifest content digest (e.g. "sha256:abc...") + pub(crate) manifest_digest: String, +} + /// Pulls the `image` from `transport` into a composefs repository at /sysroot /// Checks for boot entries in the image and returns them #[context("Pulling composefs repository")] @@ -89,12 +113,7 @@ pub(crate) async fn pull_composefs_repo( transport: &String, image: &String, allow_missing_fsverity: bool, -) -> Result<( - crate::store::ComposefsRepository, - Vec>, - Sha512HashValue, - crate::store::ComposefsFilesystem, -)> { +) -> Result { const COMPOSEFS_PULL_JOURNAL_ID: &str = "4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8"; tracing::info!( @@ -117,28 +136,37 @@ pub(crate) async fn pull_composefs_repo( tracing::debug!("Image to pull {final_imgref}"); - let (id, verity) = composefs_oci_pull(&Arc::new(repo), &final_imgref, None, None) + let pull_result = composefs_oci_pull_image(&Arc::new(repo), &final_imgref, None, None) .await .context("Pulling composefs repo")?; tracing::info!( message_id = COMPOSEFS_PULL_JOURNAL_ID, - id = id, - verity = verity.to_hex(), - "Pulled image into repository" + bootc.operation = "pull", + bootc.manifest_digest = pull_result.manifest_digest, + bootc.manifest_verity = pull_result.manifest_verity.to_hex(), + bootc.config_digest = pull_result.config_digest, + bootc.config_verity = pull_result.config_verity.to_hex(), + "Pulled image into composefs repository", ); let mut repo = open_composefs_repo(&rootfs_dir)?; repo.set_insecure(allow_missing_fsverity); let mut fs: crate::store::ComposefsFilesystem = - create_composefs_filesystem(&repo, &id, None) + create_composefs_filesystem(&repo, &pull_result.config_digest, None) .context("Failed to create composefs filesystem")?; let entries = fs.transform_for_boot(&repo)?; let id = fs.commit_image(&repo, None)?; - Ok((repo, entries, id, fs)) + Ok(PullRepoResult { + repo, + entries, + id, + fs, + manifest_digest: pull_result.manifest_digest, + }) } #[cfg(test)] diff --git a/crates/lib/src/bootc_composefs/update.rs b/crates/lib/src/bootc_composefs/update.rs index bd2b2b2ce..fc8f19ba9 100644 --- a/crates/lib/src/bootc_composefs/update.rs +++ b/crates/lib/src/bootc_composefs/update.rs @@ -251,7 +251,13 @@ pub(crate) async fn do_upgrade( ) -> Result<()> { start_finalize_stated_svc()?; - let (repo, entries, id, fs) = pull_composefs_repo( + let crate::bootc_composefs::repo::PullRepoResult { + repo, + entries, + id, + fs, + manifest_digest: _, + } = pull_composefs_repo( &imgref.transport, &imgref.image, booted_cfs.cmdline.allow_missing_fsverity, diff --git a/crates/lib/src/install.rs b/crates/lib/src/install.rs index 6ab5a3cc0..0e942ba51 100644 --- a/crates/lib/src/install.rs +++ b/crates/lib/src/install.rs @@ -201,7 +201,6 @@ use crate::task::Task; use crate::utils::sigpolicy_from_opt; use bootc_kernel_cmdline::{INITRD_ARG_PREFIX, ROOTFLAGS, bytes, utf8}; use bootc_mount::Filesystem; -use composefs::fsverity::FsVerityHashValue; /// The toplevel boot directory pub(crate) const BOOT: &str = "boot"; @@ -1951,18 +1950,17 @@ async fn install_to_filesystem_impl( if state.composefs_options.composefs_backend { // Load a fd for the mounted target physical root - let (id, verity) = initialize_composefs_repository( + let pull_result = initialize_composefs_repository( state, rootfs, state.composefs_options.allow_missing_verity, ) .await?; - tracing::info!("id: {id}, verity: {}", verity.to_hex()); setup_composefs_boot( rootfs, state, - &id, + &pull_result.config_digest, state.composefs_options.allow_missing_verity, ) .await?; From 7bec4226e027488fdf8c615d20c00a4aaaeb9f85 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 4 Mar 2026 19:22:01 +0000 Subject: [PATCH 2/2] composefs: Read manifest+config from composefs repo instead of .imginfo composefs-rs stores the OCI manifest and config as splitstreams in the repository during pull. Use this to eliminate the redundant .imginfo sidecar files that bootc was maintaining separately. Store the OCI manifest digest in the .origin file under an [image] section, and use OciImage::open() to retrieve the full manifest+config from the local composefs repo when needed (status, GC, export). This avoids both the sidecar files and the surprising network-fetch fallback that the old get_imginfo() would do if no .imginfo file existed. For backwards compatibility, get_imginfo() falls back to reading legacy .imginfo files for deployments created before this change. The do_upgrade() and write_composefs_state() functions no longer need ImgConfigManifest passed through, since the data is retrieved from the repo on demand rather than written at deploy time. get_container_manifest_and_config() is retained for is_image_pulled() which checks the remote registry to determine if an update is available. Assisted-by: OpenCode (Claude Opus 4) --- crates/lib/src/bootc_composefs/boot.rs | 21 ++---- crates/lib/src/bootc_composefs/export.rs | 2 +- crates/lib/src/bootc_composefs/repo.rs | 1 - crates/lib/src/bootc_composefs/state.rs | 31 ++++----- crates/lib/src/bootc_composefs/status.rs | 86 ++++++++++++++---------- crates/lib/src/bootc_composefs/switch.rs | 21 +----- crates/lib/src/bootc_composefs/update.rs | 40 +++-------- crates/lib/src/composefs_consts.rs | 5 ++ crates/lib/src/install.rs | 2 +- 9 files changed, 89 insertions(+), 120 deletions(-) diff --git a/crates/lib/src/bootc_composefs/boot.rs b/crates/lib/src/bootc_composefs/boot.rs index f64540c5b..bf606ba95 100644 --- a/crates/lib/src/bootc_composefs/boot.rs +++ b/crates/lib/src/bootc_composefs/boot.rs @@ -92,19 +92,14 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::bootc_composefs::state::{get_booted_bls, write_composefs_state}; +use crate::bootc_kargs::compute_new_kargs; +use crate::composefs_consts::{TYPE1_ENT_PATH, TYPE1_ENT_PATH_STAGED}; use crate::parsers::bls_config::{BLSConfig, BLSConfigType}; use crate::task::Task; -use crate::{ - bootc_composefs::repo::get_imgref, - composefs_consts::{TYPE1_ENT_PATH, TYPE1_ENT_PATH_STAGED}, -}; use crate::{ bootc_composefs::repo::open_composefs_repo, store::{ComposefsFilesystem, Storage}, }; -use crate::{ - bootc_composefs::status::get_container_manifest_and_config, bootc_kargs::compute_new_kargs, -}; use crate::{bootc_composefs::status::get_sorted_grub_uki_boot_entries, install::PostFetchState}; use crate::{ composefs_consts::{ @@ -1221,7 +1216,7 @@ fn get_secureboot_keys(fs: &Dir, p: &str) -> Result> { pub(crate) async fn setup_composefs_boot( root_setup: &RootSetup, state: &State, - image_id: &str, + pull_result: &composefs_oci::PullResult, allow_missing_fsverity: bool, ) -> Result<()> { const COMPOSEFS_BOOT_SETUP_JOURNAL_ID: &str = "1f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5"; @@ -1229,7 +1224,7 @@ pub(crate) async fn setup_composefs_boot( tracing::info!( message_id = COMPOSEFS_BOOT_SETUP_JOURNAL_ID, bootc.operation = "boot_setup", - bootc.image_id = image_id, + bootc.config_digest = pull_result.config_digest, bootc.allow_missing_fsverity = allow_missing_fsverity, "Setting up composefs boot", ); @@ -1237,7 +1232,7 @@ pub(crate) async fn setup_composefs_boot( let mut repo = open_composefs_repo(&root_setup.physical_root)?; repo.set_insecure(allow_missing_fsverity); - let mut fs = create_composefs_filesystem(&repo, image_id, None)?; + let mut fs = create_composefs_filesystem(&repo, &pull_result.config_digest, None)?; let entries = fs.transform_for_boot(&repo)?; let id = fs.commit_image(&repo, None)?; let mounted_fs = Dir::reopen_dir( @@ -1302,11 +1297,7 @@ pub(crate) async fn setup_composefs_boot( None, boot_type, boot_digest, - &get_container_manifest_and_config(&get_imgref( - &state.source.imageref.transport.to_string(), - &state.source.imageref.name, - )) - .await?, + &pull_result.manifest_digest, allow_missing_fsverity, ) .await?; diff --git a/crates/lib/src/bootc_composefs/export.rs b/crates/lib/src/bootc_composefs/export.rs index f86392421..f6043a122 100644 --- a/crates/lib/src/bootc_composefs/export.rs +++ b/crates/lib/src/bootc_composefs/export.rs @@ -48,7 +48,7 @@ pub async fn export_repo_to_image( let depl_verity = depl_verity.ok_or_else(|| anyhow::anyhow!("Image {source} not found"))?; - let imginfo = get_imginfo(storage, &depl_verity, None).await?; + let imginfo = get_imginfo(storage, &depl_verity)?; // We want the digest in the form of "sha256:abc123" let config_digest = format!("{}", imginfo.manifest.config().digest()); diff --git a/crates/lib/src/bootc_composefs/repo.rs b/crates/lib/src/bootc_composefs/repo.rs index 2bac9beaa..87250f7e1 100644 --- a/crates/lib/src/bootc_composefs/repo.rs +++ b/crates/lib/src/bootc_composefs/repo.rs @@ -96,7 +96,6 @@ pub(crate) fn get_imgref(transport: &str, image: &str) -> String { /// Result of pulling a composefs repository, including the OCI manifest digest /// needed to reconstruct image metadata from the local composefs repo. -#[allow(dead_code)] pub(crate) struct PullRepoResult { pub(crate) repo: crate::store::ComposefsRepository, pub(crate) entries: Vec>, diff --git a/crates/lib/src/bootc_composefs/state.rs b/crates/lib/src/bootc_composefs/state.rs index dcdfb161a..0fcc949b3 100644 --- a/crates/lib/src/bootc_composefs/state.rs +++ b/crates/lib/src/bootc_composefs/state.rs @@ -25,16 +25,14 @@ use rustix::{ use crate::bootc_composefs::boot::BootType; use crate::bootc_composefs::repo::get_imgref; -use crate::bootc_composefs::status::{ - ImgConfigManifest, StagedDeployment, get_sorted_type1_boot_entries, -}; +use crate::bootc_composefs::status::{StagedDeployment, get_sorted_type1_boot_entries}; use crate::parsers::bls_config::BLSConfigType; use crate::store::{BootedComposefs, Storage}; use crate::{ composefs_consts::{ COMPOSEFS_CMDLINE, COMPOSEFS_STAGED_DEPLOYMENT_FNAME, COMPOSEFS_TRANSIENT_STATE_DIR, - ORIGIN_KEY_BOOT, ORIGIN_KEY_BOOT_DIGEST, ORIGIN_KEY_BOOT_TYPE, SHARED_VAR_PATH, - STATE_DIR_RELATIVE, + ORIGIN_KEY_BOOT, ORIGIN_KEY_BOOT_DIGEST, ORIGIN_KEY_BOOT_TYPE, ORIGIN_KEY_IMAGE, + ORIGIN_KEY_MANIFEST_DIGEST, SHARED_VAR_PATH, STATE_DIR_RELATIVE, }, parsers::bls_config::BLSConfig, spec::ImageReference, @@ -221,15 +219,15 @@ pub(crate) fn update_boot_digest_in_origin( /// * `staged` - Whether this is a staged deployment (writes to transient state dir) /// * `boot_type` - Boot loader type (`Bls` or `Uki`) /// * `boot_digest` - Optional boot digest for verification -/// * `container_details` - Container manifest and config used to create this deployment +/// * `manifest_digest` - OCI manifest content digest, stored in the origin file so the +/// manifest+config can be retrieved from the composefs repo later /// /// # State Directory Structure /// /// Creates the following structure under `/sysroot/state/deploy/{deployment_id}/`: /// * `etc/` - Copy of system configuration files /// * `var` - Symlink to shared `/var` directory -/// * `{deployment_id}.origin` - OSTree-style origin configuration -/// * `{deployment_id}.imginfo` - Container image manifest and config as JSON +/// * `{deployment_id}.origin` - Origin configuration with image ref, boot, and image metadata /// /// For staged deployments, also writes to `/run/composefs/staged-deployment`. #[context("Writing composefs state")] @@ -240,7 +238,7 @@ pub(crate) async fn write_composefs_state( staged: Option, boot_type: BootType, boot_digest: String, - container_details: &ImgConfigManifest, + manifest_digest: &str, allow_missing_fsverity: bool, ) -> Result<()> { let state_path = root_path @@ -289,18 +287,15 @@ pub(crate) async fn write_composefs_state( .section(ORIGIN_KEY_BOOT) .item(ORIGIN_KEY_BOOT_DIGEST, boot_digest); + // Store the OCI manifest digest so we can retrieve the manifest+config + // from the composefs repository later (composefs-rs stores them as splitstreams). + config = config + .section(ORIGIN_KEY_IMAGE) + .item(ORIGIN_KEY_MANIFEST_DIGEST, manifest_digest); + let state_dir = Dir::open_ambient_dir(&state_path, ambient_authority()).context("Opening state dir")?; - // NOTE: This is only supposed to be temporary until we decide on where to store - // the container manifest/config - state_dir - .atomic_write( - format!("{}.imginfo", deployment_id.to_hex()), - serde_json::to_vec(&container_details)?, - ) - .context("Failed to write to .imginfo file")?; - state_dir .atomic_write( format!("{}.origin", deployment_id.to_hex()), diff --git a/crates/lib/src/bootc_composefs/status.rs b/crates/lib/src/bootc_composefs/status.rs index 72ea5a58d..e8b724ac1 100644 --- a/crates/lib/src/bootc_composefs/status.rs +++ b/crates/lib/src/bootc_composefs/status.rs @@ -3,19 +3,21 @@ use std::{collections::HashSet, io::Read, sync::OnceLock}; use anyhow::{Context, Result}; use bootc_kernel_cmdline::utf8::Cmdline; use bootc_mount::inspect_filesystem; +use composefs::fsverity::Sha512HashValue; +use composefs_oci::OciImage; use fn_error_context::context; use serde::{Deserialize, Serialize}; use crate::{ bootc_composefs::{ boot::BootType, - repo::get_imgref, selinux::are_selinux_policies_compatible, state::get_composefs_usr_overlay_status, utils::{compute_store_boot_digest_for_uki, get_uki_cmdline}, }, composefs_consts::{ - COMPOSEFS_CMDLINE, ORIGIN_KEY_BOOT_DIGEST, TYPE1_ENT_PATH, TYPE1_ENT_PATH_STAGED, USER_CFG, + COMPOSEFS_CMDLINE, ORIGIN_KEY_BOOT_DIGEST, ORIGIN_KEY_IMAGE, ORIGIN_KEY_MANIFEST_DIGEST, + TYPE1_ENT_PATH, TYPE1_ENT_PATH_STAGED, USER_CFG, }, install::EFI_LOADER_INFO, parsers::{ @@ -270,57 +272,73 @@ pub(crate) fn get_bootloader() -> Result { } } -/// Reads the .imginfo file for the provided deployment -#[context("Reading imginfo")] -pub(crate) async fn get_imginfo( - storage: &Storage, - deployment_id: &str, - imgref: Option<&ImageReference>, -) -> Result { - let imginfo_fname = format!("{deployment_id}.imginfo"); - +/// Retrieves the OCI manifest and config for a deployment from the composefs repository. +/// +/// The manifest digest is read from the deployment's `.origin` file, +/// then `OciImage::open()` retrieves manifest+config from the composefs repo +/// where composefs-rs stores them as splitstreams during pull. +/// +/// Falls back to reading legacy `.imginfo` files for backwards compatibility +/// with deployments created before the manifest digest was stored in `.origin`. +#[context("Reading image info for deployment {deployment_id}")] +pub(crate) fn get_imginfo(storage: &Storage, deployment_id: &str) -> Result { let depl_state_path = std::path::PathBuf::from(STATE_DIR_RELATIVE).join(deployment_id); - let path = depl_state_path.join(imginfo_fname); - let mut img_conf = storage + let state_dir = storage .physical_root - .open_optional(&path) - .context("Failed to open file")?; + .open_dir(&depl_state_path) + .with_context(|| format!("Opening state dir for {deployment_id}"))?; - let Some(img_conf) = &mut img_conf else { - let imgref = imgref.ok_or_else(|| anyhow::anyhow!("No imgref or imginfo file found"))?; + let origin_filename = format!("{deployment_id}.origin"); + let origin_contents = state_dir + .read_to_string(&origin_filename) + .with_context(|| format!("Reading {origin_filename}"))?; + + let ini = tini::Ini::from_string(&origin_contents).context("Failed to parse origin file")?; - let container_details = - get_container_manifest_and_config(&get_imgref(&imgref.transport, &imgref.image)) - .await?; + // Try to read the manifest digest from the origin file (new path) + if let Some(manifest_digest) = ini.get::(ORIGIN_KEY_IMAGE, ORIGIN_KEY_MANIFEST_DIGEST) { + let repo = storage.get_ensure_composefs()?; + let oci_image = OciImage::::open(&repo, &manifest_digest, None) + .with_context(|| format!("Opening OCI image for manifest {manifest_digest}"))?; - let state_dir = storage.physical_root.open_dir(depl_state_path)?; + let manifest = oci_image.manifest().clone(); + let config = oci_image + .config() + .cloned() + .ok_or_else(|| anyhow::anyhow!("OCI image has no config (artifact?)"))?; - state_dir - .atomic_write( - format!("{}.imginfo", deployment_id), - serde_json::to_vec(&container_details)?, - ) - .context("Failed to write to .imginfo file")?; + return Ok(ImgConfigManifest { config, manifest }); + } - let state_dir = state_dir.reopen_as_ownedfd()?; + // Fallback: read legacy .imginfo file for deployments created before + // the manifest digest was stored in .origin + let imginfo_fname = format!("{deployment_id}.imginfo"); + let path = depl_state_path.join(&imginfo_fname); - rustix::fs::fsync(state_dir).context("fsync")?; + let mut img_conf = storage + .physical_root + .open_optional(&path) + .with_context(|| format!("Opening legacy {imginfo_fname}"))?; - return Ok(container_details); + let Some(img_conf) = &mut img_conf else { + anyhow::bail!( + "No manifest_digest in origin and no legacy .imginfo file \ + for deployment {deployment_id}" + ); }; let mut buffer = String::new(); img_conf.read_to_string(&mut buffer)?; let img_conf = serde_json::from_str::(&buffer) - .context("Failed to parse file as JSON")?; + .context("Failed to parse .imginfo file as JSON")?; Ok(img_conf) } #[context("Getting composefs deployment metadata")] -async fn boot_entry_from_composefs_deployment( +fn boot_entry_from_composefs_deployment( storage: &Storage, origin: tini::Ini, verity: String, @@ -330,7 +348,7 @@ async fn boot_entry_from_composefs_deployment( let ostree_img_ref = OstreeImageReference::from_str(&img_name_from_config)?; let img_ref = ImageReference::from(ostree_img_ref); - let img_conf = get_imginfo(storage, &verity, Some(&img_ref)).await?; + let img_conf = get_imginfo(storage, &verity)?; let image_digest = img_conf.manifest.config().digest().to_string(); let architecture = img_conf.config.architecture().to_string(); @@ -657,7 +675,7 @@ pub(crate) async fn composefs_deployment_status_from( .with_context(|| format!("Failed to parse file {depl_file_name}.origin as ini"))?; let mut boot_entry = - boot_entry_from_composefs_deployment(storage, ini, depl_file_name.to_string()).await?; + boot_entry_from_composefs_deployment(storage, ini, depl_file_name.to_string())?; // SAFETY: boot_entry.composefs will always be present let boot_type_from_origin = boot_entry.composefs.as_ref().unwrap().boot_type; diff --git a/crates/lib/src/bootc_composefs/switch.rs b/crates/lib/src/bootc_composefs/switch.rs index e44bc478d..b6ce55ad5 100644 --- a/crates/lib/src/bootc_composefs/switch.rs +++ b/crates/lib/src/bootc_composefs/switch.rs @@ -75,15 +75,8 @@ pub(crate) async fn switch_composefs( } UpdateAction::Proceed => { - return do_upgrade( - storage, - booted_cfs, - &host, - &target_imgref, - &img_config, - &do_upgrade_opts, - ) - .await; + return do_upgrade(storage, booted_cfs, &host, &target_imgref, &do_upgrade_opts) + .await; } UpdateAction::UpdateOrigin => { @@ -95,15 +88,7 @@ pub(crate) async fn switch_composefs( } } - do_upgrade( - storage, - booted_cfs, - &host, - &target_imgref, - &img_config, - &do_upgrade_opts, - ) - .await?; + do_upgrade(storage, booted_cfs, &host, &target_imgref, &do_upgrade_opts).await?; Ok(()) } diff --git a/crates/lib/src/bootc_composefs/update.rs b/crates/lib/src/bootc_composefs/update.rs index fc8f19ba9..b939a6fef 100644 --- a/crates/lib/src/bootc_composefs/update.rs +++ b/crates/lib/src/bootc_composefs/update.rs @@ -246,7 +246,6 @@ pub(crate) async fn do_upgrade( booted_cfs: &BootedComposefs, host: &Host, imgref: &ImageReference, - img_manifest_config: &ImgConfigManifest, opts: &DoUpgradeOpts, ) -> Result<()> { start_finalize_stated_svc()?; @@ -256,7 +255,7 @@ pub(crate) async fn do_upgrade( entries, id, fs, - manifest_digest: _, + manifest_digest, } = pull_composefs_repo( &imgref.transport, &imgref.image, @@ -303,7 +302,7 @@ pub(crate) async fn do_upgrade( }), boot_type, boot_digest, - img_manifest_config, + &manifest_digest, booted_cfs.cmdline.allow_missing_fsverity, ) .await?; @@ -435,15 +434,8 @@ pub(crate) async fn upgrade_composefs( } UpdateAction::Proceed => { - return do_upgrade( - storage, - composefs, - &host, - booted_imgref, - &img_config, - &do_upgrade_opts, - ) - .await; + return do_upgrade(storage, composefs, &host, booted_imgref, &do_upgrade_opts) + .await; } UpdateAction::UpdateOrigin => { @@ -471,15 +463,8 @@ pub(crate) async fn upgrade_composefs( } UpdateAction::Proceed => { - return do_upgrade( - storage, - composefs, - &host, - booted_imgref, - &img_config, - &do_upgrade_opts, - ) - .await; + return do_upgrade(storage, composefs, &host, booted_imgref, &do_upgrade_opts) + .await; } UpdateAction::UpdateOrigin => { @@ -489,22 +474,13 @@ pub(crate) async fn upgrade_composefs( } if opts.check { - let current_manifest = - get_imginfo(storage, &*composefs.cmdline.digest, Some(booted_imgref)).await?; + let current_manifest = get_imginfo(storage, &*composefs.cmdline.digest)?; let diff = ManifestDiff::new(¤t_manifest.manifest, &img_config.manifest); diff.print(); return Ok(()); } - do_upgrade( - storage, - composefs, - &host, - booted_imgref, - &img_config, - &do_upgrade_opts, - ) - .await?; + do_upgrade(storage, composefs, &host, booted_imgref, &do_upgrade_opts).await?; Ok(()) } diff --git a/crates/lib/src/composefs_consts.rs b/crates/lib/src/composefs_consts.rs index 941fc6fed..447cfc9ab 100644 --- a/crates/lib/src/composefs_consts.rs +++ b/crates/lib/src/composefs_consts.rs @@ -22,6 +22,11 @@ pub(crate) const ORIGIN_KEY_BOOT_TYPE: &str = "boot_type"; /// Key to store the SHA256 sum of vmlinuz + initrd for a deployment pub(crate) const ORIGIN_KEY_BOOT_DIGEST: &str = "digest"; +/// Section in .origin file to store OCI image metadata +pub(crate) const ORIGIN_KEY_IMAGE: &str = "image"; +/// Key to store the OCI manifest digest (e.g. "sha256:abc...") +pub(crate) const ORIGIN_KEY_MANIFEST_DIGEST: &str = "manifest_digest"; + /// Filename for `loader/entries` pub(crate) const BOOT_LOADER_ENTRIES: &str = "entries"; /// Filename for staged boot loader entries diff --git a/crates/lib/src/install.rs b/crates/lib/src/install.rs index 0e942ba51..e505ba44b 100644 --- a/crates/lib/src/install.rs +++ b/crates/lib/src/install.rs @@ -1960,7 +1960,7 @@ async fn install_to_filesystem_impl( setup_composefs_boot( rootfs, state, - &pull_result.config_digest, + &pull_result, state.composefs_options.allow_missing_verity, ) .await?;