"httpdate",
"itoa",
"pin-project-lite",
- "socket2",
+ "socket2 0.4.9",
"tokio",
"tower-service",
"tracing",
[[package]]
name = "pin-project-lite"
-version = "0.2.10"
+version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
"log",
"podman-api",
"poise",
- "serde_path_to_error",
"tokio",
]
"serde",
]
-[[package]]
-name = "serde_path_to_error"
-version = "0.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8acc4422959dd87a76cb117c191dcbffc20467f06c9100b76721dab370f24d3a"
-dependencies = [
- "itoa",
- "serde",
-]
-
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
"winapi",
]
+[[package]]
+name = "socket2"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
[[package]]
name = "spin"
version = "0.5.2"
[[package]]
name = "tokio"
-version = "1.29.1"
+version = "1.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
+checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"
dependencies = [
- "autocfg",
"backtrace",
"bytes 1.4.0",
"libc",
"mio",
"num_cpus",
"pin-project-lite",
- "socket2",
+ "socket2 0.5.4",
"tokio-macros",
"windows-sys",
]
[dependencies]
podman-api = "0.10"
-poise = "0.5.5"
-serde_path_to_error = "0.1.13"
-tokio = { version = "1.29.1", features = ["macros", "rt-multi-thread"]}
+poise = "0.5"
+tokio = { version = "1.32", features = ["macros", "rt-multi-thread"]}
dotenv = "0.15.0"
log = "0.4.20"
fern = "0.6.2"
\ No newline at end of file
use std::collections::HashMap;
-use std::ops::Deref;
use std::process;
-use std::sync::{Arc, Mutex};
+use std::sync::{Arc, RwLock};
use std::time::{Instant, Duration};
use log::{warn};
use podman_api::models::{Container, Port};
use crate::utils::Id;
pub(crate) struct Containers {
- cache: Arc<Mutex<Option<(Instant, HashMap<[u8; 32], Container>)>>>,
+ cache: Arc<RwLock<Option<(Instant, HashMap<[u8; 32], Container>)>>>,
connection: Podman,
}
}
};
let c = Containers {
- cache: Arc::new(Mutex::new(None)),
+ cache: Arc::new(RwLock::new(None)),
connection,
};
c
}
fn time_since_update(&self) -> Duration {
- let i = match self.cache.lock().unwrap().deref() {
- Some(i) => { i.0 }
- None => { return Duration::MAX; }
- };
- Instant::now().duration_since(i)
+ match self.cache.read() {
+ Ok(i) => { Instant::now().duration_since(i.unwrap().0) }
+ Err(_) => { Duration::MAX }
+ }
}
pub(crate) async fn sync(&self) -> Result<(), ContainerError> {
pub(crate) async fn sync_now(&self) -> Result<(), ContainerError> {
return match self.sync_helper().await {
Ok(_) => { Ok(()) }
- Err(e) => {
- Err(e)
- }
+ Err(e) => { Err(e) }
};
}
// Scoping mutex actions
{
- *match self.cache.lock() {
+ *match self.cache.write() {
Ok(c) => { c }
Err(_) => {
warn!("Cache was poisoned");
--- /dev/null
+pub(crate) mod containers;
+pub(crate) mod system;
+
+use crate::cache::containers::Containers;
+use crate::cache::system::System;
+
+/// Struct combining all of the caching podman structs
+pub(crate) struct Cache {
+ pub(super) containers: Containers,
+ pub(super) system: System,
+}
\ No newline at end of file
--- /dev/null
+use std::sync::{Arc, RwLock};
+use std::time::Instant;
+use podman_api::models::Info;
+use poise::serenity_prelude::Connection;
+
+
+pub(crate) struct System {
+ updated: Arc<RwLock<Instant>>,
+ data: Arc<RwLock<Info>>,
+ connection: Connection
+}
--- /dev/null
+use log::debug;
+use podman_api::opts::ContainerListOpts;
+use crate::create_embed;
+use crate::utils::{Context, Error, EmbedData};
+
+
+/// Display's the connected podman's version information
+#[poise::command(slash_command, prefix_command)]
+pub(super) async fn version(ctx: Context<'_>) -> Result<(), Error> {
+ let version_response = match ctx.data().podman.version().await {
+ Ok(v) => v,
+ Err(e) => {
+ eprintln!("unable too get podman version.");
+ create_embed!(&ctx, "Error", format!("```{}```", e));
+ return Ok(());
+ }
+ };
+
+ create_embed!(&ctx, "Podman Version",
+ "Podman" => format!("v{}",&ctx.data().podman_version),
+ "API" => format!("v{}", match &version_response.api_version {
+ None => { "unknown" }
+ Some(v) => { v }
+ }),
+ "Go" => format!("{}", match &version_response.go_version {
+ None => { "unknown" }
+ Some(v) => { v }
+ }
+ ));
+ Ok(())
+}
+
+/// Podman system info.
+#[poise::command(slash_command, prefix_command)]
+pub(super) async fn system_info(ctx: Context<'_>) -> Result<(), Error> {
+ let info_response = match ctx.data().podman.info().await {
+ Ok(v) => v,
+ Err(e) => {
+ eprintln!("unable too get podman version.");
+ create_embed!(&ctx, "Error", format!("```{}```", e));
+ return Ok(());
+ }
+ };
+
+ let containers_options = ContainerListOpts::builder().all(true).sync(true).build();
+ let containers_response = match ctx
+ .data()
+ .podman
+ .containers()
+ .list(&containers_options)
+ .await
+ {
+ Ok(containers_response) => containers_response,
+ Err(e) => {
+ eprintln!("unable too get podman cache::containers.");
+ create_embed!(&ctx, "Error", format!("```{}```", e));
+ return Ok(());
+ }
+ };
+
+ debug!("{:?}",&info_response);
+ debug!("{:?}",&containers_response);
+
+ let mut running_number = 0;
+ let _ = &containers_response.clone().into_iter().for_each(|c| {
+ if match c.state {
+ None => {
+ false
+ }
+ Some(c) => { c == "running" }
+ } {
+ running_number += 1;
+ }
+ });
+
+ create_embed!(&ctx, "Server info",
+ "Total Containers" => format!("{}", containers_response.len()),
+ "Running Containers" => format!("{}", running_number),
+ "Uptime" => format!("{}", match &info_response.host {
+ None => { "Unknown" }
+ Some(h) => {
+ match &h.uptime {
+ None => { "Unknown" }
+ Some(u) => { u }
+ }
+ }
+ })
+ );
+
+ Ok(())
+}
+
+async fn list_containers(ctx: Context<'_>) -> Result<(), Error> {
+ let info_response = match ctx.data().podman.info().await {
+ Ok(v) => v,
+ Err(e) => {
+ eprintln!("unable too get podman version.");
+ create_embed!(&ctx, "Error", format!("```{}```", e));
+ return Ok(());
+ }
+ };
+
+ let containers_options = ContainerListOpts::builder().all(true).sync(true).build();
+ let containers_response = match ctx
+ .data()
+ .podman
+ .containers()
+ .list(&containers_options)
+ .await
+ {
+ Ok(containers_response) => containers_response,
+ Err(e) => {
+ eprintln!("unable too get podman cache::containers.");
+ create_embed!(&ctx, "Error", format!("```{}```", e));
+ return Ok(());
+ }
+ };
+
+ let mut container_list: Vec<(String, String)> = Vec::new();
+ container_list.reserve(containers_response.len());
+
+
+ todo!()
+}
\ No newline at end of file
+mod cache;
+mod commands;
mod utils;
-mod containers;
-use crate::utils::*;
-use podman_api::opts::ContainerListOpts;
use podman_api::Podman;
use poise::serenity_prelude as serenity;
use std::process;
use dotenv::dotenv;
use tokio;
-use crate::containers::{ContainerError, Containers};
+use crate::cache::containers::Containers;
+use crate::utils::Data;
-/// Display's the connected podman's version information
-#[poise::command(slash_command, prefix_command)]
-async fn version(ctx: Context<'_>) -> Result<(), Error> {
- let version_response = match ctx.data().podman.version().await {
- Ok(v) => v,
- Err(e) => {
- eprintln!("unable too get podman version.");
- create_embed!(&ctx, "Error", format!("```{}```", e));
- return Ok(());
- }
- };
-
- create_embed!(&ctx, "Podman Version",
- "Podman" => format!("v{}",&ctx.data().podman_version),
- "API" => format!("v{}", match &version_response.api_version {
- None => { "unknown" }
- Some(v) => { v }
- }),
- "Go" => format!("{}", match &version_response.go_version {
- None => { "unknown" }
- Some(v) => { v }
- }
- ));
- Ok(())
-}
-
-/// Podman system info.
-#[poise::command(slash_command, prefix_command)]
-async fn system_info(ctx: Context<'_>) -> Result<(), Error> {
- let info_response = match ctx.data().podman.info().await {
- Ok(v) => v,
- Err(e) => {
- eprintln!("unable too get podman version.");
- create_embed!(&ctx, "Error", format!("```{}```", e));
- return Ok(());
- }
- };
-
- let containers_options = ContainerListOpts::builder().all(true).sync(true).build();
- let containers_response = match ctx
- .data()
- .podman
- .containers()
- .list(&containers_options)
- .await
- {
- Ok(containers_response) => containers_response,
- Err(e) => {
- eprintln!("unable too get podman containers.");
- create_embed!(&ctx, "Error", format!("```{}```", e));
- return Ok(());
- }
- };
-
- dbg!(&info_response);
- dbg!(&containers_response);
-
- let mut running_number = 0;
- let _ = &containers_response.clone().into_iter().for_each(|c| {
- if match c.state {
- None => {
- false
- }
- Some(c) => { c == "running" }
- } {
- running_number += 1;
- }
- });
-
- create_embed!(&ctx, "Server info",
- "Total Containers" => format!("{}", containers_response.len()),
- "Running Containers" => format!("{}", running_number),
- "Uptime" => format!("{}", match &info_response.host {
- None => { "Unknown" }
- Some(h) => {
- match &h.uptime {
- None => { "Unknown" }
- Some(u) => { u }
- }
- }
- })
- );
-
- Ok(())
-}
-
-async fn list_containers(ctx: Context<'_>) -> Result<(), Error> {
- let info_response = match ctx.data().podman.info().await {
- Ok(v) => v,
- Err(e) => {
- eprintln!("unable too get podman version.");
- create_embed!(&ctx, "Error", format!("```{}```", e));
- return Ok(());
- }
- };
-
- let containers_options = ContainerListOpts::builder().all(true).sync(true).build();
- let containers_response = match ctx
- .data()
- .podman
- .containers()
- .list(&containers_options)
- .await
- {
- Ok(containers_response) => containers_response,
- Err(e) => {
- eprintln!("unable too get podman containers.");
- create_embed!(&ctx, "Error", format!("```{}```", e));
- return Ok(());
- }
- };
-
- let mut container_list: Vec<(String, String)> = Vec::new();
- container_list.reserve(containers_response.len());
-
-
- todo!()
-}
#[tokio::main]
async fn main() {
+ dotenv().ok();
let api_uri = "unix:///run/podman/podman.sock";
let podman = match Podman::new(&api_uri) {
Ok(a) => a,
process::exit(32);
}
};
-
let containers = Containers::connect(&api_uri);
match containers.sync().await {
}
}
- dotenv().ok();
let framework = poise::Framework::builder()
.options(poise::FrameworkOptions {
- commands: vec![version(), system_info()],
+ commands: vec![commands::version(), commands::system_info()],
..Default::default()
})
.token(std::env::var("DISCORD_TOKEN").expect("missing DISCORD_TOKEN"))
use std::num::ParseIntError;
use podman_api::Podman;
-use crate::containers::Containers;
+use crate::cache::containers::Containers;
/// Helper functions for getting data for discord embeds.
pub(crate) struct EmbedData;
}
-// User data, which is stored and accessible in all command invocations
+/// User data, which is stored and accessible in all command invocations
pub(crate) type Error = Box<dyn std::error::Error + Send + Sync>;
pub(crate) type Context<'a> = poise::Context<'a, Data, Error>;