@@ -253,6 +253,15 @@ pub(crate) fn get_status(
253253 . map ( |d| boot_entry_from_deployment ( sysroot, d) )
254254 . transpose ( )
255255 . context ( "Rollback deployment" ) ?;
256+ let pinned = deployments
257+ . other
258+ . iter ( )
259+ . filter_map ( |d| {
260+ d. is_pinned ( )
261+ . then ( || boot_entry_from_deployment ( sysroot, d) . ok ( ) )
262+ } )
263+ . collect :: < Option < Vec < _ > > > ( )
264+ . filter ( |v| !v. is_empty ( ) ) ;
256265 let spec = staged
257266 . as_ref ( )
258267 . or ( booted. as_ref ( ) )
@@ -280,6 +289,7 @@ pub(crate) fn get_status(
280289 booted,
281290 rollback,
282291 rollback_queued,
292+ pinned,
283293 ty,
284294 } ;
285295 Ok ( ( deployments, host) )
@@ -336,6 +346,7 @@ pub enum Slot {
336346 Staged ,
337347 Booted ,
338348 Rollback ,
349+ Pinned ,
339350}
340351
341352impl std:: fmt:: Display for Slot {
@@ -344,6 +355,7 @@ impl std::fmt::Display for Slot {
344355 Slot :: Staged => "staged" ,
345356 Slot :: Booted => "booted" ,
346357 Slot :: Rollback => "rollback" ,
358+ Slot :: Pinned => "pinned" ,
347359 } ;
348360 f. write_str ( s)
349361 }
@@ -359,10 +371,11 @@ fn write_row_name(mut out: impl Write, s: &str, prefix_len: usize) -> Result<()>
359371}
360372
361373/// Write the data for a container image based status.
362- fn human_render_imagestatus (
374+ fn human_render_image_deployment (
363375 mut out : impl Write ,
364376 slot : Slot ,
365377 image : & crate :: spec:: ImageStatus ,
378+ host_status : & crate :: spec:: HostStatus ,
366379) -> Result < ( ) > {
367380 let transport = & image. image . transport ;
368381 let imagename = & image. image . image ;
@@ -377,6 +390,7 @@ fn human_render_imagestatus(
377390 Slot :: Staged => " Staged image" . into ( ) ,
378391 Slot :: Booted => format ! ( "{} Booted image" , crate :: glyph:: Glyph :: BlackCircle ) ,
379392 Slot :: Rollback => " Rollback image" . into ( ) ,
393+ Slot :: Pinned => " Pinned image" . into ( ) ,
380394 } ;
381395 let prefix_len = prefix. chars ( ) . count ( ) ;
382396 writeln ! ( out, "{prefix}: {imageref}" ) ?;
@@ -407,20 +421,37 @@ fn human_render_imagestatus(
407421 writeln ! ( out, "{timestamp}" ) ?;
408422 }
409423
424+ if host_status. is_pinned ( slot) {
425+ write_row_name ( & mut out, "Pinned" , prefix_len) ?;
426+ writeln ! ( out, "yes" ) ?;
427+ }
428+
410429 Ok ( ( ) )
411430}
412431
413- fn human_render_ostree ( mut out : impl Write , slot : Slot , ostree_commit : & str ) -> Result < ( ) > {
432+ fn human_render_ostree_deployment (
433+ mut out : impl Write ,
434+ slot : Slot ,
435+ ostree_commit : & str ,
436+ host_status : & crate :: spec:: HostStatus ,
437+ ) -> Result < ( ) > {
414438 // TODO consider rendering more ostree stuff here like rpm-ostree status does
415439 let prefix = match slot {
416440 Slot :: Staged => " Staged ostree" . into ( ) ,
417441 Slot :: Booted => format ! ( "{} Booted ostree" , crate :: glyph:: Glyph :: BlackCircle ) ,
418442 Slot :: Rollback => " Rollback ostree" . into ( ) ,
443+ Slot :: Pinned => " Pinned ostree" . into ( ) ,
419444 } ;
420445 let prefix_len = prefix. len ( ) ;
421446 writeln ! ( out, "{prefix}" ) ?;
422447 write_row_name ( & mut out, "Commit" , prefix_len) ?;
423448 writeln ! ( out, "{ostree_commit}" ) ?;
449+
450+ if host_status. is_pinned ( slot) {
451+ write_row_name ( & mut out, "Pinned" , prefix_len) ?;
452+ writeln ! ( out, "yes" ) ?;
453+ }
454+
424455 Ok ( ( ) )
425456}
426457
@@ -438,14 +469,36 @@ fn human_readable_output_booted(mut out: impl Write, host: &Host) -> Result<()>
438469 writeln ! ( out) ?;
439470 }
440471 if let Some ( image) = & host_status. image {
441- human_render_imagestatus ( & mut out, slot_name, image) ?;
472+ human_render_image_deployment ( & mut out, slot_name, image, & host . status ) ?;
442473 } else if let Some ( ostree) = host_status. ostree . as_ref ( ) {
443- human_render_ostree ( & mut out, slot_name, & ostree. checksum ) ?;
474+ human_render_ostree_deployment (
475+ & mut out,
476+ slot_name,
477+ & ostree. checksum ,
478+ & host. status ,
479+ ) ?;
444480 } else {
445481 writeln ! ( out, "Current {slot_name} state is unknown" ) ?;
446482 }
447483 }
448484 }
485+
486+ if let Some ( pinned) = & host. status . pinned {
487+ writeln ! ( out) ?;
488+ for entry in pinned {
489+ if let Some ( image) = & entry. image {
490+ human_render_image_deployment ( & mut out, Slot :: Pinned , image, & host. status ) ?;
491+ } else if let Some ( ostree) = entry. ostree . as_ref ( ) {
492+ human_render_ostree_deployment (
493+ & mut out,
494+ Slot :: Pinned ,
495+ & ostree. checksum ,
496+ & host. status ,
497+ ) ?;
498+ }
499+ }
500+ }
501+
449502 Ok ( ( ) )
450503}
451504
@@ -480,7 +533,7 @@ mod tests {
480533 Staged image: quay.io/example/someimage:latest
481534 Digest: sha256:16dc2b6256b4ff0d2ec18d2dbfb06d117904010c8cf9732cdb022818cf7a7566 (arm64)
482535 Version: nightly (2023-10-14T19:22:15Z)
483-
536+
484537 ● Booted image: quay.io/example/someimage:latest
485538 Digest: sha256:736b359467c9437c1ac915acaae952aad854e07eb4a16a94999a48af08c83c34 (arm64)
486539 Version: nightly (2023-09-30T19:22:16Z)
@@ -498,7 +551,7 @@ mod tests {
498551 let expected = indoc:: indoc! { r"
499552 Staged ostree
500553 Commit: 1c24260fdd1be20f72a4a97a75c582834ee3431fbb0fa8e4f482bb219d633a45
501-
554+
502555 ● Booted ostree
503556 Commit: f9fa3a553ceaaaf30cf85bfe7eed46a822f7b8fd7e14c1e3389cbc3f6d27f791
504557 " } ;
@@ -514,7 +567,7 @@ mod tests {
514567 Staged image: quay.io/centos-bootc/centos-bootc:stream9
515568 Digest: sha256:47e5ed613a970b6574bfa954ab25bb6e85656552899aa518b5961d9645102b38 (s390x)
516569 Version: stream9.20240807.0
517-
570+
518571 ● Booted ostree
519572 Commit: f9fa3a553ceaaaf30cf85bfe7eed46a822f7b8fd7e14c1e3389cbc3f6d27f791
520573 " } ;
@@ -534,6 +587,25 @@ mod tests {
534587 similar_asserts:: assert_eq!( w, expected) ;
535588 }
536589
590+ #[ test]
591+ fn test_human_readable_booted_pinned_spec ( ) {
592+ // booted image, no staged/rollback
593+ let w = human_status_from_spec_fixture ( include_str ! ( "fixtures/spec-booted-pinned.yaml" ) )
594+ . expect ( "No spec found" ) ;
595+ let expected = indoc:: indoc! { r"
596+ ● Booted image: quay.io/centos-bootc/centos-bootc:stream9
597+ Digest: sha256:47e5ed613a970b6574bfa954ab25bb6e85656552899aa518b5961d9645102b38 (arm64)
598+ Version: stream9.20240807.0
599+ Pinned: yes
600+
601+ Pinned image: quay.io/centos-bootc/centos-bootc:stream9
602+ Digest: sha256:47e5ed613a970b6574bfa954ab25bb6e85656552899aa518b5961d9645102b37 (arm64)
603+ Version: stream9.20240807.0
604+ Pinned: yes
605+ " } ;
606+ similar_asserts:: assert_eq!( w, expected) ;
607+ }
608+
537609 #[ test]
538610 fn test_human_readable_staged_rollback_spec ( ) {
539611 // staged/rollback image, no booted
0 commit comments