From 61faf204b9d18176338a98c946f1ee0ba7a549bb Mon Sep 17 00:00:00 2001 From: Luke Yang Date: Wed, 28 Jun 2023 14:34:48 -0400 Subject: [PATCH] Add `container upgrade --check` function Previously, OS based on native containers could not retrieve the manifest difference between the current system container image and its corresponding remote container image without performing an actual upgrade. This PR solves this issue by allowing the manifest difference to be outputted when using the `rpm-ostree upgrade --check` command. A `ManifestDiff` struct needed to be retrieved using `ostree-rs-ext`, requring several new functions in both Rust and C that were bridged through CXX Bridge. The `cached_update` object also needed to be modifed and updated with the `ManifestDiff` in order to extend compatibility with other products using rpm-ostree. However, a notable difference between how the `--upgrade --check` function works for ostree based system and a native container based system is that native containers skip over the use of `checksums`. This is because rebasing to locally stored container images (as opposed to a remote repository) does not create a valid ostree refspec. A Rust unit test was implemented to confirm that a difference between two manifests (stored locally in the rust/test folder) can be successfully retrieved. A `kola` test was also implemented to confirm that running `rpm-ostree upgrade --check` returns the correct manifest difference for a potential upgrade. --- .cci.jenkinsfile | 2 +- Cargo.lock | 777 ++++++++++++++++-- Cargo.toml | 13 +- Makefile-rpm-ostree.am | 1 + api-doc/Makefile.am | 2 +- ci/test-container.sh | 20 +- configure.ac | 2 +- deny.toml | 5 +- docs/_config.yml | 9 +- docs/container.md | 36 +- libdnf | 2 +- libglnx | 2 +- man/rpm-ostree.xml | 14 + packaging/rpm-ostree.spec.in | 4 +- rpmostree-cxxrs.cxx | 62 ++ rpmostree-cxxrs.h | 22 + rust/libdnf-sys/Cargo.toml | 4 +- rust/rpmostree-client/Cargo.toml | 2 +- .../builtins/scriptlet_intercept/groupadd.rs | 7 +- rust/src/container.rs | 28 +- rust/src/importer.rs | 9 +- rust/src/lib.rs | 23 + rust/src/main.rs | 11 +- rust/src/passwd.rs | 109 ++- rust/src/sysroot_upgrade.rs | 101 ++- rust/test/manifest1.json | 1 + rust/test/manifest2.json | 1 + src/app/libmain.cxx | 17 + src/app/rpmostree-builtins.h | 1 + src/app/rpmostree-clientlib.cxx | 83 ++ src/app/rpmostree-clientlib.h | 2 + src/app/rpmostree-pkg-builtins.cxx | 101 +++ src/daemon/org.projectatomic.rpmostree1.xml | 6 + src/daemon/rpm-ostreed.service | 4 - src/daemon/rpmostree-sysroot-upgrader.cxx | 17 +- src/daemon/rpmostreed-deployment-utils.cxx | 188 ++++- src/daemon/rpmostreed-os.cxx | 191 ++++- src/libpriv/rpmostree-core.cxx | 13 +- src/libpriv/rpmostree-kernel.cxx | 6 +- src/libpriv/rpmostree-postprocess.cxx | 4 +- tests/common/libvm.sh | 2 +- tests/kolainst/destructive/container-image | 12 +- .../destructive/container-update-check | 117 +++ tests/kolainst/nondestructive/misc.sh | 33 + tests/vm.sh | 2 +- 45 files changed, 1876 insertions(+), 192 deletions(-) create mode 100644 rust/test/manifest1.json create mode 100644 rust/test/manifest2.json create mode 100755 tests/kolainst/destructive/container-update-check diff --git a/.cci.jenkinsfile b/.cci.jenkinsfile index 511236c7f7..305f12a5cc 100644 --- a/.cci.jenkinsfile +++ b/.cci.jenkinsfile @@ -3,7 +3,7 @@ stage("Build") { parallel rpms: { def n = 4 - buildPod(memory: "4Gi", cpu: "${n}") { + buildPod(memory: "6Gi", cpu: "${n}") { checkout scm // 2:1 job to CPU at most should keep us from getting kicked out shwrap("""RPM_BUILD_NCPUS=${n} CARGO_BUILD_JOBS=${n} ./ci/coreosci-rpmbuild.sh""") diff --git a/Cargo.lock b/Cargo.lock index 4f7759507c..6d7d8c0d64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,18 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "1.0.1" @@ -119,12 +131,34 @@ dependencies = [ "tokio", ] +[[package]] +name = "async-trait" +version = "0.1.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backoff" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" +dependencies = [ + "getrandom", + "instant", + "rand", +] + [[package]] name = "base64" version = "0.13.1" @@ -173,9 +207,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.1" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6776fc96284a0bb647b615056fc496d1fe1644a7ab01829818a6d91cae888b84" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" [[package]] name = "block-buffer" @@ -186,6 +220,42 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bootc-lib" +version = "0.1.0" +source = "git+https://github.com/containers/bootc.git?branch=main#221e382cbe5fc5ff45b2064370cf58248406d4b6" +dependencies = [ + "anyhow", + "camino", + "cap-std-ext 2.0.0", + "clap", + "fn-error-context", + "gvariant", + "hex", + "indicatif", + "k8s-openapi", + "kube", + "libc", + "liboverdrop", + "nix 0.25.1", + "once_cell", + "openssl", + "ostree-ext 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex", + "rustix 0.37.20", + "schemars", + "serde", + "serde_json", + "serde_with", + "serde_yaml", + "tempfile", + "tokio", + "tokio-util", + "toml", + "tracing", + "uuid 1.3.2", +] + [[package]] name = "build-env" version = "0.3.1" @@ -209,6 +279,9 @@ name = "camino" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +dependencies = [ + "serde", +] [[package]] name = "cap-primitives" @@ -222,7 +295,7 @@ dependencies = [ "io-lifetimes", "ipnet", "maybe-owned", - "rustix 0.37.19", + "rustix 0.37.20", "windows-sys 0.48.0", "winx", ] @@ -237,7 +310,7 @@ dependencies = [ "cap-primitives", "io-extras", "io-lifetimes", - "rustix 0.37.19", + "rustix 0.37.20", ] [[package]] @@ -257,7 +330,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6012b1e726e3e3ccf8151e2dc9cb454e593e0e7623b0e35464f5e62a15158c27" dependencies = [ "cap-tempfile", - "rustix 0.37.19", + "rustix 0.37.20", ] [[package]] @@ -268,7 +341,7 @@ checksum = "6fd9864347f55a9c31de436ec9d7d3577476f3e6eeb3cc44ae2204de9164f78d" dependencies = [ "cap-std", "rand", - "rustix 0.37.19", + "rustix 0.37.20", "uuid 1.3.2", ] @@ -323,9 +396,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.2" +version = "4.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "401a4694d2bf92537b6867d94de48c4842089645fdcdf6c71865b175d836e9c2" +checksum = "3eab9e8ceb9afdade1ab3f0fd8dbce5b1b2f468ad653baf10e771781b2b67b73" dependencies = [ "clap_builder", "clap_derive", @@ -334,27 +407,26 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.1" +version = "4.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72394f3339a76daf211e57d4bcb374410f3965dcc606dd0e03738c7888766980" +checksum = "9f2763db829349bf00cfc06251268865ed4363b93a943174f638daf3ecdba2cd" dependencies = [ "anstream", "anstyle", - "bitflags 1.3.2", "clap_lex", "strsim", ] [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -551,9 +623,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109308c20e8445959c2792e81871054c6a17e6976489a93d2769641a2ba5839c" +checksum = "5032837c1384de3708043de9d4e97bb91290faca6c16529a28aa340592a78166" dependencies = [ "cc", "cxxbridge-flags", @@ -563,9 +635,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf4c6755cdf10798b97510e0e2b3edb9573032bd9379de8fffa59d68165494f" +checksum = "51368b3d0dbf356e10fcbfd455a038503a105ee556f7ee79b6bb8c53a7247456" dependencies = [ "cc", "codespan-reporting", @@ -573,24 +645,34 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] name = "cxxbridge-flags" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882074421238e84fe3b4c65d0081de34e5b323bf64555d3e61991f76eb64a7bb" +checksum = "0d9062157072e4aafc8e56ceaf8325ce850c5ae37578c852a0d4de2cecdded13" [[package]] name = "cxxbridge-macro" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a076022ece33e7686fb76513518e219cca4fce5750a8ae6d1ce6c0f48fd1af9" +checksum = "cf01e8a540f5a4e0f284595834f81cf88572f244b768f051724537afa99a2545" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", +] + +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core 0.13.4", + "darling_macro 0.13.4", ] [[package]] @@ -599,8 +681,22 @@ version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", ] [[package]] @@ -617,13 +713,35 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core 0.13.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" dependencies = [ - "darling_core", + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", "quote", "syn 1.0.109", ] @@ -643,7 +761,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4" dependencies = [ - "darling", + "darling 0.14.4", "proc-macro2", "quote", "syn 1.0.109", @@ -670,6 +788,27 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dlv-list" version = "0.5.0" @@ -679,6 +818,12 @@ dependencies = [ "const-random", ] +[[package]] +name = "dyn-clone" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "304e6508efa593091e97a9abbc10f90aa7ca635b6d2784feff3c89d41dd12272" + [[package]] name = "either" version = "1.8.1" @@ -794,7 +939,7 @@ checksum = "2cd66269887534af4b0c3e3337404591daa8dc8b9b2b3db71f9523beb4bafb41" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -830,7 +975,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -861,7 +1006,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7833d0f115a013d51c55950a3b09d30e4b057be9961b709acb9b5b17a1108861" dependencies = [ "io-lifetimes", - "rustix 0.37.19", + "rustix 0.37.20", "windows-sys 0.48.0", ] @@ -921,7 +1066,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -1187,6 +1332,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-range-header" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" + [[package]] name = "httparse" version = "1.8.0" @@ -1229,6 +1380,36 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-openssl" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ee5d7a8f718585d1c3c61dfde28ef5b0bb14734b4db13f5ada856cdc6c612b" +dependencies = [ + "http", + "hyper", + "linked_hash_set", + "once_cell", + "openssl", + "openssl-sys", + "parking_lot", + "tokio", + "tokio-openssl", + "tower-layer", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -1294,11 +1475,12 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.3" +version = "0.17.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef509aa9bc73864d6756f0d34d35504af3cf0844373afe9b8669a5b8005a729" +checksum = "8ff8cc23a7393a397ed1d7f56e6365cba772aba9f9912ab968b03043c395d057" dependencies = [ "console", + "instant", "number_prefix", "portable-atomic", "unicode-width", @@ -1354,7 +1536,7 @@ checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", - "rustix 0.37.19", + "rustix 0.37.20", "windows-sys 0.48.0", ] @@ -1382,6 +1564,150 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json-patch" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f54898088ccb91df1b492cc80029a6fdf1c48ca0db7c6822a8babad69c94658" +dependencies = [ + "serde", + "serde_json", + "thiserror", + "treediff", +] + +[[package]] +name = "jsonpath_lib" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f" +dependencies = [ + "log", + "serde", + "serde_json", +] + +[[package]] +name = "k8s-openapi" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd990069640f9db34b3b0f7a1afc62a05ffaa3be9b66aa3c313f58346df7f788" +dependencies = [ + "base64 0.21.0", + "bytes", + "chrono", + "http", + "percent-encoding", + "serde", + "serde-value", + "serde_json", + "url", +] + +[[package]] +name = "kube" +version = "0.83.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f468b2fa6c5ef92117813238758f79e394c2d7688bd6faa3e77243f90260b0" +dependencies = [ + "k8s-openapi", + "kube-client", + "kube-core", + "kube-derive", + "kube-runtime", +] + +[[package]] +name = "kube-client" +version = "0.83.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "337eb332d253036adc3247936248d0742c6c743f51eb38a684fd9b3b2878b27c" +dependencies = [ + "base64 0.20.0", + "bytes", + "chrono", + "dirs-next", + "either", + "futures", + "http", + "http-body", + "hyper", + "hyper-openssl", + "hyper-timeout", + "jsonpath_lib", + "k8s-openapi", + "kube-core", + "openssl", + "pem", + "pin-project", + "secrecy", + "serde", + "serde_json", + "serde_yaml", + "thiserror", + "tokio", + "tokio-util", + "tower", + "tower-http", + "tracing", +] + +[[package]] +name = "kube-core" +version = "0.83.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f924177ad71936cfe612641b45bb9879890696d3c026f0846423529f4fa449af" +dependencies = [ + "chrono", + "form_urlencoded", + "http", + "json-patch", + "k8s-openapi", + "once_cell", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "kube-derive" +version = "0.83.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ce7c7a14cf3fe567ca856de41db0d61394867675cfb0d65094c55f0fa2df2e0" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "serde_json", + "syn 1.0.109", +] + +[[package]] +name = "kube-runtime" +version = "0.83.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d5e4d09df25250ffcb09df3f31105a5f49eb8f8a08da9b776ea5b6431ec476f" +dependencies = [ + "ahash", + "async-trait", + "backoff", + "derivative", + "futures", + "json-patch", + "k8s-openapi", + "kube-client", + "parking_lot", + "pin-project", + "serde", + "serde_json", + "smallvec", + "thiserror", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1405,6 +1731,15 @@ dependencies = [ "system-deps", ] +[[package]] +name = "liboverdrop" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08e5373d7512834e2fbbe4100111483a99c28ca3818639f67ab2337672301f8e" +dependencies = [ + "log", +] + [[package]] name = "libsystemd" version = "0.5.0" @@ -1447,13 +1782,28 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" dependencies = [ "cc", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linked_hash_set" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47186c6da4d81ca383c7c47c1bfc80f4b95f4720514d860a5407aaf4233f9588" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "linux-raw-sys" version = "0.1.4" @@ -1466,6 +1816,16 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b64f40e5e03e0d54f03845c8197d0291253cdbedfb1cb46b13c2c117554a9f4c" +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.17" @@ -1508,7 +1868,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffc89ccdc6e10d6907450f753537ebc5c5d3460d2e4e62ea74bd571db62c0f9e" dependencies = [ - "rustix 0.37.19", + "rustix 0.37.20", ] [[package]] @@ -1602,6 +1962,20 @@ dependencies = [ "memoffset 0.6.5", ] +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.6.5", + "pin-utils", +] + [[package]] name = "nix" version = "0.26.2" @@ -1693,9 +2067,9 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "openssl" -version = "0.10.52" +version = "0.10.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56" +checksum = "69b3f656a17a6cbc115b5c7a40c616947d213ba182135b014d6051b73ab6f019" dependencies = [ "bitflags 1.3.2", "cfg-if", @@ -1714,7 +2088,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -1725,9 +2099,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.87" +version = "0.9.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e" +checksum = "c2ce0f250f34a308dcfdbb351f511359857d4ed2134ba715a4eadd46e1ffd617" dependencies = [ "cc", "libc", @@ -1735,6 +2109,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "ordered-float" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" +dependencies = [ + "num-traits", +] + [[package]] name = "ordered-multimap" version = "0.6.0" @@ -1775,9 +2158,9 @@ dependencies = [ [[package]] name = "ostree-ext" -version = "0.11.0" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8903d59c4a56794b6ef8a2b11a5674fe85b370f1da33ae34450a6de1e39a20d6" +checksum = "8511513a60fa0c20a84ba8d30255286687c848bec21d24cd3dd4d16ecf48123b" dependencies = [ "anyhow", "async-compression 0.3.15", @@ -1803,7 +2186,48 @@ dependencies = [ "ostree", "pin-project", "regex", - "rustix 0.37.19", + "rustix 0.37.20", + "serde", + "serde_json", + "tar", + "tempfile", + "term_size", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", +] + +[[package]] +name = "ostree-ext" +version = "0.11.3" +source = "git+https://github.com/ostreedev/ostree-rs-ext.git?rev=ea853c082c09594e1559e55b91d011994feb855b#ea853c082c09594e1559e55b91d011994feb855b" +dependencies = [ + "anyhow", + "async-compression 0.3.15", + "bitflags 1.3.2", + "camino", + "cap-std-ext 2.0.0", + "cap-tempfile", + "chrono", + "clap", + "containers-image-proxy", + "flate2", + "fn-error-context", + "futures-util", + "gvariant", + "hex", + "indicatif", + "io-lifetimes", + "libc", + "libsystemd", + "olpc-cjson", + "once_cell", + "openssl", + "ostree", + "pin-project", + "regex", + "rustix 0.37.20", "serde", "serde_json", "tar", @@ -1834,12 +2258,44 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.3.5", + "smallvec", + "windows-targets 0.48.0", +] + [[package]] name = "paste" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + [[package]] name = "percent-encoding" version = "2.2.0" @@ -1928,9 +2384,9 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "portable-atomic" -version = "0.3.19" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f6a7b87c2e435a3241addceeeff740ff8b7e76b74c13bf9acb17fa454ea00b" +checksum = "767eb9f07d4a5ebcb39bbf2d452058a93c011373abf6832e24194a1c3f004794" [[package]] name = "ppv-lite86" @@ -1980,18 +2436,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" dependencies = [ "proc-macro2", ] @@ -2066,6 +2522,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + [[package]] name = "ref-cast" version = "1.0.16" @@ -2083,18 +2550,18 @@ checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] name = "regex" -version = "1.8.1" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.1", + "regex-syntax 0.7.2", ] [[package]] @@ -2114,9 +2581,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] name = "reqwest" @@ -2173,7 +2640,8 @@ version = "0.1.0" dependencies = [ "anyhow", "binread", - "bitflags 2.3.1", + "bitflags 2.3.3", + "bootc-lib", "camino", "cap-primitives", "cap-std", @@ -2200,7 +2668,7 @@ dependencies = [ "once_cell", "openssl", "os-release", - "ostree-ext", + "ostree-ext 0.11.3 (git+https://github.com/ostreedev/ostree-rs-ext.git?rev=ea853c082c09594e1559e55b91d011994feb855b)", "paste", "phf", "rand", @@ -2209,7 +2677,7 @@ dependencies = [ "reqwest", "rpmostree-client", "rust-ini", - "rustix 0.37.19", + "rustix 0.37.20", "serde", "serde_derive", "serde_json", @@ -2252,9 +2720,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" +version = "0.37.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" dependencies = [ "bitflags 1.3.2", "errno", @@ -2287,6 +2755,30 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "schemars" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02c613288622e5f0c3fdc5dbd4db1c5fbe752746b1d1a56a0630b78fd00de44f" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109da1e6b197438deb6db99952990c7f959572794b80ff93707d55a232545e7c" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -2299,6 +2791,16 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "serde", + "zeroize", +] + [[package]] name = "security-framework" version = "2.8.2" @@ -2330,22 +2832,43 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "serde" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ "serde_derive", ] +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] @@ -2354,6 +2877,7 @@ version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ + "indexmap", "itoa", "ryu", "serde", @@ -2380,6 +2904,28 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +dependencies = [ + "darling 0.13.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "serde_yaml" version = "0.9.21" @@ -2484,9 +3030,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" dependencies = [ "proc-macro2", "quote", @@ -2547,7 +3093,7 @@ dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.19", + "rustix 0.37.20", "windows-sys 0.45.0", ] @@ -2587,7 +3133,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -2653,6 +3199,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.1.0" @@ -2661,7 +3217,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -2674,6 +3230,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-openssl" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08f9ffb7809f1b20c1b398d92acf4cc719874b3b2b2d9ea2f09b4a80350878a" +dependencies = [ + "futures-util", + "openssl", + "openssl-sys", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.14" @@ -2696,6 +3264,7 @@ dependencies = [ "futures-core", "futures-sink", "pin-project-lite", + "slab", "tokio", "tracing", ] @@ -2734,6 +3303,50 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ae70283aba8d2a8b411c695c437fe25b8b5e44e23e780662002fc72fb47a82" +dependencies = [ + "base64 0.21.0", + "bitflags 2.3.3", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "mime", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -2747,6 +3360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2760,7 +3374,7 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -2802,6 +3416,15 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "treediff" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52984d277bdf2a751072b5df30ec0377febdb02f7696d64c2d7d54630bac4303" +dependencies = [ + "serde_json", +] + [[package]] name = "try-lock" version = "0.2.4" @@ -3253,3 +3876,9 @@ dependencies = [ "reqwest", "xml-rs", ] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" diff --git a/Cargo.toml b/Cargo.toml index c414e92e7a..56d315b5bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ rpm = "4" anyhow = "1.0.69" binread = "2.2.0" bitflags = "2.3" +bootc = { git = "https://github.com/containers/bootc.git", branch = "main", package = "bootc-lib"} camino = "1.1.1" cap-std-ext = "2.0" cap-std = { version = "1.0.3", features = ["fs_utf8"] } @@ -55,7 +56,7 @@ cap-primitives = "1.0.3" cap-tempfile = "1.0.15" chrono = { version = "0.4.26", features = ["serde"] } clap = { version = "4.3", features = ["derive"] } -cxx = "1.0.95" +cxx = "1.0.101" envsubst = "0.2.1" either = "1.8.1" env_logger = "0.10.0" @@ -63,26 +64,26 @@ fail = { version = "0.5", features = ["failpoints"] } fn-error-context = "0.2.0" futures = "0.3.28" indoc = "2.0.1" -indicatif = "0.17.3" +indicatif = "0.17.5" is-terminal = "0.4" libc = "0.2.146" libdnf-sys = { path = "rust/libdnf-sys", version = "0.1.0" } maplit = "1.0" memfd = "0.6.0" nix = "0.26.1" -openssl = "0.10.49" +openssl = "0.10.54" once_cell = "1.18.0" os-release = "0.1.0" -ostree-ext = "0.11.0" +ostree-ext = { git = "https://github.com/ostreedev/ostree-rs-ext.git", rev = "ea853c082c09594e1559e55b91d011994feb855b" } paste = "1.0" phf = { version = "0.11", features = ["macros"] } rand = "0.8.5" rayon = "1.6.0" -regex = "1.7" +regex = "1.8" reqwest = { version = "0.11", features = ["native-tls", "blocking", "gzip"] } rpmostree-client = { path = "rust/rpmostree-client", version = "0.1.0" } rust-ini = "0.19.0" -serde = { version = "1.0.163", features = ["derive"] } +serde = { version = "1.0.164", features = ["derive"] } serde_derive = "1.0.118" serde_json = "1.0.96" serde_yaml = "0.9.16" diff --git a/Makefile-rpm-ostree.am b/Makefile-rpm-ostree.am index 2ef84f8355..be80a6d7de 100644 --- a/Makefile-rpm-ostree.am +++ b/Makefile-rpm-ostree.am @@ -132,6 +132,7 @@ install-rpmostree-hook: install -m 0755 -t $(DESTDIR)$(bindir) rpm-ostree install -d -m 0755 $(ostreeextdir) ln -Tsr -f $(DESTDIR)$(bindir)/rpm-ostree $(ostreeextdir)/ostree-ima-sign + ln -Tsr -f $(DESTDIR)$(bindir)/rpm-ostree $(ostreeextdir)/ostree-provisional-repair ln -Tsr -f $(DESTDIR)$(bindir)/rpm-ostree $(ostreeextdir)/ostree-container INSTALL_EXEC_HOOKS += install-rpmostree-hook diff --git a/api-doc/Makefile.am b/api-doc/Makefile.am index 084dd766a5..12a1df8bae 100644 --- a/api-doc/Makefile.am +++ b/api-doc/Makefile.am @@ -78,7 +78,7 @@ content_files= \ overview.xml \ $(NULL) -# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded +# SGML files where gtk-doc abbreviations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files= \ diff --git a/ci/test-container.sh b/ci/test-container.sh index 0a5a0ba3e2..8d9ab94fe2 100755 --- a/ci/test-container.sh +++ b/ci/test-container.sh @@ -58,8 +58,6 @@ versionid=$(. /usr/lib/os-release && echo $VERSION_ID) # Let's start by trying to install a bona fide module. # NOTE: If changing this also change the layering-modules test case $versionid in - 36) module=cri-o:1.23/default;; - 37) module=cri-o:1.24/default;; 38) module=cri-o:1.25/default;; *) assert_not_reached "Unsupported Fedora version: $versionid";; esac @@ -77,16 +75,8 @@ fi versionid=$(grep -E '^VERSION_ID=' /etc/os-release) versionid=${versionid:11} # trim off VERSION_ID= case $versionid in - 37) - url_suffix=2.14.0/3.fc37/x86_64/ignition-2.14.0-3.fc37.x86_64.rpm - # 2.14.0-4 - koji_url="https://koji.fedoraproject.org/koji/buildinfo?buildID=2013062" - koji_kernel_url="https://koji.fedoraproject.org/koji/buildinfo?buildID=2084352" - kver=6.0.7 - krev=301 - ;; 38) - url_suffix=2.15.0/2.fc38/x86_64/ignition-2.15.0-2.fc38.x86_64.rpm + url_suffix=2.15.0/4.fc37/x86_64/ignition-2.15.0-4.fc37.x86_64.rpm # 2.15.0-3 koji_url="https://koji.fedoraproject.org/koji/buildinfo?buildID=2158585" koji_kernel_url="https://koji.fedoraproject.org/koji/buildinfo?buildID=2174317" @@ -158,4 +148,12 @@ if ! grep -qe "error: No such file or directory" err.txt; then fatal "did not find expected error when skipping CLI wraps." fi +# test bootc cli call +ln -s /usr/bin/rpm-ostree /usr/bin/bootc +bootc --help > out.txt +if ! grep -qe "Deploy and upgrade via bootable container images" out.txt; then + cat out.txt + fatal "did not find expected bootc message when using sym link to rpm-ostree." +fi + echo ok diff --git a/configure.ac b/configure.ac index f9aface629..b51a529bd2 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ dnl dnl SEE RELEASE.md FOR INSTRUCTIONS ON HOW TO DO A RELEASE. dnl m4_define([year_version], [2023]) -m4_define([release_version], [4]) +m4_define([release_version], [5]) m4_define([package_version], [year_version.release_version]) AC_INIT([rpm-ostree], [package_version], [coreos@lists.fedoraproject.org]) AC_CONFIG_HEADER([config.h]) diff --git a/deny.toml b/deny.toml index b9b58f92cc..dccc9f7d23 100644 --- a/deny.toml +++ b/deny.toml @@ -9,4 +9,7 @@ private = { ignore = true } [sources] unknown-registry = "deny" unknown-git = "deny" -allow-git = [] \ No newline at end of file +allow-git = [ + "https://github.com/containers/bootc.git", + "https://github.com/ostreedev/ostree-rs-ext.git", +] diff --git a/docs/_config.yml b/docs/_config.yml index 006ac4bd2d..26bd9ccfdd 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,9 +1,12 @@ -title: coreos/rpm-ostree +# Template generated by https://github.com/coreos/repo-templates; do not edit downstream + +# To test documentation changes locally or using GitHub Pages, see: +# https://github.com/coreos/fedora-coreos-tracker/blob/main/docs/testing-project-documentation-changes.md + +title: rpm-ostree description: rpm-ostree documentation baseurl: "/rpm-ostree" url: "https://coreos.github.io" -# Comment above and use below for local development -# url: "http://localhost:4000" permalink: /:title/ markdown: kramdown kramdown: diff --git a/docs/container.md b/docs/container.md index ec5d4f09cb..20fac97a8d 100644 --- a/docs/container.md +++ b/docs/container.md @@ -28,10 +28,44 @@ For example, `rpm-ostree upgrade` will look for a new container version. You can also `rpm-ostree apply-live`, etc. It also does still work to do "client side" `rpm-ostree install` etc. +## URL format for ostree native containers + +Ostree understand the following URL formats to retrieve and optionally verify +the integrity of a container image or its content: + +- `ostree-unverified-image:registry:` or + `ostree-unverified-image:docker://`: Fetch a container image + without verify either the integrity of the container itself not its content. + The container image is usually fetched over HTTPS which still provides + integrity and confidentiality but not authenticity. + +- `ostree-unverified-registry:`: Shortcut for the above use case. + +- `ostree-remote-image::registry:` & + `ostree-remote-image::docker://`: Fetch a container + image and verify that the included ostree commit is correctly signed by a key + as configured locally in the specified ostree remote + (`/etc/ostree/remotes.d/.conf`). + +- `ostree-remote-registry::`: Shortcut for the above +use case. + +- `ostree-image-signed:registry:` & + `ostree-image-signed:docker://`: Fetch a container image and + verify that the container image is signed according to the policy set in + `/etc/containers/policy.json` (see + [containers-policy.json(5)](https://github.com/containers/image/blob/main/docs/containers-policy.json.5.md#policy-requirements)). + +ostree ([ostree-rs-ext](https://github.com/ostreedev/ostree-rs-ext)) uses +[skopeo](https://github.com/containers/skopeo) to fetch container images and +thus supports the transports as documented in +[containers-transports(5)](https://github.com/containers/image/blob/main/docs/containers-transports.5.md). + ## Registry authentication Today, the ostree stack will read `/etc/ostree/auth.json` and `/run/ostree/auth.json` -which are in the same format as documented by [man containers-auth.json](https://github.com/containers/image/blob/main/docs/containers-auth.json.5.md). +which are in the same format as documented by +[containers-auth.json(5)](https://github.com/containers/image/blob/main/docs/containers-auth.json.5.md). ## Using custom builds diff --git a/libdnf b/libdnf index 2362930d10..998efa8f41 160000 --- a/libdnf +++ b/libdnf @@ -1 +1 @@ -Subproject commit 2362930d10375a348bf2659db14b0ca4b911d4b7 +Subproject commit 998efa8f41188f9dc4b08b74086c2c3e2a38f73a diff --git a/libglnx b/libglnx index 07e3e49d3e..c02eb59916 160000 --- a/libglnx +++ b/libglnx @@ -1 +1 @@ -Subproject commit 07e3e49d3e47dfd4265ffb5495111439131715ca +Subproject commit c02eb5991695be11899fe0bdf6bd71ae2ff1ae21 diff --git a/man/rpm-ostree.xml b/man/rpm-ostree.xml index 1b530856f6..dcf7e1974c 100644 --- a/man/rpm-ostree.xml +++ b/man/rpm-ostree.xml @@ -328,6 +328,20 @@ Boston, MA 02111-1307, USA. + + search + + + + Takes one or more query terms as arguments. The packages are + searched within the enabled repositories in + /etc/yum.repos.d/. Packages can be + overlayed and removed using the install + and uninstall commands. + + + + rebase diff --git a/packaging/rpm-ostree.spec.in b/packaging/rpm-ostree.spec.in index 127e807281..67d2793762 100644 --- a/packaging/rpm-ostree.spec.in +++ b/packaging/rpm-ostree.spec.in @@ -3,9 +3,9 @@ Summary: Hybrid image/package system Name: rpm-ostree -Version: 2023.4 +Version: 2023.5 Release: 1%{?dist} -License: LGPLv2+ +License: LGPL-2.0-or-later URL: https://github.com/coreos/rpm-ostree # This tarball is generated via "cd packaging && make -f Makefile.dist-packaging dist-snapshot" # in the upstream git. It also contains vendored Rust sources. diff --git a/rpmostree-cxxrs.cxx b/rpmostree-cxxrs.cxx index 62a8ea164b..6dc42b329a 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; @@ -1413,6 +1414,22 @@ struct ContainerImageState final }; #endif // CXXBRIDGE1_STRUCT_rpmostreecxx$ContainerImageState +#ifndef CXXBRIDGE1_STRUCT_rpmostreecxx$ExportedManifestDiff +#define CXXBRIDGE1_STRUCT_rpmostreecxx$ExportedManifestDiff +struct ExportedManifestDiff final +{ + bool initialized; + ::rust::u64 total; + ::rust::u64 total_size; + ::rust::u64 n_removed; + ::rust::u64 removed_size; + ::rust::u64 n_added; + ::rust::u64 added_size; + + using IsRelocatable = ::std::true_type; +}; +#endif // CXXBRIDGE1_STRUCT_rpmostreecxx$ExportedManifestDiff + #ifndef CXXBRIDGE1_ENUM_rpmostreecxx$RefspecType #define CXXBRIDGE1_ENUM_rpmostreecxx$RefspecType enum class RefspecType : ::std::uint8_t @@ -2064,6 +2081,10 @@ extern "C" const ::rpmostreecxx::OstreeRepo &repo, const ::rpmostreecxx::GCancellable &cancellable) noexcept; + ::rust::repr::PtrLen rpmostreecxx$cxxbridge1$compare_local_to_remote_container ( + const ::rpmostreecxx::OstreeRepo &repo, const ::rpmostreecxx::GCancellable &cancellable, + ::rust::Str imgref, ::rust::Box< ::rpmostreecxx::ExportedManifestDiff> *return$) noexcept; + ::rust::repr::PtrLen rpmostreecxx$cxxbridge1$query_container_image_commit ( const ::rpmostreecxx::OstreeRepo &repo, ::rust::Str c, ::rust::Box< ::rpmostreecxx::ContainerImageState> *return$) noexcept; @@ -3656,6 +3677,21 @@ container_prune (const ::rpmostreecxx::OstreeRepo &repo, } } +::rust::Box< ::rpmostreecxx::ExportedManifestDiff> +compare_local_to_remote_container (const ::rpmostreecxx::OstreeRepo &repo, + const ::rpmostreecxx::GCancellable &cancellable, + ::rust::Str imgref) +{ + ::rust::MaybeUninit< ::rust::Box< ::rpmostreecxx::ExportedManifestDiff> > return$; + ::rust::repr::PtrLen error$ = rpmostreecxx$cxxbridge1$compare_local_to_remote_container ( + repo, cancellable, imgref, &return$.value); + if (error$.ptr) + { + throw ::rust::impl< ::rust::Error>::error (error$); + } + return ::std::move (return$.value); +} + ::rust::Box< ::rpmostreecxx::ContainerImageState> query_container_image_commit (const ::rpmostreecxx::OstreeRepo &repo, ::rust::Str c) { @@ -5995,6 +6031,13 @@ extern "C" void cxxbridge1$box$rpmostreecxx$ContainerImageState$drop ( ::rust::Box< ::rpmostreecxx::ContainerImageState> *ptr) noexcept; + ::rpmostreecxx::ExportedManifestDiff * + cxxbridge1$box$rpmostreecxx$ExportedManifestDiff$alloc () noexcept; + void cxxbridge1$box$rpmostreecxx$ExportedManifestDiff$dealloc ( + ::rpmostreecxx::ExportedManifestDiff *) noexcept; + void cxxbridge1$box$rpmostreecxx$ExportedManifestDiff$drop ( + ::rust::Box< ::rpmostreecxx::ExportedManifestDiff> *ptr) noexcept; + ::rpmostreecxx::TempEtcGuard *cxxbridge1$box$rpmostreecxx$TempEtcGuard$alloc () noexcept; void cxxbridge1$box$rpmostreecxx$TempEtcGuard$dealloc (::rpmostreecxx::TempEtcGuard *) noexcept; void cxxbridge1$box$rpmostreecxx$TempEtcGuard$drop ( @@ -6335,6 +6378,25 @@ Box< ::rpmostreecxx::ContainerImageState>::drop () noexcept cxxbridge1$box$rpmostreecxx$ContainerImageState$drop (this); } template <> +::rpmostreecxx::ExportedManifestDiff * +Box< ::rpmostreecxx::ExportedManifestDiff>::allocation::alloc () noexcept +{ + return cxxbridge1$box$rpmostreecxx$ExportedManifestDiff$alloc (); +} +template <> +void +Box< ::rpmostreecxx::ExportedManifestDiff>::allocation::dealloc ( + ::rpmostreecxx::ExportedManifestDiff *ptr) noexcept +{ + cxxbridge1$box$rpmostreecxx$ExportedManifestDiff$dealloc (ptr); +} +template <> +void +Box< ::rpmostreecxx::ExportedManifestDiff>::drop () noexcept +{ + cxxbridge1$box$rpmostreecxx$ExportedManifestDiff$drop (this); +} +template <> ::rpmostreecxx::TempEtcGuard * Box< ::rpmostreecxx::TempEtcGuard>::allocation::alloc () noexcept { diff --git a/rpmostree-cxxrs.h b/rpmostree-cxxrs.h index dd2f59e89f..138ebc7680 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; @@ -1195,6 +1196,22 @@ struct ContainerImageState final }; #endif // CXXBRIDGE1_STRUCT_rpmostreecxx$ContainerImageState +#ifndef CXXBRIDGE1_STRUCT_rpmostreecxx$ExportedManifestDiff +#define CXXBRIDGE1_STRUCT_rpmostreecxx$ExportedManifestDiff +struct ExportedManifestDiff final +{ + bool initialized; + ::rust::u64 total; + ::rust::u64 total_size; + ::rust::u64 n_removed; + ::rust::u64 removed_size; + ::rust::u64 n_added; + ::rust::u64 added_size; + + using IsRelocatable = ::std::true_type; +}; +#endif // CXXBRIDGE1_STRUCT_rpmostreecxx$ExportedManifestDiff + #ifndef CXXBRIDGE1_ENUM_rpmostreecxx$RefspecType #define CXXBRIDGE1_ENUM_rpmostreecxx$RefspecType enum class RefspecType : ::std::uint8_t @@ -1768,6 +1785,11 @@ pull_container (const ::rpmostreecxx::OstreeRepo &repo, void container_prune (const ::rpmostreecxx::OstreeRepo &repo, const ::rpmostreecxx::GCancellable &cancellable); +::rust::Box< ::rpmostreecxx::ExportedManifestDiff> +compare_local_to_remote_container (const ::rpmostreecxx::OstreeRepo &repo, + const ::rpmostreecxx::GCancellable &cancellable, + ::rust::Str imgref); + ::rust::Box< ::rpmostreecxx::ContainerImageState> query_container_image_commit (const ::rpmostreecxx::OstreeRepo &repo, ::rust::Str c); diff --git a/rust/libdnf-sys/Cargo.toml b/rust/libdnf-sys/Cargo.toml index 44a9f8b1aa..1f1b74672d 100644 --- a/rust/libdnf-sys/Cargo.toml +++ b/rust/libdnf-sys/Cargo.toml @@ -7,7 +7,7 @@ links = "dnf" publish = false [dependencies] -cxx = "1.0.95" +cxx = "1.0.101" [lib] name = "libdnf_sys" @@ -17,7 +17,7 @@ path = "lib.rs" cmake = "0.1.50" system-deps = "6.1" anyhow = "1.0" -cxx-build = "1.0.95" +cxx-build = "1.0.101" # This currently needs to duplicate the libraries from libdnf [package.metadata.system-deps] diff --git a/rust/rpmostree-client/Cargo.toml b/rust/rpmostree-client/Cargo.toml index a41e1b92d3..2886312870 100644 --- a/rust/rpmostree-client/Cargo.toml +++ b/rust/rpmostree-client/Cargo.toml @@ -12,6 +12,6 @@ publish = false [dependencies] anyhow = "1.0.69" -serde = { version = "1.0.163", features = ["derive"] } +serde = { version = "1.0.164", features = ["derive"] } serde_derive = "1.0.118" serde_json = "1.0.96" diff --git a/rust/src/builtins/scriptlet_intercept/groupadd.rs b/rust/src/builtins/scriptlet_intercept/groupadd.rs index 0b74a0a463..ef9e6dc393 100644 --- a/rust/src/builtins/scriptlet_intercept/groupadd.rs +++ b/rust/src/builtins/scriptlet_intercept/groupadd.rs @@ -46,7 +46,12 @@ fn cli_cmd() -> Command { Command::new(name) .bin_name(name) .about("create a new group") - .arg(Arg::new("force").short('f').long("force")) + .arg( + Arg::new("force") + .short('f') + .long("force") + .action(ArgAction::SetTrue), + ) .arg( Arg::new("gid") .short('g') diff --git a/rust/src/container.rs b/rust/src/container.rs index 6ca9605dbf..468ced8809 100644 --- a/rust/src/container.rs +++ b/rust/src/container.rs @@ -7,13 +7,14 @@ use std::num::NonZeroU32; use std::process::Command; use std::rc::Rc; -use anyhow::Result; +use anyhow::{Context, Result}; use camino::{Utf8Path, Utf8PathBuf}; use cap_std::fs::Dir; use cap_std_ext::cap_std; use cap_std_ext::prelude::*; use chrono::prelude::*; use clap::Parser; +use fn_error_context::context; use ostree::glib; use ostree_ext::chunking::ObjectMetaSized; use ostree_ext::container::{Config, ExportOpts, ImageReference}; @@ -425,7 +426,10 @@ pub fn container_encapsulate(args: Vec) -> CxxResult<()> { let package_structure = opt .previous_build_manifest .as_ref() - .map(|p| oci_spec::image::ImageManifest::from_file(&p).map_err(anyhow::Error::new)) + .map(|p| { + oci_spec::image::ImageManifest::from_file(&p) + .map_err(|e| anyhow::anyhow!("Failed to read previous manifest {p}: {e}")) + }) .transpose()?; let mut copy_meta_keys = opt.copy_meta_keys; @@ -483,6 +487,7 @@ struct UpdateFromRunningOpts { } // This reimplements https://github.com/ostreedev/ostree/pull/2691 basically +#[context("Finding encapsulated commits")] fn find_encapsulated_commits(repo: &Utf8Path) -> Result> { let objects = Dir::open_ambient_dir(&repo.join("objects"), cap_std::ambient_authority())?; let mut r = Vec::new(); @@ -550,7 +555,10 @@ pub(crate) fn deploy_from_self_entrypoint(args: Vec) -> CxxResult<()> { let encapsulated_commits = find_encapsulated_commits(src_repo_path)?; let commit = match encapsulated_commits.as_slice() { [] => return Err(format!("No encapsulated commit found in container").into()), - [c] => c.as_str(), + [c] => { + ostree::validate_checksum_string(&c)?; + c.as_str() + } o => return Err(format!("Found {} commit objects, expected just one", o.len()).into()), }; @@ -564,12 +572,14 @@ pub(crate) fn deploy_from_self_entrypoint(args: Vec) -> CxxResult<()> { opts.insert("refs", &&refs[..]); opts.insert("flags", &(flags.bits() as i32)); let options = opts.to_variant(); - target_repo.pull_with_options( - &format!("file://{src_repo_path}"), - &options, - None, - cancellable, - )?; + target_repo + .pull_with_options( + &format!("file://{src_repo_path}"), + &options, + None, + cancellable, + ) + .context("Pulling from embedded repo")?; } println!("Imported: {commit}"); diff --git a/rust/src/importer.rs b/rust/src/importer.rs index eb91ff23a1..f552bc64ca 100644 --- a/rust/src/importer.rs +++ b/rust/src/importer.rs @@ -346,16 +346,9 @@ fn tweak_imported_file_info(file_info: &FileInfo, ro_executables: bool) { #[context("Analyzing {}", path)] fn import_filter( path: &str, - file_info: &FileInfo, + _file_info: &FileInfo, skip_extraneous: bool, ) -> Result { - // Sanity check that RPM isn't using CPIO id fields. - let uid = file_info.attribute_uint32("unix::uid"); - let gid = file_info.attribute_uint32("unix::gid"); - if uid != 0 || gid != 0 { - bail!("Unexpected non-root owned path (marked as {}:{})", uid, gid); - } - // Skip some empty lock files, they are known to cause problems: // https://github.com/projectatomic/rpm-ostree/pull/1002 if path.starts_with("/usr/etc/selinux") && path.ends_with(".LOCK") { diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 43b3688521..a15ec5f704 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -188,6 +188,24 @@ pub mod ffi { pub version: String, } + #[derive(Debug)] + 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 extern "Rust" { fn pull_container( @@ -201,6 +219,11 @@ pub mod ffi { c: &str, ) -> Result>; fn purge_refspec(repo: &OstreeRepo, refspec: &str) -> Result<()>; + fn compare_local_to_remote_container( + repo: &OstreeRepo, + cancellable: &GCancellable, + imgref: &str, + ) -> Result>; } // core.rs diff --git a/rust/src/main.rs b/rust/src/main.rs index 9088c5f045..1439b9f2ff 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -50,10 +50,19 @@ async fn dispatch_ostree_ext(args: Vec) -> Result { Ok(0) } +/// Invoke the bootc CLI code. +async fn dispatch_bootc(args: Vec) -> Result { + bootc::cli::run_from_iter(args).await?; + Ok(0) +} + /// Dispatch multicall binary to relevant logic, based on callname from `argv[0]`. async fn dispatch_multicall(callname: String, args: Vec) -> Result { match callname.as_str() { - "ostree-container" | "ostree-ima-sign" => dispatch_ostree_ext(args).await, + "ostree-container" | "ostree-ima-sign" | "ostree-provisional-repair" => { + dispatch_ostree_ext(args).await + } + "bootc" => dispatch_bootc(args).await, _ => inner_async_main(args).await, // implicitly includes "rpm-ostree" } } diff --git a/rust/src/passwd.rs b/rust/src/passwd.rs index 9348f8627d..4bedf107bc 100644 --- a/rust/src/passwd.rs +++ b/rust/src/passwd.rs @@ -315,8 +315,8 @@ fn passwd_compose_prep_impl( rootfs.create_dir_with(dest, &db)?; // TODO(lucab): consider reworking these to avoid boolean results. - let found_passwd_data = data_from_json(rootfs, treefile, dest, "passwd")?; - let found_groups_data = data_from_json(rootfs, treefile, dest, "group")?; + let found_passwd_data = write_data_from_treefile(rootfs, treefile, dest, &PasswdKind::User)?; + let found_groups_data = write_data_from_treefile(rootfs, treefile, dest, &PasswdKind::Group)?; // We should error if we are getting passwd data from JSON and group from // previous commit, or vice versa, as that'll confuse everyone when it goes @@ -340,53 +340,110 @@ fn passwd_compose_prep_impl( Ok(()) } -fn data_from_json( +// PasswdKind includes 2 types: user and group. +#[derive(Debug)] +enum PasswdKind { + User, + Group, +} + +impl PasswdKind { + // Get user/group passwd file + fn passwd_file(&self) -> &'static str { + return match *self { + PasswdKind::User => "passwd", + PasswdKind::Group => "group", + }; + } + // Get user/group shadow file + fn shadow_file(&self) -> &'static str { + return match *self { + PasswdKind::User => "shadow", + PasswdKind::Group => "gshadow", + }; + } +} + +// This function writes the static passwd/group data from the treefile to the +// target root filesystem. +fn write_data_from_treefile( rootfs: &Dir, treefile: &mut Treefile, dest_path: &str, - target: &str, + target: &PasswdKind, ) -> Result { anyhow::ensure!(!dest_path.is_empty(), "missing destination path"); let append_unique_entries = match target { - "passwd" => passwd_append_unique, - "group" => group_append_unique, - x => anyhow::bail!("invalid merge target '{}'", x), + PasswdKind::User => passwd_append_unique, + PasswdKind::Group => group_append_unique, }; - let target_etc_filename = format!("{}{}", dest_path, target); + let passwd_name = target.passwd_file(); + let target_passwd_path = format!("{}{}", dest_path, passwd_name); // Migrate the check data from the specified file to /etc. - let mut src_file = if target == "passwd" { - let check_passwd_file = match treefile.parsed.get_check_passwd() { - CheckPasswd::File(cfg) => cfg, - _ => return Ok(false), - }; - treefile.externals.passwd_file_mut(check_passwd_file)? - } else if target == "group" { - let check_groups_file = match treefile.parsed.get_check_groups() { - CheckGroups::File(cfg) => cfg, - _ => return Ok(false), - }; - treefile.externals.group_file_mut(check_groups_file)? - } else { - unreachable!("impossible merge target '{}'", target); + let mut src_file = match target { + PasswdKind::User => { + let check_passwd_file = match treefile.parsed.get_check_passwd() { + CheckPasswd::File(cfg) => cfg, + _ => return Ok(false), + }; + treefile.externals.passwd_file_mut(check_passwd_file)? + } + PasswdKind::Group => { + let check_groups_file = match treefile.parsed.get_check_groups() { + CheckGroups::File(cfg) => cfg, + _ => return Ok(false), + }; + treefile.externals.group_file_mut(check_groups_file)? + } }; let mut seen_names = HashSet::new(); rootfs - .atomic_replace_with(&target_etc_filename, |dest_bufwr| -> Result<()> { + .atomic_replace_with(&target_passwd_path, |dest_bufwr| -> Result<()> { dest_bufwr .get_mut() .as_file_mut() .set_permissions(DEFAULT_PERMS.clone())?; let mut buf_rd = BufReader::new(&mut src_file); - append_unique_entries(&mut buf_rd, &mut seen_names, dest_bufwr) - .with_context(|| format!("failed to process '{}' content from JSON", &target))?; + append_unique_entries(&mut buf_rd, &mut seen_names, dest_bufwr).with_context(|| { + format!("failed to process '{}' content from JSON", &passwd_name) + })?; Ok(()) }) - .with_context(|| format!("failed to write /{}", &target_etc_filename))?; + .with_context(|| format!("failed to write /{}", &target_passwd_path))?; + // Regenerate etc/{,g}shadow to sync with etc/{passwd,group} + let db = rootfs.open(target_passwd_path).map(BufReader::new)?; + let shadow_name = target.shadow_file(); + let target_shadow_path = format!("{}{}", dest_path, shadow_name); + + match target { + PasswdKind::User => { + let entries = nameservice::passwd::parse_passwd_content(db)?; + rootfs + .atomic_replace_with(&target_shadow_path, |target_shadow| -> Result<()> { + for user in entries { + writeln!(target_shadow, "{}:*::0:99999:7:::", user.name)?; + } + Ok(()) + }) + .with_context(|| format!("Writing {target_shadow_path}"))?; + } + PasswdKind::Group => { + let entries = nameservice::group::parse_group_content(db)?; + rootfs + .atomic_replace_with(&target_shadow_path, |target_shadow| -> Result<()> { + for group in entries { + writeln!(target_shadow, "{}:::", group.name)?; + } + Ok(()) + }) + .with_context(|| format!("Writing {target_shadow_path}"))?; + } + } Ok(true) } diff --git a/rust/src/sysroot_upgrade.rs b/rust/src/sysroot_upgrade.rs index 8699156ea9..8f806a24ad 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::Result; use ostree::glib; @@ -56,12 +57,20 @@ async fn layer_progress_print(mut r: Receiver) { } } -fn default_container_pull_config() -> Result { +fn default_container_pull_config(imgref: &OstreeImageReference) -> Result { let mut cfg = ImageProxyConfig::default(); - let isolation_systemd = crate::utils::running_in_systemd().then(|| "rpm-ostree"); - let isolation_default = rustix::process::getuid().is_root().then(|| "nobody"); - let isolation_user = isolation_systemd.or(isolation_default); - ostree_container::merge_default_container_proxy_opts_with_isolation(&mut cfg, isolation_user)?; + if imgref.imgref.transport == ostree_container::Transport::ContainerStorage { + // Fetching from containers-storage, may require privileges to read files + ostree_container::merge_default_container_proxy_opts_with_isolation(&mut cfg, None)?; + } else { + let isolation_systemd = crate::utils::running_in_systemd().then(|| "rpm-ostree"); + let isolation_default = rustix::process::getuid().is_root().then(|| "nobody"); + let isolation_user = isolation_systemd.or(isolation_default); + ostree_container::merge_default_container_proxy_opts_with_isolation( + &mut cfg, + isolation_user, + )?; + } Ok(cfg) } @@ -70,7 +79,7 @@ async fn pull_container_async( imgref: &OstreeImageReference, ) -> Result { output_message(&format!("Pulling manifest: {}", &imgref)); - let config = default_container_pull_config()?; + let config = default_container_pull_config(imgref)?; let mut imp = ImageImporter::new(repo, imgref, config).await?; let layer_progress = imp.request_progress(); let prep = match imp.prepare().await? { @@ -191,3 +200,83 @@ pub(crate) fn purge_refspec(repo: &crate::FFIOstreeRepo, imgref: &str) -> CxxRes } Ok(()) } + +pub(crate) fn compare_local_to_remote_container( + 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)?; + let r = Handle::current().block_on(async { + crate::utils::run_with_cancellable( + async { get_container_manifest_diff(repo, imgref).await }, + &cancellable, + ) + .await + })?; + Ok(Box::new(r)) +} + +pub async fn get_container_manifest_diff( + repo: &ostree::Repo, + imgref: &OstreeImageReference, +) -> Result { + use ostree_ext::container::ManifestDiff; + let previous_state = + if let Some(r) = ostree_ext::container::store::query_image_ref(&repo, &imgref.imgref)? { + r + } else { + let manifest_diff = ExportedManifestDiff { + initialized: false, + total: 0, + total_size: 0, + n_removed: 0, + removed_size: 0, + n_added: 0, + added_size: 0, + }; + return Ok(manifest_diff); + }; + + let (manifest, _) = ostree_ext::container::fetch_manifest(&imgref).await?; + let diff = ManifestDiff::new(&previous_state.manifest, &manifest); + + let manifest_diff = 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, + }; + + Ok(manifest_diff) +} + +#[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/libmain.cxx b/src/app/libmain.cxx index 60059238eb..497bef878b 100644 --- a/src/app/libmain.cxx +++ b/src/app/libmain.cxx @@ -73,6 +73,8 @@ static RpmOstreeCommand commands[] = { "Overlay additional packages", rpmostree_builtin_install }, { "uninstall", static_cast (RPM_OSTREE_BUILTIN_FLAG_CONTAINER_CAPABLE), "Remove overlayed additional packages", rpmostree_builtin_uninstall }, + { "search", static_cast (RPM_OSTREE_BUILTIN_FLAG_CONTAINER_CAPABLE), + "Search for packages", rpmostree_builtin_search }, { "override", static_cast (RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD), "Manage base package overrides", rpmostree_builtin_override }, { "reset", static_cast (RPM_OSTREE_BUILTIN_FLAG_SUPPORTS_PKG_INSTALLS), @@ -154,6 +156,14 @@ static GOptionEntry pkg_entries[] "Remove overlayed additional package", "PKG" }, { NULL } }; +static int +cmp_by_name (const void *a, const void *b) +{ + struct RpmOstreeCommand *command_a = (RpmOstreeCommand *)a; + struct RpmOstreeCommand *command_b = (RpmOstreeCommand *)b; + return strcmp (command_a->name, command_b->name); +} + static GOptionContext * option_context_new_with_commands (RpmOstreeCommandInvocation *invocation, RpmOstreeCommand *commands) @@ -171,6 +181,13 @@ option_context_new_with_commands (RpmOstreeCommandInvocation *invocation, else /* top level */ g_string_append (summary, "Builtin Commands:"); + int command_count = 0; + for (RpmOstreeCommand *command = commands; command->name != NULL; command++) + { + command_count++; + } + + qsort (commands, command_count, sizeof (RpmOstreeCommand), cmp_by_name); for (RpmOstreeCommand *command = commands; command->name != NULL; command++) { gboolean hidden = (command->flags & RPM_OSTREE_BUILTIN_FLAG_HIDDEN) > 0; diff --git a/src/app/rpmostree-builtins.h b/src/app/rpmostree-builtins.h index 43ef9ca6a8..877bdd34e0 100644 --- a/src/app/rpmostree-builtins.h +++ b/src/app/rpmostree-builtins.h @@ -50,6 +50,7 @@ BUILTINPROTO (internals); BUILTINPROTO (container); BUILTINPROTO (install); BUILTINPROTO (uninstall); +BUILTINPROTO (search); BUILTINPROTO (override); BUILTINPROTO (kargs); BUILTINPROTO (reset); diff --git a/src/app/rpmostree-clientlib.cxx b/src/app/rpmostree-clientlib.cxx index 65aa33cf93..a04fe39e67 100644 --- a/src/app/rpmostree-clientlib.cxx +++ b/src/app/rpmostree-clientlib.cxx @@ -1004,6 +1004,7 @@ rpmostree_update_deployment ( const char *local_repo_remote, const char *treefile, GVariant *options, char **out_transaction_address, GCancellable *cancellable, GError **error) { + GLNX_AUTO_PREFIX_ERROR ("Updating deployment", error); g_autoptr (GVariant) modifiers = NULL; glnx_unref_object GUnixFDList *fd_list = NULL; if (!get_modifiers_variant (set_refspec, set_revision, install_pkgs, install_fileoverride_pkgs, @@ -1243,6 +1244,82 @@ 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) +{ + int total_str = 0; + int total_size_str = 0; + int total_removed_str = 0; + int removed_size_str = 0; + int total_added_str = 0; + int added_size_str = 0; + + g_auto (GVariantDict) manifest_diff_dict; + g_variant_dict_init (&manifest_diff_dict, manifest_diff); + + g_autoptr (GVariant) total + = g_variant_dict_lookup_value (&manifest_diff_dict, "total", G_VARIANT_TYPE ("t")); + if (!total) + return FALSE; + + g_variant_get (total, "t", &total_str); + printf (" %*s%s %d", maxkeylen, "Total layers", strlen ("Total layers") ? ":" : " ", total_str); + printf ("\n"); + + g_autoptr (GVariant) total_size + = g_variant_dict_lookup_value (&manifest_diff_dict, "total_size", G_VARIANT_TYPE ("t")); + if (!total_size) + return FALSE; + + g_variant_get (total_size, "t", &total_size_str); + printf (" %*s%s %s", maxkeylen, "Size", strlen ("Size") ? ":" : " ", + g_format_size (total_size_str)); + printf ("\n"); + + g_autoptr (GVariant) total_removed + = g_variant_dict_lookup_value (&manifest_diff_dict, "total_removed", G_VARIANT_TYPE ("t")); + if (!total_removed) + return FALSE; + + g_variant_get (total_removed, "t", &total_removed_str); + printf (" %*s%s %d", maxkeylen, "Removed layers", strlen ("Removed layers") ? ":" : " ", + total_removed_str); + printf ("\n"); + + g_autoptr (GVariant) removed_size + = g_variant_dict_lookup_value (&manifest_diff_dict, "removed_size", G_VARIANT_TYPE ("t")); + if (!removed_size) + return FALSE; + + g_variant_get (removed_size, "t", &removed_size_str); + printf (" %*s%s %s", maxkeylen, "Size", strlen ("Size") ? ":" : " ", + g_format_size (removed_size_str)); + printf ("\n"); + + g_autoptr (GVariant) total_added + = g_variant_dict_lookup_value (&manifest_diff_dict, "total_added", G_VARIANT_TYPE ("t")); + if (!total_added) + return FALSE; + + g_variant_get (total_added, "t", &total_added_str); + printf (" %*s%s %d", maxkeylen, "Added layers", strlen ("Added layers") ? ":" : " ", + total_added_str); + printf ("\n"); + + g_autoptr (GVariant) added_size + = g_variant_dict_lookup_value (&manifest_diff_dict, "added_size", G_VARIANT_TYPE ("t")); + if (!added_size) + return FALSE; + + g_variant_get (added_size, "t", &added_size_str); + printf (" %*s%s %s", maxkeylen, "Size", strlen ("Size") ? ":" : " ", + g_format_size (added_size_str)); + printf ("\n"); + + return TRUE; +} + /* this is used by both `status` and `upgrade --check/--preview` */ gboolean rpmostree_print_cached_update (GVariant *cached_update, gboolean verbose, @@ -1285,6 +1362,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})")); @@ -1307,6 +1387,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/app/rpmostree-pkg-builtins.cxx b/src/app/rpmostree-pkg-builtins.cxx index f2c26730d0..1ca3564c83 100644 --- a/src/app/rpmostree-pkg-builtins.cxx +++ b/src/app/rpmostree-pkg-builtins.cxx @@ -31,6 +31,8 @@ #include +#include + static char *opt_osname; static gboolean opt_reboot; static gboolean opt_dry_run; @@ -310,3 +312,102 @@ rpmostree_builtin_uninstall (int argc, char **argv, RpmOstreeCommandInvocation * return pkg_change (invocation, sysroot_proxy, FALSE, (const char *const *)opt_install, (const char *const *)argv, cancellable, error); } + +struct cstrless +{ + bool + operator() (const gchar *a, const gchar *b) const + { + return strcmp (a, b) < 0; + } +}; + +gboolean +rpmostree_builtin_search (int argc, char **argv, RpmOstreeCommandInvocation *invocation, + GCancellable *cancellable, GError **error) +{ + GOptionContext *context; + glnx_unref_object RPMOSTreeSysroot *sysroot_proxy = NULL; + + context = g_option_context_new ("PACKAGE [PACKAGE...]"); + g_option_context_add_main_entries (context, install_option_entry, NULL); + g_option_context_add_main_entries (context, uninstall_option_entry, NULL); + + if (!rpmostree_option_context_parse (context, option_entries, &argc, &argv, invocation, + cancellable, NULL, NULL, &sysroot_proxy, error)) + return FALSE; + + if (argc < 2) + { + rpmostree_usage_error (context, "At least one PACKAGE must be specified", error); + return FALSE; + } + + glnx_unref_object RPMOSTreeOS *os_proxy = NULL; + + if (!rpmostree_load_os_proxy (sysroot_proxy, opt_osname, cancellable, &os_proxy, error)) + return FALSE; + + g_autoptr (GPtrArray) arg_names = g_ptr_array_new (); + for (guint i = 1; i < argc; i++) + { + g_ptr_array_add (arg_names, (char *)argv[i]); + } + g_ptr_array_add (arg_names, NULL); + + g_autoptr (GVariant) out_packages = NULL; + + if (!rpmostree_os_call_search_sync (os_proxy, (const char *const *)arg_names->pdata, + &out_packages, cancellable, error)) + return FALSE; + + g_autoptr (GVariantIter) iter1 = NULL; + g_variant_get (out_packages, "aa{sv}", &iter1); + + g_autoptr (GVariantIter) iter2 = NULL; + std::set query_set; + + while (g_variant_iter_loop (iter1, "a{sv}", &iter2)) + { + const gchar *key; + const gchar *name; + const gchar *summary; + const gchar *query; + const gchar *match_group = ""; + + g_autoptr (GVariant) value = NULL; + + while (g_variant_iter_loop (iter2, "{sv}", &key, &value)) + { + if (strcmp (key, "key") == 0) + g_variant_get (value, "s", &query); + else if (strcmp (key, "name") == 0) + g_variant_get (value, "s", &name); + else if (strcmp (key, "summary") == 0) + g_variant_get (value, "s", &summary); + } + + if (!query_set.count (query)) + { + query_set.insert (query); + + if (strcmp (query, "match_group_a") == 0) + match_group = "Summary & Name"; + else if (strcmp (query, "match_group_b") == 0) + match_group = "Name"; + else if (strcmp (query, "match_group_c") == 0) + match_group = "Summary"; + + g_print ("\n===== %s Matched =====\n", match_group); + } + + g_print ("%s : %s\n", name, summary); + } + + if (query_set.size () == 0) + { + g_print ("No matches found.\n"); + } + + return TRUE; +} diff --git a/src/daemon/org.projectatomic.rpmostree1.xml b/src/daemon/org.projectatomic.rpmostree1.xml index b11ff5dfd2..7765b3fe54 100644 --- a/src/daemon/org.projectatomic.rpmostree1.xml +++ b/src/daemon/org.projectatomic.rpmostree1.xml @@ -477,6 +477,12 @@ + + + + + + diff --git a/src/daemon/rpm-ostreed.service b/src/daemon/rpm-ostreed.service index 8d1ef69cba..406ead652f 100644 --- a/src/daemon/rpm-ostreed.service +++ b/src/daemon/rpm-ostreed.service @@ -20,10 +20,6 @@ MountFlags=slave # and have a system rpm-ostreed-transaction.service that runs privileged # but as a subprocess. ProtectHome=true -# Explicitly list paths here which we should never access. The initial -# entry here ensures that the skopeo process we fork won't interact with -# application containers. -BindReadOnlyPaths=-/var/lib/containers NotifyAccess=main # Significantly bump this timeout from the default because # we do a lot of stuff on daemon startup. diff --git a/src/daemon/rpmostree-sysroot-upgrader.cxx b/src/daemon/rpmostree-sysroot-upgrader.cxx index 2beb3aee3b..d533c82f78 100644 --- a/src/daemon/rpmostree-sysroot-upgrader.cxx +++ b/src/daemon/rpmostree-sysroot-upgrader.cxx @@ -434,12 +434,19 @@ 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"); + { + *out_changed = FALSE; + 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..2c99950caf 100644 --- a/src/daemon/rpmostreed-deployment-utils.cxx +++ b/src/daemon/rpmostreed-deployment-utils.cxx @@ -399,6 +399,46 @@ rpm_diff_clear (RpmDiff *diff) G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (RpmDiff, rpm_diff_clear); +typedef struct +{ + gboolean initialized; + GVariant *total; + GVariant *total_size; + GVariant *total_removed; + GVariant *removed_size; + GVariant *total_added; + GVariant *added_size; +} ManifestDiff; + +static void +manifest_diff_init (ManifestDiff *diff) +{ + g_assert (!diff->initialized); + diff->total = g_variant_new ("t", G_GUINT64_CONSTANT (0)); + diff->total_size = g_variant_new ("t", G_GUINT64_CONSTANT (0)); + diff->total_removed = g_variant_new ("t", G_GUINT64_CONSTANT (0)); + diff->removed_size = g_variant_new ("t", G_GUINT64_CONSTANT (0)); + diff->total_added = g_variant_new ("t", G_GUINT64_CONSTANT (0)); + diff->added_size = g_variant_new ("t", G_GUINT64_CONSTANT (0)); + diff->initialized = TRUE; +} + +static void +manifest_diff_clear (ManifestDiff *diff) +{ + if (!diff->initialized) + return; + g_variant_ref (diff->total); + g_variant_ref (diff->total_size); + g_variant_ref (diff->total_removed); + g_variant_ref (diff->removed_size); + g_variant_ref (diff->total_added); + g_variant_ref (diff->added_size); + diff->initialized = FALSE; +} + +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (ManifestDiff, manifest_diff_clear); + static GVariant * single_pkg_variant_new (RpmOstreePkgTypes type, RpmOstreePackage *pkg) { @@ -474,6 +514,32 @@ rpm_diff_add_db_diff (RpmDiff *diff, OstreeRepo *repo, RpmOstreePkgTypes type, return TRUE; } +static gboolean +manifest_diff_add_db_diff (ManifestDiff *diff, rpmostreecxx::ExportedManifestDiff manifest_diff, + GCancellable *cancellable, GError **error) +{ + if (manifest_diff.initialized) + { + guint64 total_converted = manifest_diff.total; + guint64 total_size_converted = manifest_diff.total_size; + guint64 n_removed_converted = manifest_diff.n_removed; + guint64 removed_size_converted = manifest_diff.removed_size; + guint64 n_added_converted = manifest_diff.n_added; + guint64 added_size_converted = manifest_diff.added_size; + diff->total = g_variant_new ("t", total_converted); + diff->total_size = g_variant_new ("t", total_size_converted); + diff->total_removed = g_variant_new ("t", n_removed_converted); + diff->removed_size = g_variant_new ("t", removed_size_converted); + diff->total_added = g_variant_new ("t", n_added_converted); + diff->added_size = g_variant_new ("t", added_size_converted); + } + if (diff->total == NULL || diff->total_size == NULL || diff->total_removed == NULL + || diff->removed_size == NULL || diff->total_added == NULL || diff->added_size == NULL) + return FALSE; + + return TRUE; +} + static void rpm_diff_add_layered_diff (RpmDiff *diff, RpmOstreePackage *old_pkg, DnfPackage *new_pkg) { @@ -519,6 +585,24 @@ rpm_diff_is_empty (RpmDiff *diff) return !diff->upgraded->len && !diff->downgraded->len && !diff->removed->len && !diff->added->len; } +static gboolean +manifest_diff_is_empty (ManifestDiff *diff) +{ + g_assert (diff->initialized); + + int removed = 0; + int added = 0; + g_variant_get (diff->total_removed, "t", &removed); + g_variant_get (diff->total_added, "t", &added); + if (!removed && !added) + { + return TRUE; + } + + return !diff->total && !diff->total_size && !diff->total_removed && !diff->removed_size + && !diff->total_added && !diff->added_size; +} + static GVariant * rpm_diff_variant_new (RpmDiff *diff) { @@ -539,6 +623,35 @@ rpm_diff_variant_new (RpmDiff *diff) return g_variant_dict_end (&dict); } +static GVariant * +manifest_diff_variant_new (ManifestDiff *diff) +{ + guint64 total_converted = 0; + guint64 total_size_converted = 0; + guint64 total_removed_converted = 0; + guint64 removed_size_converted = 0; + guint64 total_added_converted = 0; + guint64 added_size_converted = 0; + + g_variant_get (diff->total, "t", &total_converted); + g_variant_get (diff->total_size, "t", &total_size_converted); + g_variant_get (diff->total_removed, "t", &total_removed_converted); + g_variant_get (diff->removed_size, "t", &removed_size_converted); + g_variant_get (diff->total_added, "t", &total_added_converted); + g_variant_get (diff->added_size, "t", &added_size_converted); + + g_auto (GVariantDict) manifest_dict; + g_variant_dict_init (&manifest_dict, NULL); + g_variant_dict_insert (&manifest_dict, "total", "t", total_converted); + g_variant_dict_insert (&manifest_dict, "total_size", "t", total_size_converted); + g_variant_dict_insert (&manifest_dict, "total_removed", "t", total_removed_converted); + g_variant_dict_insert (&manifest_dict, "removed_size", "t", removed_size_converted); + g_variant_dict_insert (&manifest_dict, "total_added", "t", total_added_converted); + g_variant_dict_insert (&manifest_dict, "added_size", "t", added_size_converted); + + return g_variant_dict_end (&manifest_dict); +} + static DnfPackage * find_package (DnfSack *sack, gboolean newer, RpmOstreePackage *pkg) { @@ -687,13 +800,19 @@ 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); + auto refspectype = rpmostreecxx::refspec_classify (r.refspec); + 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,6 +844,10 @@ rpmostreed_update_generate_variant (OstreeDeployment *booted_deployment, }; rpm_diff_init (&rpm_diff); + g_auto (ManifestDiff) manifest_diff = { + 0, + }; + manifest_diff_init (&manifest_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; @@ -744,15 +867,53 @@ 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 */ + gboolean rpm_diff_fail = FALSE; if (is_new_checksum) { 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; + { + rpm_diff_fail = TRUE; + } + } + else + { + rpm_diff_fail = TRUE; } /* now we look at the rpm-md/layering side */ + const OstreeRepo &tmp_repo = *repo; + const GCancellable &tmp_cancellable = *cancellable; + g_autofree char *origin_remote = NULL; + g_autofree char *origin_ref = NULL; + auto refspectype = rpmostreecxx::refspec_classify (r.refspec); + if (refspectype != rpmostreecxx::RefspecType::Container) + { + if (!ostree_parse_refspec (r.refspec.c_str (), &origin_remote, &origin_ref, error)) + return FALSE; + } + + if (refspectype == rpmostreecxx::RefspecType::Container) + { + CXX_TRY_VAR (res, + rpmostreecxx::compare_local_to_remote_container (tmp_repo, tmp_cancellable, + r.refspec.c_str ()), + error); + + gboolean manifest_diff_fail = FALSE; + + if (!manifest_diff_add_db_diff (&manifest_diff, *res, cancellable, error)) + { + manifest_diff_fail = TRUE; + } + + if (rpm_diff_fail && manifest_diff_fail) + { + *out_update = NULL; + return TRUE; + } + } /* 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 +928,15 @@ 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 */ + gboolean check_container_manifest_diff = FALSE; + if (!manifest_diff_is_empty (&manifest_diff)) + { + g_variant_dict_insert (dict, "manifest-diff", "@a{sv}", + manifest_diff_variant_new (&manifest_diff)); + check_container_manifest_diff = TRUE; + } + /* now we look for advisories */ if (sack && (ostree_modified_new || rpmmd_modified_new)) { /* let's just merge the two now for convenience */ @@ -802,7 +970,7 @@ 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) + if (is_new_checksum || rpmmd_modified_new || check_container_manifest_diff) { /* 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 diff --git a/src/daemon/rpmostreed-os.cxx b/src/daemon/rpmostreed-os.cxx index 090c2dfd13..52185c663b 100644 --- a/src/daemon/rpmostreed-os.cxx +++ b/src/daemon/rpmostreed-os.cxx @@ -36,6 +36,11 @@ #include "rpmostreed-transaction.h" #include "rpmostreed-utils.h" +#include + +#include +#include + typedef struct _RpmostreedOSClass RpmostreedOSClass; struct _RpmostreedOS @@ -141,7 +146,7 @@ os_authorize_method (GDBusInterfaceSkeleton *interface, GDBusMethodInvocation *i else if (g_strcmp0 (method_name, "GetDeploymentBootConfig") == 0 || g_strcmp0 (method_name, "ListRepos") == 0 || g_strcmp0 (method_name, "WhatProvides") == 0 - || g_strcmp0 (method_name, "GetPackages") == 0) + || g_strcmp0 (method_name, "GetPackages") == 0 || g_strcmp0 (method_name, "Search") == 0) { /* Note: early return here because no need authentication * for these methods @@ -1138,6 +1143,189 @@ os_handle_get_packages (RPMOSTreeOS *interface, GDBusMethodInvocation *invocatio return TRUE; } +/* helper function to sort and search within a set of (const gchar *) */ +struct cstrless +{ + bool + operator() (const gchar *a, const gchar *b) const + { + return strcmp (a, b) < 0; + } +}; + +/* wrapper function to both query for packages and add them to the builder */ +static void +query_results_to_builder (HyQuery query, GVariantBuilder *builder, const gchar *id, + std::set *result_set) +{ + g_autoptr (GPtrArray) pkglist = hy_query_run (query); + for (guint i = 0; i < pkglist->len && (*result_set).size () < 50; i++) + { + auto pkg = static_cast (g_ptr_array_index (pkglist, i)); + if (!(*result_set).count (dnf_package_get_name (pkg))) + { + os_add_package_info_to_builder (pkg, builder, id); + (*result_set).insert (dnf_package_get_name (pkg)); + } + } +} + +/* helper function to apply Name/Summary or HY_EQ/HY_SUBSTR filters on search term */ +static void +apply_search_filter (HyQuery *query, int keyname, const gchar *const name, int cmp_type) +{ + if (!hy_is_glob_pattern (name)) + { + hy_query_filter (*query, keyname, cmp_type | HY_ICASE, name); + } + else + { + hy_query_filter (*query, keyname, HY_GLOB | HY_ICASE, name); + } +} + +/* helper function to filter package query results */ +static void +search_packages_by_filter (HyQuery query, GVariantBuilder *builder, const gchar *const *names, + std::vector keynames, const gchar *id) +{ + std::set result_set; + HyQuery intermediate_query = hy_query_clone (query); + HyQuery final_query = hy_query_clone (query); + + int names_count = 0; + for (guint i = 0; names[i] != NULL; i++) + { + names_count++; + } + + /* Name/Summary matches */ + if (keynames.size () < 2) + { + hy_query_clear (query); + for (guint i = 0; names[i] != NULL; i++) + { + apply_search_filter (&query, keynames[0], names[i], HY_EQ); + } + query_results_to_builder (query, builder, id, &result_set); + + hy_query_clear (query); + for (guint i = 0; names[i] != NULL; i++) + { + apply_search_filter (&query, keynames[0], names[i], HY_SUBSTR); + } + query_results_to_builder (query, builder, id, &result_set); + } + + /* Name AND Summary matches for more than one search term */ + /* ========================================================================================= + For each search term, apply a query with the keyname filter (Name or Summary) and unions the + results. This allows multi-term searches to return matches when search terms are found in + either the Name or Summary of a package. After this, return the intersection of the results + for each search term to filter out results that do not contain all matching terms. + ========================================================================================= */ + else if (keynames.size () >= 2 && names_count >= 2) + { + + for (guint i = 0; names[i] != NULL; i++) + { + hy_query_clear (intermediate_query); + for (guint j = 0; j < keynames.size (); j++) + { + hy_query_clear (query); + apply_search_filter (&query, keynames[j], names[i], HY_EQ); + + if (j != 0) + { + hy_query_union (intermediate_query, query); + } + else + { + intermediate_query = hy_query_clone (query); + } + + hy_query_clear (query); + apply_search_filter (&query, keynames[j], names[i], HY_SUBSTR); + hy_query_union (intermediate_query, query); + } + + if (i != 0) + { + hy_query_intersection (final_query, intermediate_query); + } + else + { + final_query = hy_query_clone (intermediate_query); + } + } + query_results_to_builder (final_query, builder, id, &result_set); + } + + /* Name AND Summary matches for only one search term */ + /* ========================================================================================= + For the case of a single search term, return the intersection of both Name and Summary matches + of the search term (instead of the union for multi-term searches). + ========================================================================================= */ + else if (keynames.size () >= 2 && names_count < 2) + { + for (guint i = 0; i < keynames.size (); i++) + { + hy_query_clear (query); + apply_search_filter (&query, keynames[i], names[0], HY_EQ); + intermediate_query = hy_query_clone (query); + + hy_query_clear (query); + apply_search_filter (&query, keynames[i], names[0], HY_SUBSTR); + hy_query_union (intermediate_query, query); + + if (i != 0) + { + hy_query_intersection (final_query, intermediate_query); + } + else + { + final_query = hy_query_clone (intermediate_query); + } + } + query_results_to_builder (final_query, builder, id, &result_set); + } +} + +static gboolean +os_handle_search (RPMOSTreeOS *interface, GDBusMethodInvocation *invocation, + const gchar *const *names) +{ + GError *local_error = NULL; + g_autoptr (GCancellable) cancellable = NULL; + + sd_journal_print (LOG_INFO, "Handling Search for caller %s", + g_dbus_method_invocation_get_sender (invocation)); + + g_autoptr (DnfContext) dnfctx + = os_create_dnf_context_simple (interface, TRUE, cancellable, &local_error); + if (dnfctx == NULL) + return os_throw_dbus_invocation_error (invocation, &local_error); + + hy_autoquery HyQuery query = hy_query_create (dnf_context_get_sack (dnfctx)); + + GVariantBuilder builder; + g_variant_builder_init (&builder, (const GVariantType *)"aa{sv}"); + + std::vector keynames_a = { HY_PKG_NAME, HY_PKG_SUMMARY }; + search_packages_by_filter (query, &builder, names, keynames_a, "match_group_a"); + + std::vector keynames_b = { HY_PKG_NAME }; + search_packages_by_filter (query, &builder, names, keynames_b, "match_group_b"); + + std::vector keynames_c = { HY_PKG_SUMMARY }; + search_packages_by_filter (query, &builder, names, keynames_c, "match_group_c"); + + GVariant *pkgs_result = g_variant_builder_end (&builder); + g_dbus_method_invocation_return_value (invocation, g_variant_new ("(@aa{sv})", pkgs_result)); + + return TRUE; +} + /* This is an older variant of Cleanup, kept for backcompat */ static gboolean os_handle_clear_rollback_target (RPMOSTreeOS *interface, GDBusMethodInvocation *invocation, @@ -1813,6 +2001,7 @@ rpmostreed_os_iface_init (RPMOSTreeOSIface *iface) iface->handle_finalize_deployment = os_handle_finalize_deployment; iface->handle_what_provides = os_handle_what_provides; iface->handle_get_packages = os_handle_get_packages; + iface->handle_search = os_handle_search; /* legacy cleanup API; superseded by Cleanup() */ iface->handle_clear_rollback_target = os_handle_clear_rollback_target; /* legacy deployment change API; superseded by UpdateDeployment() */ diff --git a/src/libpriv/rpmostree-core.cxx b/src/libpriv/rpmostree-core.cxx index 9ac15b3154..5c3b0144b0 100644 --- a/src/libpriv/rpmostree-core.cxx +++ b/src/libpriv/rpmostree-core.cxx @@ -1466,7 +1466,18 @@ check_goal_solution (RpmOstreeContext *self, GPtrArray *removed_pkgnames, * for it anyway so that we get a bug report in case it somehow happens. */ { g_autoptr (GPtrArray) packages = dnf_goal_get_packages (goal, DNF_PACKAGE_INFO_REINSTALL, -1); - g_assert_cmpint (packages->len, ==, 0); + if (packages->len > 0) + { + g_autoptr (GString) buf = g_string_new (""); + for (guint i = 0; i < packages->len; i++) + { + if (i > 0) + g_string_append_c (buf, ' '); + auto pkg = static_cast (packages->pdata[i]); + g_string_append (buf, dnf_package_get_name (pkg)); + } + return glnx_throw (error, "Request to reinstall exact base package versions: %s", buf->str); + } } /* Look at UPDATE and DOWNGRADE, and see whether they're doing what we expect */ diff --git a/src/libpriv/rpmostree-kernel.cxx b/src/libpriv/rpmostree-kernel.cxx index 2cf6d00fa8..e5dcb8f1f3 100644 --- a/src/libpriv/rpmostree-kernel.cxx +++ b/src/libpriv/rpmostree-kernel.cxx @@ -89,7 +89,8 @@ find_kernel_and_initramfs_in_bootdir (int rootfs_dfd, const char *bootdir, char if (out_ksuffix ? g_str_has_prefix (name, "vmlinuz-") : g_str_equal (name, "vmlinuz")) { if (ret_kernel) - return glnx_throw (error, "Multiple vmlinuz%s in %s", out_ksuffix ? "-" : "", bootdir); + return glnx_throw (error, "Multiple vmlinuz%s in %s, occurrences '%s' and '%s/%s'", + out_ksuffix ? "-" : "", bootdir, ret_kernel, bootdir, name); if (out_ksuffix) ret_ksuffix = g_strdup (name + strlen ("vmlinuz-")); ret_kernel = g_strconcat (bootdir, "/", name, NULL); @@ -97,7 +98,8 @@ find_kernel_and_initramfs_in_bootdir (int rootfs_dfd, const char *bootdir, char else if (g_str_equal (name, "initramfs.img") || g_str_has_prefix (name, "initramfs-")) { if (ret_initramfs) - return glnx_throw (error, "Multiple initramfs- in %s", bootdir); + return glnx_throw (error, "Multiple initramfs- in %s, occurrences '%s' and '%s/%s'", + bootdir, ret_initramfs, bootdir, name); ret_initramfs = g_strconcat (bootdir, "/", name, NULL); } } diff --git a/src/libpriv/rpmostree-postprocess.cxx b/src/libpriv/rpmostree-postprocess.cxx index bfadaa73dd..9b38da931a 100644 --- a/src/libpriv/rpmostree-postprocess.cxx +++ b/src/libpriv/rpmostree-postprocess.cxx @@ -397,8 +397,8 @@ postprocess_final (int rootfs_dfd, rpmostreecxx::Treefile &treefile, gboolean un /* Temporary workaround for https://github.com/openshift/os/issues/1036. */ { - rust::Vec child_argv = { rust::String ("semodule"), rust::String ("-n"), - rust::String ("--rebuild-if-modules-changed") }; + rust::Vec child_argv + = { rust::String ("semodule"), rust::String ("-n"), rust::String ("--refresh") }; ROSCXX_TRY (bubblewrap_run_sync (rootfs_dfd, child_argv, false, (bool)unified_core_mode), error); } diff --git a/tests/common/libvm.sh b/tests/common/libvm.sh index 25f349e8bf..c5bf52008e 100644 --- a/tests/common/libvm.sh +++ b/tests/common/libvm.sh @@ -66,7 +66,7 @@ vm_kola_spawn() { exit 1 fi setpriv --pdeathsig SIGKILL -- \ - env MANTLE_SSH_DIR="$PWD/kola-ssh" kola spawn -p qemu-unpriv \ + env MANTLE_SSH_DIR="$PWD/kola-ssh" kola spawn -p qemu \ --qemu-image "$test_image" -v --idle \ --json-info-fd 4 --output-dir "$outputdir" & # hack; need cleaner API for async kola spawn diff --git a/tests/kolainst/destructive/container-image b/tests/kolainst/destructive/container-image index 4cb34d5f8a..fc812d975f 100755 --- a/tests/kolainst/destructive/container-image +++ b/tests/kolainst/destructive/container-image @@ -162,9 +162,7 @@ EOF if test "${touched_resolv_conf}" -eq 1; then rm -vf /etc/resolv.conf fi - derived=oci:$image_dir:derived - skopeo copy containers-storage:localhost/fcos-derived $derived - rpm-ostree rebase ostree-unverified-image:$derived + rpm-ostree rebase ostree-unverified-image:containers-storage:localhost/fcos-derived ostree container image list --repo=/ostree/repo | tee imglist.txt assert_streq "$(wc -l < imglist.txt)" 1 rm $image_dir -rf @@ -181,7 +179,7 @@ EOF assert_streq $(rpm -q baz) baz-2.0-1.${arch} test -f /usr/bin/baz ! rpm -q nano - rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:oci:$image_dir:derived\"" + rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:containers-storage:localhost/fcos-derived\"" # We'll test the "apply" automatic updates policy here systemctl stop rpm-ostreed @@ -190,9 +188,7 @@ EOF rpm-ostree reload # Now revert back to the base image, but keep our layered package foo - rm "${image_dir}" -rf - skopeo copy containers-storage:localhost/fcos ${image}:latest - rpm-ostree rebase ostree-unverified-image:${image}:latest + rpm-ostree rebase ostree-unverified-image:containers-storage:localhost/fcos /tmp/autopkgtest-reboot 4 ;; 4) @@ -204,7 +200,7 @@ EOF fatal "found $p" fi done - rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:oci:$image_dir:latest\"" + rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:containers-storage:localhost/fcos\"" ;; *) echo "unexpected mark: ${AUTOPKGTEST_REBOOT_MARK}"; exit 1;; esac diff --git a/tests/kolainst/destructive/container-update-check b/tests/kolainst/destructive/container-update-check new file mode 100755 index 0000000000..d1124c47ad --- /dev/null +++ b/tests/kolainst/destructive/container-update-check @@ -0,0 +1,117 @@ +#!/bin/bash +## kola: +## # Increase timeout since this test has a lot of I/O and involves rebasing +## timeoutMin: 15 +## # 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 + "") + 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 + # 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 diff --git a/tests/kolainst/nondestructive/misc.sh b/tests/kolainst/nondestructive/misc.sh index 6965b2f280..223bd45d61 100755 --- a/tests/kolainst/nondestructive/misc.sh +++ b/tests/kolainst/nondestructive/misc.sh @@ -101,6 +101,39 @@ rpmostree_busctl_call_os GetPackages as 1 should-not-exist-p-equals-np > out.txt assert_file_has_content_literal out.txt 'aa{sv} 0' echo "ok dbus GetPackages" +rpmostree_busctl_call_os Search as 1 testdaemon > out.txt +assert_file_has_content_literal out.txt '"epoch" t 0' +assert_file_has_content_literal out.txt '"reponame" s "libtest"' +assert_file_has_content_literal out.txt '"nevra" s "testdaemon' +rpmostree_busctl_call_os Search as 1 should-not-exist-p-equals-np > out.txt +assert_file_has_content_literal out.txt 'aa{sv} 0' +echo "ok dbus Search" + +rpm-ostree search testdaemon > out.txt +assert_file_has_content_literal out.txt '===== Name Matched =====' +assert_file_has_content_literal out.txt 'testdaemon : awesome-daemon-for-testing' +echo "ok Search name match" + +rpm-ostree search awesome-daemon > out.txt +assert_file_has_content_literal out.txt '===== Summary Matched =====' +assert_file_has_content_literal out.txt 'testdaemon : awesome-daemon-for-testing' +echo "ok Search summary match" + +rpm-ostree search testdaemon awesome-daemon > out.txt +assert_file_has_content_literal out.txt '===== Summary & Name Matched =====' +assert_file_has_content_literal out.txt 'testdaemon : awesome-daemon-for-testing' +echo "ok Search name and summary match" + +rpm-ostree search "test*" > out.txt +assert_file_has_content_literal out.txt '===== Summary & Name Matched =====' +assert_file_has_content_literal out.txt '===== Name Matched =====' +assert_file_has_content_literal out.txt '===== Summary Matched =====' +assert_file_has_content_literal out.txt 'testdaemon : awesome-daemon-for-testing' +assert_file_has_content_literal out.txt 'testpkg-etc : testpkg-etc' +assert_file_has_content_literal out.txt 'testpkg-post-infinite-loop : testpkg-post-infinite-loop' +assert_file_has_content_literal out.txt 'testpkg-touch-run : testpkg-touch-run' +echo "ok Search glob pattern match" + # Verify operations as non-root runuser -u core rpm-ostree status echo "ok status doesn't require root" diff --git a/tests/vm.sh b/tests/vm.sh index a54f85d8a4..996f67304f 100755 --- a/tests/vm.sh +++ b/tests/vm.sh @@ -39,7 +39,7 @@ spawn_vm() { exec 4> .kolavm/info.json env MANTLE_SSH_DIR="$PWD/.kolavm/ssh" \ - kola spawn -k -p qemu-unpriv \ + kola spawn -k -p qemu \ --qemu-image "$image" -v --idle \ --json-info-fd 4 --output-dir "$PWD/.kolavm/output" &