|
7 | 7 | // This sub-module is the "basic" installer that handles creating basic block device
|
8 | 8 | // and filesystem setup.
|
9 | 9 | pub(crate) mod baseline;
|
| 10 | +pub(crate) mod config; |
10 | 11 |
|
11 | 12 | use std::io::BufWriter;
|
12 | 13 | use std::io::Write;
|
@@ -435,136 +436,6 @@ pub(crate) fn print_configuration() -> Result<()> {
|
435 | 436 | serde_json::to_writer(stdout, &install_config).map_err(Into::into)
|
436 | 437 | }
|
437 | 438 |
|
438 |
| -pub(crate) mod config { |
439 |
| - use super::*; |
440 |
| - |
441 |
| - /// The toplevel config entry for installation configs stored |
442 |
| - /// in bootc/install (e.g. /etc/bootc/install/05-custom.toml) |
443 |
| - #[derive(Debug, Clone, Serialize, Deserialize, Default)] |
444 |
| - #[serde(deny_unknown_fields)] |
445 |
| - pub(crate) struct InstallConfigurationToplevel { |
446 |
| - pub(crate) install: Option<InstallConfiguration>, |
447 |
| - } |
448 |
| - |
449 |
| - /// The serialized [install] section |
450 |
| - #[derive(Debug, Clone, Serialize, Deserialize, Default)] |
451 |
| - #[serde(rename = "install", rename_all = "kebab-case", deny_unknown_fields)] |
452 |
| - pub(crate) struct InstallConfiguration { |
453 |
| - /// Root filesystem type |
454 |
| - pub(crate) root_fs_type: Option<super::baseline::Filesystem>, |
455 |
| - /// Kernel arguments, applied at installation time |
456 |
| - #[serde(skip_serializing_if = "Option::is_none")] |
457 |
| - pub(crate) kargs: Option<Vec<String>>, |
458 |
| - } |
459 |
| - |
460 |
| - impl InstallConfiguration { |
461 |
| - /// Apply any values in other, overriding any existing values in `self`. |
462 |
| - fn merge(&mut self, other: Self) { |
463 |
| - fn mergeopt<T>(s: &mut Option<T>, o: Option<T>) { |
464 |
| - if let Some(o) = o { |
465 |
| - *s = Some(o); |
466 |
| - } |
467 |
| - } |
468 |
| - mergeopt(&mut self.root_fs_type, other.root_fs_type); |
469 |
| - if let Some(other_kargs) = other.kargs { |
470 |
| - self.kargs |
471 |
| - .get_or_insert_with(Default::default) |
472 |
| - .extend(other_kargs) |
473 |
| - } |
474 |
| - } |
475 |
| - |
476 |
| - // Remove all configuration which is handled by `install to-filesystem`. |
477 |
| - pub(crate) fn filter_to_external(&mut self) { |
478 |
| - self.kargs.take(); |
479 |
| - } |
480 |
| - } |
481 |
| - |
482 |
| - #[context("Loading configuration")] |
483 |
| - /// Load the install configuration, merging all found configuration files. |
484 |
| - pub(crate) fn load_config() -> Result<InstallConfiguration> { |
485 |
| - const SYSTEMD_CONVENTIONAL_BASES: &[&str] = &["/usr/lib", "/usr/local/lib", "/etc", "/run"]; |
486 |
| - let fragments = |
487 |
| - liboverdrop::scan(SYSTEMD_CONVENTIONAL_BASES, "bootc/install", &["toml"], true); |
488 |
| - let mut config: Option<InstallConfiguration> = None; |
489 |
| - for (_name, path) in fragments { |
490 |
| - let buf = std::fs::read_to_string(&path)?; |
491 |
| - let mut unused = std::collections::HashSet::new(); |
492 |
| - let de = toml::Deserializer::new(&buf); |
493 |
| - let c: InstallConfigurationToplevel = serde_ignored::deserialize(de, |path| { |
494 |
| - unused.insert(path.to_string()); |
495 |
| - }) |
496 |
| - .with_context(|| format!("Parsing {path:?}"))?; |
497 |
| - for key in unused { |
498 |
| - eprintln!("warning: {path:?}: Unknown key {key}"); |
499 |
| - } |
500 |
| - if let Some(config) = config.as_mut() { |
501 |
| - if let Some(install) = c.install { |
502 |
| - tracing::debug!("Merging install config: {install:?}"); |
503 |
| - config.merge(install); |
504 |
| - } |
505 |
| - } else { |
506 |
| - config = c.install; |
507 |
| - } |
508 |
| - } |
509 |
| - config.ok_or_else(|| anyhow::anyhow!("No bootc/install config found; this operating system must define a default configuration to be installable")) |
510 |
| - } |
511 |
| - |
512 |
| - #[test] |
513 |
| - /// Verify that we can parse our default config file |
514 |
| - fn test_parse_config() { |
515 |
| - use super::baseline::Filesystem; |
516 |
| - |
517 |
| - let c: InstallConfigurationToplevel = toml::from_str( |
518 |
| - r##"[install] |
519 |
| -root-fs-type = "xfs" |
520 |
| -"##, |
521 |
| - ) |
522 |
| - .unwrap(); |
523 |
| - let mut install = c.install.unwrap(); |
524 |
| - assert_eq!(install.root_fs_type.unwrap(), Filesystem::Xfs); |
525 |
| - let other = InstallConfigurationToplevel { |
526 |
| - install: Some(InstallConfiguration { |
527 |
| - root_fs_type: Some(Filesystem::Ext4), |
528 |
| - kargs: None, |
529 |
| - }), |
530 |
| - }; |
531 |
| - install.merge(other.install.unwrap()); |
532 |
| - assert_eq!(install.root_fs_type.unwrap(), Filesystem::Ext4); |
533 |
| - |
534 |
| - let c: InstallConfigurationToplevel = toml::from_str( |
535 |
| - r##"[install] |
536 |
| -root-fs-type = "ext4" |
537 |
| -kargs = ["console=ttyS0", "foo=bar"] |
538 |
| -"##, |
539 |
| - ) |
540 |
| - .unwrap(); |
541 |
| - let mut install = c.install.unwrap(); |
542 |
| - assert_eq!(install.root_fs_type.unwrap(), Filesystem::Ext4); |
543 |
| - let other = InstallConfigurationToplevel { |
544 |
| - install: Some(InstallConfiguration { |
545 |
| - root_fs_type: None, |
546 |
| - kargs: Some( |
547 |
| - ["console=tty0", "nosmt"] |
548 |
| - .into_iter() |
549 |
| - .map(ToOwned::to_owned) |
550 |
| - .collect(), |
551 |
| - ), |
552 |
| - }), |
553 |
| - }; |
554 |
| - install.merge(other.install.unwrap()); |
555 |
| - assert_eq!(install.root_fs_type.unwrap(), Filesystem::Ext4); |
556 |
| - assert_eq!( |
557 |
| - install.kargs, |
558 |
| - Some( |
559 |
| - ["console=ttyS0", "foo=bar", "console=tty0", "nosmt"] |
560 |
| - .into_iter() |
561 |
| - .map(ToOwned::to_owned) |
562 |
| - .collect() |
563 |
| - ) |
564 |
| - ) |
565 |
| - } |
566 |
| -} |
567 |
| - |
568 | 439 | #[context("Creating ostree deployment")]
|
569 | 440 | async fn initialize_ostree_root_from_self(
|
570 | 441 | state: &State,
|
|
0 commit comments