Skip to content

Commit c1197cd

Browse files
authored
feat: update config load process (#1891)
1 parent 124263c commit c1197cd

29 files changed

Lines changed: 255 additions & 181 deletions

File tree

.dockerignore

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
# Generated by Cargo
22
# will have compiled files and executables
3+
target
34
**/target/
45
# Keep Cargo.lock in build context for reproducible + cache-friendly builds.
56

7+
moon
8+
moon/**
9+
10+
docs
11+
12+
scripts
13+
14+
tests
15+
616
# These are backup files generated by rustfmt
717
**/*.rs.bk
818

@@ -28,9 +38,7 @@ ztm_agent_db*
2838
buck-out
2939

3040
# Dockderfile
31-
docker/mono-engine-dockerfile
32-
docker/mono-pg-dockerfile
33-
docker/aries-engine-dockerfile
41+
docker
3442

3543
# git / ci metadata (not needed for docker builds, reduces build context)
3644
.git/

Cargo.toml

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
1+
[workspace.package]
2+
edition = "2024"
3+
14
[workspace]
25
members = [
3-
"mono",
4-
"common",
5-
"jupiter",
6+
"api-model",
67
"ceres",
7-
"vault",
8-
"saturn",
9-
"orion",
10-
"orion-server",
8+
"common",
9+
"context",
1110
"extensions/rag/chat",
1211
"extensions/rag/index",
1312
"extensions/observatory",
14-
"context",
15-
"scorpio",
16-
"api-model",
1713
"io-orbit",
14+
"jupiter",
15+
"jupiter/callisto",
16+
"mono",
17+
"orion",
18+
"orion-server",
19+
"saturn",
20+
"scorpio",
21+
"vault",
1822
]
1923
default-members = ["mono", "orion", "orion-server"]
20-
resolver = "1"
24+
resolver = "3"
2125

2226

2327
[workspace.dependencies]
@@ -30,7 +34,6 @@ ceres = { path = "ceres" }
3034
callisto = { path = "jupiter/callisto" }
3135
vault = { path = "vault" }
3236
saturn = { path = "saturn" }
33-
observatory = { path = "extensions/observatory" }
3437
orion = { path = "orion" }
3538
bellatrix = { path = "orion-server/bellatrix" }
3639

@@ -93,8 +96,6 @@ secp256k1 = "0.30.0"
9396
pgp = "0.15.0"
9497
oauth2 = "5.0.0"
9598
base64 = "0.22.1"
96-
aws-config = "1.8.12"
97-
aws-sdk-s3 = "1.120"
9899

99100
utoipa = { version = "5.4.0", features = ["chrono"] }
100101
utoipa-axum = "0.2.0"
@@ -141,6 +142,7 @@ bincode = "2.0.1"
141142
rustls = "0.23.36"
142143
object_store = "0.13.1"
143144
qlean = "0.1.1"
145+
toml = "0.9"
144146

145147
[profile.release]
146148
debug = true

api-model/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "api-model"
33
version = "0.1.0"
4-
edition = "2024"
4+
edition.workspace = true
55

66

77
[lib]

ceres/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "ceres"
33
version = "0.1.0"
4-
edition = "2024"
4+
edition.workspace = true
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

common/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "common"
33
version = "0.1.0"
4-
edition = "2024"
4+
edition.workspace = true
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

@@ -29,3 +29,4 @@ pgp = { workspace = true }
2929
cedar-policy = { workspace = true }
3030
redis = { workspace = true }
3131
bincode = { workspace = true }
32+
toml = { workspace = true }

common/src/config/loader.rs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
use std::{
2+
env, fs,
3+
path::{Path, PathBuf},
4+
};
5+
6+
use anyhow::{Context, Result};
7+
use toml::Value;
8+
9+
use crate::{
10+
config::{mega_base, template::default_config_template},
11+
utils::get_current_bin_name,
12+
};
13+
14+
#[derive(Debug, Clone, Copy)]
15+
pub enum ConfigSource {
16+
Cli,
17+
Env,
18+
Cwd,
19+
Global,
20+
DefaultGenerated,
21+
}
22+
23+
pub struct LoadedConfig {
24+
pub path: PathBuf,
25+
pub source: ConfigSource,
26+
}
27+
28+
#[derive(Debug, Default)]
29+
pub struct ConfigInput {
30+
/// CLI --config
31+
pub cli_path: Option<PathBuf>,
32+
33+
/// ENV: MEGA_CONFIG
34+
pub env_path: Option<PathBuf>,
35+
}
36+
37+
pub struct ConfigLoader {
38+
input: ConfigInput,
39+
}
40+
41+
impl ConfigLoader {
42+
pub fn new(input: ConfigInput) -> Self {
43+
Self { input }
44+
}
45+
46+
/// Load config path, create default config if not exists
47+
pub fn load(&self) -> Result<LoadedConfig> {
48+
if let Some(path) = &self.input.cli_path {
49+
return Ok(LoadedConfig {
50+
path: path.clone(),
51+
source: ConfigSource::Cli,
52+
});
53+
}
54+
55+
if let Some(path) = &self.input.env_path {
56+
return Ok(LoadedConfig {
57+
path: path.clone(),
58+
source: ConfigSource::Env,
59+
});
60+
}
61+
62+
if let Some(path) = Self::cwd_config_path()? {
63+
return Ok(LoadedConfig {
64+
path,
65+
source: ConfigSource::Cwd,
66+
});
67+
}
68+
69+
if let Some(path) = Self::global_config_path()? {
70+
return Ok(LoadedConfig {
71+
path,
72+
source: ConfigSource::Global,
73+
});
74+
}
75+
76+
let path = self.create_default_config()?;
77+
Ok(LoadedConfig {
78+
path,
79+
source: ConfigSource::DefaultGenerated,
80+
})
81+
}
82+
83+
fn cwd_config_path() -> Result<Option<PathBuf>> {
84+
let cwd = env::current_dir().context("failed to get current dir")?;
85+
let path = cwd.join("config/config.toml");
86+
Ok(path.exists().then_some(path))
87+
}
88+
89+
fn global_config_path() -> Result<Option<PathBuf>> {
90+
let path = mega_base().join("etc/config.toml");
91+
Ok(path.exists().then_some(path))
92+
}
93+
94+
fn create_default_config(&self) -> Result<PathBuf> {
95+
let base_dir = mega_base();
96+
let etc_dir = base_dir.join("etc");
97+
fs::create_dir_all(&etc_dir).with_context(|| format!("failed to create {:?}", etc_dir))?;
98+
99+
let bin_name = get_current_bin_name();
100+
let template = default_config_template(&bin_name)
101+
.with_context(|| format!("no default config template for binary `{}`", bin_name))?;
102+
103+
let config = Self::render_template(template, &base_dir)?;
104+
let config_path = etc_dir.join("config.toml");
105+
106+
fs::write(&config_path, config)
107+
.with_context(|| format!("failed to write {:?}", config_path))?;
108+
109+
eprintln!(
110+
"config.toml not found, created default config at {:?}",
111+
config_path
112+
);
113+
114+
Ok(config_path)
115+
}
116+
117+
fn render_template(template: &str, base_dir: &Path) -> Result<String> {
118+
let mut value: Value =
119+
toml::from_str(template).context("failed to parse default config template")?;
120+
121+
value["base_dir"] = Value::String(base_dir.to_string_lossy().into());
122+
123+
toml::to_string_pretty(&value).context("failed to serialize default config")
124+
}
125+
}
Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ pub use config as c;
88
use config::{Source, ValueKind, builder::DefaultState};
99
use serde::{Deserialize, Deserializer, Serialize};
1010

11-
use crate::utils;
11+
use crate::errors::MegaError;
12+
13+
pub mod loader;
14+
pub mod template;
1215

1316
/// Retrieves the base directory path for Mega
1417
///
@@ -98,7 +101,7 @@ pub struct Config {
98101
}
99102

100103
impl Config {
101-
pub fn new(path: &str) -> Result<Self, ConfigError> {
104+
pub fn new(path: &str) -> Result<Self, MegaError> {
102105
let builder = c::Config::builder()
103106
.add_source(c::File::new(path, FileFormat::Toml))
104107
.add_source(
@@ -114,7 +117,7 @@ impl Config {
114117

115118
let config = variable_placeholder_substitute(builder);
116119

117-
Config::from_config(config)
120+
Ok(Config::from_config(config)?)
118121
}
119122

120123
pub fn mock() -> Self {
@@ -173,39 +176,6 @@ impl Config {
173176
}
174177
}
175178

176-
impl Default for Config {
177-
fn default() -> Self {
178-
let base_dir = mega_base();
179-
std::fs::create_dir_all(&base_dir).unwrap();
180-
181-
let bin_name = utils::get_current_bin_name();
182-
let default_config = match bin_name.as_str() {
183-
"mono" => include_str!("../../config/config.toml"),
184-
&_ => todo!(),
185-
};
186-
let default_config = default_config
187-
.lines()
188-
.map(|line| {
189-
if line.starts_with("base_dir ") {
190-
format!("base_dir = {base_dir:?}")
191-
} else {
192-
line.to_string()
193-
}
194-
})
195-
.collect::<Vec<String>>()
196-
.join("\n");
197-
198-
// default config path: $MEGA_BASE_DIR/etc/config.toml
199-
// ensure the directory exists
200-
std::fs::create_dir_all(base_dir.join("etc")).unwrap();
201-
let config_path = base_dir.join("etc").join("config.toml");
202-
std::fs::write(&config_path, default_config).unwrap();
203-
eprintln!("create default config.toml in {:?}", &config_path);
204-
205-
Config::new(config_path.to_str().unwrap()).unwrap()
206-
}
207-
}
208-
209179
/// supports braces-delimited variables (i.e. ${foo}) in config.
210180
/// ### Example:
211181
/// ```toml

common/src/config/template.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use anyhow::{Result, anyhow};
2+
3+
pub fn default_config_template(bin_name: &str) -> Result<&'static str> {
4+
match bin_name {
5+
"mono" => Ok(include_str!("../../../config/config.toml")),
6+
"orion-server" => Ok(include_str!("../../../config/config.toml")),
7+
_ => Err(anyhow!("unknown binary `{}`", bin_name)),
8+
}
9+
}

0 commit comments

Comments
 (0)