1use crate::args::Args;
2
3pub struct CtlConfig {
5 pub host: String,
7 pub port: u16,
9 pub auth_token: Option<String>,
11 pub disable_auth: bool,
13 pub config_path: Option<String>,
15 pub daemon_mode: bool,
17 pub tls_cert: Option<String>,
19 pub tls_key: Option<String>,
21}
22
23impl Default for CtlConfig {
24 fn default() -> Self {
25 CtlConfig {
26 host: "127.0.0.1".into(),
27 port: 8080,
28 auth_token: None,
29 disable_auth: false,
30 config_path: None,
31 daemon_mode: false,
32 tls_cert: None,
33 tls_key: None,
34 }
35 }
36}
37
38pub fn from_args_and_env(args: &Args) -> CtlConfig {
40 let mut cfg = CtlConfig::default();
41
42 cfg.host = args
44 .get("host")
45 .or_else(|| args.get("H"))
46 .map(String::from)
47 .or_else(|| std::env::var("RNSCTL_HOST").ok())
48 .unwrap_or(cfg.host);
49
50 cfg.port = args
51 .get("port")
52 .or_else(|| args.get("p"))
53 .and_then(|s| s.parse().ok())
54 .or_else(|| {
55 std::env::var("RNSCTL_HTTP_PORT")
56 .ok()
57 .and_then(|s| s.parse().ok())
58 })
59 .unwrap_or(cfg.port);
60
61 cfg.auth_token = args
62 .get("token")
63 .or_else(|| args.get("t"))
64 .map(String::from)
65 .or_else(|| std::env::var("RNSCTL_AUTH_TOKEN").ok());
66
67 cfg.disable_auth = args.has("disable-auth")
68 || std::env::var("RNSCTL_DISABLE_AUTH")
69 .map(|v| v == "true" || v == "1")
70 .unwrap_or(false);
71
72 cfg.config_path = args
73 .get("config")
74 .or_else(|| args.get("c"))
75 .map(String::from)
76 .or_else(|| std::env::var("RNSCTL_CONFIG_PATH").ok());
77
78 cfg.daemon_mode = args.has("daemon") || args.has("d");
79
80 cfg.tls_cert = args
81 .get("tls-cert")
82 .map(String::from)
83 .or_else(|| std::env::var("RNSCTL_TLS_CERT").ok());
84
85 cfg.tls_key = args
86 .get("tls-key")
87 .map(String::from)
88 .or_else(|| std::env::var("RNSCTL_TLS_KEY").ok());
89
90 cfg
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 fn args(s: &[&str]) -> Args {
98 Args::parse_from(s.iter().map(|s| s.to_string()).collect())
99 }
100
101 #[test]
102 fn parse_basic() {
103 let a = args(&["--port", "9090", "--host", "0.0.0.0", "-vv"]);
104 assert_eq!(a.get("port"), Some("9090"));
105 assert_eq!(a.get("host"), Some("0.0.0.0"));
106 assert_eq!(a.verbosity, 2);
107 }
108
109 #[test]
110 fn parse_short_config() {
111 let a = args(&["-c", "/tmp/rns"]);
112 assert_eq!(a.get("c"), Some("/tmp/rns"));
113 }
114
115 #[test]
116 fn parse_daemon_short() {
117 let a = args(&["-d"]);
118 assert!(a.has("d"));
119 let cfg = from_args_and_env(&a);
120 assert!(cfg.daemon_mode);
121 }
122
123 #[test]
124 fn parse_daemon_long() {
125 let a = args(&["--daemon"]);
126 assert!(a.has("daemon"));
127 let cfg = from_args_and_env(&a);
128 assert!(cfg.daemon_mode);
129 }
130
131 #[test]
132 fn parse_disable_auth() {
133 let a = args(&["--disable-auth"]);
134 assert!(a.has("disable-auth"));
135 }
136
137 #[test]
138 fn parse_help() {
139 let a = args(&["--help"]);
140 assert!(a.has("help"));
141 let a = args(&["-h"]);
142 assert!(a.has("help"));
143 }
144
145 #[test]
146 fn config_from_args() {
147 let a = args(&[
148 "--port", "3000", "--host", "0.0.0.0", "--token", "secret", "--daemon",
149 ]);
150 let cfg = from_args_and_env(&a);
151 assert_eq!(cfg.port, 3000);
152 assert_eq!(cfg.host, "0.0.0.0");
153 assert_eq!(cfg.auth_token.as_deref(), Some("secret"));
154 assert!(cfg.daemon_mode);
155 }
156}