Skip to content

Commit

Permalink
feat: Update CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
GeekMasher committed Oct 19, 2024
1 parent c502af2 commit 9269eaf
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 138 deletions.
6 changes: 3 additions & 3 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ anyhow = "1.0"
log = "0.4"
env_logger = "0.11"
glob = "0.3"
chrono = { version = "0.4.38", features = ["serde"] }
serde = { version = "1.0.209", features = ["derive"] }
serde_json = "1.0.127"
chrono = { version = "0.4", features = ["serde"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"

145 changes: 96 additions & 49 deletions cli/src/cli/agent.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,88 @@
use std::{collections::HashMap, path::PathBuf};

use bollard::{container::ListContainersOptions, API_DEFAULT_VERSION};
use clap::Subcommand;
use konarr::{
client::{projects::KonarrProject, snapshot::KonarrSnapshot, ApiResponse},
client::{
projects::{KonarrProject, KonarrProjects},
snapshot::KonarrSnapshot,
ApiResponse,
},
tools::{syft::Syft, Tool},
Config, KonarrError,
};
use log::{debug, info};
use std::{collections::HashMap, path::PathBuf, sync::Arc};
use tokio::spawn;
use tokio_schedule::{every, Job};

#[derive(Subcommand, Debug, Clone)]
pub enum AgentCommands {
Docker {
#[clap(short, long, env = "DOCKER_HOST")]
socket: Option<String>,
pub async fn setup(
config: &Config,
client: &konarr::client::KonarrClient,
) -> Result<(), konarr::KonarrError> {
// ID -> Hostname -> New Project
let mut project = if let Some(project_id) = config.agent.project_id {
KonarrProjects::by_id(&client, project_id).await?
} else if let Ok(hostname) = std::env::var("KONARR_HOST") {
match KonarrProjects::by_name(&client, &hostname).await {
Ok(project) => project,
Err(error) => {
log::error!("Failed to get project by name: {}", error);
return Err(error.into());
}
}
} else if let Ok(hostname) = std::env::var("HOST") {
match KonarrProjects::by_name(&client, &hostname).await {
Ok(project) => project,
Err(error) => {
log::error!("Failed to get project by name: {}", error);
return Err(error.into());
}
}
} else {
log::error!("Failed to get project by ID or Name");
return Err(KonarrError::UnknownError(
"Unknown project id / name".to_string(),
));
};

#[clap(long, env = "HOST")]
host: Option<String>,
},
info!("Project :: {}", project.id);

// TODO: Multi-threading is hard...
let config = Arc::new(config.clone());
let client = Arc::new(client.clone());

if config.agent.monitoring {
info!("Monitoring mode enabled");

let task = every(1).minutes().perform(move || {
// TODO: Multi-threading is hard...
let config = config.clone();
let client = client.clone();
let mut project = project.clone();

async move {
info!("Running task...");

run(&config, &client, &mut project)
.await
.expect("Panic in monitoring mode...");

info!("Finishing task... Waiting for next");
}
});
spawn(task).await.expect("Panic in monitoring mode...");

Ok(())
} else {
run(&config, &client, &mut project).await?;
Ok(())
}
}

pub async fn run(
async fn run(
config: &Config,
subcommands: Option<AgentCommands>,
client: &konarr::client::KonarrClient,
project: KonarrProject,
project: &mut KonarrProject,
) -> Result<(), konarr::KonarrError> {
let mut project = project.clone();
let snapshot = if let Some(snap) = project.snapshot {
let snapshot = if let Some(snap) = project.snapshot.clone() {
snap
} else {
info!("Creating Snapshot...");
Expand All @@ -39,49 +94,41 @@ pub async fn run(
}
}
};

debug!("Snapshot: {:#?}", snapshot);
project.snapshot = Some(snapshot);

match subcommands {
#[allow(unused_variables)]
Some(AgentCommands::Docker { socket, host }) => {
run_docker(config, socket, client, project).await?;
Ok(())
info!("Auto-Discover mode...");

// Docker
match std::env::var("DOCKER_HOST") {
Ok(socket) => {
info!("Using Docker Socket: {}", socket);
run_docker(config, Some(socket), client, project).await?;
}
None => {
info!("Auto-Discover mode...");

// Docker
match std::env::var("DOCKER_HOST") {
Ok(socket) => {
info!("Using Docker Socket: {}", socket);
run_docker(config, Some(socket), client, project).await?;
}
Err(_) => {
let docker_socket = PathBuf::from("/var/run/docker.sock");
if docker_socket.exists() {
info!("Using Docker Socket: {:?}", docker_socket);
run_docker(
config,
Some(docker_socket.to_str().unwrap().to_string()),
client,
project,
)
.await?;
}
}
Err(_) => {
let docker_socket = PathBuf::from("/var/run/docker.sock");
if docker_socket.exists() {
info!("Using Docker Socket: {:?}", docker_socket);
run_docker(
config,
Some(docker_socket.to_str().unwrap().to_string()),
client,
project,
)
.await?;
}

Err(KonarrError::UnknownError("No Agent found".to_string()))
}
}

Ok(())
}

pub async fn run_docker(
async fn run_docker(
_config: &Config,
socket: Option<String>,
client: &konarr::client::KonarrClient,
server_project: KonarrProject,
server_project: &KonarrProject,
) -> Result<(), konarr::KonarrError> {
info!("Docker Monitor Command");

Expand All @@ -96,7 +143,7 @@ pub async fn run_docker(
let version = docker.version().await?;
let engine = version.platform.unwrap_or_default().name;

let server_snapshot = server_project.snapshot.expect(
let server_snapshot = server_project.snapshot.clone().expect(
"Snapshot is required to update metadata. Please create a snapshot before running this command");

server_snapshot
Expand Down
39 changes: 21 additions & 18 deletions cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,25 @@ pub struct Arguments {
#[clap(short, long, env, default_value = "./")]
pub working_dir: PathBuf,

#[clap(short, long, env = "KONARR_MONITORING")]
// Database Settings
/// Database URL (SQLite)
#[cfg(feature = "database")]
#[clap(long, env = "KONARR_DATABASE_URL")]
pub database_url: Option<String>,

// Agent Settings
/// Monitoring Enabled
#[clap(short, long, env = "KONARR_AGENT_MONITORING")]
pub monitoring: bool,
/// Agent Token
#[clap(short, long, env = "KONARR_AGENT_TOKEN")]
pub agent_token: Option<String>,
/// Root Server Project ID
#[clap(long, env = "KONARR_AGENT_PROJECT_ID")]
pub project_id: Option<u32>,
/// Agent Hostname
#[clap(long, env = "HOST")]
pub hostname: Option<String>,

/// If the command is running in a container
#[clap(long, env = "KONARR_CONTAINER")]
Expand All @@ -50,9 +67,6 @@ pub struct Arguments {
pub enum ArgumentCommands {
#[cfg(feature = "database")]
Database {
#[clap(long, env = "KONARR_DATABASE_URL")]
database_url: Option<String>,

#[clap(subcommand)]
subcommands: Option<database::DatabaseCommands>,
},
Expand All @@ -62,20 +76,9 @@ pub enum ArgumentCommands {
subcommands: Option<display::DisplayCommands>,
},
Agent {
/// Root Server Project ID
#[clap(long, env = "KONARR_PROJECT_ID")]
project_id: Option<u32>,

#[clap(long, env = "KONARR_HOST")]
hostname: Option<String>,

/// Agent Token
#[clap(short, long, env = "KONARR_AGENT_TOKEN")]
agent_token: Option<String>,

/// Subcommands
#[clap(subcommand)]
subcommands: Option<agent::AgentCommands>,
/// Docker Socket Path
#[clap(short, long, env = "DOCKER_HOST")]
docker_socket: Option<String>,
},
#[cfg(feature = "database")]
Index {
Expand Down
75 changes: 13 additions & 62 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ use anyhow::{anyhow, Result};
mod cli;
mod utils;

use cli::{init, Arguments};
use konarr::{client::projects::KonarrProjects, Config};
use cli::init;
use konarr::Config;
use log::{error, info, warn};
use tokio::spawn;
use tokio_schedule::{every, Job};

async fn run(arguments: Arguments) -> Result<()> {
#[tokio::main]
async fn main() -> Result<()> {
let arguments = init();

#[allow(unused_mut)]
let mut config = match Config::load(&arguments.config) {
Ok(config) => config,
Expand All @@ -20,16 +21,14 @@ async fn run(arguments: Arguments) -> Result<()> {
};

match arguments.commands {
Some(cli::ArgumentCommands::Agent {
agent_token,
subcommands,
project_id,
hostname,
}) => {
Some(cli::ArgumentCommands::Agent { docker_socket }) => {
config.agent.docker_socket = docker_socket;

let client = config
.server
.client_with_token(agent_token.expect("Agent Token must be provided"))?;
.client_with_token(arguments.agent_token.expect("Agent Token must be provided"))?;
info!("Client created");

let serverinfo = client.server().await?;
info!("Server Info :: {}", serverinfo.version);

Expand All @@ -43,33 +42,10 @@ async fn run(arguments: Arguments) -> Result<()> {
serverinfo.user.unwrap().username
);

// ID -> Name -> New Project
let server_project = if let Some(project_id) = project_id {
KonarrProjects::by_id(&client, project_id).await?
} else if let Some(config_project_id) = config.project.id {
KonarrProjects::by_id(&client, config_project_id).await?
} else if let Some(hostname) = &hostname {
match KonarrProjects::by_name(&client, hostname).await {
Ok(project) => project,
Err(error) => {
error!("Failed to get project by name: {}", error);
return Err(error.into());
}
}
} else {
error!("Failed to get project by ID or Name");
return Err(anyhow::anyhow!("Failed to get project by ID or Name"));
};

info!("Project :: {}", server_project.id);

Ok(cli::agent::run(&config, subcommands, &client, server_project).await?)
Ok(cli::agent::setup(&config, &client).await?)
}
#[cfg(feature = "database")]
Some(cli::ArgumentCommands::Database {
subcommands,
database_url,
}) => {
Some(cli::ArgumentCommands::Database { subcommands }) => {
if let Some(url) = database_url {
config.database.path = Some(url.into());
}
Expand All @@ -90,28 +66,3 @@ async fn run(arguments: Arguments) -> Result<()> {
None => Err(anyhow!("No subcommand provided")),
}
}

#[tokio::main]
async fn main() -> Result<()> {
let arguments = init();

if arguments.monitoring {
info!("Monitoring mode enabled");
let task = every(1).minutes().perform(move || {
let arguments = arguments.clone();

async move {
info!("Running task...");

run(arguments).await.expect("Panic in monitoring mode...");

info!("Finishing task... Waiting for next");
}
});
spawn(task).await?;

Ok(())
} else {
run(arguments).await
}
}
17 changes: 17 additions & 0 deletions src/client/ws.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! # Konarr Websocket Client

use tokio_tungstenite::tungstenite::connect;
use url::Url;

pub struct KonarrWebsocketClient {
/// Websocket URL
url: Url,
}

impl KonarrWebsocketClient {
pub fn new(url: impl Into<Url>) -> Self {
let url = url.into();

Self { url }
}
}
Loading

0 comments on commit 9269eaf

Please sign in to comment.