Skip to content

Commit

Permalink
Merge pull request containers#848 from cgwalters/spinner-deploy
Browse files Browse the repository at this point in the history
 deploy: Add a spinner
  • Loading branch information
cgwalters authored Nov 5, 2024
2 parents 5a89d94 + daeafea commit 07593a0
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 26 deletions.
73 changes: 49 additions & 24 deletions lib/src/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ use ostree_ext::oci_spec::image::{Descriptor, Digest};
use ostree_ext::ostree::Deployment;
use ostree_ext::ostree::{self, Sysroot};
use ostree_ext::sysroot::SysrootLock;
use ostree_ext::tokio_util::spawn_blocking_cancellable_flatten;

use crate::spec::ImageReference;
use crate::spec::{BootOrder, HostSpec};
use crate::status::labels_of_config;
use crate::store::Storage;
use crate::utils::async_task_with_spinner;

// TODO use https://github.com/ostreedev/ostree-rs-ext/pull/493/commits/afc1837ff383681b947de30c0cefc70080a4f87a
const BASE_IMAGE_PREFIX: &str = "ostree/container/baseimage/bootc";
Expand Down Expand Up @@ -211,12 +213,14 @@ async fn handle_layer_progress_print(
let elapsed = end.duration_since(start);
let persec = total_read as f64 / elapsed.as_secs_f64();
let persec = indicatif::HumanBytes(persec as u64);
println!(
if let Err(e) = bar.println(&format!(
"Fetched layers: {} in {} ({}/s)",
indicatif::HumanBytes(total_read),
indicatif::HumanDuration(elapsed),
persec,
);
)) {
tracing::warn!("writing to stdout: {e}");
}
}

/// Wrapper for pulling a container image, wiring up status output.
Expand Down Expand Up @@ -373,8 +377,6 @@ async fn deploy(
image: &ImageState,
origin: &glib::KeyFile,
) -> Result<Deployment> {
let stateroot = Some(stateroot);
let mut opts = ostree::SysrootDeployTreeOpts::default();
// Compute the kernel argument overrides. In practice today this API is always expecting
// a merge deployment. The kargs code also always looks at the booted root (which
// is a distinct minor issue, but not super important as right now the install path
Expand All @@ -384,26 +386,49 @@ async fn deploy(
} else {
None
};
// Because the C API expects a Vec<&str>, we need to generate a new Vec<>
// that borrows.
let override_kargs = override_kargs
.as_deref()
.map(|v| v.iter().map(|s| s.as_str()).collect::<Vec<_>>());
if let Some(kargs) = override_kargs.as_deref() {
opts.override_kernel_argv = Some(&kargs);
}
// Copy to move into thread
let cancellable = gio::Cancellable::NONE;
return sysroot
.stage_tree_with_options(
stateroot,
image.ostree_commit.as_str(),
Some(origin),
merge_deployment,
&opts,
cancellable,
)
.map_err(Into::into);
// Clone all the things to move to worker thread
let sysroot_clone = sysroot.sysroot.clone();
// ostree::Deployment is incorrently !Send 😢 so convert it to an integer
let merge_deployment = merge_deployment.map(|d| d.index() as usize);
let stateroot = stateroot.to_string();
let ostree_commit = image.ostree_commit.to_string();
// GKeyFile also isn't Send! So we serialize that as a string...
let origin_data = origin.to_data();
let r = async_task_with_spinner(
"Deploying",
spawn_blocking_cancellable_flatten(move |cancellable| -> Result<_> {
let sysroot = sysroot_clone;
let stateroot = Some(stateroot);
let mut opts = ostree::SysrootDeployTreeOpts::default();

// Because the C API expects a Vec<&str>, we need to generate a new Vec<>
// that borrows.
let override_kargs = override_kargs
.as_deref()
.map(|v| v.iter().map(|s| s.as_str()).collect::<Vec<_>>());
if let Some(kargs) = override_kargs.as_deref() {
opts.override_kernel_argv = Some(&kargs);
}
let deployments = sysroot.deployments();
let merge_deployment = merge_deployment.map(|m| &deployments[m]);
let origin = glib::KeyFile::new();
origin.load_from_data(&origin_data, glib::KeyFileFlags::NONE)?;
let d = sysroot.stage_tree_with_options(
stateroot.as_deref(),
&ostree_commit,
Some(&origin),
merge_deployment,
&opts,
Some(cancellable),
)?;
Ok(d.index())
}),
)
.await?;
// SAFETY: We must have a staged deployment
let staged = sysroot.staged_deployment().unwrap();
assert_eq!(staged.index(), r);
Ok(staged)
}

#[context("Generating origin")]
Expand Down
12 changes: 10 additions & 2 deletions lib/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use std::time::Duration;

use anyhow::{Context, Result};
use cap_std_ext::cap_std::fs::Dir;
use indicatif::HumanDuration;
use libsystemd::logging::journal_print;
use ostree::glib;
use ostree_ext::container::SignatureSource;
use ostree_ext::ostree;
Expand Down Expand Up @@ -119,6 +121,7 @@ pub(crate) async fn async_task_with_spinner<F, T>(msg: &str, f: F) -> T
where
F: Future<Output = T>,
{
let start_time = std::time::Instant::now();
let pb = indicatif::ProgressBar::new_spinner();
let style = indicatif::ProgressStyle::default_bar();
pb.set_style(style.template("{spinner} {msg}").unwrap());
Expand All @@ -131,10 +134,15 @@ where
std::io::stdout().flush().unwrap();
}
let r = f.await;
let elapsed = HumanDuration(start_time.elapsed());
let _ = journal_print(
libsystemd::logging::Priority::Info,
&format!("completed task in {elapsed}: {msg}"),
);
if pb.is_hidden() {
println!("done");
println!("done ({elapsed})");
} else {
pb.finish_with_message(format!("{msg}: done"));
pb.finish_with_message(format!("{msg}: done ({elapsed})"));
}
r
}
Expand Down

0 comments on commit 07593a0

Please sign in to comment.