aboutsummaryrefslogtreecommitdiff
path: root/src/config/options.rs
blob: 54e948d7d645c3535cfc7c4751e01f326fff721f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use anyhow::Result;
use serde::Deserialize;

use crate::config::RuntimeConfig;

// This code is inspired by the Trunk crate (https://github.com/thedodd/trunk)

// This file parses the options that can be declared in the environment.
// runtime.rs applies business logic and builds RuntimeConfig structs.

// - Note for the future -
// There is no *need* to have a 'DIPLONAT_XXX_*' prefix for all config options.
// If some config options are shared by several modules, a ConfigOptsBase could
// contain them, and parse the 'DIPLONAT_*' prefix directly.
// Only in runtime.rs would these options find their proper location in each 
// module's struct.


/// Consul configuration options
#[derive(Clone, Default, Deserialize)]
pub struct ConfigOptsConsul {
	/// Consul's node name [default: None]
	pub node_name: Option<String>,
	/// Consul's REST URL [default: "http://127.0.0.1:8500"]
	pub url: Option<String>,
}

/// ACME configuration options
#[derive(Clone, Default, Deserialize)]
pub struct ConfigOptsAcme {
	/// Whether the ACME module is enabled [default: false]
	#[serde(default)]
	pub enable: bool,

	/// The default domain holder's e-mail [default: None]
	pub email: Option<String>,
	/// Refresh time for firewall rules [default: 300]
	pub refresh_time: Option<u16>,
}

/// Firewall configuration options
#[derive(Clone, Default, Deserialize)]
pub struct ConfigOptsFirewall {
	/// Whether the firewall module is enabled [default: false]
	#[serde(default)]
	pub enable: bool,

	/// Refresh time for firewall rules [default: 300]
	pub refresh_time: Option<u16>,
}

/// IGD configuration options
#[derive(Clone, Default, Deserialize)]
pub struct ConfigOptsIgd {
	/// Whether the IGD module is enabled [default: false]
	#[serde(default)]
	pub enable: bool,

	/// This node's private IP address [default: None]
	pub private_ip: Option<String>,
	/// Expiration time for IGD rules [default: 60]
	pub expiration_time: Option<u16>,
	/// Refresh time for IGD rules [default: 300]
	pub refresh_time: Option<u16>,
}

/// Model of all potential configuration options
pub struct ConfigOpts {
	pub consul: ConfigOptsConsul,
	pub acme: ConfigOptsAcme,
	pub firewall: ConfigOptsFirewall,
	pub igd: ConfigOptsIgd,
}

impl ConfigOpts {
	pub fn from_env() -> Result<RuntimeConfig> {
		let consul: ConfigOptsConsul = envy::prefixed("DIPLONAT_CONSUL_").from_env()?;
		let acme: ConfigOptsAcme = envy::prefixed("DIPLONAT_ACME_").from_env()?;
		let firewall: ConfigOptsFirewall = envy::prefixed("DIPLONAT_FIREWALL_").from_env()?;
		let igd: ConfigOptsIgd = envy::prefixed("DIPLONAT_IGD_").from_env()?;

		RuntimeConfig::new(Self {
			consul,
			acme,
			firewall,
			igd,
		})
	}

	// Currently only used in tests
	#[allow(dead_code)]
	pub fn from_iter<Iter: Clone>(iter: Iter) -> Result<RuntimeConfig>
	where Iter: IntoIterator<Item = (String, String)> {
		let consul: ConfigOptsConsul = envy::prefixed("DIPLONAT_CONSUL_").from_iter(iter.clone())?;
		let acme: ConfigOptsAcme = envy::prefixed("DIPLONAT_ACME_").from_iter(iter.clone())?;
		let firewall: ConfigOptsFirewall = envy::prefixed("DIPLONAT_FIREWALL_").from_iter(iter.clone())?;
		let igd: ConfigOptsIgd = envy::prefixed("DIPLONAT_IGD_").from_iter(iter.clone())?;

		RuntimeConfig::new(Self {
			consul,
			acme,
			firewall,
			igd,
		})
	}
}