Skip to content

Commit b9ea8b6

Browse files
committed
kargs: Factor out helper function for ostree case
Just reducing the size of the main `get_kargs`. Now that we've split out the helper, add a unit test. Signed-off-by: Colin Walters <[email protected]>
1 parent 0bd1956 commit b9ea8b6

File tree

1 file changed

+128
-35
lines changed

1 file changed

+128
-35
lines changed

lib/src/kargs.rs

Lines changed: 128 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,43 @@ fn get_kargs_in_root(d: &Dir, sys_arch: &str) -> Result<Vec<String>> {
4949
Ok(ret)
5050
}
5151

52+
/// Load kargs.d files from the target ostree commit root
53+
fn get_kargs_from_ostree(
54+
repo: &ostree::Repo,
55+
fetched_tree: &ostree::RepoFile,
56+
sys_arch: &str,
57+
) -> Result<Vec<String>> {
58+
let cancellable = gio::Cancellable::NONE;
59+
let queryattrs = "standard::name,standard::type";
60+
let queryflags = gio::FileQueryInfoFlags::NOFOLLOW_SYMLINKS;
61+
let fetched_iter = fetched_tree.enumerate_children(queryattrs, queryflags, cancellable)?;
62+
let mut ret = Vec::new();
63+
while let Some(fetched_info) = fetched_iter.next_file(cancellable)? {
64+
// only read and parse the file if it is a toml file
65+
let name = fetched_info.name();
66+
if let Some(name) = name.to_str() {
67+
if name.ends_with(".toml") {
68+
let fetched_child = fetched_iter.child(&fetched_info);
69+
let fetched_child = fetched_child
70+
.downcast::<ostree::RepoFile>()
71+
.expect("downcast");
72+
fetched_child.ensure_resolved()?;
73+
let fetched_contents_checksum = fetched_child.checksum();
74+
let f =
75+
ostree::Repo::load_file(repo, fetched_contents_checksum.as_str(), cancellable)?;
76+
let file_content = f.0;
77+
let mut reader =
78+
ostree_ext::prelude::InputStreamExtManual::into_read(file_content.unwrap());
79+
let s = std::io::read_to_string(&mut reader)?;
80+
let parsed_kargs =
81+
parse_kargs_toml(&s, sys_arch).with_context(|| format!("Parsing {name}"))?;
82+
ret.extend(parsed_kargs);
83+
}
84+
}
85+
}
86+
Ok(ret)
87+
}
88+
5289
/// Compute the kernel arguments for the new deployment. This starts from the booted
5390
/// karg, but applies the diff between the bootc karg files in /usr/lib/bootc/kargs.d
5491
/// between the booted deployment and the new one.
@@ -86,33 +123,7 @@ pub(crate) fn get_kargs(
86123
return Ok(kargs);
87124
}
88125

89-
let mut remote_kargs: Vec<String> = vec![];
90-
let queryattrs = "standard::name,standard::type";
91-
let queryflags = gio::FileQueryInfoFlags::NOFOLLOW_SYMLINKS;
92-
let fetched_iter = fetched_tree.enumerate_children(queryattrs, queryflags, cancellable)?;
93-
while let Some(fetched_info) = fetched_iter.next_file(cancellable)? {
94-
// only read and parse the file if it is a toml file
95-
let name = fetched_info.name();
96-
if let Some(name) = name.to_str() {
97-
if name.ends_with(".toml") {
98-
let fetched_child = fetched_iter.child(&fetched_info);
99-
let fetched_child = fetched_child
100-
.downcast::<ostree::RepoFile>()
101-
.expect("downcast");
102-
fetched_child.ensure_resolved()?;
103-
let fetched_contents_checksum = fetched_child.checksum();
104-
let f =
105-
ostree::Repo::load_file(repo, fetched_contents_checksum.as_str(), cancellable)?;
106-
let file_content = f.0;
107-
let mut reader =
108-
ostree_ext::prelude::InputStreamExtManual::into_read(file_content.unwrap());
109-
let s = std::io::read_to_string(&mut reader)?;
110-
let mut parsed_kargs =
111-
parse_kargs_toml(&s, sys_arch).with_context(|| format!("Parsing {name}"))?;
112-
remote_kargs.append(&mut parsed_kargs);
113-
}
114-
}
115-
}
126+
let remote_kargs = get_kargs_from_ostree(repo, &fetched_tree, sys_arch)?;
116127

