Skip to content

Commit d0109ac

Browse files
committed
Add HostType, change status to always succeed
Closes: #242 Basically it'd be useful for folks to be able to run `bootc status --json` and have that always work - if we're not on a bootc-booted system then we just output null data. Specifically we drop the `isContainer` field and replace it with an optional non-exhaustive enumeration. For anything we don't know about we just output `None` i.e. `null` in JSON. Signed-off-by: Colin Walters <[email protected]>
1 parent 95ccd5c commit d0109ac

File tree

4 files changed

+57
-14
lines changed

4 files changed

+57
-14
lines changed

lib/src/privtests.rs

Lines changed: 3 additions & 1 deletion
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

@@ -103,7 +105,7 @@ pub(crate) fn impl_run_container() -> Result<()> {
103105
assert!(ostree_ext::container_utils::is_ostree_container()?);
104106
let sh = Shell::new()?;
105107
let host: Host = serde_yaml::from_str(&cmd!(sh, "bootc status").read()?)?;
106-
assert!(host.status.is_container);
108+
assert!(matches!(host.status.ty, Some(HostType::BootcContainer)));
107109
println!("ok status");
108110

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

lib/src/spec.rs

Lines changed: 25 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,18 @@ 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+
/// The current system is running as a container that is bootable.
108+
BootcContainer,
109+
}
110+
97111
/// The status of the host system
98112
#[derive(Debug, Clone, Serialize, Default, Deserialize, PartialEq, Eq, JsonSchema)]
99113
#[serde(rename_all = "camelCase")]
@@ -105,15 +119,16 @@ pub struct HostStatus {
105119
/// The previously booted image
106120
pub rollback: Option<BootEntry>,
107121

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

112127
impl Host {
113128
/// Create a new host
114-
pub fn new(name: &str, spec: HostSpec) -> Self {
129+
pub fn new(spec: HostSpec) -> Self {
115130
let metadata = k8sapitypes::ObjectMeta {
116-
name: Some(name.to_owned()),
131+
name: Some(OBJECT_NAME.to_owned()),
117132
..Default::default()
118133
};
119134
Self {
@@ -128,6 +143,12 @@ impl Host {
128143
}
129144
}
130145

146+
impl Default for Host {
147+
fn default() -> Self {
148+
Self::new(Default::default())
149+
}
150+
}
151+
131152
#[cfg(test)]
132153
mod tests {
133154
use super::*;

lib/src/status.rs

Lines changed: 22 additions & 9 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,12 +247,26 @@ 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 if ostree_ext::container_utils::is_ostree_container()? {
259+
Some(HostType::BootcContainer)
260+
} else {
261+
None
262+
};
263+
264+
let mut host = Host::new(spec);
254265
host.status = HostStatus {
255266
staged,
256267
booted,
257268
rollback,
258-
is_container,
269+
ty,
259270
};
260271
Ok((deployments, host))
261272
}
@@ -265,12 +276,14 @@ pub(crate) fn get_status(
265276
pub(crate) async fn status(opts: super::cli::StatusOpts) -> Result<()> {
266277
let host = if ostree_ext::container_utils::is_ostree_container()? {
267278
let status = HostStatus {
268-
is_container: true,
279+
ty: Some(HostType::BootcContainer),
269280
..Default::default()
270281
};
271-
let mut r = Host::new(OBJECT_NAME, HostSpec { image: None });
282+
let mut r = Host::new(Default::default());
272283
r.status = status;
273284
r
285+
} else if !Utf8Path::new("/run/ostree-booted").try_exists()? {
286+
Default::default()
274287
} else {
275288
crate::cli::require_root()?;
276289
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)