diff --git a/lib/src/cli.rs b/lib/src/cli.rs index 422f1e300..253074521 100644 --- a/lib/src/cli.rs +++ b/lib/src/cli.rs @@ -497,7 +497,7 @@ async fn upgrade(opts: UpgradeOpts) -> Result<()> { let sysroot = &get_locked_sysroot().await?; let repo = &sysroot.repo(); let (booted_deployment, _deployments, host) = - crate::status::get_status_require_booted(sysroot)?; + crate::status::get_status_require_booted(sysroot).await?; let imgref = host.spec.image.as_ref(); // If there's no specified image, let's be nice and check if the booted system is using rpm-ostree if imgref.is_none() { @@ -638,7 +638,7 @@ async fn switch(opts: SwitchOpts) -> Result<()> { let sysroot = &get_locked_sysroot().await?; let repo = &sysroot.repo(); let (booted_deployment, _deployments, host) = - crate::status::get_status_require_booted(sysroot)?; + crate::status::get_status_require_booted(sysroot).await?; let new_spec = { let mut new_spec = host.spec.clone(); @@ -688,7 +688,7 @@ async fn rollback(_opts: RollbackOpts) -> Result<()> { async fn edit(opts: EditOpts) -> Result<()> { let sysroot = &get_locked_sysroot().await?; let (booted_deployment, _deployments, host) = - crate::status::get_status_require_booted(sysroot)?; + crate::status::get_status_require_booted(sysroot).await?; let new_host: Host = if let Some(filename) = opts.filename { let mut r = std::io::BufReader::new(std::fs::File::open(filename)?); serde_yaml::from_reader(&mut r)? diff --git a/lib/src/deploy.rs b/lib/src/deploy.rs index 42cf29627..f97f5b516 100644 --- a/lib/src/deploy.rs +++ b/lib/src/deploy.rs @@ -81,6 +81,21 @@ impl From for ImageState { } } +impl From for ImageState { + fn from(value: crate::podman::PodmanInspect) -> Self { + let version = None; + let ostree_commit = "".to_owned(); + let created = value.created; + Self { + backend: Backend::Container, + manifest_digest: value.digest, + created, + version, + ostree_commit, + } + } +} + impl ImageState { /// Fetch the manifest corresponding to this image. May not be available in all backends. pub(crate) fn get_manifest( @@ -388,7 +403,8 @@ pub(crate) async fn stage( pub(crate) async fn rollback(sysroot: &SysrootLock) -> Result<()> { const ROLLBACK_JOURNAL_ID: &str = "26f3b1eb24464d12aa5e7b544a6b5468"; let repo = &sysroot.repo(); - let (booted_deployment, deployments, host) = crate::status::get_status_require_booted(sysroot)?; + let (booted_deployment, deployments, host) = + crate::status::get_status_require_booted(sysroot).await?; let new_spec = { let mut new_spec = host.spec.clone(); diff --git a/lib/src/image.rs b/lib/src/image.rs index 4fd7cd9b1..064bad550 100644 --- a/lib/src/image.rs +++ b/lib/src/image.rs @@ -47,7 +47,7 @@ pub(crate) async fn push_entrypoint(source: Option<&str>, target: Option<&str>) let source = if let Some(source) = source { ImageReference::try_from(source).context("Parsing source image")? } else { - let status = crate::status::get_status_require_booted(&sysroot)?; + let status = crate::status::get_status_require_booted(&sysroot).await?; // SAFETY: We know it's booted let booted = status.2.status.booted.unwrap(); let booted_image = booted.image.unwrap().image; diff --git a/lib/src/status.rs b/lib/src/status.rs index 92f92ba09..f5541ad4a 100644 --- a/lib/src/status.rs +++ b/lib/src/status.rs @@ -15,6 +15,7 @@ use ostree_ext::sysroot::SysrootLock; use crate::cli::OutputFormat; use crate::deploy::ImageState; +use crate::podman; use crate::spec::{ Backend, BootEntry, BootOrder, Host, HostSpec, HostStatus, HostType, ImageStatus, }; @@ -154,7 +155,7 @@ pub(crate) fn create_imagestatus( /// Given an OSTree deployment, parse out metadata into our spec. #[context("Reading deployment metadata")] -fn boot_entry_from_deployment( +async fn boot_entry_from_deployment( sysroot: &SysrootLock, deployment: &ostree::Deployment, ) -> Result { @@ -171,7 +172,11 @@ fn boot_entry_from_deployment( let csum = deployment.csum(); let imgstate = match backend { Backend::Container => { - todo!() + // TODO: encapsulate this better + let rootfs = &cap_std_ext::cap_std::fs::Dir::reopen_dir( + &crate::utils::sysroot_fd_borrowed(sysroot), + )?; + ImageState::from(podman::podman_inspect(rootfs, &image.image).await?) } Backend::OstreeContainer => { ImageState::from(*ostree_container::store::query_image_commit(repo, &csum)?) @@ -233,18 +238,18 @@ impl BootEntry { } /// A variant of [`get_status`] that requires a booted deployment. -pub(crate) fn get_status_require_booted( +pub(crate) async fn get_status_require_booted( sysroot: &SysrootLock, ) -> Result<(ostree::Deployment, Deployments, Host)> { let booted_deployment = sysroot.require_booted_deployment()?; - let (deployments, host) = get_status(sysroot, Some(&booted_deployment))?; + let (deployments, host) = get_status(sysroot, Some(&booted_deployment)).await?; Ok((booted_deployment, deployments, host)) } /// Gather the ostree deployment objects, but also extract metadata from them into /// a more native Rust structure. #[context("Computing status")] -pub(crate) fn get_status( +pub(crate) async fn get_status( sysroot: &SysrootLock, booted_deployment: Option<&ostree::Deployment>, ) -> Result<(Deployments, Host)> { @@ -283,23 +288,36 @@ pub(crate) fn get_status( other, }; - let staged = deployments - .staged - .as_ref() - .map(|d| boot_entry_from_deployment(sysroot, d)) - .transpose() - .context("Staged deployment")?; - let booted = booted_deployment - .as_ref() - .map(|d| boot_entry_from_deployment(sysroot, d)) - .transpose() - .context("Booted deployment")?; - let rollback = deployments - .rollback - .as_ref() - .map(|d| boot_entry_from_deployment(sysroot, d)) - .transpose() - .context("Rollback deployment")?; + let staged = if let Some(d) = deployments.staged.as_ref() { + Some( + boot_entry_from_deployment(sysroot, d) + .await + .context("Staged deployment")?, + ) + } else { + None + }; + + let booted = if let Some(d) = booted_deployment { + Some( + boot_entry_from_deployment(sysroot, d) + .await + .context("Booted deployment")?, + ) + } else { + None + }; + + let rollback = if let Some(d) = deployments.rollback.as_ref() { + Some( + boot_entry_from_deployment(sysroot, d) + .await + .context("Rollback deployment")?, + ) + } else { + None + }; + let spec = staged .as_ref() .or(booted.as_ref()) @@ -347,7 +365,7 @@ pub(crate) async fn status(opts: super::cli::StatusOpts) -> Result<()> { } else { let sysroot = super::cli::get_locked_sysroot().await?; let booted_deployment = sysroot.booted_deployment(); - let (_deployments, host) = get_status(&sysroot, booted_deployment.as_ref())?; + let (_deployments, host) = get_status(&sysroot, booted_deployment.as_ref()).await?; host };