Skip to content

Commit 8ab8d31

Browse files
committed
Part of #904
Displays pinned deployments as part of "bootc status". Includes unit tests to ensure correct parsing of the pinned deployments, and that they are displayed in human readable formats correctly. Signed-off-by: Robert Sturla <[email protected]>
1 parent 93b22f4 commit 8ab8d31

File tree

3 files changed

+112
-13
lines changed

3 files changed

+112
-13
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
apiVersion: org.containers.bootc/v1alpha1
2+
kind: BootcHost
3+
metadata:
4+
name: host
5+
spec:
6+
image:
7+
image: quay.io/centos-bootc/centos-bootc:stream9
8+
transport: registry
9+
bootOrder: default
10+
status:
11+
staged: null
12+
booted:
13+
image:
14+
image:
15+
image: quay.io/centos-bootc/centos-bootc:stream9
16+
transport: registry
17+
architecture: arm64
18+
version: stream9.20240807.0
19+
timestamp: null
20+
imageDigest: sha256:47e5ed613a970b6574bfa954ab25bb6e85656552899aa518b5961d9645102b38
21+
cachedUpdate: null
22+
incompatible: false
23+
pinned: true
24+
ostree:
25+
checksum: 439f6bd2e2361bee292c1f31840d798c5ac5ba76483b8021dc9f7b0164ac0f48
26+
deploySerial: 0
27+
otherDeployments:
28+
- image:
29+
image:
30+
image: quay.io/centos-bootc/centos-bootc:stream9
31+
transport: registry
32+
version: stream9.20240807.0
33+
timestamp: null
34+
imageDigest: sha256:47e5ed613a970b6574bfa954ab25bb6e85656552899aa518b5961d9645102b37
35+
architecture: arm64
36+
cachedUpdate: null
37+
incompatible: false
38+
pinned: true
39+
ostree:
40+
checksum: 99b2cc3b6edce9ebaef6a6076effa5ee3e1dcff3523016ffc94a1b27c6c67e12
41+
deploySerial: 0
42+
rollback: null
43+
rollbackQueued: false
44+
type: bootcHost

lib/src/spec.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ pub struct HostStatus {
154154
pub booted: Option<BootEntry>,
155155
/// The previously booted image
156156
pub rollback: Option<BootEntry>,
157+
/// Other deployments (i.e. pinned)
158+
#[serde(skip_serializing_if = "Vec::is_empty")]
159+
#[serde(default)]
160+
pub other_deployments: Vec<BootEntry>,
157161
/// Set to true if the rollback entry is queued for the next boot.
158162
#[serde(default)]
159163
pub rollback_queued: bool,

lib/src/status.rs

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,11 @@ pub(crate) fn get_status(
253253
.map(|d| boot_entry_from_deployment(sysroot, d))
254254
.transpose()
255255
.context("Rollback deployment")?;
256+
let other_deployments = deployments
257+
.other
258+
.iter()
259+
.map(|d| boot_entry_from_deployment(sysroot, d))
260+
.collect::<Result<Vec<_>>>()?;
256261
let spec = staged
257262
.as_ref()
258263
.or(booted.as_ref())
@@ -279,6 +284,7 @@ pub(crate) fn get_status(
279284
staged,
280285
booted,
281286
rollback,
287+
other_deployments,
282288
rollback_queued,
283289
ty,
284290
};
@@ -361,7 +367,7 @@ fn write_row_name(mut out: impl Write, s: &str, prefix_len: usize) -> Result<()>
361367
/// Write the data for a container image based status.
362368
fn human_render_slot(
363369
mut out: impl Write,
364-
slot: Slot,
370+
slot: Option<Slot>,
365371
entry: &crate::spec::BootEntry,
366372
image: &crate::spec::ImageStatus,
367373
) -> Result<()> {
@@ -375,9 +381,10 @@ fn human_render_slot(
375381
Cow::Owned(format!("{transport}:{imagename}"))
376382
};
377383
let prefix = match slot {
378-
Slot::Staged => " Staged image".into(),
379-
Slot::Booted => format!("{} Booted image", crate::glyph::Glyph::BlackCircle),
380-
Slot::Rollback => " Rollback image".into(),
384+
Some(Slot::Staged) => " Staged image".into(),
385+
Some(Slot::Booted) => format!("{} Booted image", crate::glyph::Glyph::BlackCircle),
386+
Some(Slot::Rollback) => " Rollback image".into(),
387+
_ => " Other image".into(),
381388
};
382389
let prefix_len = prefix.chars().count();
383390
writeln!(out, "{prefix}: {imageref}")?;
@@ -408,6 +415,11 @@ fn human_render_slot(
408415
writeln!(out, "{timestamp}")?;
409416
}
410417

418+
if entry.pinned {
419+
write_row_name(&mut out, "Pinned", prefix_len)?;
420+
writeln!(out, "yes")?;
421+
}
422+
411423
tracing::debug!("pinned={}", entry.pinned);
412424

413425
Ok(())
@@ -416,20 +428,27 @@ fn human_render_slot(
416428
/// Output a rendering of a non-container boot entry.
417429
fn human_render_slot_ostree(
418430
mut out: impl Write,
419-
slot: Slot,
431+
slot: Option<Slot>,
420432
entry: &crate::spec::BootEntry,
421433
ostree_commit: &str,
422434
) -> Result<()> {
423435
// TODO consider rendering more ostree stuff here like rpm-ostree status does
424436
let prefix = match slot {
425-
Slot::Staged => " Staged ostree".into(),
426-
Slot::Booted => format!("{} Booted ostree", crate::glyph::Glyph::BlackCircle),
427-
Slot::Rollback => " Rollback ostree".into(),
437+
Some(Slot::Staged) => " Staged ostree".into(),
438+
Some(Slot::Booted) => format!("{} Booted ostree", crate::glyph::Glyph::BlackCircle),
439+
Some(Slot::Rollback) => " Rollback ostree".into(),
440+
_ => " Other ostree".into(),
428441
};
429442
let prefix_len = prefix.len();
430443
writeln!(out, "{prefix}")?;
431444
write_row_name(&mut out, "Commit", prefix_len)?;
432445
writeln!(out, "{ostree_commit}")?;
446+
447+
if entry.pinned {
448+
write_row_name(&mut out, "Pinned", prefix_len)?;
449+
writeln!(out, "yes")?;
450+
}
451+
433452
tracing::debug!("pinned={}", entry.pinned);
434453
Ok(())
435454
}
@@ -448,14 +467,27 @@ fn human_readable_output_booted(mut out: impl Write, host: &Host) -> Result<()>
448467
writeln!(out)?;
449468
}
450469
if let Some(image) = &host_status.image {
451-
human_render_slot(&mut out, slot_name, host_status, image)?;
470+
human_render_slot(&mut out, Some(slot_name), host_status, image)?;
452471
} else if let Some(ostree) = host_status.ostree.as_ref() {
453-
human_render_slot_ostree(&mut out, slot_name, host_status, &ostree.checksum)?;
472+
human_render_slot_ostree(&mut out, Some(slot_name), host_status, &ostree.checksum)?;
454473
} else {
455474
writeln!(out, "Current {slot_name} state is unknown")?;
456475
}
457476
}
458477
}
478+
479+
if !host.status.other_deployments.is_empty() {
480+
for entry in &host.status.other_deployments {
481+
writeln!(out)?;
482+
483+
if let Some(image) = &entry.image {
484+
human_render_slot(&mut out, None, entry, image)?;
485+
} else if let Some(ostree) = entry.ostree.as_ref() {
486+
human_render_slot_ostree(&mut out, None, entry, &ostree.checksum)?;
487+
}
488+
}
489+
}
490+
459491
Ok(())
460492
}
461493

