mirror of
https://github.com/containers/bootc.git
synced 2026-02-05 15:45:53 +01:00
Clean up staging flow
Add a helper `stage()` which takes all the data we need, and use it in both the `upgrade` and `switch` paths. This drops out an "internal error" message and avoids the "utils" code growth. Signed-off-by: Colin Walters <walters@verbum.org>
This commit is contained in:
@@ -13,12 +13,11 @@ use ostree_ext::container as ostree_container;
|
||||
use ostree_ext::container::SignatureSource;
|
||||
use ostree_ext::keyfileext::KeyFileExt;
|
||||
use ostree_ext::ostree;
|
||||
use ostree_ext::sysroot::SysrootLock;
|
||||
use std::ffi::OsString;
|
||||
use std::os::unix::process::CommandExt;
|
||||
use tokio::sync::mpsc::Receiver;
|
||||
|
||||
use crate::utils::{get_image_origin, print_staged};
|
||||
|
||||
/// Perform an upgrade operation
|
||||
#[derive(Debug, Parser)]
|
||||
pub(crate) struct UpgradeOpts {
|
||||
@@ -240,16 +239,37 @@ pub(crate) async fn print_deprecated_warning(msg: &str) {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
|
||||
}
|
||||
|
||||
/// Stage (queue deployment of) a fetched container image.
|
||||
async fn stage(
|
||||
sysroot: &SysrootLock,
|
||||
stateroot: &str,
|
||||
imgref: &ostree_container::OstreeImageReference,
|
||||
image: Box<LayeredImageState>,
|
||||
origin: &glib::KeyFile,
|
||||
) -> Result<()> {
|
||||
let cancellable = gio::Cancellable::NONE;
|
||||
let stateroot = Some(stateroot);
|
||||
let merge_deployment = sysroot.merge_deployment(stateroot);
|
||||
let _new_deployment = sysroot.stage_tree_with_options(
|
||||
stateroot,
|
||||
image.merge_commit.as_str(),
|
||||
Some(origin),
|
||||
merge_deployment.as_ref(),
|
||||
&Default::default(),
|
||||
cancellable,
|
||||
)?;
|
||||
println!("Queued for next boot: {imgref}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Implementation of the `bootc upgrade` CLI command.
|
||||
async fn upgrade(opts: UpgradeOpts) -> Result<()> {
|
||||
ensure_self_unshared_mount_namespace().await?;
|
||||
let cancellable = gio::Cancellable::NONE;
|
||||
let sysroot = &get_locked_sysroot().await?;
|
||||
let repo = &sysroot.repo().unwrap();
|
||||
let booted_deployment = &sysroot.require_booted_deployment()?;
|
||||
let status = crate::status::DeploymentStatus::from_deployment(booted_deployment, true)?;
|
||||
let osname = booted_deployment.osname().unwrap();
|
||||
let osname_v = Some(osname.as_str());
|
||||
let origin = booted_deployment
|
||||
.origin()
|
||||
.ok_or_else(|| anyhow::anyhow!("Deployment is missing an origin"))?;
|
||||
@@ -272,17 +292,7 @@ async fn upgrade(opts: UpgradeOpts) -> Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let merge_deployment = sysroot.merge_deployment(osname_v);
|
||||
|
||||
let new_deployment = sysroot.stage_tree_with_options(
|
||||
osname_v,
|
||||
fetched.merge_commit.as_str(),
|
||||
Some(&origin),
|
||||
merge_deployment.as_ref(),
|
||||
&Default::default(),
|
||||
cancellable,
|
||||
)?;
|
||||
print_staged(&new_deployment)?;
|
||||
stage(sysroot, &osname, &imgref, fetched, &origin).await?;
|
||||
|
||||
if let Some(path) = opts.touch_if_changed {
|
||||
std::fs::write(&path, "").with_context(|| format!("Writing {path}"))?;
|
||||
@@ -297,10 +307,9 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
|
||||
let cancellable = gio::Cancellable::NONE;
|
||||
let sysroot = get_locked_sysroot().await?;
|
||||
let booted_deployment = &sysroot.require_booted_deployment()?;
|
||||
let (origin, booted_image) = get_image_origin(booted_deployment)?;
|
||||
let (origin, booted_image) = crate::utils::get_image_origin(booted_deployment)?;
|
||||
let booted_refspec = origin.optional_string("origin", "refspec")?;
|
||||
let osname = booted_deployment.osname().unwrap();
|
||||
let osname_v = Some(osname.as_str());
|
||||
let repo = &sysroot.repo().unwrap();
|
||||
|
||||
let transport = ostree_container::Transport::try_from(opts.transport.as_str())?;
|
||||
@@ -318,7 +327,6 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
|
||||
let target = ostree_container::OstreeImageReference { sigverify, imgref };
|
||||
|
||||
let fetched = pull(repo, &target, opts.quiet).await?;
|
||||
let merge_deployment = sysroot.merge_deployment(osname_v);
|
||||
|
||||
if !opts.retain {
|
||||
// By default, we prune the previous ostree ref or container image
|
||||
@@ -338,16 +346,7 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
|
||||
ostree_container::deploy::ORIGIN_CONTAINER,
|
||||
target.to_string().as_str(),
|
||||
);
|
||||
|
||||
let new_deployment = sysroot.stage_tree_with_options(
|
||||
osname_v,
|
||||
fetched.merge_commit.as_str(),
|
||||
Some(&origin),
|
||||
merge_deployment.as_ref(),
|
||||
&Default::default(),
|
||||
cancellable,
|
||||
)?;
|
||||
print_staged(&new_deployment)?;
|
||||
stage(&sysroot, &osname, &target, fetched, &origin).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -37,16 +37,6 @@ pub(crate) fn origin_has_rpmostree_stuff(kf: &glib::KeyFile) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Print the deployment we staged.
|
||||
pub(crate) fn print_staged(deployment: &ostree::Deployment) -> Result<()> {
|
||||
let (_origin, imgref) = get_image_origin(deployment)?;
|
||||
let imgref = imgref.ok_or_else(|| {
|
||||
anyhow::anyhow!("Internal error: expected a container deployment to be staged")
|
||||
})?;
|
||||
println!("Queued for next boot: {imgref}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Implement the `Serialize` trait for types that are `Display`.
|
||||
/// https://stackoverflow.com/questions/58103801/serialize-using-the-display-trait
|
||||
pub(crate) fn ser_with_display<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
|
||||
|
||||
Reference in New Issue
Block a user