Skip to content

Commit 41c759c

Browse files
authored
Merge pull request fedora-iot#119 from say-paul/fix-os-type-detection
Detect OS via bootc incompatible flag; simplify logic
2 parents 92e6eda + 29f88be commit 41c759c

3 files changed

Lines changed: 37 additions & 19 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ test = true
1919
anyhow = "1"
2020
log = "0.4"
2121
clap = { version = "4.0", features = ["derive"] }
22-
config = "0.13.4"
22+
config = "0.15.13"
2323
pretty_env_logger = "0.5.0"
2424
nix = "0.30.1"
2525
glob = "0.3.0"

src/lib/handler.rs

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,54 @@
22

33
use anyhow::{Context, Result, anyhow, bail};
44
use serde_json::Value;
5-
use std::path::Path;
65
use std::process::Command;
76
use std::str;
87

98
use crate::grub::get_boot_counter;
109

1110
/// Detects if the system is managed by bootc or is a rpm-ostree system
11+
/// Inspect bootc status JSON and decide based on `status.booted.incompatible`.
1212
fn detect_os_deployment() -> Option<&'static str> {
13-
// 1. Check if this is a bootc-managed host.
14-
if let Ok(output) = Command::new("bootc")
13+
let output = match Command::new("bootc")
1514
.args(["status", "--booted", "--json"])
1615
.output()
17-
&& output.status.success()
18-
&& let Ok(json) = serde_json::from_slice::<Value>(&output.stdout)
19-
&& json.get("kind").and_then(|v| v.as_str()) == Some("BootcHost")
2016
{
21-
log::info!("System detected as bootc-managed host.");
22-
return Some("bootc");
23-
}
17+
Ok(output) => output,
18+
Err(_) => return None,
19+
};
2420

25-
// 2. If not bootc, check if it's an ostree-based OS by looking for /run/ostree-booted.
26-
if Path::new("/run/ostree-booted").exists() {
27-
log::info!("System detected as ostree-based (via /run/ostree-booted).");
28-
return Some("rpm-ostree");
21+
if !output.status.success() {
22+
log::error!("'bootc status --booted --json' exited with non-zero status");
23+
return None;
2924
}
3025

31-
// 3. If neither check passes, the deployment type is unsupported.
32-
log::warn!("System is neither bootc nor a known ostree variant.");
33-
None
26+
let json: Value = match serde_json::from_slice::<Value>(&output.stdout) {
27+
Ok(json) => json,
28+
Err(_) => {
29+
log::error!("Failed to parse JSON from 'bootc status --booted --json'");
30+
return None;
31+
}
32+
};
33+
34+
match json
35+
.get("status")
36+
.and_then(|s| s.get("booted"))
37+
.and_then(|b| b.get("incompatible"))
38+
.and_then(|i| i.as_bool())
39+
{
40+
Some(true) => {
41+
log::info!("System detected as rpm-ostree (incompatible=true)");
42+
Some("rpm-ostree")
43+
}
44+
Some(false) => {
45+
log::info!("System detected as bootc (incompatible=false)");
46+
Some("bootc")
47+
}
48+
None => {
49+
log::error!("bootc status JSON missing boolean field status.booted.incompatible");
50+
None
51+
}
52+
}
3453
}
3554

3655
/// reboots the system if boot_counter is greater than 0 or can be forced too

src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use greenboot::{
99
unset_boot_counter, unset_rollback_trigger,
1010
};
1111
use greenboot::{is_boot_rw, remount_boot_ro, remount_boot_rw};
12-
use serde::Deserialize;
1312
use std::process::Command;
1413

1514
/// greenboot config path
@@ -25,7 +24,7 @@ struct Cli {
2524
#[clap(subcommand)]
2625
command: Commands,
2726
}
28-
#[derive(Debug, Deserialize)]
27+
#[derive(Debug)]
2928
/// config params for greenboot
3029
struct GreenbootConfig {
3130
max_reboot: u16,

0 commit comments

Comments
 (0)