add configurable automatic admin command execution after startup
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
025afb61cb
commit
b2d8da489c
4 changed files with 56 additions and 2 deletions
|
@ -334,6 +334,8 @@ pub struct Config {
|
||||||
pub admin_escape_commands: bool,
|
pub admin_escape_commands: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub admin_console_automatic: bool,
|
pub admin_console_automatic: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
pub admin_execute: Vec<String>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub sentry: bool,
|
pub sentry: bool,
|
||||||
|
@ -592,6 +594,7 @@ impl fmt::Display for Config {
|
||||||
"Activate admin console after startup",
|
"Activate admin console after startup",
|
||||||
&self.admin_console_automatic.to_string(),
|
&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 outgoing federated typing", &self.allow_outgoing_typing.to_string());
|
||||||
line("Allow incoming federated typing", &self.allow_incoming_typing.to_string());
|
line("Allow incoming federated typing", &self.allow_incoming_typing.to_string());
|
||||||
line(
|
line(
|
||||||
|
|
|
@ -24,6 +24,10 @@ pub(crate) struct Args {
|
||||||
/// Activate admin command console automatically after startup.
|
/// Activate admin command console automatically after startup.
|
||||||
#[arg(long, num_args(0))]
|
#[arg(long, num_args(0))]
|
||||||
pub(crate) console: bool,
|
pub(crate) console: bool,
|
||||||
|
|
||||||
|
/// Execute console command automatically after startup.
|
||||||
|
#[arg(long)]
|
||||||
|
pub(crate) execute: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse commandline arguments into structured data
|
/// 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));
|
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
|
// 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.
|
// set multiple conf items at once and the user still needs granular overrides.
|
||||||
for option in &args.option {
|
for option in &args.option {
|
||||||
|
|
|
@ -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 {
|
fn configure_output(mut output: MadSkin) -> MadSkin {
|
||||||
use termimad::{crossterm::style::Color, Alignment, CompoundStyle, LineStyle};
|
use termimad::{crossterm::style::Color, Alignment, CompoundStyle, LineStyle};
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
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;
|
pub use create::create_admin_room;
|
||||||
use loole::{Receiver, Sender};
|
use loole::{Receiver, Sender};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
|
@ -20,7 +20,10 @@ use ruma::{
|
||||||
OwnedEventId, OwnedRoomId, RoomId, UserId,
|
OwnedEventId, OwnedRoomId, RoomId, UserId,
|
||||||
};
|
};
|
||||||
use serde_json::value::to_raw_value;
|
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};
|
use crate::{globals, rooms, rooms::state::RoomMutexGuard, Dep};
|
||||||
|
|
||||||
|
@ -84,6 +87,8 @@ impl crate::Service for Service {
|
||||||
async fn worker(self: Arc<Self>) -> Result<()> {
|
async fn worker(self: Arc<Self>) -> Result<()> {
|
||||||
let receiver = self.receiver.lock().await;
|
let receiver = self.receiver.lock().await;
|
||||||
let mut signals = self.services.server.signal.subscribe();
|
let mut signals = self.services.server.signal.subscribe();
|
||||||
|
|
||||||
|
self.startup_execute().await;
|
||||||
self.console_auto_start().await;
|
self.console_auto_start().await;
|
||||||
|
|
||||||
loop {
|
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.
|
/// Possibly spawn the terminal console at startup if configured.
|
||||||
async fn console_auto_start(&self) {
|
async fn console_auto_start(&self) {
|
||||||
#[cfg(feature = "console")]
|
#[cfg(feature = "console")]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue