mirror of
https://github.com/containers/bootc.git
synced 2026-02-05 15:45:53 +01:00
install: support configuring sysroot.bls-append-except-default
Add a new [install.ostree] configuration section to allow setting the ostree sysroot.bls-append-except-default option during installation. Closes: https://github.com/bootc-dev/bootc/issues/1710 Signed-off-by: Joel Capitao <jcapitao@redhat.com> Co-authored-by: Jean-Baptiste Trystram <jbtrystram@redhat.com> Assisted-by: Claude (Sonnet 4)
This commit is contained in:
committed by
Colin Walters
parent
c68e2b4987
commit
b901498d44
@@ -795,7 +795,21 @@ async fn initialize_ostree_root(state: &State, root_setup: &RootSetup) -> Result
|
||||
crate::lsm::ensure_dir_labeled(rootfs_dir, "boot", None, 0o755.into(), sepolicy)?;
|
||||
}
|
||||
|
||||
for (k, v) in DEFAULT_REPO_CONFIG.iter() {
|
||||
// Build the list of ostree repo config options: defaults + install config
|
||||
let ostree_opts = state
|
||||
.install_config
|
||||
.as_ref()
|
||||
.and_then(|c| c.ostree.as_ref())
|
||||
.into_iter()
|
||||
.flat_map(|o| o.to_config_tuples());
|
||||
|
||||
let repo_config: Vec<_> = DEFAULT_REPO_CONFIG
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(ostree_opts)
|
||||
.collect();
|
||||
|
||||
for (k, v) in repo_config.iter() {
|
||||
Command::new("ostree")
|
||||
.args(["config", "--repo", "ostree/repo", "set", k, v])
|
||||
.cwd_dir(rootfs_dir.try_clone()?)
|
||||
|
||||
@@ -58,6 +58,9 @@ pub(crate) struct BasicFilesystems {
|
||||
// pub(crate) esp: Option<FilesystemCustomization>,
|
||||
}
|
||||
|
||||
/// Configuration for ostree repository
|
||||
pub(crate) type OstreeRepoOpts = ostree_ext::repo_options::RepoOptions;
|
||||
|
||||
/// The serialized [install] section
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
#[serde(rename = "install", rename_all = "kebab-case", deny_unknown_fields)]
|
||||
@@ -73,6 +76,8 @@ pub(crate) struct InstallConfiguration {
|
||||
pub(crate) kargs: Option<Vec<String>>,
|
||||
/// Supported architectures for this configuration
|
||||
pub(crate) match_architectures: Option<Vec<String>>,
|
||||
/// Ostree repository configuration
|
||||
pub(crate) ostree: Option<OstreeRepoOpts>,
|
||||
}
|
||||
|
||||
fn merge_basic<T>(s: &mut Option<T>, o: Option<T>, _env: &EnvProperties) {
|
||||
@@ -119,6 +124,17 @@ impl Mergeable for BasicFilesystems {
|
||||
}
|
||||
}
|
||||
|
||||
impl Mergeable for OstreeRepoOpts {
|
||||
/// Apply any values in other, overriding any existing values in `self`.
|
||||
fn merge(&mut self, other: Self, env: &EnvProperties) {
|
||||
merge_basic(
|
||||
&mut self.bls_append_except_default,
|
||||
other.bls_append_except_default,
|
||||
env,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mergeable for InstallConfiguration {
|
||||
/// Apply any values in other, overriding any existing values in `self`.
|
||||
fn merge(&mut self, other: Self, env: &EnvProperties) {
|
||||
@@ -133,6 +149,7 @@ impl Mergeable for InstallConfiguration {
|
||||
#[cfg(feature = "install-to-disk")]
|
||||
merge_basic(&mut self.block, other.block, env);
|
||||
self.filesystem.merge(other.filesystem, env);
|
||||
self.ostree.merge(other.ostree, env);
|
||||
if let Some(other_kargs) = other.kargs {
|
||||
self.kargs
|
||||
.get_or_insert_with(Default::default)
|
||||
@@ -572,4 +589,54 @@ root-fs-type = "xfs"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_ostree() {
|
||||
let env = EnvProperties {
|
||||
sys_arch: "x86_64".to_string(),
|
||||
};
|
||||
|
||||
// Table-driven test cases for parsing bls-append-except-default
|
||||
let parse_cases = [
|
||||
("console=ttyS0", "console=ttyS0"),
|
||||
("console=ttyS0,115200n8", "console=ttyS0,115200n8"),
|
||||
("rd.lvm.lv=vg/root", "rd.lvm.lv=vg/root"),
|
||||
];
|
||||
for (input, expected) in parse_cases {
|
||||
let toml_str = format!(
|
||||
r#"[install.ostree]
|
||||
bls-append-except-default = "{input}"
|
||||
"#
|
||||
);
|
||||
let c: InstallConfigurationToplevel = toml::from_str(&toml_str).unwrap();
|
||||
assert_eq!(
|
||||
c.install
|
||||
.unwrap()
|
||||
.ostree
|
||||
.unwrap()
|
||||
.bls_append_except_default
|
||||
.unwrap(),
|
||||
expected
|
||||
);
|
||||
}
|
||||
|
||||
// Test merging: other config should override original
|
||||
let mut install: InstallConfiguration = toml::from_str(
|
||||
r#"[ostree]
|
||||
bls-append-except-default = "console=ttyS0"
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
let other = InstallConfiguration {
|
||||
ostree: Some(OstreeRepoOpts {
|
||||
bls_append_except_default: Some("console=tty0".to_string()),
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
install.merge(other, &env);
|
||||
assert_eq!(
|
||||
install.ostree.unwrap().bls_append_except_default.unwrap(),
|
||||
"console=tty0"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ pub mod ostree_prepareroot;
|
||||
pub mod refescape;
|
||||
#[doc(hidden)]
|
||||
pub mod repair;
|
||||
pub mod repo_options;
|
||||
pub mod sysroot;
|
||||
pub mod tar;
|
||||
pub mod tokio_util;
|
||||
|
||||
30
crates/ostree-ext/src/repo_options.rs
Normal file
30
crates/ostree-ext/src/repo_options.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
//! Configuration options for an ostree repository
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Configuration options for an ostree repository.
|
||||
///
|
||||
/// This struct represents configurable options for an ostree repository
|
||||
/// that can be set via the `ostree config set` command.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case", default)]
|
||||
pub struct RepoOptions {
|
||||
/// Boot Loader Spec entries that should append arguments only for non-default entries.
|
||||
///
|
||||
/// Corresponds to the `sysroot.bls-append-except-default` ostree config key.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub bls_append_except_default: Option<String>,
|
||||
}
|
||||
|
||||
impl RepoOptions {
|
||||
/// Returns an iterator of (key, value) tuples for ostree repo configuration.
|
||||
///
|
||||
/// Each tuple represents an ostree config key and its value, suitable for
|
||||
/// passing to `ostree config set`.
|
||||
pub fn to_config_tuples(&self) -> impl Iterator<Item = (&'static str, &str)> {
|
||||
self.bls_append_except_default
|
||||
.as_ref()
|
||||
.map(|v| ("sysroot.bls-append-except-default", v.as_str()))
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
@@ -102,9 +102,16 @@ pub(crate) fn test_bootc_install_config() -> Result<()> {
|
||||
}
|
||||
|
||||
pub(crate) fn test_bootc_install_config_all() -> Result<()> {
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
struct TestOstreeConfig {
|
||||
bls_append_except_default: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct TestInstallConfig {
|
||||
kargs: Vec<String>,
|
||||
ostree: Option<TestOstreeConfig>,
|
||||
}
|
||||
|
||||
let config_d = std::path::Path::new("/run/bootc/install/");
|
||||
@@ -113,6 +120,8 @@ pub(crate) fn test_bootc_install_config_all() -> Result<()> {
|
||||
let content = indoc! {r#"
|
||||
[install]
|
||||
kargs = ["karg1=1", "karg2=2"]
|
||||
[install.ostree]
|
||||
bls-append-except-default = "grub_users=\"\""
|
||||
"#};
|
||||
std::fs::write(&test_toml_path, content)?;
|
||||
defer! {
|
||||
@@ -124,6 +133,13 @@ pub(crate) fn test_bootc_install_config_all() -> Result<()> {
|
||||
let config: TestInstallConfig =
|
||||
serde_json::from_str(&config).context("Parsing install config")?;
|
||||
assert_eq! {config.kargs, vec!["karg1=1".to_string(), "karg2=2".to_string(), "localtestkarg=somevalue".to_string(), "otherlocalkarg=42".to_string()]};
|
||||
assert_eq!(
|
||||
config
|
||||
.ostree
|
||||
.as_ref()
|
||||
.and_then(|o| o.bls_append_except_default.as_deref()),
|
||||
Some("grub_users=\"\"")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user