diff --git a/Cargo.lock b/Cargo.lock
index 4f7759507c..0829e2bab7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -222,7 +222,7 @@ dependencies = [
"io-lifetimes",
"ipnet",
"maybe-owned",
- "rustix 0.37.19",
+ "rustix 0.37.20",
"windows-sys 0.48.0",
"winx",
]
@@ -237,7 +237,7 @@ dependencies = [
"cap-primitives",
"io-extras",
"io-lifetimes",
- "rustix 0.37.19",
+ "rustix 0.37.20",
]
[[package]]
@@ -257,7 +257,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 +268,7 @@ checksum = "6fd9864347f55a9c31de436ec9d7d3577476f3e6eeb3cc44ae2204de9164f78d"
dependencies = [
"cap-std",
"rand",
- "rustix 0.37.19",
+ "rustix 0.37.20",
"uuid 1.3.2",
]
@@ -323,9 +323,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,22 +334,21 @@ 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",
@@ -861,7 +860,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",
]
@@ -1294,11 +1293,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 +1354,7 @@ checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
"hermit-abi 0.3.1",
"io-lifetimes",
- "rustix 0.37.19",
+ "rustix 0.37.20",
"windows-sys 0.48.0",
]
@@ -1508,7 +1508,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]]
@@ -1693,9 +1693,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",
@@ -1725,9 +1725,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",
@@ -1775,9 +1775,9 @@ dependencies = [
[[package]]
name = "ostree-ext"
-version = "0.11.0"
+version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8903d59c4a56794b6ef8a2b11a5674fe85b370f1da33ae34450a6de1e39a20d6"
+checksum = "a690495144c18cb333a67a2ec61dd008831710bbd37804cfa79ab93b51146a6f"
dependencies = [
"anyhow",
"async-compression 0.3.15",
@@ -1803,7 +1803,7 @@ dependencies = [
"ostree",
"pin-project",
"regex",
- "rustix 0.37.19",
+ "rustix 0.37.20",
"serde",
"serde_json",
"tar",
@@ -1928,9 +1928,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"
@@ -2088,13 +2088,13 @@ dependencies = [
[[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 +2114,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"
@@ -2209,7 +2209,7 @@ dependencies = [
"reqwest",
"rpmostree-client",
"rust-ini",
- "rustix 0.37.19",
+ "rustix 0.37.20",
"serde",
"serde_derive",
"serde_json",
@@ -2252,9 +2252,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",
@@ -2330,18 +2330,18 @@ 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_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",
@@ -2547,7 +2547,7 @@ dependencies = [
"cfg-if",
"fastrand",
"redox_syscall 0.3.5",
- "rustix 0.37.19",
+ "rustix 0.37.20",
"windows-sys 0.45.0",
]
diff --git a/Cargo.toml b/Cargo.toml
index c414e92e7a..e28bb83189 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -63,14 +63,14 @@ 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"
@@ -78,11 +78,11 @@ 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/ci/test-container.sh b/ci/test-container.sh
index 0a5a0ba3e2..c7490e9044 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"
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/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/libdnf b/libdnf
index 2362930d10..3fca06e8b1 160000
--- a/libdnf
+++ b/libdnf
@@ -1 +1 @@
-Subproject commit 2362930d10375a348bf2659db14b0ca4b911d4b7
+Subproject commit 3fca06e8b1037f117ba57b5e824ea59a343b44ed
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/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/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/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-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/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/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" &