Skip to content

Commit dacd6e0

Browse files
committed
DRAFT: List logically bound images
For now this is just the implementation, but it does not contain the important bug fix for #846 which is to allow this command to run inside a container and not just on a bootc booted host Signed-off-by: Omer Tuchfeld <[email protected]>
1 parent 07593a0 commit dacd6e0

File tree

2 files changed

+62
-14
lines changed

2 files changed

+62
-14
lines changed

lib/src/cli.rs

+26-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use ostree_ext::container as ostree_container;
2121
use ostree_ext::keyfileext::KeyFileExt;
2222
use ostree_ext::ostree;
2323
use schemars::schema_for;
24+
use serde::{Deserialize, Serialize};
2425

2526
use crate::deploy::RequiredHostSpec;
2627
use crate::lints;
@@ -235,13 +236,36 @@ pub(crate) enum ImageCmdOpts {
235236
},
236237
}
237238

239+
#[derive(ValueEnum, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
240+
#[serde(rename_all = "kebab-case")]
241+
pub(crate) enum ImageListType {
242+
/// List all images
243+
#[default]
244+
All,
245+
/// List only logically bound images
246+
Logical,
247+
/// List only host images
248+
Host,
249+
}
250+
251+
impl std::fmt::Display for ImageListType {
252+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
253+
self.to_possible_value().unwrap().get_name().fmt(f)
254+
}
255+
}
256+
238257
/// Subcommands which operate on images.
239258
#[derive(Debug, clap::Subcommand, PartialEq, Eq)]
240259
pub(crate) enum ImageOpts {
241260
/// List fetched images stored in the bootc storage.
242261
///
243262
/// Note that these are distinct from images stored via e.g. `podman`.
244-
List,
263+
List {
264+
/// Type of image to list
265+
#[clap(long)]
266+
#[arg(default_value_t)]
267+
list_type: ImageListType,
268+
},
245269
/// Copy a container image from the bootc storage to `containers-storage:`.
246270
///
247271
/// The source and target are both optional; if both are left unspecified,
@@ -876,7 +900,7 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
876900
}
877901
},
878902
Opt::Image(opts) => match opts {
879-
ImageOpts::List => crate::image::list_entrypoint().await,
903+
ImageOpts::List { list_type } => crate::image::list_entrypoint(list_type).await,
880904
ImageOpts::CopyToStorage { source, target } => {
881905
crate::image::push_entrypoint(source.as_deref(), target.as_deref()).await
882906
}

lib/src/image.rs

+36-12
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,56 @@ use bootc_utils::CommandRunExt;
77
use fn_error_context::context;
88
use ostree_ext::container::{ImageReference, Transport};
99

10-
use crate::imgstorage::Storage;
10+
use crate::cli::ImageListType;
1111

1212
/// The name of the image we push to containers-storage if nothing is specified.
1313
const IMAGE_DEFAULT: &str = "localhost/bootc";
1414

15-
#[context("Listing images")]
16-
pub(crate) async fn list_entrypoint() -> Result<()> {
17-
let sysroot = crate::cli::get_storage().await?;
18-
let repo = &sysroot.repo();
19-
20-
let images = ostree_ext::container::store::list_images(repo).context("Querying images")?;
21-
22-
println!("# Host images");
15+
#[context("Listing host images")]
16+
pub(crate) fn list_host_images(sysroot: &crate::store::Storage) -> Result<()> {
17+
let repo = sysroot.repo();
18+
let images = ostree_ext::container::store::list_images(&repo).context("Querying images")?;
2319
for image in images {
2420
println!("{image}");
2521
}
26-
println!();
2722

28-
println!("# Logically bound images");
23+
Ok(())
24+
}
25+
26+
#[context("Listing logical images")]
27+
pub(crate) fn list_logical_images(sysroot: &crate::store::Storage) -> Result<()> {
2928
let mut listcmd = sysroot.get_ensure_imgstore()?.new_image_cmd()?;
3029
listcmd.arg("list");
3130
listcmd.run()?;
3231

3332
Ok(())
3433
}
3534

35+
#[context("Listing images")]
36+
pub(crate) async fn list_entrypoint(list_type: ImageListType) -> Result<()> {
37+
// TODO: Get the storage from the container image, not the booted storage
38+
let sysroot: crate::store::Storage = crate::cli::get_storage().await?;
39+
40+
match list_type {
41+
ImageListType::All => {
42+
println!("# Host images");
43+
list_host_images(&sysroot)?;
44+
println!();
45+
46+
println!("# Logically bound images");
47+
list_logical_images(&sysroot)?;
48+
}
49+
ImageListType::Host => {
50+
list_host_images(&sysroot)?;
51+
}
52+
ImageListType::Logical => {
53+
list_logical_images(&sysroot)?;
54+
}
55+
}
56+
57+
Ok(())
58+
}
59+
3660
/// Implementation of `bootc image push-to-storage`.
3761
#[context("Pushing image")]
3862
pub(crate) async fn push_entrypoint(source: Option<&str>, target: Option<&str>) -> Result<()> {
@@ -79,7 +103,7 @@ pub(crate) async fn push_entrypoint(source: Option<&str>, target: Option<&str>)
79103
/// Thin wrapper for invoking `podman image <X>` but set up for our internal
80104
/// image store (as distinct from /var/lib/containers default).
81105
pub(crate) async fn imgcmd_entrypoint(
82-
storage: &Storage,
106+
storage: &crate::imgstorage::Storage,
83107
arg: &str,
84108
args: &[std::ffi::OsString],
85109
) -> std::result::Result<(), anyhow::Error> {

0 commit comments

Comments
 (0)