mirror of
https://github.com/moghtech/komodo.git
synced 2026-03-11 17:44:19 -05:00
implement more periphery routes + periphery client
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1463,6 +1463,7 @@ name = "periphery_client"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"helpers",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
||||
@@ -1,59 +1,69 @@
|
||||
use std::{path::PathBuf, str::FromStr};
|
||||
|
||||
use ::run_command::async_run_command;
|
||||
use anyhow::{anyhow, Context};
|
||||
use anyhow::anyhow;
|
||||
use async_timing_util::unix_timestamp_ms;
|
||||
use types::{Build, Deployment, GithubToken, Log};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use types::{Build, Command, Deployment, GithubToken, GithubUsername, Log};
|
||||
|
||||
use crate::run_monitor_command;
|
||||
|
||||
pub async fn clone_build_repo(
|
||||
Build {
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct CloneArgs {
|
||||
name: String,
|
||||
repo: Option<String>,
|
||||
branch: Option<String>,
|
||||
on_clone: Option<Command>,
|
||||
pub github_account: Option<GithubUsername>,
|
||||
}
|
||||
|
||||
impl From<&Deployment> for CloneArgs {
|
||||
fn from(d: &Deployment) -> Self {
|
||||
CloneArgs {
|
||||
name: d.name.clone(),
|
||||
repo: d.repo.clone(),
|
||||
branch: d.branch.clone(),
|
||||
on_clone: d.on_clone.clone(),
|
||||
github_account: d.github_account.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Build> for CloneArgs {
|
||||
fn from(b: &Build) -> Self {
|
||||
CloneArgs {
|
||||
name: b.name.clone(),
|
||||
repo: b.repo.clone(),
|
||||
branch: b.branch.clone(),
|
||||
on_clone: b.on_clone.clone(),
|
||||
github_account: b.github_account.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn clone_repo(
|
||||
clone_args: impl Into<CloneArgs>,
|
||||
repo_dir: &str,
|
||||
access_token: Option<GithubToken>,
|
||||
) -> anyhow::Result<Vec<Log>> {
|
||||
let CloneArgs {
|
||||
name,
|
||||
repo,
|
||||
branch,
|
||||
on_clone,
|
||||
..
|
||||
}: &Build,
|
||||
destination: &str,
|
||||
access_token: Option<GithubToken>,
|
||||
) -> anyhow::Result<Vec<Log>> {
|
||||
} = clone_args.into();
|
||||
let repo = repo.as_ref().ok_or(anyhow!("build has no repo attached"))?;
|
||||
let clone_log = clone(repo, destination, branch, access_token).await;
|
||||
let mut repo_dir = PathBuf::from_str(repo_dir)?;
|
||||
repo_dir.push(name);
|
||||
let destination = repo_dir.display().to_string();
|
||||
let clone_log = clone(repo, &destination, &branch, access_token).await;
|
||||
let mut logs = vec![clone_log];
|
||||
if let Some(command) = on_clone {
|
||||
let mut path = PathBuf::from_str(destination)
|
||||
.context("failed to parse destination path to pathbuf")?;
|
||||
path.push(&command.path);
|
||||
repo_dir.push(&command.path);
|
||||
let on_clone_log = run_monitor_command(
|
||||
"on clone",
|
||||
format!("cd {} && {}", path.display(), command.command),
|
||||
)
|
||||
.await;
|
||||
logs.push(on_clone_log);
|
||||
}
|
||||
Ok(logs)
|
||||
}
|
||||
|
||||
pub async fn clone_deployment_repo(
|
||||
Deployment {
|
||||
repo,
|
||||
branch,
|
||||
on_clone,
|
||||
..
|
||||
}: &Deployment,
|
||||
destination: &str,
|
||||
access_token: Option<GithubToken>,
|
||||
) -> anyhow::Result<Vec<Log>> {
|
||||
let repo = repo.as_ref().ok_or(anyhow!("build has no repo attached"))?;
|
||||
let clone_log = clone(repo, destination, branch, access_token).await;
|
||||
let mut logs = vec![clone_log];
|
||||
if let Some(command) = on_clone {
|
||||
let mut path = PathBuf::from_str(destination)
|
||||
.context("failed to parse destination path to pathbuf")?;
|
||||
path.push(&command.path);
|
||||
let on_clone_log = run_monitor_command(
|
||||
"on clone",
|
||||
format!("cd {} && {}", path.display(), command.command),
|
||||
format!("cd {} && {}", repo_dir.display(), command.command),
|
||||
)
|
||||
.await;
|
||||
logs.push(on_clone_log);
|
||||
|
||||
@@ -7,6 +7,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
types = { path = "../types" }
|
||||
helpers = { path = "../helpers" }
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
|
||||
58
lib/periphery_client/src/container.rs
Normal file
58
lib/periphery_client/src/container.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
use serde_json::json;
|
||||
use types::{BasicContainerInfo, Deployment, Log, Server};
|
||||
|
||||
use crate::PeripheryClient;
|
||||
|
||||
impl PeripheryClient {
|
||||
pub async fn container_list(&self, server: &Server) -> anyhow::Result<Vec<BasicContainerInfo>> {
|
||||
self.get_json(server, "/container/list").await
|
||||
}
|
||||
|
||||
pub async fn container_start(
|
||||
&self,
|
||||
server: &Server,
|
||||
container_name: &str,
|
||||
) -> anyhow::Result<Log> {
|
||||
self.post_json(
|
||||
server,
|
||||
&format!("/container/start"),
|
||||
&json!({ "name": container_name }),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn container_stop(
|
||||
&self,
|
||||
server: &Server,
|
||||
container_name: &str,
|
||||
) -> anyhow::Result<Log> {
|
||||
self.post_json(
|
||||
server,
|
||||
&format!("/container/stop"),
|
||||
&json!({ "name": container_name }),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn container_remove(
|
||||
&self,
|
||||
server: &Server,
|
||||
container_name: &str,
|
||||
) -> anyhow::Result<Log> {
|
||||
self.post_json(
|
||||
server,
|
||||
&format!("/container/remove"),
|
||||
&json!({ "name": container_name }),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn deploy(&self, server: &Server, deployment: &Deployment) -> anyhow::Result<Log> {
|
||||
self.post_json(server, &format!("/container/deploy"), deployment)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn container_prune(&self, server: &Server) -> anyhow::Result<Log> {
|
||||
self.post_json(server, "container/prune", &json!({})).await
|
||||
}
|
||||
}
|
||||
15
lib/periphery_client/src/git.rs
Normal file
15
lib/periphery_client/src/git.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
use helpers::git::CloneArgs;
|
||||
use types::{Log, Server};
|
||||
|
||||
use crate::PeripheryClient;
|
||||
|
||||
impl PeripheryClient {
|
||||
pub async fn clone(
|
||||
&self,
|
||||
server: &Server,
|
||||
clone_args: impl Into<CloneArgs>,
|
||||
) -> anyhow::Result<Vec<Log>> {
|
||||
let clone_args: CloneArgs = clone_args.into();
|
||||
self.post_json(server, "/git/clone", &clone_args).await
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
use anyhow::{anyhow, Context};
|
||||
use reqwest::StatusCode;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde_json::json;
|
||||
use types::{BasicContainerInfo, Deployment, Log, Server};
|
||||
use types::Server;
|
||||
|
||||
mod container;
|
||||
mod git;
|
||||
mod network;
|
||||
mod stats;
|
||||
|
||||
pub struct PeripheryClient {
|
||||
http_client: reqwest::Client,
|
||||
@@ -15,52 +19,12 @@ impl PeripheryClient {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn container_list(&self, server: &Server) -> anyhow::Result<Vec<BasicContainerInfo>> {
|
||||
self.get_json(server, "/container/list").await
|
||||
pub async fn get_github_accounts(&self, server: &Server) -> anyhow::Result<Vec<String>> {
|
||||
self.get_json(server, "/accounts/github").await
|
||||
}
|
||||
|
||||
pub async fn container_start(
|
||||
&self,
|
||||
server: &Server,
|
||||
container_name: &str,
|
||||
) -> anyhow::Result<Log> {
|
||||
self.post_json(
|
||||
server,
|
||||
&format!("/container/start"),
|
||||
&json!({ "name": container_name }),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn container_stop(
|
||||
&self,
|
||||
server: &Server,
|
||||
container_name: &str,
|
||||
) -> anyhow::Result<Log> {
|
||||
self.post_json(
|
||||
server,
|
||||
&format!("/container/stop"),
|
||||
&json!({ "name": container_name }),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn container_remove(
|
||||
&self,
|
||||
server: &Server,
|
||||
container_name: &str,
|
||||
) -> anyhow::Result<Log> {
|
||||
self.post_json(
|
||||
server,
|
||||
&format!("/container/remove"),
|
||||
&json!({ "name": container_name }),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn deploy(&self, server: &Server, deployment: &Deployment) -> anyhow::Result<Log> {
|
||||
self.post_json(server, &format!("/container/deploy"), deployment)
|
||||
.await
|
||||
pub async fn get_docker_accounts(&self, server: &Server) -> anyhow::Result<Vec<String>> {
|
||||
self.get_json(server, "/accounts/docker").await
|
||||
}
|
||||
|
||||
async fn get_json<R: DeserializeOwned>(
|
||||
|
||||
32
lib/periphery_client/src/network.rs
Normal file
32
lib/periphery_client/src/network.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use serde_json::json;
|
||||
use types::{Log, Server};
|
||||
|
||||
use crate::PeripheryClient;
|
||||
|
||||
impl PeripheryClient {
|
||||
pub async fn network_create(
|
||||
&self,
|
||||
server: &Server,
|
||||
name: &str,
|
||||
driver: Option<String>,
|
||||
) -> anyhow::Result<Log> {
|
||||
self.post_json(
|
||||
server,
|
||||
"/network/create",
|
||||
&json!({
|
||||
"name": name,
|
||||
"driver": driver
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn network_delete(&self, server: &Server, name: &str) -> anyhow::Result<Log> {
|
||||
self.post_json(server, "/network/delete", &json!({ "name": name }))
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn network_prune(&self, server: &Server) -> anyhow::Result<Log> {
|
||||
self.post_json(server, "/network/prune", &json!({})).await
|
||||
}
|
||||
}
|
||||
13
lib/periphery_client/src/stats.rs
Normal file
13
lib/periphery_client/src/stats.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
use types::{Server, SystemStats};
|
||||
|
||||
use crate::PeripheryClient;
|
||||
|
||||
impl PeripheryClient {
|
||||
pub async fn get_system_stats(&self, server: &Server) -> anyhow::Result<SystemStats> {
|
||||
self.get_json(server, "/stats/system").await
|
||||
}
|
||||
|
||||
pub async fn get_docker_stats(&self, server: &Server) -> anyhow::Result<SystemStats> {
|
||||
self.get_json(server, "/stats/docker").await
|
||||
}
|
||||
}
|
||||
@@ -301,12 +301,18 @@ pub struct PeripheryConfig {
|
||||
pub docker_accounts: DockerAccounts,
|
||||
#[serde(default)]
|
||||
pub github_accounts: GithubAccounts,
|
||||
#[serde(default = "default_repo_dir")]
|
||||
pub repo_dir: String,
|
||||
}
|
||||
|
||||
fn default_periphery_port() -> u16 {
|
||||
9001
|
||||
}
|
||||
|
||||
fn default_repo_dir() -> String {
|
||||
"/repos".to_string()
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct UserCredentials {
|
||||
pub username: String,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
port = 9001 # optional.
|
||||
is_builder = false
|
||||
port = 9001 # optional. 9001 is default
|
||||
is_builder = false # optional. false is default
|
||||
repo_dir = "/repos" # optional. /repos is default
|
||||
|
||||
[github_accounts]
|
||||
[github_accounts] # optional
|
||||
github_username1 = "github_token1"
|
||||
github_username2 = "github_token2"
|
||||
|
||||
[docker_accounts]
|
||||
[docker_accounts] # optional
|
||||
docker_username1 = "docker_token1"
|
||||
docker_username2 = "docker_token2"
|
||||
@@ -1,5 +1,42 @@
|
||||
use axum::Router;
|
||||
use anyhow::anyhow;
|
||||
use axum::{routing::post, Extension, Json, Router};
|
||||
use helpers::{
|
||||
git::{self, CloneArgs},
|
||||
handle_anyhow_error,
|
||||
};
|
||||
use types::{Build, Deployment, GithubToken, Log, PeripheryConfig};
|
||||
|
||||
use crate::PeripheryConfigExtension;
|
||||
|
||||
pub fn router() -> Router {
|
||||
Router::new()
|
||||
Router::new().route(
|
||||
"/clone",
|
||||
post(|config, clone_args| async move {
|
||||
clone(config, clone_args).await.map_err(handle_anyhow_error)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
async fn clone(
|
||||
Extension(config): PeripheryConfigExtension,
|
||||
Json(clone_args): Json<CloneArgs>,
|
||||
) -> anyhow::Result<Json<Vec<Log>>> {
|
||||
let access_token = get_github_token(&clone_args.github_account, &config)?;
|
||||
let logs = git::clone_repo(clone_args, &config.repo_dir, access_token).await?;
|
||||
Ok(Json(logs))
|
||||
}
|
||||
|
||||
fn get_github_token(
|
||||
github_account: &Option<String>,
|
||||
config: &PeripheryConfig,
|
||||
) -> anyhow::Result<Option<GithubToken>> {
|
||||
match github_account {
|
||||
Some(account) => match config.github_accounts.get(account) {
|
||||
Some(token) => Ok(Some(token.to_owned())),
|
||||
None => Err(anyhow!(
|
||||
"did not find token in config for github account {account} "
|
||||
)),
|
||||
},
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user