refactor config module
This commit is contained in:
parent
113384b6ce
commit
86e40f90a1
5 changed files with 60 additions and 76 deletions
|
|
@ -3,4 +3,4 @@ mqtt:
|
||||||
client_id: "weather_portal_dev"
|
client_id: "weather_portal_dev"
|
||||||
user: "homeassistant"
|
user: "homeassistant"
|
||||||
# password comes from env
|
# password comes from env
|
||||||
jwt_key: apuOQZyML+8PixmVDP4nXU4M # loaded from env on prod
|
jwt_secret: apuOQZyML+8PixmVDP4nXU4M # loaded from env on prod
|
||||||
|
|
|
||||||
117
src/config.gleam
117
src/config.gleam
|
|
@ -1,5 +1,10 @@
|
||||||
import envoy
|
import envoy
|
||||||
import glaml
|
import glaml
|
||||||
|
import gleam/dict
|
||||||
|
import gleam/erlang/node
|
||||||
|
import gleam/io
|
||||||
|
import gleam/list
|
||||||
|
import gleam/option.{type Option, None, Some}
|
||||||
import gleam/result
|
import gleam/result
|
||||||
import simplifile
|
import simplifile
|
||||||
|
|
||||||
|
|
@ -9,7 +14,7 @@ pub type Config {
|
||||||
mqtt_user: String,
|
mqtt_user: String,
|
||||||
mqtt_pw: String,
|
mqtt_pw: String,
|
||||||
mqtt_client_id: String,
|
mqtt_client_id: String,
|
||||||
jwt_key: String,
|
jwt_secret: String,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,71 +35,59 @@ fn parse_yaml(contents: String) -> Result(glaml.Document, String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_config(doc: glaml.Document) -> Result(Config, String) {
|
fn get_config_value(
|
||||||
let root = glaml.document_root(doc)
|
root: glaml.Node,
|
||||||
|
yaml_key: Option(String),
|
||||||
// Extract values from YAML
|
env_var: Option(String),
|
||||||
use mqtt_host_result <- result.try(
|
) -> String {
|
||||||
glaml.select_sugar(root, "mqtt.host")
|
let from_env = case env_var {
|
||||||
|> result.map_error(fn(_) { "mqtt.host not found in config.yml" }),
|
Some(var) -> envoy.get(var)
|
||||||
)
|
None -> Error(Nil)
|
||||||
use mqtt_user_result <- result.try(
|
}
|
||||||
glaml.select_sugar(root, "mqtt.user")
|
|
||||||
|> result.map_error(fn(_) { "mqtt.user not found in config.yml" }),
|
case from_env {
|
||||||
)
|
Ok(val) -> val
|
||||||
use mqtt_client_id_result <- result.try(
|
Error(_) -> {
|
||||||
glaml.select_sugar(root, "mqtt.client_id")
|
// Fall back to YAML if env var not found
|
||||||
|> result.map_error(fn(_) { "mqtt.client_id not found in config.yml" }),
|
case yaml_key {
|
||||||
)
|
Some(key) -> {
|
||||||
use jwt_key_result <- result.try(
|
let assert Ok(node) = glaml.select_sugar(root, key)
|
||||||
glaml.select_sugar(root, "jwt_key")
|
let assert glaml.NodeStr(str) = node
|
||||||
|> result.map_error(fn(_) { "jwt_key not found in config.yml" }),
|
str
|
||||||
)
|
}
|
||||||
|
None -> {
|
||||||
// Extract strings from nodes
|
panic as { "Config value not found in environment or YAML" }
|
||||||
case
|
}
|
||||||
mqtt_host_result,
|
}
|
||||||
mqtt_user_result,
|
|
||||||
jwt_key_result,
|
|
||||||
mqtt_client_id_result
|
|
||||||
{
|
|
||||||
glaml.NodeStr(host),
|
|
||||||
glaml.NodeStr(user),
|
|
||||||
glaml.NodeStr(key),
|
|
||||||
glaml.NodeStr(client_id)
|
|
||||||
-> {
|
|
||||||
let yaml_config =
|
|
||||||
Config(
|
|
||||||
mqtt_host: host,
|
|
||||||
mqtt_user: user,
|
|
||||||
mqtt_pw: "placeholder",
|
|
||||||
mqtt_client_id: client_id,
|
|
||||||
jwt_key: key,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Override with env vars
|
|
||||||
let final_config =
|
|
||||||
Config(
|
|
||||||
mqtt_host: envoy.get("MQTT_HOST")
|
|
||||||
|> result.unwrap(yaml_config.mqtt_host),
|
|
||||||
mqtt_user: envoy.get("MQTT_USER")
|
|
||||||
|> result.unwrap(yaml_config.mqtt_user),
|
|
||||||
mqtt_pw: envoy.get("MQTT_PW")
|
|
||||||
|> result.unwrap(yaml_config.mqtt_pw),
|
|
||||||
mqtt_client_id: envoy.get("MQTT_CLIENT_ID")
|
|
||||||
|> result.unwrap(yaml_config.mqtt_client_id),
|
|
||||||
jwt_key: envoy.get("JWT_KEY")
|
|
||||||
|> result.unwrap(yaml_config.jwt_key),
|
|
||||||
)
|
|
||||||
|
|
||||||
Ok(final_config)
|
|
||||||
}
|
}
|
||||||
_, _, _, _ -> Error("Config values must be strings in config.yml")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_config() -> Result(Config, String) {
|
fn compile_config(doc: glaml.Document) -> Config {
|
||||||
|
let root = glaml.document_root(doc)
|
||||||
|
let get = fn(yaml_key: option.Option(String), env_var: option.Option(String)) -> String {
|
||||||
|
get_config_value(root, yaml_key, env_var)
|
||||||
|
}
|
||||||
|
|
||||||
|
Config(
|
||||||
|
mqtt_host: get(Some("mqtt.host"), None),
|
||||||
|
mqtt_pw: get(None, Some("MQTT_PW")),
|
||||||
|
mqtt_user: get(Some("mqtt.user"), None),
|
||||||
|
jwt_secret: get(Some("jwt_secret"), Some("JWT_SECRET")),
|
||||||
|
mqtt_client_id: get(Some("mqtt.client_id"), Some("MQTT_CLIENT_ID")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_doc() -> Result(glaml.Document, String) {
|
||||||
use file_content <- result.try(load_file())
|
use file_content <- result.try(load_file())
|
||||||
use doc <- result.try(parse_yaml(file_content))
|
use doc <- result.try(parse_yaml(file_content))
|
||||||
compile_config(doc)
|
Ok(doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_config() -> Config {
|
||||||
|
let doc = get_doc()
|
||||||
|
case doc {
|
||||||
|
Ok(doc) -> compile_config(doc)
|
||||||
|
Error(err) -> panic as { "fail to load config: " <> err }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,8 @@ import mqtt_dummy
|
||||||
import sensors
|
import sensors
|
||||||
|
|
||||||
pub fn main() -> Nil {
|
pub fn main() -> Nil {
|
||||||
case config.load_config() {
|
let cfg = config.load_config()
|
||||||
Ok(cfg) -> {
|
|
||||||
io.println("Config loaded successfully!")
|
io.println("Config loaded successfully!")
|
||||||
io.println("MQTT Host: " <> cfg.mqtt_host)
|
|
||||||
io.println("MQTT User: " <> cfg.mqtt_user)
|
|
||||||
io.println("MQTT PW: " <> cfg.mqtt_pw)
|
|
||||||
io.println("JWT Key: " <> cfg.jwt_key)
|
|
||||||
}
|
|
||||||
Error(err) -> {
|
|
||||||
io.println("Failed to load config: " <> err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let assert Ok(subject) = mqtt_dummy.start()
|
let assert Ok(subject) = mqtt_dummy.start()
|
||||||
let mailbox = mqtt_dummy.subscribe(subject)
|
let mailbox = mqtt_dummy.subscribe(subject)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import config
|
import config
|
||||||
|
import envoy
|
||||||
import gleeunit
|
import gleeunit
|
||||||
import gleeunit/should
|
import gleeunit/should
|
||||||
|
|
||||||
|
|
@ -8,7 +9,8 @@ pub fn main() -> Nil {
|
||||||
|
|
||||||
// gleeunit test functions end in `_test`
|
// gleeunit test functions end in `_test`
|
||||||
pub fn file_read_test() {
|
pub fn file_read_test() {
|
||||||
let assert Ok(cfg) = config.load_config()
|
envoy.set("MQTT_PW", "TEST")
|
||||||
|
let cfg = config.load_config()
|
||||||
|
|
||||||
cfg.mqtt_host
|
cfg.mqtt_host
|
||||||
|> should.equal("192.168.1.11")
|
|> should.equal("192.168.1.11")
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ pub fn main() -> Nil {
|
||||||
gleeunit.main()
|
gleeunit.main()
|
||||||
}
|
}
|
||||||
|
|
||||||
// gleeunit test functions end in `_test`
|
|
||||||
pub fn file_read_test() {
|
pub fn file_read_test() {
|
||||||
let reading =
|
let reading =
|
||||||
sensors.sensor_name(sensors.Temperature)
|
sensors.sensor_name(sensors.Temperature)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue