Skip to content

Commit 0f272c8

Browse files
committed
feat!: add CONFIG_DIR and CONFIG_NAME in host_pre_init and env expansion
This should allow easy execution of external scripts that are carried with the config, like for example using a python script as host_pre_init Also had to rework config --options so it does not show internal fields
1 parent e9de194 commit 0f272c8

File tree

5 files changed

+69
-12
lines changed

5 files changed

+69
-12
lines changed

src/commands/cmd_config.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,37 @@ fn get_image_config(ctx: &Context, image: &str) -> Result<String> {
3838
}
3939

4040
fn show_options() -> Result<()> {
41-
let docstring = Config::commented_fields()
42-
.unwrap()
43-
// replacing vec with array for people that dont know rust
44-
.replace("Vec<", "Array<");
45-
46-
// print config version in same style
41+
// print config version in same style as the rest of options
4742
println!(
48-
"/// Schema version, must be one of {:?}\nversion: u32\n",
49-
(1..=Config::VERSION).collect::<Vec<_>>()
43+
"/// Config schema version (valid versions: {})\nversion: u32\n",
44+
(1..=Config::VERSION)
45+
.map(|x| x.to_string())
46+
.collect::<Vec<_>>()
47+
.join(", ")
5048
);
5149

52-
println!(r#"{docstring}"#);
50+
let iter = Config::field_names()
51+
.into_iter()
52+
.zip(Config::field_types().into_iter())
53+
.zip(Config::field_docs().into_iter())
54+
.map(|((name, r#type), docs)| (name, r#type, docs));
55+
56+
// convert some types to be easier to understand for non-rust users
57+
let convert_type = |x: &str| -> String { x.replace("Vec<", "Array<") };
58+
59+
for (name, t, docs) in iter {
60+
// skip any that contains '@skip' in its docs
61+
if docs.join("\n").contains("@skip") {
62+
continue;
63+
}
64+
65+
// format like rust docs
66+
for i in docs {
67+
println!("///{i}");
68+
}
69+
70+
println!("{name}: {}\n", convert_type(t));
71+
}
5372

5473
Ok(())
5574
}

src/commands/cmd_start.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,14 @@ pub fn start_container(ctx: Context, mut cli_args: CmdStartArgs) -> Result<()> {
6363
}
6464
};
6565

66-
// TODO add env var that points to the directory where the config was located!
66+
let config_dir = match config.path.as_ref() {
67+
// NOTE it should never be a directory so it should always work right?
68+
Some(x) => x.parent().unwrap(),
69+
None => panic!("Config path is None after loading!"),
70+
};
71+
72+
let config_name = config.name.expect("Config name is not set after loading!");
73+
6774
if let Some(host_pre_init) = &config.host_pre_init {
6875
// avoid infinite loop using env var
6976
if std::env::var(crate::ENV_EXE_PATH).is_err() {
@@ -85,6 +92,8 @@ pub fn start_container(ctx: Context, mut cli_args: CmdStartArgs) -> Result<()> {
8592
.args(std::env::args().skip(2))
8693
// pass the path to arcam in the env var
8794
.env(crate::ENV_EXE_PATH, argv0)
95+
.env(crate::ENV_CFG_DIR, config_dir)
96+
.env(crate::ENV_CFG_NAME, config_name)
8897
.exec()
8998
.into());
9099
}
@@ -104,6 +113,8 @@ pub fn start_container(ctx: Context, mut cli_args: CmdStartArgs) -> Result<()> {
104113
"HOME" => Some(home.to_string()),
105114
"CONTAINER" | "CONTAINER_NAME" => Some(container_name.clone()),
106115
"RAND" | "RANDOM" => Some(rand::random::<u32>().to_string()),
116+
"CONFIG_DIR" => Some(config_dir.to_string_lossy().to_string()),
117+
"CONFIG_NAME" => Some(config_name.clone()),
107118

108119
// fallback to environ
109120
_ => {

src/config.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,16 @@ impl ConfigFile {
4444
let file_contents = std::fs::read_to_string(file)
4545
.with_context(|| format!("while reading config file {:?}", file))?;
4646

47-
Self::config_from_str(&file_contents)
48-
.with_context(|| format!("while parsing config file {:?}", file))
47+
let mut config = Self::config_from_str(&file_contents)
48+
.with_context(|| format!("while parsing config file {:?}", file))?;
49+
50+
// set the original path of file
51+
config.path = Some(file.to_path_buf());
52+
53+
// set name of the config to be file name (no extension)
54+
config.name = file.file_stem().map(|x| x.to_string_lossy().to_string());
55+
56+
Ok(config)
4957
}
5058
}
5159

src/config/v1.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use code_docs::{code_docs_struct, DocumentedStruct};
44
use serde::{Deserialize, Serialize};
5+
use std::path::PathBuf;
56

67
// save all the fields and docs so they can be printed as always up-to-date documentation
78
code_docs_struct! {
@@ -10,6 +11,18 @@ code_docs_struct! {
1011
#[derive(Debug, Clone, Default, PartialEq, Deserialize, Serialize)]
1112
#[serde(deny_unknown_fields)]
1213
pub struct ConfigV1 {
14+
/// Path to the config
15+
/// @skip
16+
#[serde(skip)]
17+
pub path: Option<PathBuf>,
18+
19+
/// Name of the config
20+
/// @skip
21+
#[serde(skip)]
22+
pub name: Option<String>,
23+
24+
// --- real config options --- //
25+
1326
/// Image used for the container
1427
pub image: String,
1528

src/vars.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ pub const ENV_ENTER_ON_START: &str = ENV_VAR_PREFIX!("ENTER_ON_START");
6161
/// Stores path to arcam executable and prevents infinite loop with host_pre_init
6262
pub const ENV_EXE_PATH: &str = ENV_VAR_PREFIX!("EXE_PATH");
6363

64+
/// Path to the directory where the config was loaded from
65+
pub const ENV_CFG_DIR: &str = ENV_VAR_PREFIX!("CFG_DIR");
66+
67+
/// Name of the config loaded
68+
pub const ENV_CFG_NAME: &str = ENV_VAR_PREFIX!("CFG_NAME");
69+
6470
/// Where scripts are executed from
6571
pub const INIT_D_DIR: &str = "/init.d";
6672

0 commit comments

Comments
 (0)