From 21c7b3cb45ddd99d49c236f0cdb901c2dddb509d Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 19 Sep 2024 17:06:25 -0400 Subject: [PATCH 1/3] status: Change transport display Registry is the assumed default; let's be quieter (less output) in this default/expected case. If we're using something else (e.g. `oci`) then put it inline with the image name as that's something one can pass to e.g. `skopeo`. Signed-off-by: Colin Walters --- lib/src/fixtures/spec-via-local-oci.yaml | 28 +++++++++++++++++ lib/src/status.rs | 38 ++++++++++++++++-------- 2 files changed, 53 insertions(+), 13 deletions(-) create mode 100644 lib/src/fixtures/spec-via-local-oci.yaml diff --git a/lib/src/fixtures/spec-via-local-oci.yaml b/lib/src/fixtures/spec-via-local-oci.yaml new file mode 100644 index 00000000..a8231b68 --- /dev/null +++ b/lib/src/fixtures/spec-via-local-oci.yaml @@ -0,0 +1,28 @@ +apiVersion: org.containers.bootc/v1alpha1 +kind: BootcHost +metadata: + name: host +spec: + image: + image: /var/mnt/osupdate:latest + transport: oci + bootOrder: default +status: + staged: null + booted: + image: + image: + image: /var/mnt/osupdate + transport: oci + version: stream9.20240807.0 + timestamp: null + imageDigest: sha256:47e5ed613a970b6574bfa954ab25bb6e85656552899aa518b5961d9645102b38 + cachedUpdate: null + incompatible: false + pinned: false + ostree: + checksum: 439f6bd2e2361bee292c1f31840d798c5ac5ba76483b8021dc9f7b0164ac0f48 + deploySerial: 0 + rollback: null + rollbackQueued: false + type: bootcHost \ No newline at end of file diff --git a/lib/src/status.rs b/lib/src/status.rs index 1f00d020..e2f3eb18 100644 --- a/lib/src/status.rs +++ b/lib/src/status.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::collections::VecDeque; use std::io::IsTerminal; use std::io::Write; @@ -332,11 +333,16 @@ fn human_readable_output(mut out: impl Write, host: &Host) -> Result<()> { ] { if let Some(host_status) = status { if let Some(image) = &host_status.image { - writeln!( - out, - "Current {} image: {}", - status_string, image.image.image - )?; + let transport = &image.image.transport; + let imagename = &image.image.image; + // Registry is the default, so don't show that + let imageref = if transport == "registry" { + Cow::Borrowed(imagename) + } else { + // But for non-registry we include the transport + Cow::Owned(format!("{transport}:{imagename}")) + }; + writeln!(out, "Current {status_string} image: {imageref}")?; let version = image .version @@ -347,11 +353,9 @@ fn human_readable_output(mut out: impl Write, host: &Host) -> Result<()> { .as_ref() .map(|t| t.to_string()) .unwrap_or_else(|| "No timestamp present".to_owned()); - let transport = &image.image.transport; let digest = &image.image_digest; writeln!(out, " Image version: {version} ({timestamp})")?; - writeln!(out, " Image transport: {transport}")?; writeln!(out, " Image digest: {digest}")?; } else { writeln!(out, "Current {status_string} state is native ostree")?; @@ -383,11 +387,9 @@ mod tests { let expected = indoc::indoc! { r" Current staged image: quay.io/example/someimage:latest Image version: nightly (2023-10-14 19:22:15 UTC) - Image transport: registry Image digest: sha256:16dc2b6256b4ff0d2ec18d2dbfb06d117904010c8cf9732cdb022818cf7a7566 Current booted image: quay.io/example/someimage:latest Image version: nightly (2023-09-30 19:22:16 UTC) - Image transport: registry Image digest: sha256:736b359467c9437c1ac915acaae952aad854e07eb4a16a94999a48af08c83c34 No rollback image present "}; @@ -417,7 +419,6 @@ mod tests { let expected = indoc::indoc! { r" Current staged image: quay.io/centos-bootc/centos-bootc:stream9 Image version: stream9.20240807.0 (No timestamp present) - Image transport: registry Image digest: sha256:47e5ed613a970b6574bfa954ab25bb6e85656552899aa518b5961d9645102b38 Current booted state is native ostree No rollback image present @@ -434,7 +435,6 @@ mod tests { No staged image present Current booted image: quay.io/centos-bootc/centos-bootc:stream9 Image version: stream9.20240807.0 (No timestamp present) - Image transport: registry Image digest: sha256:47e5ed613a970b6574bfa954ab25bb6e85656552899aa518b5961d9645102b38 No rollback image present "}; @@ -449,17 +449,29 @@ mod tests { let expected = indoc::indoc! { r" Current staged image: quay.io/example/someimage:latest Image version: nightly (2023-10-14 19:22:15 UTC) - Image transport: registry Image digest: sha256:16dc2b6256b4ff0d2ec18d2dbfb06d117904010c8cf9732cdb022818cf7a7566 No booted image present Current rollback image: quay.io/example/someimage:latest Image version: nightly (2023-09-30 19:22:16 UTC) - Image transport: registry Image digest: sha256:736b359467c9437c1ac915acaae952aad854e07eb4a16a94999a48af08c83c34 "}; similar_asserts::assert_eq!(w, expected); } + #[test] + fn test_via_oci() { + let w = human_status_from_spec_fixture(include_str!("fixtures/spec-via-local-oci.yaml")) + .unwrap(); + let expected = indoc::indoc! { r" + No staged image present + Current booted image: oci:/var/mnt/osupdate + Image version: stream9.20240807.0 (No timestamp present) + Image digest: sha256:47e5ed613a970b6574bfa954ab25bb6e85656552899aa518b5961d9645102b38 + No rollback image present + "}; + similar_asserts::assert_eq!(w, expected); + } + #[test] fn test_convert_signatures() { use std::str::FromStr; From 3f11c4f70d7da861daa24d694325581638b7dd77 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 19 Sep 2024 17:08:42 -0400 Subject: [PATCH 2/3] status: Minor code refactorings - Rename variable to `slot_name` as I think it's a bit clearer Signed-off-by: Colin Walters --- lib/src/status.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/status.rs b/lib/src/status.rs index e2f3eb18..139df78b 100644 --- a/lib/src/status.rs +++ b/lib/src/status.rs @@ -326,7 +326,7 @@ pub(crate) async fn status(opts: super::cli::StatusOpts) -> Result<()> { } fn human_readable_output(mut out: impl Write, host: &Host) -> Result<()> { - for (status_string, status) in [ + for (slot_name, status) in [ ("staged", &host.status.staged), ("booted", &host.status.booted), ("rollback", &host.status.rollback), @@ -342,7 +342,7 @@ fn human_readable_output(mut out: impl Write, host: &Host) -> Result<()> { // But for non-registry we include the transport Cow::Owned(format!("{transport}:{imagename}")) }; - writeln!(out, "Current {status_string} image: {imageref}")?; + writeln!(out, "Current {slot_name} image: {imageref}")?; let version = image .version @@ -358,10 +358,10 @@ fn human_readable_output(mut out: impl Write, host: &Host) -> Result<()> { writeln!(out, " Image version: {version} ({timestamp})")?; writeln!(out, " Image digest: {digest}")?; } else { - writeln!(out, "Current {status_string} state is native ostree")?; + writeln!(out, "Current {slot_name} state is native ostree")?; } } else { - writeln!(out, "No {status_string} image present")?; + writeln!(out, "No {slot_name} image present")?; } } Ok(()) From 11508eb91a3dc87b617898961f55baf28e7ba21d Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 19 Sep 2024 17:11:55 -0400 Subject: [PATCH 3/3] status: Factor out helpers for rendering container image Prep for more work; no functional changes. Signed-off-by: Colin Walters --- lib/src/status.rs | 69 ++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/lib/src/status.rs b/lib/src/status.rs index 139df78b..8e652d50 100644 --- a/lib/src/status.rs +++ b/lib/src/status.rs @@ -325,6 +325,46 @@ pub(crate) async fn status(opts: super::cli::StatusOpts) -> Result<()> { Ok(()) } +/// Write the data for a container image based status. +fn human_render_imagestatus( + mut out: impl Write, + slot_name: &str, + image: &crate::spec::ImageStatus, +) -> Result<()> { + let transport = &image.image.transport; + let imagename = &image.image.image; + // Registry is the default, so don't show that + let imageref = if transport == "registry" { + Cow::Borrowed(imagename) + } else { + // But for non-registry we include the transport + Cow::Owned(format!("{transport}:{imagename}")) + }; + writeln!(out, "Current {slot_name} image: {imageref}")?; + + let version = image + .version + .as_deref() + .unwrap_or("No image version defined"); + let timestamp = image + .timestamp + .as_ref() + .map(|t| t.to_string()) + .unwrap_or_else(|| "No timestamp present".to_owned()); + let digest = &image.image_digest; + + writeln!(out, " Image version: {version} ({timestamp})")?; + writeln!(out, " Image digest: {digest}")?; + Ok(()) +} + +fn human_render_ostree(mut out: impl Write, slot_name: &str, _ostree_commit: &str) -> Result<()> { + // TODO consider rendering more ostree stuff here like rpm-ostree status does + writeln!(out, "Current {slot_name} state is native ostree")?; + Ok(()) +} + +/// Implementation of rendering our host structure in a "human readable" way. fn human_readable_output(mut out: impl Write, host: &Host) -> Result<()> { for (slot_name, status) in [ ("staged", &host.status.staged), @@ -333,32 +373,11 @@ fn human_readable_output(mut out: impl Write, host: &Host) -> Result<()> { ] { if let Some(host_status) = status { if let Some(image) = &host_status.image { - let transport = &image.image.transport; - let imagename = &image.image.image; - // Registry is the default, so don't show that - let imageref = if transport == "registry" { - Cow::Borrowed(imagename) - } else { - // But for non-registry we include the transport - Cow::Owned(format!("{transport}:{imagename}")) - }; - writeln!(out, "Current {slot_name} image: {imageref}")?; - - let version = image - .version - .as_deref() - .unwrap_or("No image version defined"); - let timestamp = image - .timestamp - .as_ref() - .map(|t| t.to_string()) - .unwrap_or_else(|| "No timestamp present".to_owned()); - let digest = &image.image_digest; - - writeln!(out, " Image version: {version} ({timestamp})")?; - writeln!(out, " Image digest: {digest}")?; + human_render_imagestatus(&mut out, slot_name, image)?; + } else if let Some(ostree) = host_status.ostree.as_ref() { + human_render_ostree(&mut out, slot_name, &ostree.checksum)?; } else { - writeln!(out, "Current {slot_name} state is native ostree")?; + writeln!(out, "Current {slot_name} state is unknown")?; } } else { writeln!(out, "No {slot_name} image present")?;