1use std::env;
4
5use clap::{builder::RangedU64ValueParser, Arg, ArgMatches, Command};
6use serde::Deserialize;
7
8use sylvia_iot_corelib::constants::DbEngine;
9
10#[derive(Default, Deserialize)]
12pub struct Config {
13 pub auth: Option<String>,
15 pub broker: Option<String>,
17 pub db: Option<Db>,
18 #[serde(rename = "mqChannels")]
19 pub mq_channels: Option<MqChannels>,
20}
21
22#[derive(Default, Deserialize)]
24pub struct Db {
25 pub engine: Option<String>,
29 pub mongodb: Option<MongoDb>,
30 pub sqlite: Option<Sqlite>,
31}
32
33#[derive(Default, Deserialize)]
35pub struct MongoDb {
36 pub url: Option<String>,
38 pub database: Option<String>,
39 #[serde(rename = "poolSize")]
40 pub pool_size: Option<u32>,
41}
42
43#[derive(Default, Deserialize)]
45pub struct Sqlite {
46 pub path: Option<String>,
48}
49
50#[derive(Default, Deserialize)]
52pub struct MqChannels {
53 pub broker: Option<DataData>,
54 pub coremgr: Option<DataData>,
55}
56
57#[derive(Default, Deserialize)]
59pub struct DataData {
60 pub url: Option<String>,
62 pub prefetch: Option<u16>,
64 #[serde(rename = "sharedPrefix")]
66 pub shared_prefix: Option<String>,
67}
68
69pub const DEF_AUTH: &'static str = "http://localhost:1080/auth";
70pub const DEF_BROKER: &'static str = "http://localhost:2080/broker";
71pub const DEF_ENGINE: &'static str = DbEngine::SQLITE;
72pub const DEF_MONGODB_URL: &'static str = "mongodb://localhost:27017";
73pub const DEF_MONGODB_DB: &'static str = "data";
74pub const DEF_SQLITE_PATH: &'static str = "data.db";
75pub const DEF_MQ_PREFETCH: u16 = 100;
76pub const DEF_MQ_SHAREDPREFIX: &'static str = "$share/sylvia-iot-data/";
77pub const DEF_MQ_CHANNEL_URL: &'static str = "amqp://localhost";
78
79pub fn reg_args(cmd: Command) -> Command {
81 cmd.arg(
82 Arg::new("data.auth")
83 .long("data.auth")
84 .help("sylvia-iot-auth host (ex: http://localhost:1080/auth)")
85 .num_args(1),
86 )
87 .arg(
88 Arg::new("data.broker")
89 .long("data.broker")
90 .help("sylvia-iot-broker host (ex: http://localhost:2080/broker)")
91 .num_args(1),
92 )
93 .arg(
94 Arg::new("data.db.engine")
95 .long("data.db.engine")
96 .help("database engine")
97 .num_args(1)
98 .value_parser([DbEngine::MONGODB, DbEngine::SQLITE]),
99 )
100 .arg(
101 Arg::new("data.db.mongodb.url")
102 .long("data.db.mongodb.url")
103 .help("MongoDB URL (scheme://[username][:password][@][host][:port]")
104 .num_args(1),
105 )
106 .arg(
107 Arg::new("data.db.mongodb.database")
108 .long("data.db.mongodb.database")
109 .help("database nane")
110 .num_args(1),
111 )
112 .arg(
113 Arg::new("data.db.mongodb.poolsize")
114 .long("data.db.mongodb.poolsize")
115 .help("connection pool size")
116 .num_args(1)
117 .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u32::MAX as u64)),
118 )
119 .arg(
120 Arg::new("data.db.sqlite.path")
121 .long("data.db.sqlite.path")
122 .help("SQLite path")
123 .num_args(1),
124 )
125 .arg(
126 Arg::new("data.mq-channels.broker.url")
127 .long("data.mq-channels.broker.url")
128 .help("URL of `broker.data` channel")
129 .num_args(1),
130 )
131 .arg(
132 Arg::new("data.mq-channels.broker.prefetch")
133 .long("data.mq-channels.broker.prefetch")
134 .help("AMQP prefetch for `broker.data` channel")
135 .num_args(1)
136 .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
137 )
138 .arg(
139 Arg::new("data.mq-channels.broker.sharedprefix")
140 .long("data.mq-channels.broker.sharedprefix")
141 .help("MQTT shared subscription prefix of `broker.data` channel")
142 .num_args(1),
143 )
144 .arg(
145 Arg::new("data.mq-channels.coremgr.url")
146 .long("data.mq-channels.coremgr.url")
147 .help("URL of `coremgr.data` channel")
148 .num_args(1),
149 )
150 .arg(
151 Arg::new("data.mq-channels.coremgr.prefetch")
152 .long("data.mq-channels.coremgr.prefetch")
153 .help("AMQP prefetch for `coremgr.data` channel")
154 .num_args(1)
155 .value_parser(RangedU64ValueParser::<u64>::new().range(1..=u16::MAX as u64)),
156 )
157 .arg(
158 Arg::new("data.mq-channels.coremgr.sharedprefix")
159 .long("data.mq-channels.coremgr.sharedprefix")
160 .help("MQTT shared subscription prefix of `coremgr.data` channel")
161 .num_args(1),
162 )
163}
164
165pub fn read_args(args: &ArgMatches) -> Config {
170 apply_default(&Config {
171 auth: match args.get_one::<String>("data.auth") {
172 None => match env::var("DATA_AUTH") {
173 Err(_) => None,
174 Ok(v) => Some(v),
175 },
176 Some(v) => Some(v.clone()),
177 },
178 broker: match args.get_one::<String>("data.broker") {
179 None => match env::var("DATA_BROKER") {
180 Err(_) => None,
181 Ok(v) => Some(v),
182 },
183 Some(v) => Some(v.clone()),
184 },
185 db: Some(Db {
186 engine: match args.get_one::<String>("data.db.engine") {
187 None => match env::var("DATA_DB_ENGINE") {
188 Err(_) => None,
189 Ok(v) => Some(v),
190 },
191 Some(v) => Some(v.clone()),
192 },
193 mongodb: Some(MongoDb {
194 url: match args.get_one::<String>("data.db.mongodb.url") {
195 None => match env::var("DATA_DB_MONGODB_URL") {
196 Err(_) => None,
197 Ok(v) => Some(v),
198 },
199 Some(v) => Some(v.clone()),
200 },
201 database: match args.get_one::<String>("data.db.mongodb.database") {
202 None => match env::var("DATA_DB_MONGODB_DATABASE") {
203 Err(_) => None,
204 Ok(v) => Some(v),
205 },
206 Some(v) => Some(v.clone()),
207 },
208 pool_size: match args.get_one::<u64>("data.db.mongodb.poolsize") {
209 None => match env::var("DATA_DB_MONGODB_POOLSIZE") {
210 Err(_) => None,
211 Ok(v) => match v.parse::<u32>() {
212 Err(_) => None,
213 Ok(v) => Some(v),
214 },
215 },
216 Some(v) => Some(*v as u32),
217 },
218 }),
219 sqlite: Some(Sqlite {
220 path: match args.get_one::<String>("data.db.sqlite.path") {
221 None => match env::var("DATA_DB_SQLITE_PATH") {
222 Err(_) => None,
223 Ok(v) => Some(v),
224 },
225 Some(v) => Some(v.clone()),
226 },
227 }),
228 }),
229 mq_channels: Some(MqChannels {
230 broker: Some(DataData {
231 url: match args.get_one::<String>("data.mq-channels.broker.url") {
232 None => match env::var("DATA_MQCHANNELS_BROKER_URL") {
233 Err(_) => None,
234 Ok(v) => Some(v),
235 },
236 Some(v) => Some(v.clone()),
237 },
238 prefetch: match args.get_one::<u64>("data.mq-channels.broker.prefetch") {
239 None => match env::var("DATA_MQCHANNELS_BROKER_PREFETCH") {
240 Err(_) => None,
241 Ok(v) => match v.parse::<u16>() {
242 Err(_) => None,
243 Ok(v) => Some(v),
244 },
245 },
246 Some(v) => Some(*v as u16),
247 },
248 shared_prefix: match args.get_one::<String>("data.mq-channels.broker.sharedprefix")
249 {
250 None => match env::var("DATA_MQCHANNELS_BROKER_SHAREDPREFIX") {
251 Err(_) => None,
252 Ok(v) => Some(v),
253 },
254 Some(v) => Some(v.clone()),
255 },
256 }),
257 coremgr: Some(DataData {
258 url: match args.get_one::<String>("data.mq-channels.coremgr.url") {
259 None => match env::var("DATA_MQCHANNELS_COREMGR_URL") {
260 Err(_) => None,
261 Ok(v) => Some(v),
262 },
263 Some(v) => Some(v.clone()),
264 },
265 prefetch: match args.get_one::<u64>("data.mq-channels.coremgr.prefetch") {
266 None => match env::var("DATA_MQCHANNELS_COREMGR_PREFETCH") {
267 Err(_) => None,
268 Ok(v) => match v.parse::<u16>() {
269 Err(_) => None,
270 Ok(v) => Some(v),
271 },
272 },
273 Some(v) => Some(*v as u16),
274 },
275 shared_prefix: match args.get_one::<String>("data.mq-channels.coremgr.sharedprefix")
276 {
277 None => match env::var("DATA_MQCHANNELS_COREMGR_SHAREDPREFIX") {
278 Err(_) => None,
279 Ok(v) => Some(v),
280 },
281 Some(v) => Some(v.clone()),
282 },
283 }),
284 }),
285 })
286}
287
288pub fn apply_default(config: &Config) -> Config {
290 Config {
291 auth: match config.auth.as_ref() {
292 None => Some(DEF_AUTH.to_string()),
293 Some(auth) => Some(auth.clone()),
294 },
295 broker: match config.broker.as_ref() {
296 None => Some(DEF_BROKER.to_string()),
297 Some(broker) => Some(broker.clone()),
298 },
299 db: match config.db.as_ref() {
300 None => Some(Db {
301 engine: Some(DEF_ENGINE.to_string()),
302 mongodb: Some(MongoDb {
303 url: Some(DEF_MONGODB_URL.to_string()),
304 database: Some(DEF_MONGODB_DB.to_string()),
305 pool_size: None,
306 }),
307 sqlite: Some(Sqlite {
308 path: Some(DEF_SQLITE_PATH.to_string()),
309 }),
310 }),
311 Some(db) => Some(Db {
312 engine: match db.engine.as_ref() {
313 None => Some(DEF_ENGINE.to_string()),
314 Some(engine) => match engine.as_str() {
315 DbEngine::MONGODB => Some(DbEngine::MONGODB.to_string()),
316 DbEngine::SQLITE => Some(DbEngine::SQLITE.to_string()),
317 _ => Some(DEF_ENGINE.to_string()),
318 },
319 },
320 mongodb: match db.mongodb.as_ref() {
321 None => Some(MongoDb {
322 url: Some(DEF_MONGODB_URL.to_string()),
323 database: Some(DEF_MONGODB_DB.to_string()),
324 pool_size: None,
325 }),
326 Some(mongodb) => Some(MongoDb {
327 url: match mongodb.url.as_ref() {
328 None => Some(DEF_MONGODB_URL.to_string()),
329 Some(url) => Some(url.to_string()),
330 },
331 database: match mongodb.database.as_ref() {
332 None => Some(DEF_MONGODB_DB.to_string()),
333 Some(database) => Some(database.to_string()),
334 },
335 pool_size: mongodb.pool_size,
336 }),
337 },
338 sqlite: match db.sqlite.as_ref() {
339 None => Some(Sqlite {
340 path: Some(DEF_SQLITE_PATH.to_string()),
341 }),
342 Some(sqlite) => Some(Sqlite {
343 path: match sqlite.path.as_ref() {
344 None => Some(DEF_SQLITE_PATH.to_string()),
345 Some(path) => Some(path.to_string()),
346 },
347 }),
348 },
349 }),
350 },
351 mq_channels: match config.mq_channels.as_ref() {
352 None => Some(MqChannels {
353 broker: Some(DataData {
354 url: Some(DEF_MQ_CHANNEL_URL.to_string()),
355 prefetch: Some(DEF_MQ_PREFETCH),
356 shared_prefix: Some(DEF_MQ_SHAREDPREFIX.to_string()),
357 }),
358 coremgr: Some(DataData {
359 url: Some(DEF_MQ_CHANNEL_URL.to_string()),
360 prefetch: Some(DEF_MQ_PREFETCH),
361 shared_prefix: Some(DEF_MQ_SHAREDPREFIX.to_string()),
362 }),
363 }),
364 Some(mq_channels) => Some(MqChannels {
365 broker: match mq_channels.broker.as_ref() {
366 None => Some(DataData {
367 url: Some(DEF_MQ_CHANNEL_URL.to_string()),
368 prefetch: Some(DEF_MQ_PREFETCH),
369 shared_prefix: Some(DEF_MQ_SHAREDPREFIX.to_string()),
370 }),
371 Some(channel) => Some(DataData {
372 url: match channel.url.as_ref() {
373 None => Some(DEF_MQ_CHANNEL_URL.to_string()),
374 Some(url) => Some(url.to_string()),
375 },
376 prefetch: match channel.prefetch {
377 None => Some(DEF_MQ_PREFETCH),
378 Some(prefetch) => Some(prefetch),
379 },
380 shared_prefix: match channel.shared_prefix.as_ref() {
381 None => Some(DEF_MQ_SHAREDPREFIX.to_string()),
382 Some(shared_prefix) => Some(shared_prefix.to_string()),
383 },
384 }),
385 },
386 coremgr: match mq_channels.coremgr.as_ref() {
387 None => Some(DataData {
388 url: Some(DEF_MQ_CHANNEL_URL.to_string()),
389 prefetch: Some(DEF_MQ_PREFETCH),
390 shared_prefix: Some(DEF_MQ_SHAREDPREFIX.to_string()),
391 }),
392 Some(channel) => Some(DataData {
393 url: match channel.url.as_ref() {
394 None => Some(DEF_MQ_CHANNEL_URL.to_string()),
395 Some(url) => Some(url.to_string()),
396 },
397 prefetch: match channel.prefetch {
398 None => Some(DEF_MQ_PREFETCH),
399 Some(prefetch) => Some(prefetch),
400 },
401 shared_prefix: match channel.shared_prefix.as_ref() {
402 None => Some(DEF_MQ_SHAREDPREFIX.to_string()),
403 Some(shared_prefix) => Some(shared_prefix.to_string()),
404 },
405 }),
406 },
407 }),
408 },
409 }
410}