add configurable automatic admin command execution after startup

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-08-11 23:07:58 +00:00
parent 025afb61cb
commit b2d8da489c
4 changed files with 56 additions and 2 deletions

View file

@ -334,6 +334,8 @@ pub struct Config {
pub admin_escape_commands: bool,
#[serde(default)]
pub admin_console_automatic: bool,
#[serde(default)]
pub admin_execute: Vec<String>,
#[serde(default)]
pub sentry: bool,
@ -592,6 +594,7 @@ impl fmt::Display for Config {
"Activate admin console after startup",
&self.admin_console_automatic.to_string(),
);
line("Execute admin commands after startup", &self.admin_execute.join(", "));
line("Allow outgoing federated typing", &self.allow_outgoing_typing.to_string());
line("Allow incoming federated typing", &self.allow_incoming_typing.to_string());
line(

View file

@ -24,6 +24,10 @@ pub(crate) struct Args {
/// Activate admin command console automatically after startup.
#[arg(long, num_args(0))]
pub(crate) console: bool,
/// Execute console command automatically after startup.
#[arg(long)]
pub(crate) execute: Vec<String>,
}
/// Parse commandline arguments into structured data
@ -39,6 +43,11 @@ pub(crate) fn update(mut config: Figment, args: &Args) -> Result<Figment> {
config = config.join(("admin_console_automatic", true));
}
// Execute commands after any commands listed in configuration file
for command in &args.execute {
config = config.adjoin(("admin_execute", [command]));
}
// All other individual overrides can go last in case we have options which
// set multiple conf items at once and the user still needs granular overrides.
for option in &args.option {

View file

@ -194,6 +194,12 @@ impl Console {
}
}
/// Standalone/static markdown printer.
pub fn print(markdown: &str) {
let output = configure_output(MadSkin::default_dark());
output.print_text(markdown);
}
fn configure_output(mut output: MadSkin) -> MadSkin {
use termimad::{crossterm::style::Color, Alignment, CompoundStyle, LineStyle};

View file

@ -9,7 +9,7 @@ use std::{
};
use async_trait::async_trait;
use conduit::{debug, error, error::default_log, pdu::PduBuilder, Err, Error, PduEvent, Result, Server};
use conduit::{debug, error, error::default_log, info, pdu::PduBuilder, Err, Error, PduEvent, Result, Server};
pub use create::create_admin_room;
use loole::{Receiver, Sender};
use ruma::{
@ -20,7 +20,10 @@ use ruma::{
OwnedEventId, OwnedRoomId, RoomId, UserId,
};
use serde_json::value::to_raw_value;
use tokio::sync::{Mutex, RwLock};
use tokio::{
sync::{Mutex, RwLock},
time::{sleep, Duration},
};
use crate::{globals, rooms, rooms::state::RoomMutexGuard, Dep};
@ -84,6 +87,8 @@ impl crate::Service for Service {
async fn worker(self: Arc<Self>) -> Result<()> {
let receiver = self.receiver.lock().await;
let mut signals = self.services.server.signal.subscribe();
self.startup_execute().await;
self.console_auto_start().await;
loop {
@ -356,6 +361,37 @@ impl Service {
}
}
/// Execute admin commands after startup
async fn startup_execute(&self) {
sleep(Duration::from_millis(500)).await; //TODO: remove this after run-states are broadcast
for (i, command) in self.services.server.config.admin_execute.iter().enumerate() {
self.startup_execute_command(i, command.clone()).await;
tokio::task::yield_now().await;
}
}
/// Execute one admin command after startup
async fn startup_execute_command(&self, i: usize, command: String) {
debug!("Startup command #{i}: executing {command:?}");
match self.command_in_place(command, None).await {
Err(e) => error!("Startup command #{i} failed: {e:?}"),
Ok(None) => info!("Startup command #{i} completed (no output)."),
Ok(Some(output)) => Self::startup_command_output(i, &output),
}
}
#[cfg(feature = "console")]
fn startup_command_output(i: usize, content: &RoomMessageEventContent) {
info!("Startup command #{i} completed:");
console::print(content.body());
}
#[cfg(not(feature = "console"))]
fn startup_command_output(i: usize, content: &RoomMessageEventContent) {
info!("Startup command #{i} completed:\n{:#?}", content.body());
}
/// Possibly spawn the terminal console at startup if configured.
async fn console_auto_start(&self) {
#[cfg(feature = "console")]