mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-23 02:27:40 +08:00
Merge #2804
2804: Add environement variable `MEILI_CONFIG_FILE_PATH` to define the config file path r=Kerollmops a=choznerol # Pull Request ## What does this PR do? Fixes #2800 ~This is a draft PR base on the code in #2745. I will `rebase` and mark it ready for review only after #2745 merge.~ Done rebase ## PR checklist Please check if your PR fulfills the following requirements: - [x] Does this PR fix an existing issue? - [x] Have you read the contributing guidelines? - [x] Have you made sure that the title is accurate and descriptive of the changes? ## Demo With `config.toml`, `config_copy1.toml` and `config_copy2.toml` present: > <img width="692" alt="image" src="https://user-images.githubusercontent.com/12410942/192566891-6b3c9d26-736f-4e23-a09b-687fca1cb50d.png"> `MEILI_CONFIG_FILE_PATH` works: > <img width="773" alt="image" src="https://user-images.githubusercontent.com/12410942/192567023-f751536e-992a-4e90-a176-cb19122248be.png"> `--config-file-path` still works: > <img width="768" alt="image" src="https://user-images.githubusercontent.com/12410942/192567318-88c80b24-7873-4cec-8d08-16fe4d228055.png"> When both present, `--config-file-path` taks precedence: > <img width="1214" alt="image" src="https://user-images.githubusercontent.com/12410942/192567477-8a7cffe1-96f0-42a9-a348-6dbec20dc1e7.png"> Co-authored-by: Lawrence Chou <choznerol@protonmail.com>
This commit is contained in:
commit
b0749407f3
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -2134,6 +2134,7 @@ dependencies = [
|
|||||||
"static-files",
|
"static-files",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
"tar",
|
"tar",
|
||||||
|
"temp-env",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"time",
|
"time",
|
||||||
@ -3490,6 +3491,15 @@ dependencies = [
|
|||||||
"xattr",
|
"xattr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "temp-env"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a30d48359f77fbb6af3d7b928cc2d092e1dc90b44f397e979ef08ae15733ed65"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.3.0"
|
version = "3.3.0"
|
||||||
|
@ -91,6 +91,7 @@ manifest-dir-macros = "0.1.16"
|
|||||||
maplit = "1.0.2"
|
maplit = "1.0.2"
|
||||||
urlencoding = "2.1.2"
|
urlencoding = "2.1.2"
|
||||||
yaup = "0.2.1"
|
yaup = "0.2.1"
|
||||||
|
temp-env = "0.3.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["analytics", "meilisearch-lib/default", "mini-dashboard"]
|
default = ["analytics", "meilisearch-lib/default", "mini-dashboard"]
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::{BufReader, Read};
|
use std::io::{BufReader, Read};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@ -51,6 +52,7 @@ const MEILI_LOG_LEVEL: &str = "MEILI_LOG_LEVEL";
|
|||||||
#[cfg(feature = "metrics")]
|
#[cfg(feature = "metrics")]
|
||||||
const MEILI_ENABLE_METRICS_ROUTE: &str = "MEILI_ENABLE_METRICS_ROUTE";
|
const MEILI_ENABLE_METRICS_ROUTE: &str = "MEILI_ENABLE_METRICS_ROUTE";
|
||||||
|
|
||||||
|
const DEFAULT_CONFIG_FILE_PATH: &str = "./config.toml";
|
||||||
const DEFAULT_DB_PATH: &str = "./data.ms";
|
const DEFAULT_DB_PATH: &str = "./data.ms";
|
||||||
const DEFAULT_HTTP_ADDR: &str = "localhost:7700";
|
const DEFAULT_HTTP_ADDR: &str = "localhost:7700";
|
||||||
const DEFAULT_ENV: &str = "development";
|
const DEFAULT_ENV: &str = "development";
|
||||||
@ -261,32 +263,38 @@ impl Opt {
|
|||||||
// Parse the args to get the config_file_path.
|
// Parse the args to get the config_file_path.
|
||||||
let mut opts = Opt::parse();
|
let mut opts = Opt::parse();
|
||||||
let mut config_read_from = None;
|
let mut config_read_from = None;
|
||||||
if let Some(config_file_path) = opts
|
let user_specified_config_file_path = opts
|
||||||
.config_file_path
|
.config_file_path
|
||||||
.clone()
|
.clone()
|
||||||
.or_else(|| Some(PathBuf::from("./config.toml")))
|
.or_else(|| env::var("MEILI_CONFIG_FILE_PATH").map(PathBuf::from).ok());
|
||||||
{
|
let config_file_path = user_specified_config_file_path
|
||||||
match std::fs::read(&config_file_path) {
|
.clone()
|
||||||
Ok(config) => {
|
.unwrap_or_else(|| PathBuf::from(DEFAULT_CONFIG_FILE_PATH));
|
||||||
// If the file is successfully read, we deserialize it with `toml`.
|
|
||||||
let opt_from_config = toml::from_slice::<Opt>(&config)?;
|
match std::fs::read(&config_file_path) {
|
||||||
// Return an error if config file contains 'config_file_path'
|
Ok(config) => {
|
||||||
// Using that key in the config file doesn't make sense bc it creates a logical loop (config file referencing itself)
|
// If the file is successfully read, we deserialize it with `toml`.
|
||||||
if opt_from_config.config_file_path.is_some() {
|
let opt_from_config = toml::from_slice::<Opt>(&config)?;
|
||||||
anyhow::bail!("`config_file_path` is not supported in config file")
|
// Return an error if config file contains 'config_file_path'
|
||||||
}
|
// Using that key in the config file doesn't make sense bc it creates a logical loop (config file referencing itself)
|
||||||
// We inject the values from the toml in the corresponding env vars if needs be. Doing so, we respect the priority toml < env vars < cli args.
|
if opt_from_config.config_file_path.is_some() {
|
||||||
opt_from_config.export_to_env();
|
anyhow::bail!("`config_file_path` is not supported in config file")
|
||||||
// Once injected we parse the cli args once again to take the new env vars into scope.
|
}
|
||||||
opts = Opt::parse();
|
// We inject the values from the toml in the corresponding env vars if needs be. Doing so, we respect the priority toml < env vars < cli args.
|
||||||
config_read_from = Some(config_file_path);
|
opt_from_config.export_to_env();
|
||||||
|
// Once injected we parse the cli args once again to take the new env vars into scope.
|
||||||
|
opts = Opt::parse();
|
||||||
|
config_read_from = Some(config_file_path);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
if let Some(path) = user_specified_config_file_path {
|
||||||
|
// If we have an error while reading the file defined by the user.
|
||||||
|
anyhow::bail!(
|
||||||
|
"unable to open or read the {:?} configuration file: {}.",
|
||||||
|
path,
|
||||||
|
e,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// If we have an error while reading the file defined by the user.
|
|
||||||
Err(_) if opts.config_file_path.is_some() => anyhow::bail!(
|
|
||||||
"unable to open or read the {:?} configuration file.",
|
|
||||||
opts.config_file_path.unwrap().display().to_string()
|
|
||||||
),
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,10 +529,41 @@ fn default_log_level() -> String {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_valid_opt() {
|
fn test_valid_opt() {
|
||||||
assert!(Opt::try_parse_from(Some("")).is_ok());
|
assert!(Opt::try_parse_from(Some("")).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_meilli_config_file_path_valid() {
|
||||||
|
temp_env::with_vars(
|
||||||
|
vec![("MEILI_CONFIG_FILE_PATH", Some("../config.toml"))], // Relative path in meilisearch_http package
|
||||||
|
|| {
|
||||||
|
assert!(Opt::try_build().is_ok());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_meilli_config_file_path_invalid() {
|
||||||
|
temp_env::with_vars(
|
||||||
|
vec![("MEILI_CONFIG_FILE_PATH", Some("../configgg.toml"))],
|
||||||
|
|| {
|
||||||
|
let possible_error_messages = [
|
||||||
|
"unable to open or read the \"../configgg.toml\" configuration file: No such file or directory (os error 2).",
|
||||||
|
"unable to open or read the \"../configgg.toml\" configuration file: The system cannot find the file specified. (os error 2).", // Windows
|
||||||
|
];
|
||||||
|
let error_message = Opt::try_build().unwrap_err().to_string();
|
||||||
|
assert!(
|
||||||
|
possible_error_messages.contains(&error_message.as_str()),
|
||||||
|
"Expected onf of {:?}, got {:?}.",
|
||||||
|
possible_error_messages,
|
||||||
|
error_message
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user