Skip to content

Commit

Permalink
DRAFT: List logically bound images
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
omertuc committed Nov 5, 2024
1 parent 07593a0 commit dacd6e0
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 14 deletions.
28 changes: 26 additions & 2 deletions lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use ostree_ext::container as ostree_container;
use ostree_ext::keyfileext::KeyFileExt;
use ostree_ext::ostree;
use schemars::schema_for;
use serde::{Deserialize, Serialize};

use crate::deploy::RequiredHostSpec;
use crate::lints;
Expand Down Expand Up @@ -235,13 +236,36 @@ pub(crate) enum ImageCmdOpts {
},
}

#[derive(ValueEnum, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "kebab-case")]
pub(crate) enum ImageListType {
/// List all images
#[default]
All,
/// List only logically bound images
Logical,
/// List only host images
Host,
}

impl std::fmt::Display for ImageListType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.to_possible_value().unwrap().get_name().fmt(f)
}
}

/// Subcommands which operate on images.
#[derive(Debug, clap::Subcommand, PartialEq, Eq)]
pub(crate) enum ImageOpts {
/// List fetched images stored in the bootc storage.
///
/// Note that these are distinct from images stored via e.g. `podman`.
List,
List {
/// Type of image to list
#[clap(long)]
#[arg(default_value_t)]
list_type: ImageListType,
},
/// Copy a container image from the bootc storage to `containers-storage:`.
///
/// The source and target are both optional; if both are left unspecified,
Expand Down Expand Up @@ -876,7 +900,7 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
}
},
Opt::Image(opts) => match opts {
ImageOpts::List => crate::image::list_entrypoint().await,
ImageOpts::List { list_type } => crate::image::list_entrypoint(list_type).await,
ImageOpts::CopyToStorage { source, target } => {
crate::image::push_entrypoint(source.as_deref(), target.as_deref()).await
}
Expand Down
48 changes: 36 additions & 12 deletions lib/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,56 @@ use bootc_utils::CommandRunExt;
use fn_error_context::context;
use ostree_ext::container::{ImageReference, Transport};

use crate::imgstorage::Storage;
use crate::cli::ImageListType;

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

#[context("Listing images")]
pub(crate) async fn list_entrypoint() -> Result<()> {
let sysroot = crate::cli::get_storage().await?;
let repo = &sysroot.repo();

let images = ostree_ext::container::store::list_images(repo).context("Querying images")?;

println!("# Host images");
#[context("Listing host images")]
pub(crate) fn list_host_images(sysroot: &crate::store::Storage) -> Result<()> {
let repo = sysroot.repo();
let images = ostree_ext::container::store::list_images(&repo).context("Querying images")?;
for image in images {
println!("{image}");
}
println!();

println!("# Logically bound images");
Ok(())
}

#[context("Listing logical images")]
pub(crate) fn list_logical_images(sysroot: &crate::store::Storage) -> Result<()> {
let mut listcmd = sysroot.get_ensure_imgstore()?.new_image_cmd()?;
listcmd.arg("list");
listcmd.run()?;

Ok(())
}

#[context("Listing images")]
pub(crate) async fn list_entrypoint(list_type: ImageListType) -> Result<()> {
// TODO: Get the storage from the container image, not the booted storage
let sysroot: crate::store::Storage = crate::cli::get_storage().await?;

match list_type {
ImageListType::All => {
println!("# Host images");
list_host_images(&sysroot)?;
println!();

println!("# Logically bound images");
list_logical_images(&sysroot)?;
}
ImageListType::Host => {
list_host_images(&sysroot)?;
}
ImageListType::Logical => {
list_logical_images(&sysroot)?;
}
}

Ok(())
}

/// Implementation of `bootc image push-to-storage`.
#[context("Pushing image")]
pub(crate) async fn push_entrypoint(source: Option<&str>, target: Option<&str>) -> Result<()> {
Expand Down Expand Up @@ -79,7 +103,7 @@ pub(crate) async fn push_entrypoint(source: Option<&str>, target: Option<&str>)
/// Thin wrapper for invoking `podman image <X>` but set up for our internal
/// image store (as distinct from /var/lib/containers default).
pub(crate) async fn imgcmd_entrypoint(
storage: &Storage,
storage: &crate::imgstorage::Storage,
arg: &str,
args: &[std::ffi::OsString],
) -> std::result::Result<(), anyhow::Error> {
Expand Down

0 comments on commit dacd6e0

Please sign in to comment.