Skip to content

Commit

Permalink
rust/treefile: Support creating client from /etc dropins
Browse files Browse the repository at this point in the history
Add support for creating a client treefile based on the dropins in
`/etc/rpm-ostree/origin.d`. This will currently be used only by the
container flow, but could eventually also end up being used client-side
as discussed in coreos#2326.
  • Loading branch information
jlebon committed Jan 21, 2022
1 parent 0295407 commit ef5723b
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 2 deletions.
1 change: 1 addition & 0 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ pub mod ffi {
workdir: i32,
) -> Result<Box<Treefile>>;
fn treefile_new_client(filename: &str, basearch: &str) -> Result<Box<Treefile>>;
fn treefile_new_client_from_etc(basearch: &str) -> Result<Box<Treefile>>;

fn get_workdir(&self) -> i32;
fn get_passwd_fd(&mut self) -> i32;
Expand Down
49 changes: 47 additions & 2 deletions rust/src/treefile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ use ostree_ext::{glib, ostree};
use serde_derive::{Deserialize, Serialize};
use std::collections::btree_map::Entry;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::fs::File;
use std::fs::{read_dir, File};
use std::io::prelude::*;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::os::unix::io::{AsRawFd, RawFd};
use std::path::Path;
use std::path::{Path, PathBuf};
use std::pin::Pin;
use std::{collections, fs, io};
use tracing::{event, instrument, Level};
Expand All @@ -46,6 +46,9 @@ const INCLUDE_MAXDEPTH: u32 = 50;
/// it's intended to be informative.
const COMPOSE_JSON_PATH: &str = "usr/share/rpm-ostree/treefile.json";

/// Path to client-side treefiles.
const CLIENT_TREEFILES_DIR: &str = "/etc/rpm-ostree/origin.d";

/// This struct holds file descriptors for any external files/data referenced by
/// a TreeComposeConfig.
#[derive(Debug, Default)]
Expand Down Expand Up @@ -1021,6 +1024,14 @@ impl TreefileExternals {
}
Ok(())
}

fn assert_nonempty(&self) {
// can't use the Default trick here because we can't auto-derive Eq because of `File`
assert!(self.postprocess_script.is_none());
assert!(self.add_files.is_empty());
assert!(self.passwd.is_none());
assert!(self.group.is_none());
}
}

/// For increased readability in YAML/JSON, we support whitespace in individual
Expand Down Expand Up @@ -2260,3 +2271,37 @@ pub(crate) fn treefile_new_client(filename: &str, basearch: &str) -> CxxResult<B
r.error_if_base()?;
Ok(r)
}

fn iter_etc_treefiles() -> Result<impl Iterator<Item = Result<PathBuf>>> {
Ok(read_dir(CLIENT_TREEFILES_DIR)?.filter_map(|res| match res {
Ok(e) => {
let path = e.path();
if let Some(ext) = path.extension() {
if ext == "yaml" {
return Some(anyhow::Result::Ok(path));
}
}
None
}
Err(err) => Some(Err(anyhow::Error::msg(err))),
}))
}

/// Create a new client treefile using the treefile dropins in /etc/rpm-ostree/origin.d/.
pub(crate) fn treefile_new_client_from_etc(basearch: &str) -> CxxResult<Box<Treefile>> {
let basearch = opt_string(basearch);
let mut cfg = TreeComposeConfig::default();
let mut tfs = iter_etc_treefiles()?.collect::<Result<Vec<PathBuf>>>()?;
tfs.sort(); // sort because order matters; later treefiles override earlier ones
for tf in tfs {
let new_cfg = treefile_parse_and_process(tf, basearch)?;
new_cfg.config.base.error_if_nonempty()?;
new_cfg.externals.assert_nonempty();
let mut new_cfg = new_cfg.config;
treefile_merge(&mut new_cfg, &mut cfg);
cfg = new_cfg;
}
let r = Treefile::new_from_config(cfg, None)?;
r.error_if_base()?;
Ok(Box::new(r))
}

0 comments on commit ef5723b

Please sign in to comment.