117128
// get the diff between the existing and remote kargs
118129
let mut added_kargs: Vec<String> = remote_kargs
@@ -156,6 +167,9 @@ fn parse_kargs_toml(contents: &str, sys_arch: &str) -> Result<Vec<String>> {
156167

157168
#[cfg(test)]
158169
mod tests {
170+
use fn_error_context::context;
171+
use rustix::fd::{AsFd, AsRawFd};
172+
159173
use super::*;
160174

161175
#[test]
@@ -208,6 +222,20 @@ match-architectures = ["x86_64", "aarch64"]
208222
assert!(parse_kargs_toml(test_missing, "x86_64").is_err());
209223
}
210224

225+
#[context("writing test kargs")]
226+
fn write_test_kargs(td: &Dir) -> Result<()> {
227+
td.write(
228+
"usr/lib/bootc/kargs.d/01-foo.toml",
229+
r##"kargs = ["console=tty0", "nosmt"]"##,
230+
)?;
231+
td.write(
232+
"usr/lib/bootc/kargs.d/02-bar.toml",
233+
r##"kargs = ["console=ttyS1"]"##,
234+
)?;
235+
236+
Ok(())
237+
}
238+
211239
#[test]
212240
fn test_get_kargs_in_root() -> Result<()> {
213241
let td = cap_std_ext::cap_tempfile::TempDir::new(cap_std::ambient_authority())?;
@@ -220,18 +248,83 @@ match-architectures = ["x86_64", "aarch64"]
220248
// Non-toml file
221249
td.write("usr/lib/bootc/kargs.d/somegarbage", "garbage")?;
222250
assert_eq!(get_kargs_in_root(&td, "x86_64").unwrap().len(), 0);
223-
td.write(
224-
"usr/lib/bootc/kargs.d/01-foo.toml",
225-
r##"kargs = ["console=tty0", "nosmt"]"##,
226-
)?;
227-
td.write(
228-
"usr/lib/bootc/kargs.d/02-bar.toml",
229-
r##"kargs = ["console=ttyS1"]"##,
230-
)?;
251+
252+
write_test_kargs(&td)?;
231253

232254
let args = get_kargs_in_root(&td, "x86_64").unwrap();
233255
similar_asserts::assert_eq!(args, ["console=tty0", "nosmt", "console=ttyS1"]);
234256

235257
Ok(())
236258
}
259+
260+
#[context("ostree commit")]
261+
fn ostree_commit(
262+
repo: &ostree::Repo,
263+
d: &Dir,
264+
path: &Utf8Path,
265+
ostree_ref: &str,
266+
) -> Result<()> {
267+
let cancellable = gio::Cancellable::NONE;
268+
let txn = repo.auto_transaction(cancellable)?;
269+
270+
let mt = ostree::MutableTree::new();
271+
repo.write_dfd_to_mtree(d.as_fd().as_raw_fd(), path.as_str(), &mt, None, cancellable)
272+
.context("Writing merged filesystem to mtree")?;
273+
274+
let merged_root = repo
275+
.write_mtree(&mt, cancellable)
276+
.context("Writing mtree")?;
277+
let merged_root = merged_root.downcast::<ostree::RepoFile>().unwrap();
278+
let merged_commit = repo
279+
.write_commit(None, None, None, None, &merged_root, cancellable)
280+
.context("Writing commit")?;
281+
repo.transaction_set_ref(None, &ostree_ref, Some(merged_commit.as_str()));
282+
txn.commit(cancellable)?;
283+
Ok(())
284+
}
285+
286+
#[test]
287+
fn test_get_kargs_in_ostree() -> Result<()> {
288+
let cancellable = gio::Cancellable::NONE;
289+
let td = cap_std_ext::cap_tempfile::TempDir::new(cap_std::ambient_authority())?;
290+
291+
td.create_dir("repo")?;
292+
let repo = &ostree::Repo::create_at(
293+
td.as_fd().as_raw_fd(),
294+
"repo",
295+
ostree::RepoMode::Bare,
296+
None,
297+
gio::Cancellable::NONE,
298+
)?;
299+
300+
td.create_dir("rootfs")?;
301+
let test_rootfs = &td.open_dir("rootfs")?;
302+
303+
ostree_commit(repo, &test_rootfs, ".".into(), "testref")?;
304+
// Helper closure to read the kargs
305+
let get_kargs = |sys_arch: &str| -> Result<Vec<String>> {
306+
let rootfs = repo.read_commit("testref", cancellable)?.0;
307+
let rootfs = rootfs.downcast_ref::<ostree::RepoFile>().unwrap();
308+
let fetched_tree = rootfs.resolve_relative_path("/usr/lib/bootc/kargs.d");
309+
let fetched_tree = fetched_tree
310+
.downcast::<ostree::RepoFile>()
311+
.expect("downcast");
312+
if !fetched_tree.query_exists(cancellable) {
313+
return Ok(Default::default());
314+
}
315+
get_kargs_from_ostree(repo, &fetched_tree, sys_arch)
316+
};
317+
318+
// rootfs is empty
319+
assert_eq!(get_kargs("x86_64").unwrap().len(), 0);
320+
321+
test_rootfs.create_dir_all("usr/lib/bootc/kargs.d")?;
322+
write_test_kargs(&test_rootfs).unwrap();
323+
ostree_commit(repo, &test_rootfs, ".".into(), "testref")?;
324+
325+
let args = get_kargs("x86_64").unwrap();
326+
similar_asserts::assert_eq!(args, ["console=tty0", "nosmt", "console=ttyS1"]);
327+
328+
Ok(())
329+
}
237330
}

0 commit comments

Comments
 (0)