Skip to content

Commit d2a2326

Browse files
authored
Merge pull request #244 from cgwalters/reliable-status
Add `HostType`, change `status` to always succeed
2 parents 226227f + 69a7f37 commit d2a2326

File tree

4 files changed

+51
-21
lines changed

4 files changed

+51
-21
lines changed

lib/src/privtests.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use fn_error_context::context;
66
use rustix::fd::AsFd;
77
use xshell::{cmd, Shell};
88

9+
use crate::spec::HostType;
10+
911
use super::cli::TestingOpts;
1012
use super::spec::Host;
1113

@@ -100,10 +102,9 @@ pub(crate) fn impl_run_host() -> Result<()> {
100102

101103
#[context("Container tests")]
102104
pub(crate) fn impl_run_container() -> Result<()> {
103-
assert!(ostree_ext::container_utils::is_ostree_container()?);
104105
let sh = Shell::new()?;
105106
let host: Host = serde_yaml::from_str(&cmd!(sh, "bootc status").read()?)?;
106-
assert!(host.status.is_container);
107+
assert!(matches!(host.status.ty, None));
107108
println!("ok status");
108109

109110
for c in ["upgrade", "update"] {

lib/src/spec.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use crate::k8sapitypes;
77

88
const API_VERSION: &str = "org.containers.bootc/v1alpha1";
99
const KIND: &str = "BootcHost";
10+
/// The default object name we use; there's only one.
11+
pub(crate) const OBJECT_NAME: &str = "host";
1012

1113
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
1214
#[serde(rename_all = "camelCase")]
@@ -94,6 +96,16 @@ pub struct BootEntry {
9496
pub ostree: Option<BootEntryOstree>,
9597
}
9698

99+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
100+
#[serde(rename_all = "camelCase")]
101+
#[non_exhaustive]
102+
/// The detected type of running system. Note that this is not exhaustive
103+
/// and new variants may be added in the future.
104+
pub enum HostType {
105+
/// The current system is deployed in a bootc compatible way.
106+
BootcHost,
107+
}
108+
97109
/// The status of the host system
98110
#[derive(Debug, Clone, Serialize, Default, Deserialize, PartialEq, Eq, JsonSchema)]
99111
#[serde(rename_all = "camelCase")]
@@ -105,15 +117,16 @@ pub struct HostStatus {
105117
/// The previously booted image
106118
pub rollback: Option<BootEntry>,
107119

108-
/// Whether or not the current system state is an ostree-based container
109-
pub is_container: bool,
120+
/// The detected type of system
121+
#[serde(rename = "type")]
122+
pub ty: Option<HostType>,
110123
}
111124

112125
impl Host {
113126
/// Create a new host
114-
pub fn new(name: &str, spec: HostSpec) -> Self {
127+
pub fn new(spec: HostSpec) -> Self {
115128
let metadata = k8sapitypes::ObjectMeta {
116-
name: Some(name.to_owned()),
129+
name: Some(OBJECT_NAME.to_owned()),
117130
..Default::default()
118131
};
119132
Self {
@@ -128,6 +141,12 @@ impl Host {
128141
}
129142
}
130143

144+
impl Default for Host {
145+
fn default() -> Self {
146+
Self::new(Default::default())
147+
}
148+
}
149+
131150
#[cfg(test)]
132151
mod tests {
133152
use super::*;

lib/src/status.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use std::collections::VecDeque;
22

3-
use crate::spec::{BootEntry, Host, HostSpec, HostStatus, ImageStatus};
3+
use crate::spec::{BootEntry, Host, HostSpec, HostStatus, HostType, ImageStatus};
44
use crate::spec::{ImageReference, ImageSignature};
55
use anyhow::{Context, Result};
6+
use camino::Utf8Path;
67
use fn_error_context::context;
78
use ostree::glib;
89
use ostree_container::OstreeImageReference;
@@ -12,8 +13,6 @@ use ostree_ext::oci_spec;
1213
use ostree_ext::ostree;
1314
use ostree_ext::sysroot::SysrootLock;
1415

15-
const OBJECT_NAME: &str = "host";
16-
1716
impl From<ostree_container::SignatureSource> for ImageSignature {
1817
fn from(sig: ostree_container::SignatureSource) -> Self {
1918
use ostree_container::SignatureSource;
@@ -223,8 +222,6 @@ pub(crate) fn get_status(
223222
other,
224223
};
225224

226-
let is_container = ostree_ext::container_utils::is_ostree_container()?;
227-
228225
let staged = deployments
229226
.staged
230227
.as_ref()
@@ -250,27 +247,33 @@ pub(crate) fn get_status(
250247
image: Some(img.image.clone()),
251248
})
252249
.unwrap_or_default();
253-
let mut host = Host::new(OBJECT_NAME, spec);
250+
251+
let ty = if booted
252+
.as_ref()
253+
.map(|b| b.image.is_some())
254+
.unwrap_or_default()
255+
{
256+
// We're only of type BootcHost if we booted via container image
257+
Some(HostType::BootcHost)
258+
} else {
259+
None
260+
};
261+
262+
let mut host = Host::new(spec);
254263
host.status = HostStatus {
255264
staged,
256265
booted,
257266
rollback,
258-
is_container,
267+
ty,
259268
};
260269
Ok((deployments, host))
261270
}
262271

263272
/// Implementation of the `bootc status` CLI command.
264273
#[context("Status")]
265274
pub(crate) async fn status(opts: super::cli::StatusOpts) -> Result<()> {
266-
let host = if ostree_ext::container_utils::is_ostree_container()? {
267-
let status = HostStatus {
268-
is_container: true,
269-
..Default::default()
270-
};
271-
let mut r = Host::new(OBJECT_NAME, HostSpec { image: None });
272-
r.status = status;
273-
r
275+
let host = if !Utf8Path::new("/run/ostree-booted").try_exists()? {
276+
Default::default()
274277
} else {
275278
crate::cli::require_root()?;
276279
let sysroot = super::cli::get_locked_sysroot().await?;

tests/kolainst/basic

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ case "${AUTOPKGTEST_REBOOT_MARK:-}" in
1919
echo "booted into $image"
2020
echo "ok status test"
2121

22+
host_ty=$(jq -r '.status.type' < status.json)
23+
test "${host_ty}" = "bootcHost"
24+
# Now fake things out with an empty /run
25+
unshare -m /bin/sh -c 'mount -t tmpfs tmpfs /run; bootc status --json > status-no-run.json'
26+
host_ty_norun=$(jq -r '.status.type' < status-no-run.json)
27+
test "${host_ty_norun}" = "null"
28+
2229
test "null" = $(jq '.status.staged' < status.json)
2330
# Should be a no-op
2431
bootc update

0 commit comments

Comments
 (0)