@@ -490,7 +522,7 @@ mod tests {
490522
Staged image: quay.io/example/someimage:latest
491523
Digest: sha256:16dc2b6256b4ff0d2ec18d2dbfb06d117904010c8cf9732cdb022818cf7a7566 (arm64)
492524
Version: nightly (2023-10-14T19:22:15Z)
493-
525+
494526
● Booted image: quay.io/example/someimage:latest
495527
Digest: sha256:736b359467c9437c1ac915acaae952aad854e07eb4a16a94999a48af08c83c34 (arm64)
496528
Version: nightly (2023-09-30T19:22:16Z)
@@ -508,7 +540,7 @@ mod tests {
508540
let expected = indoc::indoc! { r"
509541
Staged ostree
510542
Commit: 1c24260fdd1be20f72a4a97a75c582834ee3431fbb0fa8e4f482bb219d633a45
511-
543+
512544
● Booted ostree
513545
Commit: f9fa3a553ceaaaf30cf85bfe7eed46a822f7b8fd7e14c1e3389cbc3f6d27f791
514546
"};
@@ -524,7 +556,7 @@ mod tests {
524556
Staged image: quay.io/centos-bootc/centos-bootc:stream9
525557
Digest: sha256:47e5ed613a970b6574bfa954ab25bb6e85656552899aa518b5961d9645102b38 (s390x)
526558
Version: stream9.20240807.0
527-
559+
528560
● Booted ostree
529561
Commit: f9fa3a553ceaaaf30cf85bfe7eed46a822f7b8fd7e14c1e3389cbc3f6d27f791
530562
"};
@@ -588,4 +620,23 @@ mod tests {
588620
Some(ImageSignature::OstreeRemote("fedora".into()))
589621
);
590622
}
623+
624+
#[test]
625+
fn test_human_readable_booted_pinned_spec() {
626+
// booted image, no staged/rollback
627+
let w = human_status_from_spec_fixture(include_str!("fixtures/spec-booted-pinned.yaml"))
628+
.expect("No spec found");
629+
let expected = indoc::indoc! { r"
630+
● Booted image: quay.io/centos-bootc/centos-bootc:stream9
631+
Digest: sha256:47e5ed613a970b6574bfa954ab25bb6e85656552899aa518b5961d9645102b38 (arm64)
632+
Version: stream9.20240807.0
633+
Pinned: yes
634+
635+
Other image: quay.io/centos-bootc/centos-bootc:stream9
636+
Digest: sha256:47e5ed613a970b6574bfa954ab25bb6e85656552899aa518b5961d9645102b37 (arm64)
637+
Version: stream9.20240807.0
638+
Pinned: yes
639+
"};
640+
similar_asserts::assert_eq!(w, expected);
641+
}
591642
}

0 commit comments

Comments
 (0)