232 lines
9.2 KiB
Diff
232 lines
9.2 KiB
Diff
From fd14e9295a04cb051a70779fd6039d2d25ce9b85 Mon Sep 17 00:00:00 2001
|
|
From: licunlong <licunlong1@huawei.com>
|
|
Date: Mon, 3 Jul 2023 15:39:47 +0800
|
|
Subject: [PATCH] refactor: don't copy unit file to .toml file when loading a
|
|
unit
|
|
|
|
We used to do this because we thought confique could only infer
|
|
the file format from the file extension, so we copied the file
|
|
to .toml to tell confique this is a toml file. But actually,
|
|
confique allows us to specify the file format if we use Partial.
|
|
|
|
Let's use confique::Partial to avoid copying files.
|
|
---
|
|
coms/service/src/config.rs | 24 ++++++++++++--------
|
|
core/bin/manager/pre_install.rs | 40 +++++++++++++++++----------------
|
|
core/bin/unit/entry/config.rs | 25 +++++++++++++--------
|
|
core/bin/unit/util/unit_file.rs | 17 +++-----------
|
|
5 files changed, 69 insertions(+), 57 deletions(-)
|
|
|
|
diff --git a/coms/service/src/config.rs b/coms/service/src/config.rs
|
|
index e698ac2..3b7eb43 100644
|
|
--- a/coms/service/src/config.rs
|
|
+++ b/coms/service/src/config.rs
|
|
@@ -13,7 +13,7 @@
|
|
#![allow(non_snake_case)]
|
|
use super::comm::ServiceUnitComm;
|
|
use super::rentry::{NotifyAccess, SectionService, ServiceCommand, ServiceType};
|
|
-use confique::Config;
|
|
+use confique::{Config, FileFormat, Partial};
|
|
use std::cell::RefCell;
|
|
use std::collections::{HashMap, VecDeque};
|
|
use std::path::PathBuf;
|
|
@@ -64,15 +64,21 @@ impl ServiceConfig {
|
|
}
|
|
|
|
pub(super) fn load(&self, paths: Vec<PathBuf>, update: bool) -> Result<()> {
|
|
- let mut builder = ServiceConfigData::builder().env();
|
|
-
|
|
- log::debug!("service load path: {:?}", paths);
|
|
- // fragment
|
|
- for v in paths {
|
|
- builder = builder.file(v);
|
|
+ type ConfigPartial = <ServiceConfigData as Config>::Partial;
|
|
+ let mut partial: ConfigPartial = Partial::from_env().context(ConfiqueSnafu)?;
|
|
+ /* The first config wins, so add default values at last. */
|
|
+ log::debug!("Loading service config from: {:?}", paths);
|
|
+ for path in paths {
|
|
+ partial = match confique::File::with_format(&path, FileFormat::Toml).load() {
|
|
+ Err(e) => {
|
|
+ log::error!("Failed to load {path:?}: {e}, skipping");
|
|
+ continue;
|
|
+ }
|
|
+ Ok(v) => partial.with_fallback(v),
|
|
+ }
|
|
}
|
|
-
|
|
- *self.data.borrow_mut() = match builder.load() {
|
|
+ partial = partial.with_fallback(ConfigPartial::default_values());
|
|
+ *self.data.borrow_mut() = match ServiceConfigData::from_partial(partial) {
|
|
Err(e) => {
|
|
/* The error message is pretty readable, just print it out. */
|
|
log::error!("{e}");
|
|
diff --git a/core/bin/manager/pre_install.rs b/core/bin/manager/pre_install.rs
|
|
index 88150c0..08c795a 100644
|
|
--- a/core/bin/manager/pre_install.rs
|
|
+++ b/core/bin/manager/pre_install.rs
|
|
@@ -15,7 +15,7 @@ use crate::unit::{unit_name_to_type, UeConfigInstall, UnitType};
|
|
use basic::fs_util;
|
|
use basic::path_lookup::LookupPaths;
|
|
use bitflags::bitflags;
|
|
-use confique::Config;
|
|
+use confique::{Config, FileFormat, Partial};
|
|
use nix::unistd::UnlinkatFlags;
|
|
use std::{
|
|
cell::RefCell,
|
|
@@ -553,14 +553,14 @@ impl Install {
|
|
}
|
|
|
|
let canon_path = path.canonicalize()?;
|
|
- let tmp = format!("{}.toml", canon_path.as_path().display());
|
|
- if let Err(e) = std::fs::copy(canon_path, &tmp).context(IoSnafu) {
|
|
- log::warn!("copy file content to toml file error: {}", e);
|
|
- return Err(e);
|
|
- }
|
|
-
|
|
- let mut builder = UeConfigData::builder().env();
|
|
- builder = builder.file(&tmp);
|
|
+ type ConfigPartial = <UeConfigData as Config>::Partial;
|
|
+ let mut partial: ConfigPartial = Partial::from_env().context(ConfiqueSnafu)?;
|
|
+ /* The first config wins, so add default values at last. */
|
|
+ partial = partial.with_fallback(
|
|
+ confique::File::with_format(canon_path, FileFormat::Toml)
|
|
+ .load()
|
|
+ .context(ConfiqueSnafu)?,
|
|
+ );
|
|
|
|
let dropin_dir_name = format!("{}.d", unit_install.name());
|
|
|
|
@@ -570,7 +570,7 @@ impl Install {
|
|
let dropin_dir = base_dir.join(&dropin_dir_name);
|
|
|
|
if !dropin_dir.exists() {
|
|
- log::debug!("dropin path is not exist, ignore it: {:?}", &dropin_dir);
|
|
+ log::debug!("Dropin path {dropin_dir:?} does not exist, ignoring");
|
|
continue;
|
|
}
|
|
|
|
@@ -578,24 +578,26 @@ impl Install {
|
|
for entry in dirs {
|
|
let dir_entry = entry?;
|
|
let fragment = dir_entry.path();
|
|
- if fragment.is_file() {
|
|
- let file_name = String::from(fragment.file_name().unwrap().to_str().unwrap());
|
|
- if file_name.starts_with('.') || !file_name.ends_with(".toml") {
|
|
+ if !fragment.is_file() {
|
|
+ log::debug!("Fragment file {fragment:?} is not a file, ignoring");
|
|
+ continue;
|
|
+ }
|
|
+ partial = match confique::File::with_format(&fragment, FileFormat::Toml).load() {
|
|
+ Err(e) => {
|
|
+ log::error!("Failed to load {fragment:?}: {e}, skipping.");
|
|
continue;
|
|
}
|
|
-
|
|
- builder = builder.file(fragment);
|
|
- }
|
|
+ Ok(v) => partial.with_fallback(v),
|
|
+ };
|
|
}
|
|
}
|
|
-
|
|
- let configer = builder.load().context(ConfiqueSnafu)?;
|
|
+ partial = partial.with_fallback(ConfigPartial::default_values());
|
|
+ let configer = UeConfigData::from_partial(partial).context(ConfiqueSnafu)?;
|
|
unit_install.fill_struct(&configer);
|
|
|
|
for also in &configer.Install.Also {
|
|
self.unit_install_discover(also, ctx.clone())?;
|
|
}
|
|
- // fs::remove_file(&tmp);
|
|
|
|
Ok(())
|
|
}
|
|
diff --git a/core/bin/unit/entry/config.rs b/core/bin/unit/entry/config.rs
|
|
index 705512d..91313c4 100644
|
|
--- a/core/bin/unit/entry/config.rs
|
|
+++ b/core/bin/unit/entry/config.rs
|
|
@@ -14,7 +14,7 @@
|
|
use super::base::UeBase;
|
|
use crate::unit::rentry::{UeConfigInstall, UeConfigUnit};
|
|
use crate::unit::util::UnitFile;
|
|
-use confique::Config;
|
|
+use confique::{Config, FileFormat, Partial};
|
|
use serde::{Deserialize, Deserializer, Serialize};
|
|
use std::cell::RefCell;
|
|
use std::rc::Rc;
|
|
@@ -132,21 +132,28 @@ impl UeConfig {
|
|
}
|
|
|
|
pub(super) fn load_fragment_and_dropin(&self, files: &UnitFile, name: &String) -> Result<()> {
|
|
- let mut builder = UeConfigData::builder().env();
|
|
-
|
|
+ type ConfigPartial = <UeConfigData as Config>::Partial;
|
|
+ let mut partial: ConfigPartial = Partial::from_env().context(ConfiqueSnafu)?;
|
|
+ /* The first config wins, so add default values at last. */
|
|
let unit_conf_frag = files.get_unit_id_fragment_pathbuf(name);
|
|
if unit_conf_frag.is_empty() {
|
|
return Err(format!("{name} doesn't have corresponding config file").into());
|
|
}
|
|
// fragment
|
|
- for v in unit_conf_frag {
|
|
- if !v.exists() {
|
|
- return Err(format!("Config file {:?} of {name} doesn't exist", v).into());
|
|
+ for path in unit_conf_frag {
|
|
+ if !path.exists() {
|
|
+ return Err(format!("Config file {:?} of {name} doesn't exist", path).into());
|
|
}
|
|
- builder = builder.file(&v);
|
|
+ partial = match confique::File::with_format(&path, FileFormat::Toml).load() {
|
|
+ Err(e) => {
|
|
+ log::error!("Failed to load {path:?}: {e}, skipping");
|
|
+ continue;
|
|
+ }
|
|
+ Ok(v) => partial.with_fallback(v),
|
|
+ };
|
|
}
|
|
-
|
|
- let mut configer = builder.load().context(ConfiqueSnafu)?;
|
|
+ partial = partial.with_fallback(ConfigPartial::default_values());
|
|
+ let mut configer = UeConfigData::from_partial(partial).context(ConfiqueSnafu)?;
|
|
|
|
// dropin
|
|
for v in files.get_unit_wants_symlink_units(name) {
|
|
diff --git a/core/bin/unit/util/unit_file.rs b/core/bin/unit/util/unit_file.rs
|
|
index 0a0fa9f..eb9404b 100644
|
|
--- a/core/bin/unit/util/unit_file.rs
|
|
+++ b/core/bin/unit/util/unit_file.rs
|
|
@@ -118,12 +118,7 @@ impl UnitFileData {
|
|
if file_name.starts_with('.') || file_name.ends_with(".toml") {
|
|
continue;
|
|
}
|
|
- let path = format!("{}.toml", fragment.to_string_lossy());
|
|
-
|
|
- if let Err(e) = std::fs::copy(fragment, &path) {
|
|
- log::warn!("copy file content to toml file error: {}", e);
|
|
- }
|
|
- res.push(Path::new(&path).to_path_buf());
|
|
+ res.push(fragment);
|
|
}
|
|
}
|
|
/* {/etc/sysmater, /usr/lib/sysmaster}/foo.service */
|
|
@@ -135,14 +130,8 @@ impl UnitFileData {
|
|
if config_path.is_symlink() {
|
|
return None;
|
|
}
|
|
- /* Add .toml to the original path name */
|
|
- let path_toml = format!("{}.toml", config_path.to_string_lossy());
|
|
- let to = Path::new(&path_toml);
|
|
- if let Err(e) = std::fs::copy(config_path, to) {
|
|
- log::warn!("copy file content to toml file error: {}", e);
|
|
- return None;
|
|
- }
|
|
- res.push(to.to_path_buf());
|
|
+
|
|
+ res.push(config_path);
|
|
Some(res)
|
|
}
|
|
|
|
--
|
|
2.33.0
|
|
|