Environment variables can now be used directly inside the config instead of requiring special handling
This commit is contained in:
parent
82859d8e46
commit
d06c0b6980
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -2,6 +2,15 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.68"
|
||||
|
@ -37,6 +46,7 @@ dependencies = [
|
|||
"impl_cast",
|
||||
"paste",
|
||||
"pollster",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rumqttc",
|
||||
"serde",
|
||||
|
@ -784,6 +794,8 @@ version = "1.7.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ tracing = "0.1.37"
|
|||
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
|
||||
bytes = "1.3.0"
|
||||
pollster = "0.2.5"
|
||||
regex = "1.7.0"
|
||||
|
||||
[profile.release]
|
||||
lto=true
|
||||
|
|
|
@ -5,6 +5,10 @@ base_url = "https://login.huizinga.dev/api/oidc"
|
|||
host="olympus.lan.huizinga.dev"
|
||||
port=8883
|
||||
username="mqtt"
|
||||
password="${MQTT_PASSWORD}"
|
||||
|
||||
[ntfy]
|
||||
topic = "${NTFY_TOPIC}"
|
||||
|
||||
[presence]
|
||||
topic = "automation_dev/presence"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::{fs, error::Error, collections::HashMap, net::{Ipv4Addr, SocketAddr}};
|
||||
|
||||
use tracing::{debug, trace};
|
||||
use regex::{Regex, Captures};
|
||||
use tracing::{debug, trace, warn};
|
||||
use rumqttc::AsyncClient;
|
||||
use serde::Deserialize;
|
||||
|
||||
|
@ -14,7 +15,6 @@ pub struct Config {
|
|||
pub mqtt: MqttConfig,
|
||||
#[serde(default)]
|
||||
pub fullfillment: FullfillmentConfig,
|
||||
#[serde(default)]
|
||||
pub ntfy: NtfyConfig,
|
||||
pub presence: MqttDeviceConfig,
|
||||
pub light_sensor: LightSensorConfig,
|
||||
|
@ -33,7 +33,7 @@ pub struct MqttConfig {
|
|||
pub host: String,
|
||||
pub port: u16,
|
||||
pub username: String,
|
||||
pub password: Option<String>,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
@ -68,19 +68,13 @@ fn default_fullfillment_port() -> u16 {
|
|||
pub struct NtfyConfig {
|
||||
#[serde(default = "default_ntfy_url")]
|
||||
pub url: String,
|
||||
pub topic: Option<String>,
|
||||
pub topic: String,
|
||||
}
|
||||
|
||||
fn default_ntfy_url() -> String {
|
||||
"https://ntfy.sh".into()
|
||||
}
|
||||
|
||||
impl Default for NtfyConfig {
|
||||
fn default() -> Self {
|
||||
Self { url: default_ntfy_url(), topic: None }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct LightSensorConfig {
|
||||
#[serde(flatten)]
|
||||
|
@ -161,11 +155,23 @@ impl Config {
|
|||
pub fn build(filename: &str) -> Result<Self, Box<dyn Error>> {
|
||||
debug!("Loading config: {filename}");
|
||||
let file = fs::read_to_string(filename)?;
|
||||
let mut config: Self = toml::from_str(&file)?;
|
||||
|
||||
config.mqtt.password = Some(std::env::var("MQTT_PASSWORD").or(config.mqtt.password.ok_or("MQTT password needs to be set in either config [mqtt.password] or the environment [MQTT_PASSWORD]"))?);
|
||||
config.ntfy.topic = Some(std::env::var("NTFY_TOPIC").or(config.ntfy.topic.ok_or("ntfy.sh topic needs to be set in either config [ntfy.url] or the environment [NTFY_TOPIC]!"))?);
|
||||
// Substitute in environment variables
|
||||
let re = Regex::new(r"\$\{(.*)\}").unwrap();
|
||||
let file = re.replace_all(&file, |caps: &Captures| {
|
||||
let key = caps.get(1).unwrap().as_str();
|
||||
debug!("Substituting '{key}' in config");
|
||||
match std::env::var(key) {
|
||||
Ok(value) => value,
|
||||
Err(_) => {
|
||||
// @TODO Would be nice if we could propagate this error upwards
|
||||
warn!("Environment variable '{key}' is not set, using empty string as default");
|
||||
"".to_string()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let config = toml::from_str(&file)?;
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![feature(async_closure)]
|
||||
use std::{time::Duration, sync::{Arc, RwLock}, process, net::SocketAddr};
|
||||
use std::{time::Duration, sync::{Arc, RwLock}, process};
|
||||
|
||||
use axum::{Router, Json, routing::post, http::StatusCode, extract::FromRef};
|
||||
|
||||
|
@ -45,7 +45,7 @@ async fn main() {
|
|||
|
||||
// Configure MQTT
|
||||
let mut mqttoptions = MqttOptions::new("rust-test", config.mqtt.host, config.mqtt.port);
|
||||
mqttoptions.set_credentials(config.mqtt.username, config.mqtt.password.unwrap());
|
||||
mqttoptions.set_credentials(config.mqtt.username, config.mqtt.password);
|
||||
mqttoptions.set_keep_alive(Duration::from_secs(5));
|
||||
mqttoptions.set_transport(Transport::tls_with_default_config());
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ impl Notification {
|
|||
|
||||
impl Ntfy {
|
||||
pub fn new(config: NtfyConfig) -> Self {
|
||||
Self { base_url: config.url, topic: config.topic.unwrap() }
|
||||
Self { base_url: config.url, topic: config.topic }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user