diff --git a/Cargo.lock b/Cargo.lock index ce8d2a73f8..4e8355ca02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2180,8 +2180,6 @@ dependencies = [ [[package]] name = "ostree-ext" version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ba95e8a8a7120e39607eb8c8b90a7081705618cd21064f5344a162c65c1825" dependencies = [ "anyhow", "async-compression 0.3.15", diff --git a/Cargo.toml b/Cargo.toml index 135ae9cbb9..8242b2dda3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -129,3 +129,6 @@ bin-unit-tests = [] sanitizers = [] default = [] + +[patch.crates-io] +ostree-ext = { path = "../../ostreedev/ostree-rs-ext/lib" } diff --git a/rpmostree-cxxrs.cxx b/rpmostree-cxxrs.cxx index 42b1de545f..abe6ea20cd 100644 --- a/rpmostree-cxxrs.cxx +++ b/rpmostree-cxxrs.cxx @@ -1293,6 +1293,7 @@ enum class SystemHostType : ::std::uint8_t; enum class BubblewrapMutability : ::std::uint8_t; struct Bubblewrap; struct ContainerImageState; +struct ExportedManifestDiff; enum class RefspecType : ::std::uint8_t; struct TempEtcGuard; struct FilesystemScriptPrep; @@ -1396,6 +1397,29 @@ struct Bubblewrap final : public ::rust::Opaque }; #endif // CXXBRIDGE1_STRUCT_rpmostreecxx$Bubblewrap +#ifndef CXXBRIDGE1_STRUCT_rpmostreecxx$ExportedManifestDiff +#define CXXBRIDGE1_STRUCT_rpmostreecxx$ExportedManifestDiff +struct ExportedManifestDiff final +{ + // Check if the struct is initialized + bool initialized; + // The total number of packages in the next upgrade + ::std::uint64_t total; + // The size of the total number of packages in the next upgrade + ::std::uint64_t total_size; + // The total number of removed packages in the next upgrade + ::std::uint64_t n_removed; + // The size of total number of removed packages in the next upgrade + ::std::uint64_t removed_size; + // The total number of added packages in the next upgrade + ::std::uint64_t n_added; + // The size of total number of added packages in the next upgrade + ::std::uint64_t added_size; + + using IsRelocatable = ::std::true_type; +}; +#endif // CXXBRIDGE1_STRUCT_rpmostreecxx$ExportedManifestDiff + #ifndef CXXBRIDGE1_STRUCT_rpmostreecxx$ContainerImageState #define CXXBRIDGE1_STRUCT_rpmostreecxx$ContainerImageState // `ContainerImageState` is currently identical to ostree-rs-ext's `LayeredImageState` struct, @@ -1408,6 +1432,7 @@ struct ContainerImageState final bool is_layered; ::rust::String image_digest; ::rust::String version; + ::rpmostreecxx::ExportedManifestDiff cached_update_diff; using IsRelocatable = ::std::true_type; }; @@ -2073,6 +2098,11 @@ extern "C" ::rust::repr::PtrLen rpmostreecxx$cxxbridge1$purge_refspec (::rpmostreecxx::OstreeRepo const &repo, ::rust::Str refspec) noexcept; + + ::rust::repr::PtrLen + rpmostreecxx$cxxbridge1$check_container_update (::rpmostreecxx::OstreeRepo const &repo, + ::rpmostreecxx::GCancellable const &cancellable, + ::rust::Str imgref, bool *return$) noexcept; ::std::size_t rpmostreecxx$cxxbridge1$TempEtcGuard$operator$sizeof () noexcept; ::std::size_t rpmostreecxx$cxxbridge1$TempEtcGuard$operator$alignof () noexcept; ::std::size_t rpmostreecxx$cxxbridge1$FilesystemScriptPrep$operator$sizeof () noexcept; @@ -2197,6 +2227,10 @@ extern "C" ::rust::Str opt_deploy_id, ::rust::Str opt_os_name, ::rpmostreecxx::OstreeDeployment **return$) noexcept; + bool rpmostreecxx$cxxbridge1$deployment_add_manifest_diff ( + ::rpmostreecxx::GVariantDict const &dict, + ::rpmostreecxx::ExportedManifestDiff const &diff) noexcept; + ::rust::repr::PtrLen rpmostreecxx$cxxbridge1$daemon_sanitycheck_environment ( ::rpmostreecxx::OstreeSysroot const &sysroot) noexcept; @@ -3690,6 +3724,20 @@ purge_refspec (::rpmostreecxx::OstreeRepo const &repo, ::rust::Str refspec) } } +bool +check_container_update (::rpmostreecxx::OstreeRepo const &repo, + ::rpmostreecxx::GCancellable const &cancellable, ::rust::Str imgref) +{ + ::rust::MaybeUninit return$; + ::rust::repr::PtrLen error$ + = rpmostreecxx$cxxbridge1$check_container_update (repo, cancellable, imgref, &return$.value); + if (error$.ptr) + { + throw ::rust::impl< ::rust::Error>::error (error$); + } + return ::std::move (return$.value); +} + ::std::size_t TempEtcGuard::layout::size () noexcept { @@ -4049,6 +4097,13 @@ deployment_get_base (::rpmostreecxx::OstreeSysroot &sysroot, ::rust::Str opt_dep return ::std::move (return$.value); } +bool +deployment_add_manifest_diff (::rpmostreecxx::GVariantDict const &dict, + ::rpmostreecxx::ExportedManifestDiff const &diff) noexcept +{ + return rpmostreecxx$cxxbridge1$deployment_add_manifest_diff (dict, diff); +} + void daemon_sanitycheck_environment (::rpmostreecxx::OstreeSysroot const &sysroot) { diff --git a/rpmostree-cxxrs.h b/rpmostree-cxxrs.h index 488776a899..74ec7634f6 100644 --- a/rpmostree-cxxrs.h +++ b/rpmostree-cxxrs.h @@ -1075,6 +1075,7 @@ enum class SystemHostType : ::std::uint8_t; enum class BubblewrapMutability : ::std::uint8_t; struct Bubblewrap; struct ContainerImageState; +struct ExportedManifestDiff; enum class RefspecType : ::std::uint8_t; struct TempEtcGuard; struct FilesystemScriptPrep; @@ -1178,6 +1179,29 @@ struct Bubblewrap final : public ::rust::Opaque }; #endif // CXXBRIDGE1_STRUCT_rpmostreecxx$Bubblewrap +#ifndef CXXBRIDGE1_STRUCT_rpmostreecxx$ExportedManifestDiff +#define CXXBRIDGE1_STRUCT_rpmostreecxx$ExportedManifestDiff +struct ExportedManifestDiff final +{ + // Check if the struct is initialized + bool initialized; + // The total number of packages in the next upgrade + ::std::uint64_t total; + // The size of the total number of packages in the next upgrade + ::std::uint64_t total_size; + // The total number of removed packages in the next upgrade + ::std::uint64_t n_removed; + // The size of total number of removed packages in the next upgrade + ::std::uint64_t removed_size; + // The total number of added packages in the next upgrade + ::std::uint64_t n_added; + // The size of total number of added packages in the next upgrade + ::std::uint64_t added_size; + + using IsRelocatable = ::std::true_type; +}; +#endif // CXXBRIDGE1_STRUCT_rpmostreecxx$ExportedManifestDiff + #ifndef CXXBRIDGE1_STRUCT_rpmostreecxx$ContainerImageState #define CXXBRIDGE1_STRUCT_rpmostreecxx$ContainerImageState // `ContainerImageState` is currently identical to ostree-rs-ext's `LayeredImageState` struct, @@ -1190,6 +1214,7 @@ struct ContainerImageState final bool is_layered; ::rust::String image_digest; ::rust::String version; + ::rpmostreecxx::ExportedManifestDiff cached_update_diff; using IsRelocatable = ::std::true_type; }; @@ -1774,6 +1799,9 @@ query_container_image_commit (::rpmostreecxx::OstreeRepo const &repo, ::rust::St void purge_refspec (::rpmostreecxx::OstreeRepo const &repo, ::rust::Str refspec); +bool check_container_update (::rpmostreecxx::OstreeRepo const &repo, + ::rpmostreecxx::GCancellable const &cancellable, ::rust::Str imgref); + ::rust::Box< ::rpmostreecxx::TempEtcGuard> prepare_tempetc_guard (::std::int32_t rootfs); ::rust::Box< ::rpmostreecxx::FilesystemScriptPrep> @@ -1844,6 +1872,9 @@ ::rpmostreecxx::OstreeDeployment *deployment_get_base (::rpmostreecxx::OstreeSys ::rust::Str opt_deploy_id, ::rust::Str opt_os_name); +bool deployment_add_manifest_diff (::rpmostreecxx::GVariantDict const &dict, + ::rpmostreecxx::ExportedManifestDiff const &diff) noexcept; + void daemon_sanitycheck_environment (::rpmostreecxx::OstreeSysroot const &sysroot); ::rust::String deployment_generate_id (::rpmostreecxx::OstreeDeployment const &deployment) noexcept; diff --git a/rust/src/deployment_utils.rs b/rust/src/deployment_utils.rs index b284469d4a..f4663341e3 100644 --- a/rust/src/deployment_utils.rs +++ b/rust/src/deployment_utils.rs @@ -5,7 +5,7 @@ use crate::cxxrsutil::*; use anyhow::{anyhow, format_err, Result}; use ostree_ext::glib::translate::*; -use ostree_ext::ostree; +use ostree_ext::{glib, ostree}; use std::pin::Pin; /// Get a currently unique (for this host) identifier for the deployment. @@ -96,3 +96,24 @@ fn deployment_get_base_impl( }), } } + +// Insert the pending manifest diff, if any. Returns true iff the layers changed. +pub fn deployment_add_manifest_diff( + dict: &crate::ffi::GVariantDict, + diff: &crate::ffi::ExportedManifestDiff, +) -> bool { + if diff.n_removed == 0 && diff.n_added == 0 { + return false; + } + let dict = &dict.glib_reborrow(); + // Add a child dict + let diffv = glib::VariantDict::new(None); + diffv.insert("total", diff.total); + diffv.insert("total-size", diff.total_size); + diffv.insert("n-removed", diff.n_removed); + diffv.insert("removed-size", diff.removed_size); + diffv.insert("n-added", diff.n_added); + diffv.insert("added-size", diff.added_size); + dict.insert("manifest-diff", diffv); + return true; +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 1bd877a620..0ddd310967 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -187,6 +187,25 @@ pub mod ffi { pub is_layered: bool, pub image_digest: String, pub version: String, + pub cached_update_diff: ExportedManifestDiff, + } + + #[derive(Debug, Default)] + pub(crate) struct ExportedManifestDiff { + /// Check if the struct is initialized + pub initialized: bool, + /// The total number of packages in the next upgrade + pub total: u64, + /// The size of the total number of packages in the next upgrade + pub total_size: u64, + /// The total number of removed packages in the next upgrade + pub n_removed: u64, + /// The size of total number of removed packages in the next upgrade + pub removed_size: u64, + /// The total number of added packages in the next upgrade + pub n_added: u64, + /// The size of total number of added packages in the next upgrade + pub added_size: u64, } // sysroot_upgrade.rs @@ -202,6 +221,11 @@ pub mod ffi { c: &str, ) -> Result>; fn purge_refspec(repo: &OstreeRepo, refspec: &str) -> Result<()>; + fn check_container_update( + repo: &OstreeRepo, + cancellable: &GCancellable, + imgref: &str, + ) -> Result; } // core.rs @@ -303,7 +327,7 @@ pub mod ffi { opt_deploy_id: &str, opt_os_name: &str, ) -> Result<*mut OstreeDeployment>; - + fn deployment_add_manifest_diff(dict: &GVariantDict, diff: &ExportedManifestDiff) -> bool; } // A grab-bag of metadata from the deployment's ostree commit diff --git a/rust/src/sysroot_upgrade.rs b/rust/src/sysroot_upgrade.rs index e4a483f9a5..eea8554e34 100644 --- a/rust/src/sysroot_upgrade.rs +++ b/rust/src/sysroot_upgrade.rs @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT use crate::cxxrsutil::*; +use crate::ffi::ExportedManifestDiff; use crate::ffi::{output_message, ContainerImageState}; use anyhow::{Context, Result}; use ostree::glib; @@ -10,7 +11,7 @@ use ostree_container::store::{ ImageImporter, ImageProxyConfig, ImportProgress, ManifestLayerState, PrepareResult, }; use ostree_container::OstreeImageReference; -use ostree_ext::container as ostree_container; +use ostree_ext::container::{self as ostree_container, ManifestDiff}; use ostree_ext::ostree; use tokio::runtime::Handle; use tokio::sync::mpsc::Receiver; @@ -23,12 +24,20 @@ impl From> for crate::ffi::Conta .and_then(|c| ostree_container::version_for_config(c)) .map(ToOwned::to_owned) .unwrap_or_default(); + let cached_update_diff = s + .cached_update + .map(|c| { + let diff = ManifestDiff::new(&s.manifest, &c.manifest); + export_diff(&diff) + }) + .unwrap_or_default(); crate::ffi::ContainerImageState { base_commit: s.base_commit, merge_commit: s.merge_commit, is_layered: s.is_layered, image_digest: s.manifest_digest, version, + cached_update_diff, } } } @@ -72,14 +81,20 @@ fn default_container_pull_config(imgref: &OstreeImageReference) -> Result Result { + let config = default_container_pull_config(imgref)?; + let mut imp = ImageImporter::new(repo, imgref, config).await?; + imp.require_bootable(); + Ok(imp) +} + async fn pull_container_async( repo: &ostree::Repo, imgref: &OstreeImageReference, ) -> Result { output_message(&format!("Pulling manifest: {}", &imgref)); - let config = default_container_pull_config(imgref)?; - let mut imp = ImageImporter::new(repo, imgref, config).await?; - imp.require_bootable(); + let mut imp = new_importer(repo, imgref).await?; let layer_progress = imp.request_progress(); let prep = match imp.prepare().await? { PrepareResult::AlreadyPresent(r) => return Ok(r.into()), @@ -187,3 +202,75 @@ pub(crate) fn purge_refspec(repo: &crate::FFIOstreeRepo, imgref: &str) -> CxxRes } Ok(()) } + +/// Check for an updated manifest for the given container image reference, and return a diff. +pub(crate) fn check_container_update( + repo: &crate::FFIOstreeRepo, + cancellable: &crate::FFIGCancellable, + imgref: &str, +) -> CxxResult { + let repo = &repo.glib_reborrow(); + let cancellable = cancellable.glib_reborrow(); + let imgref = &OstreeImageReference::try_from(imgref)?; + Handle::current() + .block_on(async { + crate::utils::run_with_cancellable( + async { impl_check_container_update(repo, imgref).await }, + &cancellable, + ) + .await + }) + .map_err(Into::into) +} + +/// Unfortunately we can't export external types into our C++ bridge, so manually copy things +/// to another copy of the struct. +fn export_diff(diff: &ManifestDiff) -> ExportedManifestDiff { + ExportedManifestDiff { + initialized: true, + total: diff.total, + total_size: diff.total_size, + n_removed: diff.n_removed, + removed_size: diff.removed_size, + n_added: diff.n_added, + added_size: diff.added_size, + } +} + +/// Implementation of fetching a container manifest diff. +async fn impl_check_container_update( + repo: &ostree::Repo, + imgref: &OstreeImageReference, +) -> Result { + let mut imp = new_importer(repo, imgref).await?; + let have_update = match imp.prepare().await? { + PrepareResult::AlreadyPresent(_) => false, + PrepareResult::Ready(_) => true, + }; + Ok(have_update) +} + +#[test] +fn test_container_manifest_diff() -> Result<()> { + use ostree_ext::container::ManifestDiff; + use ostree_ext::oci_spec::image::ImageManifest; + let a: ImageManifest = serde_json::from_str(include_str!("../test/manifest1.json")).unwrap(); + let b: ImageManifest = serde_json::from_str(include_str!("../test/manifest2.json")).unwrap(); + let diff = ManifestDiff::new(&a, &b); + + let cmp_total = diff.total; + let cmp_total_size = diff.total_size; + let cmp_removed = diff.n_removed; + let cmp_removed_size = diff.removed_size; + let cmp_added = diff.n_added; + let cmp_added_size = diff.added_size; + + assert_eq!(cmp_total, 51 as u64); + assert_eq!(cmp_total_size, 697035490 as u64); + assert_eq!(cmp_removed, 4 as u64); + assert_eq!(cmp_removed_size, 170473141 as u64); + assert_eq!(cmp_added, 4 as u64); + assert_eq!(cmp_added_size, 170472856 as u64); + + Ok(()) +} diff --git a/rust/test/manifest1.json b/rust/test/manifest1.json new file mode 100644 index 0000000000..c9528d6d5b --- /dev/null +++ b/rust/test/manifest1.json @@ -0,0 +1 @@ +{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:f3b50d0849a19894aa27ca2346a78efdacf2c56bdc2a3493672d2a819990fedf","size":9301},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:75f4abe8518ec55cb8bf0d358a737084f38e2c030a28651d698c0b7569d680a6","size":1387849},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:777cb841d2803f775a36fba62bcbfe84b2a1e0abc27cf995961b63c3d218a410","size":48676116},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:1179dc1e2994ec0466787ec43967db9016b4b93c602bb9675d7fe4c0993366ba","size":124705297},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:74555b3730c4c0f77529ead433db58e038070666b93a5cc0da262d7b8debff0e","size":38743650},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:0ff8b1fdd38e5cfb6390024de23ba4b947cd872055f62e70f2c21dad5c928925","size":77161948},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:76b83eea62b7b93200a056b5e0201ef486c67f1eeebcf2c7678ced4d614cece2","size":21970157},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:d85c742f69904cb8dbf98abca4724d364d91792fcf8b5f5634ab36dda162bfc4","size":59797135},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:167e5df36d0fcbed876ca90c1ed1e6c79b5e2bdaba5eae74ab86444654b19eff","size":49410348},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:b34384ba76fa1e335cc8d75522508d977854f2b423f8aceb50ca6dfc2f609a99","size":21714783},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:7bf2d65ebf222ee10115284abf6909b1a3da0f3bd6d8d849e30723636b7145cb","size":15264848},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:a75bbf55d8de4dbd54e429e16fbd46688717faf4ea823c94676529cc2525fd5f","size":14373701},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:cf728677fa8c84bfcfd71e17953062421538d492d7fbfdd0dbce8eb1e5f6eec3","size":8400473},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:caff60c1ef085fb500c94230ccab9338e531578635070230b1413b439fd53f8f","size":6914489},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:65ca8f9bddaa720b74c5a7401bf273e93eba6b3b855a62422a8258373e0b1ae0","size":8294965},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:387bab4fcb713e9691617a645b6af2b7ad29fe5e009b0b0d3215645ef315481c","size":6600369},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:f63dcde5a664dad3eb3321bbcf2913d9644d16561a67c86ab61d814c1462583d","size":16869027},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:8bcd90242651342fbd2ed5ca3e60d03de90fdd28c3a9f634329f6e1c21c79718","size":5735283},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:cb65c21a0659b5b826881280556995a7ca4818c2b9b7a89e31d816a996fa8640","size":4528663},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:5187f51b62f4a2e82198a75afcc623a0323d4804fa7848e2e0acb30d77b8d9ab","size":5266030},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:bfef79d6d35378fba9093083ff6bd7b5ed9f443f87517785e6ff134dc8d08c6a","size":4316135},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:1cf332fd50b382af7941d6416994f270c894e9d60fb5c6cecf25de887673bbcb","size":3914655},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:e0d80be6e71bfae398f06f7a7e3b224290f3dde7544c8413f922934abeb1f599","size":2441858},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:48ff87e7a7af41d7139c5230e2e939aa97cafb1f62a114825bda5f5904e04a0e","size":3818782},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:8bcc652ccaa27638bd5bd2d7188053f1736586afbae87b3952e9211c773e3563","size":3885971},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:d83d9388b8c8c1e7c97b6b18f5107b74354700ebce9da161ccb73156a2c54a2e","size":3442642},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:efc465ae44a18ee395e542eb97c8d1fc21bf9d5fb49244ba4738e9bf48bfd3dc","size":3066348},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:c5c471cce08aa9cc7d96884a9e1981b7bb67ee43524af47533f50a8ddde7a83d","size":909923},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:8956cd951abc481ba364cf8ef5deca7cc9185b59ed95ae40b52e42afdc271d8e","size":3553645},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:5b0963a6c89d595b5c4786e2f3ce0bc168a262efab74dfce3d7c8d1063482c60","size":1495301},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:bf2df295da2716291f9dd4707158bca218b4a7920965955a4808b824c1bee2b6","size":3063142},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:19b2ea8d63794b8249960d581216ae1ccb80f8cfe518ff8dd1f12d65d19527a5","size":8109718},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:420636df561ccc835ef9665f41d4bc91c5f00614a61dca266af2bcd7bee2cc25","size":3003935},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:5ae67caf0978d82848d47ff932eee83a1e5d2581382c9c47335f69c9d7acc180","size":2468557},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:4f4b8bb8463dc74bb7f32eee78d02b71f61a322967b6d6cbb29829d262376f74","size":2427605},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:69373f86b83e6e5a962de07f40ff780a031b42d2568ffbb8b3c36de42cc90dec","size":2991782},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:2d05c2f993f9761946701da37f45fc573a2db8467f92b3f0d356f5f7adaf229e","size":3085765},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:41925843e5c965165bedc9c8124b96038f08a89c95ba94603a5f782dc813f0a8","size":2724309},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:a8c39f2998073e0e8b55fb88ccd68d2621a0fb6e31a528fd4790a1c90f8508a9","size":2512079},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:b905f801d092faba0c155597dd1303fa8c0540116af59c111ed7744e486ed63b","size":2341122},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:4f46b58b37828fa71fa5d7417a8ca7a62761cc6a72eb1592943572fc2446b054","size":2759344},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:3fbae92ecc64cf253b643a0e75b56514dc694451f163b47fb4e15af373238e10","size":2539288},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:744dd4a3ec521668942661cf1f184eb8f07f44025ce1aa35d5072ad9d72946fe","size":2415870},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:6c74c0a05a36bddabef1fdfae365ff87a9c5dd1ec7345d9e20f7f8ab04b39fc6","size":2145078},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:910ff6f93303ebedde3459f599b06d7b70d8f0674e3fe1d6623e3af809245cc4","size":5098511},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:2752e2f62f38fea3a390f111d673d2529dbf929f6c67ec7ef4359731d1a7edd8","size":1051999},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:5065c3aac5fcc3c1bde50a19d776974353301f269a936dd2933a67711af3b703","size":2713694},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:8bf6993eea50bbd8b448e6fd719f83c82d1d40b623f2c415f7727e766587ea83","size":1686714},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:630221744f0f9632f4f34f74241e65f79e78f938100266a119113af1ce10a1c5","size":2061581},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:e7e2eae322bca0ffa01bb2cae72288507bef1a11ad51f99d0a4faba1b1e000b9","size":2079706},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:bb6374635385b0c2539c284b137d831bd45fbe64b5e49aee8ad92d14c156a41b","size":3142398},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:40493ecd0f9ab499a2bec715415c3a98774ea6d1c9c01eb30a6b56793204a02d","size":69953187}]} diff --git a/rust/test/manifest2.json b/rust/test/manifest2.json new file mode 100644 index 0000000000..76b1b1bd59 --- /dev/null +++ b/rust/test/manifest2.json @@ -0,0 +1 @@ +{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:ca0f7e342503b45a1110aba49177e386242e9192ab1742a95998b6b99c2a0150","size":9301},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:bca674ffe2ebe92b9e952bc807b9f1cd0d559c057e95ac81f3bae12a9b96b53e","size":1387854},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:777cb841d2803f775a36fba62bcbfe84b2a1e0abc27cf995961b63c3d218a410","size":48676116},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:1179dc1e2994ec0466787ec43967db9016b4b93c602bb9675d7fe4c0993366ba","size":124705297},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:74555b3730c4c0f77529ead433db58e038070666b93a5cc0da262d7b8debff0e","size":38743650},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:0b5d930ffc92d444b0a7b39beed322945a3038603fbe2a56415a6d02d598df1f","size":77162517},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:8d12d20c2d1c8f05c533a2a1b27a457f25add8ad38382523660c4093f180887b","size":21970100},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:d85c742f69904cb8dbf98abca4724d364d91792fcf8b5f5634ab36dda162bfc4","size":59797135},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:167e5df36d0fcbed876ca90c1ed1e6c79b5e2bdaba5eae74ab86444654b19eff","size":49410348},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:b34384ba76fa1e335cc8d75522508d977854f2b423f8aceb50ca6dfc2f609a99","size":21714783},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:7bf2d65ebf222ee10115284abf6909b1a3da0f3bd6d8d849e30723636b7145cb","size":15264848},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:a75bbf55d8de4dbd54e429e16fbd46688717faf4ea823c94676529cc2525fd5f","size":14373701},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:cf728677fa8c84bfcfd71e17953062421538d492d7fbfdd0dbce8eb1e5f6eec3","size":8400473},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:caff60c1ef085fb500c94230ccab9338e531578635070230b1413b439fd53f8f","size":6914489},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:65ca8f9bddaa720b74c5a7401bf273e93eba6b3b855a62422a8258373e0b1ae0","size":8294965},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:387bab4fcb713e9691617a645b6af2b7ad29fe5e009b0b0d3215645ef315481c","size":6600369},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:f63dcde5a664dad3eb3321bbcf2913d9644d16561a67c86ab61d814c1462583d","size":16869027},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:8bcd90242651342fbd2ed5ca3e60d03de90fdd28c3a9f634329f6e1c21c79718","size":5735283},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:cb65c21a0659b5b826881280556995a7ca4818c2b9b7a89e31d816a996fa8640","size":4528663},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:5187f51b62f4a2e82198a75afcc623a0323d4804fa7848e2e0acb30d77b8d9ab","size":5266030},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:bfef79d6d35378fba9093083ff6bd7b5ed9f443f87517785e6ff134dc8d08c6a","size":4316135},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:1cf332fd50b382af7941d6416994f270c894e9d60fb5c6cecf25de887673bbcb","size":3914655},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:e0d80be6e71bfae398f06f7a7e3b224290f3dde7544c8413f922934abeb1f599","size":2441858},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:48ff87e7a7af41d7139c5230e2e939aa97cafb1f62a114825bda5f5904e04a0e","size":3818782},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:8bcc652ccaa27638bd5bd2d7188053f1736586afbae87b3952e9211c773e3563","size":3885971},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:d83d9388b8c8c1e7c97b6b18f5107b74354700ebce9da161ccb73156a2c54a2e","size":3442642},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:efc465ae44a18ee395e542eb97c8d1fc21bf9d5fb49244ba4738e9bf48bfd3dc","size":3066348},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:c5c471cce08aa9cc7d96884a9e1981b7bb67ee43524af47533f50a8ddde7a83d","size":909923},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:8956cd951abc481ba364cf8ef5deca7cc9185b59ed95ae40b52e42afdc271d8e","size":3553645},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:5b0963a6c89d595b5c4786e2f3ce0bc168a262efab74dfce3d7c8d1063482c60","size":1495301},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:bf2df295da2716291f9dd4707158bca218b4a7920965955a4808b824c1bee2b6","size":3063142},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:19b2ea8d63794b8249960d581216ae1ccb80f8cfe518ff8dd1f12d65d19527a5","size":8109718},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:420636df561ccc835ef9665f41d4bc91c5f00614a61dca266af2bcd7bee2cc25","size":3003935},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:5ae67caf0978d82848d47ff932eee83a1e5d2581382c9c47335f69c9d7acc180","size":2468557},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:4f4b8bb8463dc74bb7f32eee78d02b71f61a322967b6d6cbb29829d262376f74","size":2427605},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:69373f86b83e6e5a962de07f40ff780a031b42d2568ffbb8b3c36de42cc90dec","size":2991782},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:2d05c2f993f9761946701da37f45fc573a2db8467f92b3f0d356f5f7adaf229e","size":3085765},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:41925843e5c965165bedc9c8124b96038f08a89c95ba94603a5f782dc813f0a8","size":2724309},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:a8c39f2998073e0e8b55fb88ccd68d2621a0fb6e31a528fd4790a1c90f8508a9","size":2512079},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:b905f801d092faba0c155597dd1303fa8c0540116af59c111ed7744e486ed63b","size":2341122},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:4f46b58b37828fa71fa5d7417a8ca7a62761cc6a72eb1592943572fc2446b054","size":2759344},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:3fbae92ecc64cf253b643a0e75b56514dc694451f163b47fb4e15af373238e10","size":2539288},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:744dd4a3ec521668942661cf1f184eb8f07f44025ce1aa35d5072ad9d72946fe","size":2415870},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:6c74c0a05a36bddabef1fdfae365ff87a9c5dd1ec7345d9e20f7f8ab04b39fc6","size":2145078},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:910ff6f93303ebedde3459f599b06d7b70d8f0674e3fe1d6623e3af809245cc4","size":5098511},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:2752e2f62f38fea3a390f111d673d2529dbf929f6c67ec7ef4359731d1a7edd8","size":1051999},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:5065c3aac5fcc3c1bde50a19d776974353301f269a936dd2933a67711af3b703","size":2713694},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:8bf6993eea50bbd8b448e6fd719f83c82d1d40b623f2c415f7727e766587ea83","size":1686714},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:630221744f0f9632f4f34f74241e65f79e78f938100266a119113af1ce10a1c5","size":2061581},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:e7e2eae322bca0ffa01bb2cae72288507bef1a11ad51f99d0a4faba1b1e000b9","size":2079706},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:bb6374635385b0c2539c284b137d831bd45fbe64b5e49aee8ad92d14c156a41b","size":3142398},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:cb9b8a4ac4a8df62df79e6f0348a14b3ec239816d42985631c88e76d4e3ff815","size":69952385}]} diff --git a/src/app/rpmostree-clientlib.cxx b/src/app/rpmostree-clientlib.cxx index 9545a4df5a..dd0357efe4 100644 --- a/src/app/rpmostree-clientlib.cxx +++ b/src/app/rpmostree-clientlib.cxx @@ -1244,6 +1244,65 @@ rpmostree_print_diff_advisories (GVariant *rpm_diff, GVariant *advisories, gbool return TRUE; } +/* print "manifest-diff" */ +gboolean +rpmostree_print_manifest_diff (GVariant *manifest_diff, guint maxkeylen, GError **error) +{ + if (!manifest_diff) + return TRUE; /* Nothing to 🖨️ */ + + g_auto (GVariantDict) manifest_diff_dict; + g_variant_dict_init (&manifest_diff_dict, manifest_diff); + + guint64 total = 0; + if (!g_variant_dict_lookup (&manifest_diff_dict, "total", "t", &total)) + return glnx_throw (error, "Missing \"total\" key"); + + printf (" %*s%s %" G_GUINT64_FORMAT "\n", maxkeylen, "Total layers", + strlen ("Total layers") ? ":" : " ", total); + + { + guint64 total_size = 0; + if (!g_variant_dict_lookup (&manifest_diff_dict, "total-size", "t", &total_size)) + return glnx_throw (error, "Missing \"total_size\" key"); + g_autofree char *formatted = g_format_size (total_size); + printf (" %*s%s %s", maxkeylen, "Size", strlen ("Size") ? ":" : " ", formatted); + printf ("\n"); + } + + guint64 total_removed = 0; + if (!g_variant_dict_lookup (&manifest_diff_dict, "n-removed", "t", &total_removed)) + return glnx_throw (error, "Missing \"total_removed\" key"); + + printf (" %*s%s %" G_GUINT64_FORMAT "\n", maxkeylen, "Removed layers", + strlen ("Removed layers") ? ":" : " ", total_removed); + + { + guint64 removed_size = 0; + if (!g_variant_dict_lookup (&manifest_diff_dict, "removed-size", "t", &removed_size)) + return glnx_throw (error, "Missing \"removed_size\" key"); + g_autofree char *formatted = g_format_size (removed_size); + printf (" %*s%s %s\n", maxkeylen, "Size", strlen ("Size") ? ":" : " ", formatted); + } + + guint64 total_added = 0; + if (!g_variant_dict_lookup (&manifest_diff_dict, "n-added", "t", &total_added)) + return glnx_throw (error, "Missing \"total_added\" key"); + printf (" %*s%s %" G_GUINT64_FORMAT "\n", maxkeylen, "Added layers", + strlen ("Added layers") ? ":" : " ", total_added); + + { + guint64 added_size = 0; + if (!g_variant_dict_lookup (&manifest_diff_dict, "added_size", "t", &added_size)) + return glnx_throw (error, "Missing \"added_size\" key"); + + g_autofree char *formatted = g_format_size (added_size); + printf (" %*s%s %s\n", maxkeylen, "Size", strlen ("Size") ? ":" : " ", formatted); + } + + return TRUE; +} + /* this is used by both `status` and `upgrade --check/--preview` */ gboolean rpmostree_print_cached_update (GVariant *cached_update, gboolean verbose, @@ -1286,6 +1345,9 @@ rpmostree_print_cached_update (GVariant *cached_update, gboolean verbose, g_autoptr (GVariant) rpm_diff = g_variant_dict_lookup_value (&dict, "rpm-diff", G_VARIANT_TYPE ("a{sv}")); + g_autoptr (GVariant) manifest_diff + = g_variant_dict_lookup_value (&dict, "manifest-diff", G_VARIANT_TYPE ("a{sv}")); + g_autoptr (GVariant) advisories = g_variant_dict_lookup_value (&dict, "advisories", G_VARIANT_TYPE ("a(suuasa{sv})")); @@ -1308,6 +1370,9 @@ rpmostree_print_cached_update (GVariant *cached_update, gboolean verbose, max_key_len, error)) return FALSE; + if (!rpmostree_print_manifest_diff (manifest_diff, max_key_len, error)) + return FALSE; + return TRUE; } diff --git a/src/app/rpmostree-clientlib.h b/src/app/rpmostree-clientlib.h index dd4f22c4c8..a47e672d62 100644 --- a/src/app/rpmostree-clientlib.h +++ b/src/app/rpmostree-clientlib.h @@ -111,6 +111,8 @@ gboolean rpmostree_print_diff_advisories (GVariant *rpm_diff, GVariant *advisori gboolean verbose, gboolean verbose_advisories, guint max_key_len, GError **error); +gboolean rpmostree_print_manifest_diff (GVariant *manifest_diff, guint maxkeylen, GError **error); + gboolean rpmostree_print_cached_update (GVariant *cached_update, gboolean verbose, gboolean verbose_advisories, GCancellable *cancellable, GError **error); diff --git a/src/daemon/rpmostree-sysroot-upgrader.cxx b/src/daemon/rpmostree-sysroot-upgrader.cxx index 2beb3aee3b..4a24b0ed45 100644 --- a/src/daemon/rpmostree-sysroot-upgrader.cxx +++ b/src/daemon/rpmostree-sysroot-upgrader.cxx @@ -434,12 +434,23 @@ rpmostree_sysroot_upgrader_pull_base (RpmOstreeSysrootUpgrader *self, const char return glnx_throw (error, "Specifying commit overrides for container-image-reference " "type refspecs is not supported"); if (check) - return glnx_throw (error, "Cannot currently check for updates without downloading"); + { + CXX_TRY_VAR ( + changed, + rpmostreecxx::check_container_update (*self->repo, *cancellable, r.refspec.c_str ()), + error); + *out_changed = changed; + return TRUE; + } + else + { + CXX_TRY_VAR ( + import, + rpmostreecxx::pull_container (*self->repo, *cancellable, r.refspec.c_str ()), + error); - CXX_TRY_VAR (import, - rpmostreecxx::pull_container (*self->repo, *cancellable, r.refspec.c_str ()), - error); - new_base_rev = g_strdup (import->merge_commit.c_str ()); + new_base_rev = g_strdup (import->merge_commit.c_str ()); + } break; } case rpmostreecxx::RefspecType::Checksum: diff --git a/src/daemon/rpmostreed-deployment-utils.cxx b/src/daemon/rpmostreed-deployment-utils.cxx index 4848050942..ea860f654e 100644 --- a/src/daemon/rpmostreed-deployment-utils.cxx +++ b/src/daemon/rpmostreed-deployment-utils.cxx @@ -677,6 +677,8 @@ rpmostreed_update_generate_variant (OstreeDeployment *booted_deployment, const char *new_checksum = NULL; const char *new_base_checksum = NULL; g_autofree char *new_base_checksum_owned = NULL; + auto refspectype = rpmostreecxx::refspec_classify (r.refspec); + if (staged_deployment) { new_checksum = ostree_deployment_get_csum (staged_deployment); @@ -687,13 +689,18 @@ rpmostreed_update_generate_variant (OstreeDeployment *booted_deployment, } else { - if (!ostree_repo_resolve_rev_ext (repo, r.refspec.c_str (), TRUE, - static_cast (0), - &new_base_checksum_owned, error)) - return FALSE; - new_base_checksum = new_base_checksum_owned; - /* just assume that the hypothetical new deployment would also be layered if we are */ - is_new_layered = (current_base_checksum_owned != NULL); + if (refspectype != rpmostreecxx::RefspecType::Container) + { + if (!ostree_repo_resolve_rev_ext (repo, r.refspec.c_str (), TRUE, + static_cast (0), + &new_base_checksum_owned, error)) + { + return FALSE; + } + new_base_checksum = new_base_checksum_owned; + /* just assume that the hypothetical new deployment would also be layered if we are */ + is_new_layered = (current_base_checksum_owned != NULL); + } } /* Graciously handle rev no longer in repo; e.g. mucking around with rebase/rollback; we @@ -725,12 +732,15 @@ rpmostreed_update_generate_variant (OstreeDeployment *booted_deployment, }; rpm_diff_init (&rpm_diff); - /* we'll need these later for advisories, so just keep them around */ g_autoptr (GPtrArray) ostree_modified_new = NULL; g_autoptr (GPtrArray) rpmmd_modified_new = NULL; + bool container_changed = false; + if (staged_deployment) { + g_debug ("Computing diff with staged deployment"); + /* ok we have a staged deployment; we just need to do a simple diff and BOOM done! */ /* XXX: we're marking all pkgs as BASE right now even though there could be layered * pkgs too -- we can tease those out in the future if needed */ @@ -744,15 +754,41 @@ rpmostreed_update_generate_variant (OstreeDeployment *booted_deployment, * - if a new base checksum was pulled, do a db diff of the old and new bases * - if there are currently any layered pkgs, lookup in sack for newer versions */ - if (is_new_checksum) + + if (is_new_checksum && refspectype != rpmostreecxx::RefspecType::Container) { if (!rpm_diff_add_db_diff (&rpm_diff, repo, RPM_OSTREE_PKG_TYPE_BASE, current_base_checksum, new_base_checksum, &ostree_modified_new, cancellable, error)) - return FALSE; + { + return FALSE; + } } /* now we look at the rpm-md/layering side */ + g_autofree char *origin_remote = NULL; + g_autofree char *origin_ref = NULL; + + if (refspectype != rpmostreecxx::RefspecType::Container) + { + if (!ostree_parse_refspec (r.refspec.c_str (), &origin_remote, &origin_ref, error)) + return FALSE; + } + else + { + // Make this an operation we allow to fail, see the other call + try + { + auto state = rpmostreecxx::query_container_image_commit (*repo, current_checksum); + container_changed = rpmostreecxx::deployment_add_manifest_diff (*dict, state->cached_update_diff); + g_debug ("container changed: %d", container_changed); + } + catch (std::exception &e) + { + sd_journal_print (LOG_ERR, "failed to query container image base metadata: %s", + e.what ()); + } + } /* check that it's actually layered (i.e. the requests are not all just dormant) */ if (sack && is_new_layered && rpmostree_origin_has_packages (origin)) @@ -767,8 +803,8 @@ rpmostreed_update_generate_variant (OstreeDeployment *booted_deployment, if (!rpm_diff_is_empty (&rpm_diff)) g_variant_dict_insert (dict, "rpm-diff", "@a{sv}", rpm_diff_variant_new (&rpm_diff)); - /* now we look for advisories */ + /* now we look for advisories */ if (sack && (ostree_modified_new || rpmmd_modified_new)) { /* let's just merge the two now for convenience */ @@ -802,8 +838,10 @@ rpmostreed_update_generate_variant (OstreeDeployment *booted_deployment, } /* but if there are no updates, then just ditch the whole thing and return NULL */ - if (is_new_checksum || rpmmd_modified_new) + refspectype = rpmostreecxx::refspec_classify (r.refspec); + if (is_new_checksum || rpmmd_modified_new || container_changed) { + g_debug ("Recomputed cached update"); /* include a "state" checksum for cache invalidation; for now this is just the * checksum of the deployment against which we ran, though we could base it off more * things later if needed */ @@ -811,7 +849,10 @@ rpmostreed_update_generate_variant (OstreeDeployment *booted_deployment, *out_update = g_variant_ref_sink (g_variant_dict_end (dict)); } else - *out_update = NULL; + { + g_debug ("No cached update"); + *out_update = NULL; + } return TRUE; } diff --git a/tests/kolainst/destructive/container-rebase-upgrade b/tests/kolainst/destructive/container-rebase-upgrade index ee463b5db8..8c60700805 100755 --- a/tests/kolainst/destructive/container-rebase-upgrade +++ b/tests/kolainst/destructive/container-rebase-upgrade @@ -40,10 +40,8 @@ rpm-ostree upgrade podman image rm -f shouldnotexist || true test -d /run/containers # https://github.com/coreos/rpm-ostree/issues/4176 -if rpm-ostree upgrade --check 2>err.txt; then - fatal "expected upgrade --check not to work yet" -fi -assert_file_has_content_literal err.txt "Cannot currently check for updates without downloading" +rpm-ostree upgrade --check > err.txt || true +assert_file_has_content_literal err.txt 'No updates available.' rpm-ostree upgrade echo "ok upgrade after podman" diff --git a/tests/kolainst/destructive/container-update-check b/tests/kolainst/destructive/container-update-check new file mode 100755 index 0000000000..dd021d9997 --- /dev/null +++ b/tests/kolainst/destructive/container-update-check @@ -0,0 +1,114 @@ +#!/bin/bash +## kola: +## # Increase timeout since this test has a lot of I/O and involves rebasing +## timeoutMin: 30 +## # This test only runs on FCOS due to a problem with skopeo copy on +## # RHCOS. See: https://github.com/containers/skopeo/issues/1846 +## distros: fcos +## # Needs internet access as we fetch files from koji +## tags: "needs-internet platform-independent" +## minMemory: 2048 +# +# Copyright (C) 2023 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +set -euo pipefail + +. ${KOLA_EXT_DATA}/libtest.sh + +set -x + +libtest_prepare_offline +cd "$(mktemp -d)" + +# TODO: It'd be much better to test this via a registry +image_dir=/var/tmp/fcos +image=oci:$image_dir + +case "${AUTOPKGTEST_REBOOT_MARK:-}" in + "") + checksum=$(rpm-ostree status --json | jq -r '.deployments[0].checksum') + rm ${image_dir} -rf + # Since we're switching OS update stream, turn off zincati + systemctl mask --now zincati + ostree container encapsulate --repo=/ostree/repo ${checksum} "${image}" --label ostree.bootable=TRUE + + skopeo copy $image containers-storage:localhost/fcos + rm "${image_dir}" -rf + td=$(mktemp -d) + cd ${td} +cat > Containerfile << EOF +FROM localhost/fcos +# RUN rpm-ostree install man +EOF + + touched_resolv_conf=0 + if test '!' -f /etc/resolv.conf; then + podmanv=$(podman --version) + case "${podmanv#podman version }" in + 3.*) touched_resolv_conf=1; touch /etc/resolv.conf;; + esac + fi + podman build --net=host -t localhost/fcos-derived --squash . + if test "${touched_resolv_conf}" -eq 1; then + rm -vf /etc/resolv.conf + fi + + rpm-ostree rebase ostree-unverified-image:containers-storage:localhost/fcos-derived + rm $image_dir -rf + + /tmp/autopkgtest-reboot 1 + ;; + 1) + rpm-ostree status + rpm-ostree upgrade --check > out.txt || true + assert_file_has_content_literal out.txt 'No updates available.' + + checksum=$(rpm-ostree status --json | jq -r '.deployments[0].checksum') + rm ${image_dir} -rf + systemctl mask --now zincati + ostree container encapsulate --repo=/ostree/repo ${checksum} "${image}" --label ostree.bootable=TRUE + + skopeo copy $image containers-storage:localhost/fcos + rm "${image_dir}" -rf + td=$(mktemp -d) + cd ${td} +cat > Containerfile << EOF +FROM localhost/fcos +RUN rpm-ostree install man +EOF + + touched_resolv_conf=0 + if test '!' -f /etc/resolv.conf; then + podmanv=$(podman --version) + case "${podmanv#podman version }" in + 3.*) touched_resolv_conf=1; touch /etc/resolv.conf;; + esac + fi + podman build --net=host -t localhost/fcos-derived --squash . + if test "${touched_resolv_conf}" -eq 1; then + rm -vf /etc/resolv.conf + fi + + rpm-ostree upgrade --check > out.txt || true + assert_file_has_content_literal out.txt 'AvailableUpdate:' + assert_file_has_content_literal out.txt 'Total layers:' + assert_file_has_content_literal out.txt 'Size:' + assert_file_has_content_literal out.txt 'Removed layers:' + assert_file_has_content_literal out.txt 'Added layers:' + +esac