diff --git a/.cci.jenkinsfile b/.cci.jenkinsfile index c855148453..2e34ffd254 100644 --- a/.cci.jenkinsfile +++ b/.cci.jenkinsfile @@ -47,9 +47,7 @@ parallel insttests: { # include our built rpm-ostree in the image mkdir -p overrides/rpm mv *.rpm overrides/rpm - # for now, we cherry-pick newer libsolv to test that it correctly detects our rpmdb - # https://github.com/coreos/rpm-ostree/issues/2548 - (cd overrides/rpm && curl -LO https://kojipkgs.fedoraproject.org//packages/libsolv/0.7.17/1.fc33/x86_64/libsolv-0.7.17-1.fc33.x86_64.rpm) + ${env.WORKSPACE}/ci/cosa-overrides.sh coreos-assembler fetch coreos-assembler build ${env.WORKSPACE}/ci/composepost-checks.sh diff --git a/.dockerignore b/.dockerignore index eae2fec031..25085f8ecb 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,3 @@ .cosa target +compose-cache/ diff --git a/Cargo.lock b/Cargo.lock index 1c5a83cda9..be2b0f2bab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,6 +53,19 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +[[package]] +name = "async-compression" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443ccbb270374a2b1055fc72da40e1f237809cd6bb0e97e66d264cd138473a6" +dependencies = [ + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + [[package]] name = "atty" version = "0.2.14" @@ -208,7 +221,7 @@ dependencies = [ "ansi_term 0.11.0", "atty", "bitflags", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", @@ -246,6 +259,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "containers-image-proxy" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80eba3bafa242f7c7d97f131c3e85c20d7dff23827b99dd36a29abcf217c52f7" +dependencies = [ + "anyhow", + "fn-error-context", + "futures-util", + "lazy_static", + "nix 0.22.0", + "semver", + "serde", + "serde_json", + "tokio", + "tracing", +] + [[package]] name = "core-foundation" version = "0.9.1" @@ -399,6 +430,72 @@ dependencies = [ "syn", ] +[[package]] +name = "darling" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "derive_builder" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d13202debe11181040ae9063d739fa32cfcaaebe2275fe387703460ae2365b30" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73" +dependencies = [ + "derive_builder_core", + "syn", +] + [[package]] name = "dlv-list" version = "0.2.3" @@ -667,6 +764,18 @@ dependencies = [ "wasi", ] +[[package]] +name = "getset" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b328c01a4d71d2d8173daa93562a73ab0fe85616876f02500f53d82948c504" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "gio" version = "0.14.3" @@ -901,6 +1010,12 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.2.3" @@ -1251,6 +1366,19 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" +[[package]] +name = "oci-spec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63f0f82a50257e72a6f13616dc093f3d0874294629bf8b7d0bc2a098e3db324f" +dependencies = [ + "derive_builder", + "getset", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "once_cell" version = "1.8.0" @@ -1332,9 +1460,9 @@ dependencies = [ [[package]] name = "ostree" -version = "0.13.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9358905170a49b82e5baecb879bb944c42736a4b02074a40286a7b20665af381" +checksum = "ed97148d69c9822e948d9c1d2e288e3efd11592814981f46fce6f47cb7837d4e" dependencies = [ "bitflags", "gio", @@ -1349,44 +1477,47 @@ dependencies = [ [[package]] name = "ostree-ext" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e40c1a1b52ed5164b0fda610952438afff5162ff2dafa49e55c0a78698228d" +version = "0.4.0" +source = "git+https://github.com/ostreedev/ostree-rs-ext?branch=main#dc692921a9fa44ba09cbd82591082c073211889f" dependencies = [ "anyhow", + "async-compression", + "bitflags", "bytes", "camino", "cjson", + "containers-image-proxy", "flate2", "fn-error-context", "futures-util", "gvariant", "hex", "indicatif", + "lazy_static", "libc", - "maplit", "nix 0.22.0", + "oci-spec", "openat", "openat-ext", "openssl", "ostree", "phf 0.9.0", + "pin-project", "serde", "serde_json", "structopt", "tar", "tempfile", "tokio", - "tokio-stream", "tokio-util", "tracing", ] [[package]] name = "ostree-sys" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46755b75b81ac66623ee86d6eee779a82acf495a8a6a94ab458a96ad3e6880d1" +checksum = "6f21a33d095678ef9b32503ce042d4101477ab9a20c971d5f27e7f42d5a2bc79" dependencies = [ "gio-sys", "glib-sys", @@ -1520,6 +1651,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.7" @@ -1911,6 +2062,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" + [[package]] name = "serde" version = "1.0.130" @@ -2018,6 +2175,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "structopt" version = "0.3.25" @@ -2182,18 +2345,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.25" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.25" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ "proc-macro2", "quote", @@ -2276,22 +2439,11 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-stream" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8864d706fdb3cc0843a49647ac892720dac98a6eeb818b77190592cf4994066" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-util" -version = "0.6.7" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" dependencies = [ "bytes", "futures-core", diff --git a/Cargo.toml b/Cargo.toml index 3ca73f9ba4..3ca4e7c936 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ openat = "0.1.21" openat-ext = "^0.2.2" openssl = "0.10.38" os-release = "0.1.0" -ostree-ext = "0.3.0" +ostree-ext = "0.5.0" paste = "1.0" phf = { version = "0.10", features = ["macros"] } rand = "0.8.4" diff --git a/ci/cosa-overrides.sh b/ci/cosa-overrides.sh new file mode 100755 index 0000000000..80d1b5a2c1 --- /dev/null +++ b/ci/cosa-overrides.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# Inject ideally temporary overrides into our cosa build +# skopeo for containers https://github.com/containers/skopeo/pull/1476 +cd overrides/rpm +curl -L --remote-name-all \ + https://kojipkgs.fedoraproject.org//packages/skopeo/1.5.1/1.fc35/x86_64/skopeo-1.5.1-1.fc35.x86_64.rpm diff --git a/ci/prow/Dockerfile b/ci/prow/Dockerfile index 40317501f9..ae7962b301 100644 --- a/ci/prow/Dockerfile +++ b/ci/prow/Dockerfile @@ -4,7 +4,7 @@ COPY . . RUN ./ci/build.sh && make install DESTDIR=/cosa/component-install RUN make -C tests/kolainst install DESTDIR=/cosa/component-tests # Uncomment this to fake a build to test the code below -# RUN mkdir -p /cosa/component-install/usr/bin && echo foo > /cosa/component-install/usr/bin/foo +#RUN mkdir -p /cosa/component-install/usr/bin && echo foo > /cosa/component-install/usr/bin/foo FROM quay.io/coreos-assembler/coreos-assembler:latest WORKDIR /srv @@ -15,5 +15,7 @@ COPY --from=builder /cosa /cosa RUN rsync -rlv /cosa/component-install/ / # Merge installed tests RUN rsync -rlv /cosa/component-tests/ / -COPY --from=builder /src/ci/prow/fcos-e2e.sh /usr/bin/fcos-e2e +# Grab all of our ci scripts +COPY --from=builder /src/ci/ /ci/ +RUN ln -sr /ci/prow/fcos-e2e.sh /usr/bin/fcos-e2e USER builder diff --git a/ci/prow/fcos-e2e.sh b/ci/prow/fcos-e2e.sh index 6365ad84e8..ff4cc1f0a3 100755 --- a/ci/prow/fcos-e2e.sh +++ b/ci/prow/fcos-e2e.sh @@ -10,6 +10,7 @@ rpm-ostree --version cd $(mktemp -d) cosa init https://github.com/coreos/fedora-coreos-config/ rsync -rlv /cosa/component-install/ overrides/rootfs/ +/ci/cosa-overrides.sh cosa fetch cosa build cosa kola run 'ext.rpm-ostree.*' diff --git a/packaging/rpm-ostree.spec.in b/packaging/rpm-ostree.spec.in index c2610ad2df..2a9ad1eca3 100644 --- a/packaging/rpm-ostree.spec.in +++ b/packaging/rpm-ostree.spec.in @@ -48,7 +48,7 @@ BuildRequires: gnome-common BuildRequires: /usr/bin/g-ir-scanner # Core requirements # One way to check this: `objdump -p /path/to/rpm-ostree | grep LIBOSTREE` and pick the highest (though that might miss e.g. new struct members) -BuildRequires: pkgconfig(ostree-1) >= 2021.1 +BuildRequires: pkgconfig(ostree-1) >= 2021.5 BuildRequires: pkgconfig(polkit-gobject-1) BuildRequires: pkgconfig(json-glib-1.0) BuildRequires: pkgconfig(rpm) >= 4.14.0 diff --git a/rust/src/lib.rs b/rust/src/lib.rs index f747d24c93..856e7fa66b 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -133,23 +133,27 @@ pub mod ffi { fn cliwrap_destdir() -> String; } - /// `ContainerImport` is currently identical to ostree-rs-ext's `Import` struct, because + /// `ContainerImageState` is currently identical to ostree-rs-ext's `LayeredImageState` struct, because /// cxx.rs currently requires types used as extern Rust types to be defined by the same crate /// that contains the bridge using them, so we redefine an `ContainerImport` struct here. - pub(crate) struct ContainerImport { - pub ostree_commit: String, + pub(crate) struct ContainerImageState { + pub base_commit: String, + pub merge_commit: String, + pub is_layered: bool, pub image_digest: String, } // sysroot_upgrade.rs extern "Rust" { - fn import_container( + fn pull_container( repo: Pin<&mut OstreeRepo>, cancellable: Pin<&mut GCancellable>, - imgref: String, - ) -> Result>; - - fn fetch_digest(imgref: String, cancellable: Pin<&mut GCancellable>) -> Result; + imgref: &str, + ) -> Result>; + fn query_container_image( + repo: Pin<&mut OstreeRepo>, + imgref: &str, + ) -> Result>; } // core.rs diff --git a/rust/src/origin.rs b/rust/src/origin.rs index 80073f0702..91baa82c1f 100644 --- a/rust/src/origin.rs +++ b/rust/src/origin.rs @@ -37,12 +37,14 @@ pub(crate) fn origin_to_treefile_inner(kf: &KeyFile) -> Result> { Some(r) } else if let Some(r) = keyfile_get_optional_string(kf, ORIGIN, "baserefspec")? { Some(r) + } else if let Some(r) = keyfile_get_optional_string(kf, ORIGIN, "container-image-reference")? { + // TODO - consider this key deprecated and remove it + Some(r) } else { - keyfile_get_optional_string(kf, ORIGIN, "container-image-reference")? + keyfile_get_optional_string(kf, ORIGIN, ostree_ext::container::deploy::ORIGIN_CONTAINER)? }; - let refspec_str = refspec_str.ok_or_else(|| { - anyhow::anyhow!("Failed to find refspec/baserefspec/container-image-reference in origin") - })?; + let refspec_str = refspec_str + .ok_or_else(|| anyhow::anyhow!("Failed to find refspec/baserefspec/container in origin"))?; cfg.derive.base_refspec = Some(refspec_str); cfg.packages = parse_stringlist(kf, PACKAGES, "requested")?; cfg.derive.packages_local = parse_localpkglist(kf, PACKAGES, "requested-local")?; diff --git a/rust/src/sysroot_upgrade.rs b/rust/src/sysroot_upgrade.rs index a46468d5c4..8150c19e25 100644 --- a/rust/src/sysroot_upgrade.rs +++ b/rust/src/sysroot_upgrade.rs @@ -3,48 +3,94 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT use crate::cxxrsutil::*; -use crate::ffi::ContainerImport; -use std::convert::TryInto; +use crate::ffi::{output_message, ContainerImageState}; +use anyhow::Result; +use ostree::glib; +use ostree_container::store::LayeredImageImporter; +use ostree_container::store::PrepareResult; +use ostree_container::OstreeImageReference; +use ostree_ext::container as ostree_container; +use ostree_ext::ostree; +use std::convert::TryFrom; use std::pin::Pin; use tokio::runtime::Handle; +impl Into for ostree_container::store::LayeredImageState { + fn into(self) -> crate::ffi::ContainerImageState { + crate::ffi::ContainerImageState { + base_commit: self.base_commit, + merge_commit: self.merge_commit, + is_layered: self.is_layered, + image_digest: self.manifest_digest, + } + } +} + +async fn pull_container_async( + repo: &ostree::Repo, + imgref: &OstreeImageReference, +) -> Result { + output_message(&format!("Pulling manifest: {}", &imgref)); + let mut imp = LayeredImageImporter::new(repo, imgref).await?; + let prep = match imp.prepare().await? { + PrepareResult::AlreadyPresent(r) => return Ok(r.into()), + PrepareResult::Ready(r) => r, + }; + let digest = prep.manifest_digest.clone(); + output_message(&format!("Importing: {} (digest: {})", &imgref, &digest)); + if prep.base_layer.commit.is_none() { + let size = glib::format_size(prep.base_layer.size()); + output_message(&format!( + "Downloading base layer: {} ({})", + prep.base_layer.digest(), + size + )); + } else { + output_message(&format!("Using base: {}", prep.base_layer.digest())); + } + // TODO add nice download progress + for layer in prep.layers.iter() { + if layer.commit.is_some() { + output_message(&format!("Using layer: {}", layer.digest())); + } else { + let size = glib::format_size(layer.size()); + output_message(&format!("Downloading layer: {} ({})", layer.digest(), size)); + } + } + let import = imp.import(prep).await?; + // TODO log the discarded bits from import + let state = import.state; + Ok(state.into()) +} + /// Import ostree commit in container image using ostree-rs-ext's API. -pub(crate) fn import_container( +pub(crate) fn pull_container( mut repo: Pin<&mut crate::FFIOstreeRepo>, mut cancellable: Pin<&mut crate::FFIGCancellable>, - imgref: String, -) -> CxxResult> { - let repo = repo.gobj_wrap(); + imgref: &str, +) -> CxxResult> { + let repo = &repo.gobj_wrap(); let cancellable = cancellable.gobj_wrap(); - let imgref = imgref.as_str().try_into()?; + let imgref = &OstreeImageReference::try_from(imgref)?; - let imported = Handle::current().block_on(async { + let r = Handle::current().block_on(async { crate::utils::run_with_cancellable( - async { ostree_ext::container::import(&repo, &imgref, None).await }, + async { pull_container_async(repo, imgref).await }, &cancellable, ) .await })?; - Ok(Box::new(ContainerImport { - ostree_commit: imported.ostree_commit, - image_digest: imported.image_digest, - })) + Ok(Box::new(r)) } -/// Fetch the image digest for `imgref` using ostree-rs-ext's API. -pub(crate) fn fetch_digest( - imgref: String, - mut cancellable: Pin<&mut crate::FFIGCancellable>, -) -> CxxResult { - let imgref = imgref.as_str().try_into()?; - let cancellable = cancellable.gobj_wrap(); - - let digest = Handle::current().block_on(async { - crate::utils::run_with_cancellable( - async { ostree_ext::container::fetch_manifest_info(&imgref).await }, - &cancellable, - ) - .await - })?; - Ok(digest.manifest_digest) +/// C++ wrapper for querying image state; requires a pulled image +pub(crate) fn query_container_image( + mut repo: Pin<&mut crate::FFIOstreeRepo>, + imgref: &str, +) -> CxxResult> { + let repo = &repo.gobj_wrap(); + let imgref = &OstreeImageReference::try_from(imgref)?; + let state = ostree_container::store::query_image(repo, imgref)? + .ok_or_else(|| anyhow::anyhow!("Failed to find image {}", imgref))?; + Ok(Box::new(state.into())) } diff --git a/src/daemon/rpmostree-sysroot-upgrader.cxx b/src/daemon/rpmostree-sysroot-upgrader.cxx index 0be4b95fc5..d602d88069 100644 --- a/src/daemon/rpmostree-sysroot-upgrader.cxx +++ b/src/daemon/rpmostree-sysroot-upgrader.cxx @@ -450,28 +450,13 @@ rpmostree_sysroot_upgrader_pull_base (RpmOstreeSysrootUpgrader *self, if (override_commit) return glnx_throw (error, "Specifying commit overrides for container-image-reference type refspecs is not supported"); - if (strstr (refspec, "@")) - return glnx_throw (error, "Pinned to specific container image digest, cannot upgrade"); - - /* Check to see if the digest that `refspec` points to is the same before pulling a new container image. */ - const char *cur_digest = rpmostree_origin_get_container_image_reference_digest (self->original_origin); - if (cur_digest) - { - rpmostree_output_message ("Pulling manifest: %s", refspec); - auto new_digest = CXX_TRY_VAL(fetch_digest(std::string(refspec), *cancellable), error); - if (strcmp (new_digest.c_str(), cur_digest) == 0) - { - /* No new digest. */ - *out_changed = FALSE; - return TRUE; - } - } - - rpmostree_output_message ("Pulling: %s", refspec); - auto import = CXX_TRY_VAL(import_container(*self->repo, *cancellable, std::string(refspec)), error); - - rpmostree_origin_set_container_image_reference_digest (self->original_origin, import->image_digest.c_str()); - new_base_rev = strdup (import->ostree_commit.c_str()); + auto refspec_s = std::string(refspec); + auto import = CXX_TRY_VAL(pull_container(*self->repo, *cancellable, refspec_s), error); + // Note this duplicates https://github.com/ostreedev/ostree-rs-ext/blob/22a663f64e733e7ba8382f11f853ce4202652254/lib/src/container/store.rs#L64 + if (import->is_layered) + new_base_rev = strdup (import->merge_commit.c_str()); + else + new_base_rev = strdup (import->base_commit.c_str()); break; } case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: diff --git a/src/daemon/rpmostreed-deployment-utils.cxx b/src/daemon/rpmostreed-deployment-utils.cxx index 7e496e1365..e366cc2bd7 100644 --- a/src/daemon/rpmostreed-deployment-utils.cxx +++ b/src/daemon/rpmostreed-deployment-utils.cxx @@ -302,8 +302,8 @@ rpmostreed_deployment_generate_variant (OstreeSysroot *sysroot, case RPMOSTREE_REFSPEC_TYPE_CONTAINER: { g_variant_dict_insert (dict, "container-image-reference", "s", refspec); - auto digest = rpmostree_origin_get_container_image_reference_digest (origin); - g_variant_dict_insert (dict, "container-image-reference-digest", "s", digest); + auto state = CXX_TRY_VAL(query_container_image (*repo, refspec), error); + g_variant_dict_insert (dict, "container-image-reference-digest", "s", state->image_digest.c_str()); } break; case RPMOSTREE_REFSPEC_TYPE_CHECKSUM: diff --git a/src/libpriv/rpmostree-origin.cxx b/src/libpriv/rpmostree-origin.cxx index 0e727bb5eb..9cefbad3c9 100644 --- a/src/libpriv/rpmostree-origin.cxx +++ b/src/libpriv/rpmostree-origin.cxx @@ -234,11 +234,6 @@ rpmostree_origin_remove_transient_state (RpmOstreeOrigin *origin) rpmostree_origin_set_override_commit (origin, NULL, NULL); } -const char * -rpmostree_origin_get_container_image_reference_digest (RpmOstreeOrigin *origin) -{ - return origin->cached_digest; -} const char * rpmostree_origin_get_refspec (RpmOstreeOrigin *origin) @@ -523,23 +518,6 @@ rpmostree_origin_set_regenerate_initramfs (RpmOstreeOrigin *origin, g_key_file_get_string_list (origin->kf, "rpmostree", "initramfs-args", NULL, NULL); } -void -rpmostree_origin_set_container_image_reference_digest (RpmOstreeOrigin *origin, - const char *digest) -{ - if (digest != NULL) - { - g_key_file_set_string (origin->kf, "origin", "container-image-reference-digest", digest); - } - else - { - g_key_file_remove_key (origin->kf, "origin", "container-image-reference-digest", NULL); - } - - g_free (origin->cached_digest); - origin->cached_digest = g_strdup (digest); -} - void rpmostree_origin_set_override_commit (RpmOstreeOrigin *origin, const char *checksum, diff --git a/src/libpriv/rpmostree-origin.h b/src/libpriv/rpmostree-origin.h index 42575400da..e7d0a7bf5b 100644 --- a/src/libpriv/rpmostree-origin.h +++ b/src/libpriv/rpmostree-origin.h @@ -57,9 +57,6 @@ rpmostree_origin_dup (RpmOstreeOrigin *origin); void rpmostree_origin_remove_transient_state (RpmOstreeOrigin *origin); -const char * -rpmostree_origin_get_container_image_reference_digest (RpmOstreeOrigin *origin); - const char * rpmostree_origin_get_refspec (RpmOstreeOrigin *origin); @@ -146,10 +143,6 @@ rpmostree_origin_set_regenerate_initramfs (RpmOstreeOrigin *origin, gboolean regenerate, char **args); -void -rpmostree_origin_set_container_image_reference_digest (RpmOstreeOrigin *origin, - const char *digest); - void rpmostree_origin_set_override_commit (RpmOstreeOrigin *origin, const char *checksum, diff --git a/tests/kolainst/destructive/container-image b/tests/kolainst/destructive/container-image index 5b04ed7bd5..f8546e9c56 100755 --- a/tests/kolainst/destructive/container-image +++ b/tests/kolainst/destructive/container-image @@ -27,17 +27,22 @@ set -x libtest_prepare_offline cd $(mktemp -d) -image=containers-storage:localhost/fcos:latest +# TODO: It'd be much better to test this via a registry +image_dir=/var/tmp/fcos +image=oci:$image_dir image_pull=ostree-unverified-image:$image +tmp_imagedir=/var/tmp/fcos-tmp case "${AUTOPKGTEST_REBOOT_MARK:-}" in "") - # Test rebase + # Take the existing ostree commit, and export it to a container image, then rebase to it. + checksum=$(rpm-ostree status --json | jq -r '.deployments[0].checksum') - rpm-ostree ex-container export --repo=/ostree/repo ${checksum} "${image}" + rm ${image_dir} -rf + rpm-ostree ex-container 'export' --repo=/ostree/repo ${checksum} "${image}" rpm-ostree rebase "$image_pull" --experimental | tee out.txt - assert_file_has_content_literal out.txt 'Pulling: '"$image_pull" - rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:containers-storage:localhost/fcos:latest\"" + assert_file_has_content out.txt 'Importing.*'"$image_pull" + rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:$image\"" rpmostree_assert_status ".deployments[0][\"checksum\"] == \"${checksum}\"" echo "ok rebase to container image reference" @@ -47,6 +52,9 @@ case "${AUTOPKGTEST_REBOOT_MARK:-}" in /tmp/autopkgtest-reboot 1 ;; 1) + # Add a new RPM via local layering, then export the new locally-generated commit as + # a base image, then test upgrading to that. + if rpm-ostree deploy 42 2>err.txt; then fatal "unexpectedly deployed version from container image reference" fi @@ -70,6 +78,7 @@ case "${AUTOPKGTEST_REBOOT_MARK:-}" in with_foo_commit=$(rpm-ostree status --json | jq -r '.deployments[0].checksum') ostree refs ${with_foo_commit} --create vmcheck_tmp/new_update new_commit=$(ostree commit -b vmcheck --tree=ref=vmcheck_tmp/new_update) + rm "${image_dir}" -rf rpm-ostree ex-container export --repo=/ostree/repo ${new_commit} "$image" rpm-ostree uninstall foo @@ -79,9 +88,35 @@ case "${AUTOPKGTEST_REBOOT_MARK:-}" in /tmp/autopkgtest-reboot 2 ;; 2) + # Export the booted image again, but this time test layered containers via a `podman build`. + rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"${image_pull}\"" assert_streq $(rpm -q foo) foo-1.2-3.x86_64 - echo "ok upgrade" + + checksum=$(rpm-ostree status --json | jq -r '.deployments[0].checksum') + rm "${image_dir}" -rf + rpm-ostree ex-container 'export' --repo=/ostree/repo ${checksum} "${image}" + # https://github.com/ostreedev/ostree-rs-ext/issues/153 + skopeo copy $image containers-storage:localhost/fcos + td=$(mktemp -d) + cd ${td} +cat > Dockerfile << 'EOF' +FROM localhost/fcos +RUN echo some config file > /etc/someconfig.conf +RUN echo somedata > /usr/share/somenewdata +EOF + podman build -t localhost/fcos-derived --squash . + derived=oci:$image_dir:derived + skopeo copy containers-storage:localhost/fcos-derived $derived + rpm-ostree rebase --experimental ostree-unverified-image:$derived + rm $image_dir -rf + /tmp/autopkgtest-reboot 3 + ;; + 3) + grep -qF 'some config file' /etc/someconfig.conf || (echo missing someconfig.conf; exit 1) + grep -qF somedata /usr/share/somenewdata || (echo missing somenewdata; exit 1) + + rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:oci:$image_dir:derived\"" ;; *) echo "unexpected mark: ${AUTOPKGTEST_REBOOT_MARK}"; exit 1;; esac diff --git a/tests/kolainst/destructive/ex-container b/tests/kolainst/destructive/ex-container deleted file mode 100755 index 896b787487..0000000000 --- a/tests/kolainst/destructive/ex-container +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2021 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 - -booted_commit=$(rpm-ostree status --json | jq -r '.deployments[0].checksum') -rpm-ostree ex-container export --repo=/ostree/repo ${booted_commit} containers-storage:localhost/fcos -target_sha256=$(podman run --entrypoint bash --rm -i localhost/fcos -c 'sha256sum /usr/bin/rpm-ostree' | cut -f 1 -d ' ') -src_sha256=$(sha256sum /usr/bin/rpm-ostree | cut -f 1 -d ' ') -assert_streq "${src_sha256}" "${target_sha256}" -echo "ok container export" - -# TODO test container import too, ideally via registry. But I don't want to -# make this test super flaky right now by pulling from the internet, and -# we need infrastructure to mock up serving via local registry.