implement the reload feature
This commit is contained in:
parent
1f6e64d34e
commit
1b5f2eb695
5 changed files with 74 additions and 20 deletions
32
Cargo.lock
generated
32
Cargo.lock
generated
|
@ -50,6 +50,7 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"ldap3",
|
"ldap3",
|
||||||
"log",
|
"log",
|
||||||
|
"nix",
|
||||||
"rand",
|
"rand",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
"rpassword",
|
"rpassword",
|
||||||
|
@ -432,6 +433,12 @@ version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitmaps"
|
name = "bitmaps"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
|
@ -571,7 +578,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
|
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
"clap_lex",
|
"clap_lex",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
@ -1433,7 +1440,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"ryu",
|
"ryu",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
|
@ -1563,6 +1570,17 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.27.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.1",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "2.2.1"
|
version = "2.2.1"
|
||||||
|
@ -1793,7 +1811,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
|
checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -1901,7 +1919,7 @@ version = "0.2.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1910,7 +1928,7 @@ version = "0.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2109,7 +2127,7 @@ version = "0.37.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
|
checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"errno",
|
"errno",
|
||||||
"io-lifetimes",
|
"io-lifetimes",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -2218,7 +2236,7 @@ version = "2.9.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
|
checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
|
@ -27,6 +27,7 @@ rusoto_credential = "0.48.0"
|
||||||
rusoto_s3 = { version = "0.48.0", default_features = false, features = ["rustls"] }
|
rusoto_s3 = { version = "0.48.0", default_features = false, features = ["rustls"] }
|
||||||
hyper-rustls = { version = "0.24", features = ["http2"] }
|
hyper-rustls = { version = "0.24", features = ["http2"] }
|
||||||
rusoto_signature = "0.48.0"
|
rusoto_signature = "0.48.0"
|
||||||
|
nix = { version = "0.27", features = ["signal"] }
|
||||||
serde = "1.0.137"
|
serde = "1.0.137"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
rmp-serde = "0.15"
|
rmp-serde = "0.15"
|
||||||
|
|
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct CompanionConfig {
|
pub struct CompanionConfig {
|
||||||
pub pid: Option<String>,
|
pub pid: Option<PathBuf>,
|
||||||
pub imap: ImapConfig,
|
pub imap: ImapConfig,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
|
@ -17,7 +17,7 @@ pub struct CompanionConfig {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct ProviderConfig {
|
pub struct ProviderConfig {
|
||||||
pub pid: Option<String>,
|
pub pid: Option<PathBuf>,
|
||||||
pub imap: ImapConfig,
|
pub imap: ImapConfig,
|
||||||
pub lmtp: LmtpConfig,
|
pub lmtp: LmtpConfig,
|
||||||
pub users: UserManagement,
|
pub users: UserManagement,
|
||||||
|
|
33
src/main.rs
33
src/main.rs
|
@ -13,9 +13,11 @@ mod server;
|
||||||
mod storage;
|
mod storage;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
use anyhow::{bail, Result, Context};
|
use anyhow::{bail, Result, Context};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
use nix::{unistd::Pid, sys::signal};
|
||||||
|
|
||||||
use config::*;
|
use config::*;
|
||||||
use server::Server;
|
use server::Server;
|
||||||
|
@ -92,7 +94,7 @@ enum CompanionCommand {
|
||||||
Daemon,
|
Daemon,
|
||||||
Reload {
|
Reload {
|
||||||
#[clap(short, long, env = "AEROGRAMME_PID")]
|
#[clap(short, long, env = "AEROGRAMME_PID")]
|
||||||
pid: Option<u64>,
|
pid: Option<i32>,
|
||||||
},
|
},
|
||||||
Wizard,
|
Wizard,
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
|
@ -104,7 +106,10 @@ enum ProviderCommand {
|
||||||
/// Runs the IMAP+LMTP server daemon
|
/// Runs the IMAP+LMTP server daemon
|
||||||
Daemon,
|
Daemon,
|
||||||
/// Reload the daemon
|
/// Reload the daemon
|
||||||
Reload,
|
Reload {
|
||||||
|
#[clap(short, long, env = "AEROGRAMME_PID")]
|
||||||
|
pid: Option<i32>,
|
||||||
|
},
|
||||||
/// Manage static accounts
|
/// Manage static accounts
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
Account(AccountManagement),
|
Account(AccountManagement),
|
||||||
|
@ -161,9 +166,7 @@ async fn main() -> Result<()> {
|
||||||
let server = Server::from_companion_config(config).await?;
|
let server = Server::from_companion_config(config).await?;
|
||||||
server.run().await?;
|
server.run().await?;
|
||||||
},
|
},
|
||||||
CompanionCommand::Reload { pid: _pid } => {
|
CompanionCommand::Reload { pid } => reload(*pid, config.pid)?,
|
||||||
unimplemented!();
|
|
||||||
},
|
|
||||||
CompanionCommand::Wizard => {
|
CompanionCommand::Wizard => {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
},
|
},
|
||||||
|
@ -177,9 +180,7 @@ async fn main() -> Result<()> {
|
||||||
let server = Server::from_provider_config(config).await?;
|
let server = Server::from_provider_config(config).await?;
|
||||||
server.run().await?;
|
server.run().await?;
|
||||||
},
|
},
|
||||||
ProviderCommand::Reload => {
|
ProviderCommand::Reload { pid } => reload(*pid, config.pid)?,
|
||||||
unimplemented!();
|
|
||||||
},
|
|
||||||
ProviderCommand::Account(cmd) => {
|
ProviderCommand::Account(cmd) => {
|
||||||
let user_file = match config.users {
|
let user_file = match config.users {
|
||||||
UserManagement::Static(conf) => conf.user_list,
|
UserManagement::Static(conf) => conf.user_list,
|
||||||
|
@ -260,6 +261,22 @@ async fn main() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reload(pid: Option<i32>, pid_path: Option<PathBuf>) -> Result<()> {
|
||||||
|
let final_pid = match (pid, pid_path) {
|
||||||
|
(Some(pid), _) => pid,
|
||||||
|
(_, Some(path)) => {
|
||||||
|
let mut f = std::fs::OpenOptions::new().read(true).open(path)?;
|
||||||
|
let mut pidstr = String::new();
|
||||||
|
f.read_to_string(&mut pidstr)?;
|
||||||
|
pidstr.parse::<i32>()?
|
||||||
|
},
|
||||||
|
_ => bail!("Unable to infer your daemon's PID"),
|
||||||
|
};
|
||||||
|
let pid = Pid::from_raw(final_pid);
|
||||||
|
signal::kill(pid, signal::Signal::SIGUSR1)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn account_management(root: &Command, cmd: &AccountManagement, users: PathBuf) -> Result<()> {
|
fn account_management(root: &Command, cmd: &AccountManagement, users: PathBuf) -> Result<()> {
|
||||||
let mut ulist: UserList = read_config(users.clone()).context(format!("'{:?}' must be a user database", users))?;
|
let mut ulist: UserList = read_config(users.clone()).context(format!("'{:?}' must be a user database", users))?;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use futures::try_join;
|
use futures::try_join;
|
||||||
|
@ -14,18 +16,21 @@ use crate::login::{ldap_provider::*, static_provider::*};
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
lmtp_server: Option<Arc<LmtpServer>>,
|
lmtp_server: Option<Arc<LmtpServer>>,
|
||||||
imap_server: Option<imap::Server>,
|
imap_server: Option<imap::Server>,
|
||||||
|
pid_file: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
pub async fn from_companion_config(config: CompanionConfig) -> Result<Self> {
|
pub async fn from_companion_config(config: CompanionConfig) -> Result<Self> {
|
||||||
|
tracing::info!("Init as companion");
|
||||||
let login = Arc::new(StaticLoginProvider::new(config.users).await?);
|
let login = Arc::new(StaticLoginProvider::new(config.users).await?);
|
||||||
|
|
||||||
let lmtp_server = None;
|
let lmtp_server = None;
|
||||||
let imap_server = Some(imap::new(config.imap, login.clone()).await?);
|
let imap_server = Some(imap::new(config.imap, login.clone()).await?);
|
||||||
Ok(Self { lmtp_server, imap_server })
|
Ok(Self { lmtp_server, imap_server, pid_file: config.pid })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn from_provider_config(config: ProviderConfig) -> Result<Self> {
|
pub async fn from_provider_config(config: ProviderConfig) -> Result<Self> {
|
||||||
|
tracing::info!("Init as provider");
|
||||||
let login: ArcLoginProvider = match config.users {
|
let login: ArcLoginProvider = match config.users {
|
||||||
UserManagement::Static(x) => Arc::new(StaticLoginProvider::new(x).await?),
|
UserManagement::Static(x) => Arc::new(StaticLoginProvider::new(x).await?),
|
||||||
UserManagement::Ldap(x) => Arc::new(LdapLoginProvider::new(x)?),
|
UserManagement::Ldap(x) => Arc::new(LdapLoginProvider::new(x)?),
|
||||||
|
@ -34,11 +39,24 @@ impl Server {
|
||||||
let lmtp_server = Some(LmtpServer::new(config.lmtp, login.clone()));
|
let lmtp_server = Some(LmtpServer::new(config.lmtp, login.clone()));
|
||||||
let imap_server = Some(imap::new(config.imap, login.clone()).await?);
|
let imap_server = Some(imap::new(config.imap, login.clone()).await?);
|
||||||
|
|
||||||
Ok(Self { lmtp_server, imap_server })
|
Ok(Self { lmtp_server, imap_server, pid_file: config.pid })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(self) -> Result<()> {
|
pub async fn run(self) -> Result<()> {
|
||||||
tracing::info!("Starting Aerogramme...");
|
let pid = std::process::id();
|
||||||
|
tracing::info!(pid=pid, "Starting main loops");
|
||||||
|
|
||||||
|
// write the pid file
|
||||||
|
if let Some(pid_file) = self.pid_file {
|
||||||
|
let mut file = std::fs::OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open(pid_file)?;
|
||||||
|
file.write_all(pid.to_string().as_bytes())?;
|
||||||
|
drop(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let (exit_signal, provoke_exit) = watch_ctrl_c();
|
let (exit_signal, provoke_exit) = watch_ctrl_c();
|
||||||
let _exit_on_err = move |err: anyhow::Error| {
|
let _exit_on_err = move |err: anyhow::Error| {
|
||||||
|
|
Loading…
Reference in a new issue