Skip to content

Commit f7e78fb

Browse files
authored
Merge pull request #57 from say-paul/enable-rpm-ostree-rollback
enable rollback as per detected system type
2 parents cd19ce8 + e1a6182 commit f7e78fb

1 file changed

Lines changed: 52 additions & 9 deletions

File tree

src/lib/handler.rs

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,39 @@
11
use anyhow::{Context, Result, anyhow, bail};
2+
use std::path::Path;
23
use std::process::Command;
34
use std::str;
45

56
use crate::grub::get_boot_counter;
67

8+
/// Detects if the system is managed by bootc or is a rpm-ostree system
9+
fn detect_os_deployment() -> Option<&'static str> {
10+
// 1. Check if this is a bootc-managed host.
11+
if let Ok(output) = Command::new("bootc")
12+
.args(["status", "--booted", "--json"])
13+
.output()
14+
{
15+
if output.status.success() {
16+
let stdout_str = String::from_utf8_lossy(&output.stdout);
17+
// Check for the key-value pair as a substring. This is less robust
18+
// than proper JSON parsing but avoids the external dependency.
19+
if stdout_str.contains(r#""type": "bootcHost""#) {
20+
log::info!("System detected as bootc-managed host.");
21+
return Some("bootc");
22+
}
23+
}
24+
}
25+
26+
// 2. If not bootc, check if it's an ostree-based OS by looking for /run/ostree-booted.
27+
if Path::new("/run/ostree-booted").exists() {
28+
log::info!("System detected as ostree-based (via /run/ostree-booted).");
29+
return Some("rpm-ostree");
30+
}
31+
32+
// 3. If neither check passes, the deployment type is unsupported.
33+
log::warn!("System is neither bootc nor a known ostree variant.");
34+
None
35+
}
36+
737
/// reboots the system if boot_counter is greater than 0 or can be forced too
838
pub fn handle_reboot(force: bool) -> Result<()> {
939
if !force {
@@ -17,7 +47,7 @@ pub fn handle_reboot(force: bool) -> Result<()> {
1747
Ok(())
1848
}
1949

20-
/// rollback to previous deployment if boot counter is less than 0
50+
/// Rollback to the previous deployment if the boot counter allows.
2151
pub fn handle_rollback() -> Result<()> {
2252
let boot_counter = get_boot_counter("/boot/grub2/grubenv")?;
2353

@@ -28,17 +58,30 @@ pub fn handle_rollback() -> Result<()> {
2858
}
2959
// Proceed with rollback if boot_counter is <= 0
3060
Some(counter) if counter <= 0 => {
31-
log::info!("Greenboot will now attempt to rollback to previous deployment");
32-
let status = Command::new("bootc")
33-
.arg("rollback")
34-
.status()
35-
.context("Failed to execute bootc rollback")?;
36-
if !status.success() {
37-
bail!("Rollback error: {}", status);
61+
log::info!("Greenboot will now attempt to rollback to a previous deployment.");
62+
if let Some(deployment_cmd) = detect_os_deployment() {
63+
log::info!(
64+
"Deployment manager '{}' detected, attempting rollback.",
65+
deployment_cmd
66+
);
67+
let status = Command::new(deployment_cmd)
68+
.arg("rollback")
69+
.status()
70+
.context(format!("Failed to execute '{} rollback'", deployment_cmd))?;
71+
72+
if !status.success() {
73+
bail!(
74+
"Rollback with '{}' failed with status: {}",
75+
deployment_cmd,
76+
status
77+
);
78+
}
79+
} else {
80+
bail!("Rollback only supported in bootc or rpm-ostree environment.");
3881
}
3982
Ok(())
4083
}
41-
// Reject if boot_counter is > 0 with the actual value
84+
// Reject if boot_counter is > 0
4285
Some(counter) => bail!("Rollback not initiated as boot_counter is {}", counter),
4386
}
4487
}

0 commit comments

Comments
 (0)