Skip to content

Commit f450cf3

Browse files
judavicgwalters
authored andcommitted
system-reinstall-bootc: add progress indication and fix implicit pull bug
Add a spinner during the capability check step and a status message before the long-running installation, addressing issue #1270. Also fix a latent bug: `bootc_has_clean` was called inside `reinstall_command`, which runs `podman run <image>` and would implicitly pull the image if not already cached locally. The flow is now three clearly distinct phases: 1. Pull phase: `pull_if_not_present` explicitly pulls the image first, with a message so the user knows what is happening. 2. Capability check phase: `bootc_has_clean` is called after the image is guaranteed to be local, with a spinner labeled "Checking image capabilities...". 3. Install phase: `reinstall_command` is now a pure command builder that takes `has_clean: bool` as a parameter with no I/O side effects. Fixes: #1270 Signed-off-by: Juan Gomez <1766933+judavi@users.noreply.github.com>
1 parent 8d2f98b commit f450cf3

File tree

4 files changed

+31
-5
lines changed

4 files changed

+31
-5
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/system-reinstall-bootc/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ tempfile = { workspace = true }
3232
tracing = { workspace = true }
3333
uzers = { workspace = true }
3434

35+
# Workspace dependencies (additional)
36+
indicatif = { workspace = true }
37+
3538
# Crate-specific dependencies
3639
crossterm = "0.29.0"
3740
dialoguer = "0.12.0"

crates/system-reinstall-bootc/src/main.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use bootc_utils::CommandRunExt;
55
use clap::Parser;
66
use fn_error_context::context;
77
use rustix::process::getuid;
8+
use std::time::Duration;
89

910
mod btrfs;
1011
mod config;
@@ -54,11 +55,24 @@ fn run() -> Result<()> {
5455

5556
podman::ensure_podman_installed()?;
5657

57-
//pull image early so it can be inspected, e.g. to check for cloud-init
58+
// Pull phase: explicitly pull the image before any other operations that use it.
59+
// This ensures no implicit pulls happen in later steps (e.g. capability check).
5860
podman::pull_if_not_present(&opts.image)?;
5961

6062
println!();
6163

64+
// Capability check phase: run after the image is guaranteed to be present locally.
65+
let spinner = indicatif::ProgressBar::new_spinner();
66+
spinner.set_style(
67+
indicatif::ProgressStyle::default_spinner()
68+
.template("{spinner} {msg}")
69+
.expect("Failed to parse spinner template"),
70+
);
71+
spinner.set_message("Checking image capabilities...");
72+
spinner.enable_steady_tick(Duration::from_millis(150));
73+
let has_clean = podman::bootc_has_clean(&opts.image)?;
74+
spinner.finish_and_clear();
75+
6276
let ssh_key_file = tempfile::NamedTempFile::new()?;
6377
let ssh_key_file_path = ssh_key_file
6478
.path()
@@ -71,7 +85,8 @@ fn run() -> Result<()> {
7185

7286
prompt::mount_warning()?;
7387

74-
let mut reinstall_podman_command = podman::reinstall_command(&opts, ssh_key_file_path)?;
88+
let mut reinstall_podman_command =
89+
podman::reinstall_command(&opts, ssh_key_file_path, has_clean)?;
7590

7691
println!();
7792
println!("Going to run command:");
@@ -85,6 +100,9 @@ fn run() -> Result<()> {
85100

86101
prompt::temporary_developer_protection_prompt()?;
87102

103+
println!("Starting bootc installation. This may take several minutes...");
104+
println!();
105+
88106
reinstall_podman_command
89107
.run_inherited_with_cmd_context()
90108
.context("running reinstall command")?;

crates/system-reinstall-bootc/src/podman.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::process::Command;
88
use which::which;
99

1010
#[context("bootc_has_clean")]
11-
fn bootc_has_clean(image: &str) -> Result<bool> {
11+
pub(crate) fn bootc_has_clean(image: &str) -> Result<bool> {
1212
let output = Command::new("podman")
1313
.args([
1414
"run",
@@ -25,7 +25,11 @@ fn bootc_has_clean(image: &str) -> Result<bool> {
2525
}
2626

2727
#[context("reinstall_command")]
28-
pub(crate) fn reinstall_command(opts: &ReinstallOpts, ssh_key_file: &str) -> Result<Command> {
28+
pub(crate) fn reinstall_command(
29+
opts: &ReinstallOpts,
30+
ssh_key_file: &str,
31+
has_clean: bool,
32+
) -> Result<Command> {
2933
let mut podman_command_and_args = [
3034
// We use podman to run the bootc container. This might change in the future to remove the
3135
// podman dependency.
@@ -80,7 +84,7 @@ pub(crate) fn reinstall_command(opts: &ReinstallOpts, ssh_key_file: &str) -> Res
8084
// bootc system for the first time.
8185
// This only happens if the bootc version in the image >= 1.1.8 (this is when the cleanup
8286
// feature was introduced)
83-
if bootc_has_clean(&opts.image)? {
87+
if has_clean {
8488
bootc_command_and_args.push("--cleanup".to_string());
8589
}
8690

0 commit comments

Comments
 (0)