diff --git a/lib/src/cli.rs b/lib/src/cli.rs index 080ef32a..8c172e37 100644 --- a/lib/src/cli.rs +++ b/lib/src/cli.rs @@ -802,6 +802,7 @@ where kargs: kargs.as_deref(), target_imgref: target_imgref.as_ref(), proxy_cfg: Some(proxyopts.into()), + ..Default::default() }; let state = crate::container::deploy::deploy( sysroot, diff --git a/lib/src/container/deploy.rs b/lib/src/container/deploy.rs index 855f1186..38e41df3 100644 --- a/lib/src/container/deploy.rs +++ b/lib/src/container/deploy.rs @@ -27,6 +27,12 @@ pub struct DeployOpts<'a> { /// Configuration for fetching containers. pub proxy_cfg: Option, + + /// If true, then no image reference will be written; but there will be refs + /// for the fetched layers. This ensures that if the machine is later updated + /// to a different container image, the fetch process will reuse shared layers, but + /// it will not be necessary to remove the previous image. + pub no_imgref: bool, } /// Write a container image to an OSTree deployment. @@ -48,6 +54,9 @@ pub async fn deploy( if let Some(target) = options.target_imgref { imp.set_target(target); } + if options.no_imgref { + imp.set_no_imgref(); + } let state = match imp.prepare().await? { PrepareResult::AlreadyPresent(r) => r, PrepareResult::Ready(prep) => imp.import(prep).await?, diff --git a/lib/src/container/store.rs b/lib/src/container/store.rs index f6ceb69c..61fdb344 100644 --- a/lib/src/container/store.rs +++ b/lib/src/container/store.rs @@ -131,6 +131,7 @@ pub struct ImageImporter { pub(crate) proxy: ImageProxy, imgref: OstreeImageReference, target_imgref: Option, + no_imgref: bool, // If true, do not write final image ref pub(crate) proxy_img: OpenedImage, layer_progress: Option>, @@ -405,6 +406,7 @@ impl ImageImporter { proxy, proxy_img, target_imgref: None, + no_imgref: false, imgref: imgref.clone(), layer_progress: None, layer_byte_progress: None, @@ -416,6 +418,13 @@ impl ImageImporter { self.target_imgref = Some(target.clone()) } + /// Do not write the final image ref, but do write refs for shared layers. + /// This is useful in scenarios where you want to "pre-pull" an image, + /// but in such a way that it does not need to be manually removed later. + pub fn set_no_imgref(&mut self) { + self.no_imgref = true; + } + /// Determine if there is a new manifest, and if so return its digest. pub async fn prepare(&mut self) -> Result { self.prepare_internal(false).await @@ -787,7 +796,9 @@ impl ImageImporter { let merged_commit = repo .write_commit(None, None, None, Some(&metadata), &merged_root, cancellable) .context("Writing commit")?; - repo.transaction_set_ref(None, &ostree_ref, Some(merged_commit.as_str())); + if !self.no_imgref { + repo.transaction_set_ref(None, &ostree_ref, Some(merged_commit.as_str())); + } txn.commit(cancellable)?; // Here we re-query state just to run through the same code path, // though it'd be cheaper to synthesize it from the data we already have.