aboutsummaryrefslogblamecommitdiff
path: root/src/config/runtime.rs
blob: 6649d39e15df4bf94977eeb111f683ec4ad532f5 (plain) (tree)















































































































                                                                                                                         
use std::time::Duration;

use anyhow::{Result, anyhow};

use crate::config::{ConfigOpts, ConfigOptsAcme, ConfigOptsBase, ConfigOptsConsul};

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

// In this file, we take ConfigOpts and transform them into ready-to-use RuntimeConfig.
// We apply default values and business logic.

pub struct RuntimeConfigAcme {
	pub email: String,
}

pub struct RuntimeConfigConsul {
	pub node_name: String,
	pub url: String,
}

pub struct RuntimeConfigFirewall {
	pub refresh_time: Duration,
}

pub struct RuntimeConfigIgd {
	pub private_ip: String,
	pub expiration_time: Duration,
	pub refresh_time: Duration,
}

pub struct RuntimeConfig {
	pub acme: Option<RuntimeConfigAcme>,
	pub consul: RuntimeConfigConsul,
	pub firewall: RuntimeConfigFirewall,
	pub igd: RuntimeConfigIgd,
}

impl RuntimeConfig {
	pub fn new(opts: ConfigOpts) -> Result<Self> {
		let acme = RuntimeConfigAcme::new(opts.acme.clone())?;
		let consul = RuntimeConfigConsul::new(opts.consul.clone())?;
		let firewall = RuntimeConfigFirewall::new(opts.base.clone())?;
		let igd = RuntimeConfigIgd::new(opts.base.clone())?;

		Ok(Self {
			acme,
			consul,
			firewall,
			igd,
		})
	}
}

impl RuntimeConfigAcme {
	pub fn new(opts: ConfigOptsAcme) -> Result<Option<Self>> {
		if !opts.enable {
			return Ok(None);
		}

		let email = opts.email.unwrap();

		Ok(Some(Self {
			email,
		}))
	}
}

impl RuntimeConfigConsul {
	pub(super) fn new(opts: ConfigOptsConsul) -> Result<Self> {
		let node_name = opts.node_name.unwrap();
		let url = opts.url.unwrap_or(super::CONSUL_URL.to_string());

		Ok(Self {
			node_name,
			url,
		})
	}
}

impl RuntimeConfigFirewall {
	pub(super) fn new(opts: ConfigOptsBase) -> Result<Self> {
		let refresh_time = Duration::from_secs(
				opts.refresh_time.unwrap_or(super::REFRESH_TIME).into());

		Ok(Self {
			refresh_time,
		})
	}
}

impl RuntimeConfigIgd {
	pub(super) fn new(opts: ConfigOptsBase) -> Result<Self> {
		let private_ip = opts.private_ip.unwrap();
		let expiration_time = Duration::from_secs(
				opts.expiration_time.unwrap_or(super::EXPIRATION_TIME).into());
		let refresh_time = Duration::from_secs(
				opts.refresh_time.unwrap_or(super::REFRESH_TIME).into());

		if refresh_time.as_secs() * 2 > expiration_time.as_secs() {
	      return Err(anyhow!(
	        "IGD expiration time (currently: {}s) must be at least twice bigger than refresh time (currently: {}s)", 
	        expiration_time.as_secs(),
	        refresh_time.as_secs()));
	    }

		Ok(Self {
			private_ip,
			expiration_time,
			refresh_time,
		})
	}
}