diff --git a/core/src/actions/build.rs b/core/src/actions/build.rs index 4bbb8773a..c767ba500 100644 --- a/core/src/actions/build.rs +++ b/core/src/actions/build.rs @@ -1,6 +1,7 @@ use anyhow::{anyhow, Context}; use async_timing_util::unix_timestamp_ms; use diff::Diff; +use helpers::to_monitor_name; use mungos::{doc, to_bson}; use types::{ traits::Permissioned, Build, Log, Operation, PermissionLevel, Update, UpdateStatus, @@ -33,14 +34,14 @@ impl State { pub async fn create_build( &self, - name: String, + name: &str, server_id: String, user: &RequestUser, ) -> anyhow::Result { self.get_server_check_permissions(&server_id, user, PermissionLevel::Write) .await?; let build = Build { - name, + name: to_monitor_name(name), server_id, permissions: [(user.id.clone(), PermissionLevel::Write)] .into_iter() @@ -148,10 +149,12 @@ impl State { Ok(new_build) } - pub async fn build_build(&self, build_id: &str, user: &RequestUser) -> anyhow::Result { + pub async fn build(&self, build_id: &str, user: &RequestUser) -> anyhow::Result { let mut build = self .get_build_check_permissions(build_id, user, PermissionLevel::Write) .await?; + let server = self.db.get_server(&build.server_id).await?; + build.version.increment(); let mut update = Update { @@ -167,15 +170,13 @@ impl State { update.id = self.add_update(update.clone()).await?; - let server = self.db.get_server(&build.server_id).await?; - - let update_logs = self + let build_logs = self .periphery .build(&server, &build) .await .context("failed at call to periphery to build")?; - match update_logs { + match build_logs { Some(logs) => { update.logs.extend(logs); update.success = all_logs_success(&update.logs); diff --git a/core/src/actions/deployment.rs b/core/src/actions/deployment.rs index 5329fcc7e..e0a282b96 100644 --- a/core/src/actions/deployment.rs +++ b/core/src/actions/deployment.rs @@ -1,6 +1,7 @@ use anyhow::{anyhow, Context}; use async_timing_util::unix_timestamp_ms; use diff::Diff; +use helpers::to_monitor_name; use types::{ traits::Permissioned, Deployment, Log, Operation, PermissionLevel, Update, UpdateStatus, UpdateTarget, @@ -32,14 +33,14 @@ impl State { pub async fn create_deployment( &self, - name: String, + name: &str, server_id: String, user: &RequestUser, ) -> anyhow::Result { self.get_server_check_permissions(&server_id, user, PermissionLevel::Write) .await?; let deployment = Deployment { - name, + name: to_monitor_name(name), server_id, permissions: [(user.id.clone(), PermissionLevel::Write)] .into_iter() @@ -159,6 +160,46 @@ impl State { Ok(new_deployment) } + pub async fn deploy(&self, deployment_id: &str, user: &RequestUser) -> anyhow::Result { + let mut deployment = self + .get_deployment_check_permissions(deployment_id, user, PermissionLevel::Write) + .await?; + if let Some(build_id) = &deployment.build_id { + let build = self.db.get_build(build_id).await?; + deployment.docker_run_args.image = if let Some(docker_account) = &build.docker_account { + if deployment.docker_run_args.docker_account.is_none() { + deployment.docker_run_args.docker_account = Some(docker_account.to_string()) + } + format!("{docker_account}/{}", to_monitor_name(&build.name)) + } else { + to_monitor_name(&build.name) + }; + }; + let server = self.db.get_server(&deployment.server_id).await?; + let mut update = Update { + target: UpdateTarget::Deployment(deployment_id.to_string()), + operation: Operation::DeployDeployment, + start_ts: unix_timestamp_ms() as i64, + status: UpdateStatus::InProgress, + operator: user.id.clone(), + success: true, + // version: deployment.docker_run_args., + ..Default::default() + }; + + update.id = self.add_update(update.clone()).await?; + + let deploy_log = self.periphery.deploy(&server, &deployment).await?; + + update.logs.push(deploy_log); + update.status = UpdateStatus::Complete; + update.end_ts = Some(unix_timestamp_ms() as i64); + + self.update_update(update.clone()).await?; + + Ok(update) + } + pub async fn reclone_deployment( &self, deployment_id: &str, diff --git a/core/src/actions/server.rs b/core/src/actions/server.rs index b0bb55399..3f4e31a7a 100644 --- a/core/src/actions/server.rs +++ b/core/src/actions/server.rs @@ -1,6 +1,7 @@ use anyhow::{anyhow, Context}; use async_timing_util::unix_timestamp_ms; use diff::Diff; +use helpers::to_monitor_name; use types::{ traits::Permissioned, Log, Operation, PermissionLevel, Server, Update, UpdateStatus, UpdateTarget, @@ -28,7 +29,7 @@ impl State { pub async fn create_server( &self, - name: String, + name: &str, address: String, user: &RequestUser, ) -> anyhow::Result { @@ -38,7 +39,7 @@ impl State { )); } let server = Server { - name, + name: to_monitor_name(name), address, permissions: [(user.id.clone(), PermissionLevel::Write)] .into_iter() diff --git a/core/src/api/build.rs b/core/src/api/build.rs index 167ab2199..3167a87be 100644 --- a/core/src/api/build.rs +++ b/core/src/api/build.rs @@ -46,7 +46,7 @@ pub fn router() -> Router { Extension(user): RequestUserExtension, Json(build): Json| async move { let build = state - .create_build(build.name, build.server_id, &user) + .create_build(&build.name, build.server_id, &user) .await .map_err(handle_anyhow_error)?; response!(Json(build)) @@ -88,7 +88,7 @@ pub fn router() -> Router { Extension(user): RequestUserExtension, Path(build_id): Path| async move { let update = state - .build_build(&build_id.id, &user) + .build(&build_id.id, &user) .await .map_err(handle_anyhow_error)?; response!(Json(update)) diff --git a/core/src/api/deployment.rs b/core/src/api/deployment.rs index 5cf256a64..ae5d7d009 100644 --- a/core/src/api/deployment.rs +++ b/core/src/api/deployment.rs @@ -46,7 +46,7 @@ pub fn router() -> Router { Extension(user): RequestUserExtension, Json(deployment): Json| async move { let deployment = state - .create_deployment(deployment.name, deployment.server_id, &user) + .create_deployment(&deployment.name, deployment.server_id, &user) .await .map_err(handle_anyhow_error)?; response!(Json(deployment)) @@ -81,6 +81,20 @@ pub fn router() -> Router { }, ), ) + .route( + "/deploy/:id", + post( + |Extension(state): StateExtension, + Extension(user): RequestUserExtension, + Path(deployment_id): Path| async move { + let update = state + .deploy(&deployment_id.id, &user) + .await + .map_err(handle_anyhow_error)?; + response!(Json(update)) + }, + ), + ) .route( "/reclone/:id", post( diff --git a/core/src/api/server.rs b/core/src/api/server.rs index fa9758865..06315564c 100644 --- a/core/src/api/server.rs +++ b/core/src/api/server.rs @@ -46,7 +46,7 @@ pub fn router() -> Router { Extension(user): RequestUserExtension, Json(server): Json| async move { let server = state - .create_server(server.name, server.address, &user) + .create_server(&server.name, server.address, &user) .await .map_err(handle_anyhow_error)?; response!(Json(server)) diff --git a/core/src/auth/jwt.rs b/core/src/auth/jwt.rs index b243ea290..98a1e0b47 100644 --- a/core/src/auth/jwt.rs +++ b/core/src/auth/jwt.rs @@ -3,13 +3,14 @@ use std::sync::Arc; use anyhow::{anyhow, Context}; use async_timing_util::{get_timelength_in_ms, unix_timestamp_ms}; use axum::{body::Body, http::Request, Extension}; -use db::DbClient; use hmac::{Hmac, Mac}; use jwt::{SignWithKey, VerifyWithKey}; use mungos::{Deserialize, Serialize}; use sha2::Sha256; use types::{CoreConfig, UserId}; +use crate::state::State; + pub type JwtExtension = Extension>; pub type RequestUserExtension = Extension>; @@ -66,23 +67,24 @@ impl JwtClient { .to_str()? .replace("Bearer ", "") .replace("bearer ", ""); - let db_client = req + let state = req .extensions() - .get::>() - .ok_or(anyhow!("failed at getting db handle"))?; + .get::>() + .ok_or(anyhow!("failed at getting state handle"))?; let user = self - .auth_jwt(&jwt, db_client) + .auth_jwt(&jwt, &state) .await .context("failed to authenticate jwt")?; Ok(Arc::new(user)) } - pub async fn auth_jwt(&self, jwt: &str, db_client: &DbClient) -> anyhow::Result { + pub async fn auth_jwt(&self, jwt: &str, state: &State) -> anyhow::Result { let claims: JwtClaims = jwt .verify_with_key(&self.key) .context("failed to verify claims")?; if claims.exp > unix_timestamp_ms() { - let user = db_client + let user = state + .db .users .find_one_by_id(&claims.id) .await? diff --git a/core/src/auth/mod.rs b/core/src/auth/mod.rs index 508672cd6..5c054321d 100644 --- a/core/src/auth/mod.rs +++ b/core/src/auth/mod.rs @@ -34,7 +34,7 @@ pub async fn auth_request( let user = jwt_client .authenticate(&req) .await - .map_err(|e| (StatusCode::UNAUTHORIZED, format!("error: {e:#?}")))?; + .map_err(|e| (StatusCode::UNAUTHORIZED, format!("{e:#?}")))?; req.extensions_mut().insert(user); Ok(next.run(req).await) } diff --git a/core/src/ws/update.rs b/core/src/ws/update.rs index 98f77fd0b..0669a2398 100644 --- a/core/src/ws/update.rs +++ b/core/src/ws/update.rs @@ -25,7 +25,7 @@ use types::{PermissionLevel, Update, UpdateTarget, User}; use crate::{ auth::{JwtClient, JwtExtension}, - state::StateExtension, + state::{State, StateExtension}, }; pub type UpdateWsSender = Mutex>; @@ -84,7 +84,7 @@ pub async fn ws_handler( ) -> impl IntoResponse { let mut reciever = state.update.reciever.clone(); ws.on_upgrade(|socket| async move { - let login_res = login(socket, &jwt_client, &state.db).await; + let login_res = login(socket, &jwt_client, &state).await; if login_res.is_none() { return; } @@ -151,12 +151,12 @@ pub async fn ws_handler( async fn login( mut socket: WebSocket, jwt_client: &JwtClient, - db_client: &DbClient, + state: &State, ) -> Option<(WebSocket, String)> { if let Some(jwt) = socket.recv().await { match jwt { Ok(jwt) => match jwt { - Message::Text(jwt) => match jwt_client.auth_jwt(&jwt, db_client).await { + Message::Text(jwt) => match jwt_client.auth_jwt(&jwt, state).await { Ok(user) => { let _ = socket .send(Message::Text( diff --git a/lib/helpers/src/docker/build.rs b/lib/helpers/src/docker/build.rs index 019dbae0e..ccbfe0d68 100644 --- a/lib/helpers/src/docker/build.rs +++ b/lib/helpers/src/docker/build.rs @@ -1,11 +1,12 @@ use std::{path::PathBuf, str::FromStr}; use anyhow::{anyhow, Context}; -use run_command::async_run_command; use types::{Build, DockerBuildArgs, Log, Version}; use crate::{git, run_monitor_command, to_monitor_name}; +use super::docker_login; + pub async fn prune_images() -> Log { let command = format!("docker image prune -a -f"); run_monitor_command("prune images", command).await @@ -32,7 +33,9 @@ pub async fn build( .as_ref() .ok_or(anyhow!("build missing docker build args"))?; let name = to_monitor_name(name); - let docker_account_pw = get_docker_username_pw(docker_account, &docker_token)?; + let using_account = docker_login(docker_account, &docker_token) + .await + .context("failed to login to docker")?; let repo_dir = PathBuf::from_str(repo_dir) .context(format!("invalid repo dir: {repo_dir}"))? .join(&name); @@ -54,10 +57,6 @@ pub async fn build( .await; logs.push(pre_build_log); } - if let Some((username, password)) = &docker_account_pw { - let login = format!("docker login -u {username} -p {password}"); - async_run_command(&login).await; - } let build_dir = repo_dir.join(build_path); let cd = build_dir.display(); let dockerfile_path = match dockerfile_path { @@ -66,7 +65,7 @@ pub async fn build( }; let image_name = get_image_name(docker_account, &name); let image_tags = image_tags(&image_name, &version); - let docker_push = if docker_account_pw.is_some() { + let docker_push = if using_account { format!(" && docker image push --all-tags {image_name}") } else { String::new() @@ -78,21 +77,6 @@ pub async fn build( Ok(logs) } -fn get_docker_username_pw( - docker_account: &Option, - docker_token: &Option, -) -> anyhow::Result> { - match docker_account { - Some(docker_account) => match docker_token { - Some(docker_token) => Ok(Some((docker_account.to_owned(), docker_token.to_owned()))), - None => Err(anyhow!( - "docker token for account {docker_account} has not been configured on this client" - )), - }, - None => Ok(None), - } -} - fn get_image_name(docker_account: &Option, name: &str) -> String { match docker_account { Some(docker_account) => format!("{docker_account}/{name}"), diff --git a/lib/helpers/src/docker/container.rs b/lib/helpers/src/docker/container.rs index 7bc43930c..df51eaada 100644 --- a/lib/helpers/src/docker/container.rs +++ b/lib/helpers/src/docker/container.rs @@ -6,6 +6,8 @@ use types::{ use crate::{run_monitor_command, to_monitor_name}; +use super::docker_login; + pub async fn container_log(container_name: &str, tail: Option) -> Log { let tail = match tail { Some(tail) => format!(" --tail {tail}"), @@ -65,7 +67,10 @@ pub async fn stop_and_remove_container(container_name: &str) -> Log { run_monitor_command("docker stop and remove", command).await } -pub async fn deploy(deployment: &Deployment) -> Log { +pub async fn deploy(deployment: &Deployment, docker_token: &Option) -> Log { + if let Err(e) = docker_login(&deployment.docker_run_args.docker_account, docker_token).await { + return Log::error("docker login", format!("{e:#?}")); + } let _ = stop_and_remove_container(&to_monitor_name(&deployment.name)).await; let command = docker_run_command(deployment); run_monitor_command("docker run", command).await @@ -134,7 +139,7 @@ fn parse_network(network: &Option) -> String { fn parse_restart(restart: &RestartMode) -> String { let restart = match restart { - RestartMode::OnFailure => format!("on-failure:10"), + RestartMode::OnFailure => "on-failure:10".to_string(), _ => restart.to_string(), }; format!(" --restart {restart}") diff --git a/lib/helpers/src/docker/mod.rs b/lib/helpers/src/docker/mod.rs index 13dd9c87a..74e42c3ce 100644 --- a/lib/helpers/src/docker/mod.rs +++ b/lib/helpers/src/docker/mod.rs @@ -3,7 +3,38 @@ mod client; mod container; mod network; +use anyhow::anyhow; pub use build::*; pub use client::*; pub use container::*; pub use network::*; +use run_command::async_run_command; + +pub fn get_docker_username_pw( + docker_account: &Option, + docker_token: &Option, +) -> anyhow::Result> { + match docker_account { + Some(docker_account) => match docker_token { + Some(docker_token) => Ok(Some((docker_account.to_owned(), docker_token.to_owned()))), + None => Err(anyhow!( + "docker token for account {docker_account} has not been configured on this client" + )), + }, + None => Ok(None), + } +} + +pub async fn docker_login( + docker_account: &Option, + docker_token: &Option, +) -> anyhow::Result { + let docker_account_u_pw = get_docker_username_pw(docker_account, docker_token)?; + if let Some((username, password)) = &docker_account_u_pw { + let login = format!("docker login -u {username} -p {password}"); + async_run_command(&login).await; + Ok(true) + } else { + Ok(false) + } +} diff --git a/lib/monitor_client/src/build.rs b/lib/monitor_client/src/build.rs index 3f8e89e6d..98bcf1a71 100644 --- a/lib/monitor_client/src/build.rs +++ b/lib/monitor_client/src/build.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use monitor_types::{Build, SystemStats, Update}; use serde_json::json; @@ -5,7 +6,9 @@ use crate::MonitorClient; impl MonitorClient { pub async fn list_builds(&self) -> anyhow::Result> { - self.get("/api/build/list").await + self.get("/api/build/list") + .await + .context("failed at list builds") } pub async fn create_build(&self, name: &str, server_id: &str) -> anyhow::Result { @@ -14,24 +17,32 @@ impl MonitorClient { json!({ "name": name, "server_id": server_id }), ) .await + .context(format!( + "failed at creating build with name {name} on server id {server_id}" + )) } pub async fn delete_build(&self, id: &str) -> anyhow::Result { self.delete::<(), _>(&format!("/api/build/delete/{id}"), None) .await + .context(format!("failed at deleting build {id}")) } pub async fn update_build(&self, build: Build) -> anyhow::Result { - self.patch("/api/build/update", build).await + self.patch("/api/build/update", build) + .await + .context("failed at updating build") } - pub async fn build_build(&self, id: &str) -> anyhow::Result { - self.post::<(), _>(&format!("/api/build/build/{id}"), None) + pub async fn build(&self, build_id: &str) -> anyhow::Result { + self.post::<(), _>(&format!("/api/build/build/{build_id}"), None) .await + .context(format!("failed at building build {build_id}")) } pub async fn reclone_build(&self, id: &str) -> anyhow::Result { self.post::<(), _>(&format!("/api/build/reclone/{id}"), None) .await + .context(format!("failed at recloning build {id}")) } } diff --git a/lib/monitor_client/src/deployment.rs b/lib/monitor_client/src/deployment.rs index 8a914aec5..f6013eb7e 100644 --- a/lib/monitor_client/src/deployment.rs +++ b/lib/monitor_client/src/deployment.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use monitor_types::{Deployment, SystemStats, Update}; use serde_json::json; @@ -5,7 +6,9 @@ use crate::MonitorClient; impl MonitorClient { pub async fn list_deployments(&self) -> anyhow::Result> { - self.get("/api/deployment/list").await + self.get("/api/deployment/list") + .await + .context("failed at list deployments") } pub async fn create_deployment( @@ -18,19 +21,32 @@ impl MonitorClient { json!({ "name": name, "server_id": server_id }), ) .await + .context(format!( + "failed at create_deployment with name {name} and server id {server_id}" + )) } pub async fn delete_deployment(&self, id: &str) -> anyhow::Result { self.delete::<(), _>(&format!("/api/deployment/delete/{id}"), None) .await + .context(format!("failed at deleting deployment {id}")) } pub async fn update_deployment(&self, deployment: Deployment) -> anyhow::Result { - self.patch("/api/deployment/update", deployment).await + self.patch("/api/deployment/update", deployment) + .await + .context("failed at updating deployment") + } + + pub async fn deploy(&self, deployment_id: &str) -> anyhow::Result { + self.post::<(), _>(&format!("/api/deployment/deploy/{deployment_id}"), None) + .await + .context(format!("failed at deploy deployment {deployment_id}")) } pub async fn reclone_deployment(&self, id: &str) -> anyhow::Result { self.post::<(), _>(&format!("/api/deployment/reclone/{id}"), None) .await + .context(format!("failed at reclone deployment {id}")) } } diff --git a/lib/monitor_client/src/server.rs b/lib/monitor_client/src/server.rs index c7aa270cb..a06bfee42 100644 --- a/lib/monitor_client/src/server.rs +++ b/lib/monitor_client/src/server.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use monitor_types::{Server, SystemStats}; use serde_json::json; @@ -5,7 +6,9 @@ use crate::MonitorClient; impl MonitorClient { pub async fn list_servers(&self) -> anyhow::Result> { - self.get("/api/server/list").await + self.get("/api/server/list") + .await + .context("failed at list servers") } pub async fn create_server(&self, name: &str, address: &str) -> anyhow::Result { @@ -14,18 +17,26 @@ impl MonitorClient { json!({ "name": name, "address": address }), ) .await + .context(format!( + "failed at creating server with name {name} at address {address}" + )) } pub async fn delete_server(&self, id: &str) -> anyhow::Result { self.delete::<(), _>(&format!("/api/server/delete/{id}"), None) .await + .context(format!("failed at delete server {id}")) } pub async fn update_server(&self, server: Server) -> anyhow::Result { - self.patch("/api/server/update", server).await + self.patch("/api/server/update", server) + .await + .context("failed at update server") } pub async fn get_server_stats(&self, id: &str) -> anyhow::Result { - self.get(&format!("/api/server/stats/{id}")).await + self.get(&format!("/api/server/stats/{id}")) + .await + .context(format!("failed to get server stats at id {id}")) } } diff --git a/lib/types/src/lib.rs b/lib/types/src/lib.rs index 64b1c9d2c..3d3eae22d 100644 --- a/lib/types/src/lib.rs +++ b/lib/types/src/lib.rs @@ -188,6 +188,10 @@ pub struct Deployment { #[diff(attr(#[serde(skip_serializing_if = "option_diff_no_change")]))] pub build_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[diff(attr(#[serde(skip_serializing_if = "option_diff_no_change")]))] + pub build_version: Option, + // deployment repo related #[serde(skip_serializing_if = "Option::is_none")] #[diff(attr(#[serde(skip_serializing_if = "option_diff_no_change")]))] @@ -692,12 +696,16 @@ pub enum DockerContainerState { #[diff(attr(#[derive(Debug, PartialEq, Serialize)]))] pub enum RestartMode { #[serde(rename = "no")] + #[strum(serialize = "no")] NoRestart, #[serde(rename = "on-failure")] + #[strum(serialize = "on-failure")] OnFailure, #[serde(rename = "always")] + #[strum(serialize = "always")] Always, #[serde(rename = "unless-stopped")] + #[strum(serialize = "unless-stopped")] UnlessStopped, } diff --git a/periphery/src/api/build.rs b/periphery/src/api/build.rs index 33700f5fa..efa4402e8 100644 --- a/periphery/src/api/build.rs +++ b/periphery/src/api/build.rs @@ -4,9 +4,9 @@ use anyhow::anyhow; use axum::{routing::post, Extension, Json, Router}; use helpers::{docker, handle_anyhow_error}; use tokio::sync::Mutex; -use types::{Build, DockerToken, Log, PeripheryConfig, PERIPHERY_BUILDER_BUSY}; +use types::{Build, Log, PERIPHERY_BUILDER_BUSY}; -use crate::PeripheryConfigExtension; +use crate::{helpers::get_docker_token, PeripheryConfigExtension}; type BusyExtension = Extension>>; @@ -46,18 +46,3 @@ async fn build_image( *lock = false; Ok(Json(logs)) } - -fn get_docker_token( - docker_account: &Option, - config: &PeripheryConfig, -) -> anyhow::Result> { - match docker_account { - Some(account) => match config.docker_accounts.get(account) { - Some(token) => Ok(Some(token.to_owned())), - None => Err(anyhow!( - "did not find token in config for docker account {account} " - )), - }, - None => Ok(None), - } -} diff --git a/periphery/src/api/container.rs b/periphery/src/api/container.rs index 0f29dd7e2..762e87094 100644 --- a/periphery/src/api/container.rs +++ b/periphery/src/api/container.rs @@ -9,9 +9,9 @@ use helpers::{ handle_anyhow_error, to_monitor_name, }; use serde::Deserialize; -use types::Deployment; +use types::{Deployment, Log}; -use crate::response; +use crate::{helpers::get_docker_token, response, PeripheryConfigExtension}; #[derive(Deserialize)] struct Container { @@ -66,39 +66,21 @@ pub fn router() -> Router { Json(docker::stop_and_remove_container(&to_monitor_name(&container.name)).await) }), ) - .route( - "/deploy", - post(|Json(deployment): Json| async move { - Json(docker::deploy(&deployment).await) - }), - ) + .route("/deploy", post(deploy)) .route( "/prune", post(|| async { Json(docker::prune_containers().await) }), ) - // .route( - // "/stats/:name", - // get( - // |Extension(dc): DockerExtension, Path(Container { name }): Path| async move { - // let stats = dc - // .get_container_stats(&name) - // .await - // .map_err(handle_anyhow_error)?; - // response!(Json(stats)) - // }, - // ), - // ) - // .route( - // "/stats/list", - // get( - // |Extension(dc): DockerExtension| async move { - // let stats_list = dc - // .get_container_stats_list() - // .await - // .map_err(handle_anyhow_error)?; - // response!(Json(stats_list)) - // }, - // ), - // ) .layer(DockerClient::extension()) } + +async fn deploy( + Extension(config): PeripheryConfigExtension, + Json(deployment): Json, +) -> Json { + let log = match get_docker_token(&deployment.docker_run_args.docker_account, &config) { + Ok(docker_token) => docker::deploy(&deployment, &docker_token).await, + Err(e) => Log::error("docker login", format!("{e:#?}")), + }; + Json(log) +} diff --git a/periphery/src/api/git.rs b/periphery/src/api/git.rs index 74251500b..7f1bd1f9b 100644 --- a/periphery/src/api/git.rs +++ b/periphery/src/api/git.rs @@ -1,15 +1,14 @@ use std::{path::PathBuf, str::FromStr}; -use anyhow::anyhow; use axum::{routing::post, Extension, Json, Router}; use helpers::{ git::{self, CloneArgs}, handle_anyhow_error, to_monitor_name, }; use serde::Deserialize; -use types::{GithubToken, Log, PeripheryConfig}; +use types::Log; -use crate::PeripheryConfigExtension; +use crate::{helpers::get_github_token, PeripheryConfigExtension}; #[derive(Deserialize)] pub struct DeleteRepoBody { @@ -58,18 +57,3 @@ async fn delete_repo( }; Ok(Json(log)) } - -fn get_github_token( - github_account: &Option, - config: &PeripheryConfig, -) -> anyhow::Result> { - 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), - } -} diff --git a/periphery/src/helpers.rs b/periphery/src/helpers.rs index 9fadd9b54..24fd5c5f2 100644 --- a/periphery/src/helpers.rs +++ b/periphery/src/helpers.rs @@ -1,6 +1,39 @@ +use anyhow::anyhow; +use types::{DockerToken, GithubToken, PeripheryConfig}; + #[macro_export] macro_rules! response { ($x:expr) => { Ok::<_, (axum::http::StatusCode, String)>($x) }; } + +pub fn get_github_token( + github_account: &Option, + config: &PeripheryConfig, +) -> anyhow::Result> { + 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), + } +} + +pub fn get_docker_token( + docker_account: &Option, + config: &PeripheryConfig, +) -> anyhow::Result> { + match docker_account { + Some(account) => match config.docker_accounts.get(account) { + Some(token) => Ok(Some(token.to_owned())), + None => Err(anyhow!( + "did not find token in config for docker account {account} " + )), + }, + None => Ok(None), + } +} diff --git a/tests/src/main.rs b/tests/src/main.rs index a421b067e..54e1e7c28 100644 --- a/tests/src/main.rs +++ b/tests/src/main.rs @@ -17,10 +17,10 @@ async fn main() -> anyhow::Result<()> { let start_ts = unix_timestamp_ms(); - let mut builds = monitor.list_builds().await?; - let mut build = builds.pop().unwrap(); + // let mut builds = monitor.list_builds().await?; + // let mut build = builds.pop().unwrap(); - println!("{build:#?}"); + // println!("{build:#?}"); // build.name = format!("{}_1", build.name); // build.repo = Some("mbecker20/monitor".to_string()); @@ -28,9 +28,9 @@ async fn main() -> anyhow::Result<()> { // let build = monitor.update_build(build).await?; - let update = monitor.reclone_build(&build.id).await?; + // let update = monitor.reclone_build(&build.id).await?; - println!("{update:#?}"); + // println!("{update:#?}"); // let mut deployments = monitor.list_deployments().await?; // let mut deployment = deployments.pop().unwrap(); @@ -44,6 +44,9 @@ async fn main() -> anyhow::Result<()> { // println!("{deployment:#?}"); + let update = deploy_mongo(&monitor).await?; + println!("{update:#?}"); + let end_ts = unix_timestamp_ms(); let finished_in = (end_ts - start_ts) as f64 / 1000.0; println!("\nfinished in {finished_in} s"); diff --git a/tests/src/tests.rs b/tests/src/tests.rs index 29b466dd2..32233fed8 100644 --- a/tests/src/tests.rs +++ b/tests/src/tests.rs @@ -1,6 +1,6 @@ use anyhow::{anyhow, Context}; use monitor_client::{ - types::{Build, Deployment, Server, SystemStats}, + types::{Build, Conversion, Deployment, Server, SystemStats, Update}, MonitorClient, }; @@ -35,3 +35,23 @@ pub async fn get_server_stats(monitor: &MonitorClient) -> anyhow::Result anyhow::Result { + let servers = monitor + .list_servers() + .await + .context("failed at list servers")?; + let server = servers.get(0).ok_or(anyhow!("no servers"))?; + println!("got server"); + let mut deployment = monitor.create_deployment("mongo_test", &server.id).await?; + println!("created deployment"); + deployment.docker_run_args.image = "mongo".to_string(); + deployment.docker_run_args.ports.push(Conversion { + local: "27020".to_string(), + container: "27017".to_string(), + }); + let deployment = monitor.update_deployment(deployment).await?; + println!("updated deployment"); + let update = monitor.deploy(&deployment.id).await?; + Ok(update) +}