fmt. copy deployment / build

This commit is contained in:
mbecker20
2023-06-30 05:29:15 +00:00
parent d66c5ed618
commit fe6c371a9f
17 changed files with 243 additions and 53 deletions
+8 -4
View File
@@ -5,11 +5,12 @@ use monitor_types::{
busy::Busy,
entities::{
build::Build,
builder::Builder,
deployment::{Deployment, DockerContainerState},
server::{Server, ServerStatus},
update::Update,
user::User,
PermissionLevel, builder::Builder,
PermissionLevel,
},
permissioned::Permissioned,
};
@@ -114,7 +115,10 @@ impl State {
))
}
pub async fn get_deployment_state(&self, deployment: &Deployment) -> anyhow::Result<DockerContainerState> {
pub async fn get_deployment_state(
&self,
deployment: &Deployment,
) -> anyhow::Result<DockerContainerState> {
if deployment.config.server_id.is_empty() {
return Ok(DockerContainerState::NotDeployed);
}
@@ -133,7 +137,7 @@ impl State {
let state = match container {
Some(container) => container.state,
None => DockerContainerState::NotDeployed
None => DockerContainerState::NotDeployed,
};
Ok(state)
@@ -358,4 +362,4 @@ pub fn empty_or_only_spaces(word: &str) -> bool {
}
}
true
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ use monitor_types::entities::{
deployment::{BasicContainerInfo, Deployment, DockerContainerState},
server::{
stats::{
AllSystemStats, BasicSystemStats, CpuUsage, ServerHealth, SingleDiskUsage, StatsState,
AllSystemStats, BasicSystemStats, ServerHealth, SingleDiskUsage, StatsState,
SystemComponent,
},
Server, ServerConfig, ServerStatus,
+79 -4
View File
@@ -14,9 +14,7 @@ use monitor_types::{
},
monitor_timestamp,
permissioned::Permissioned,
requests::api::{
CreateBuild, DeleteBuild, Deploy, GetBuild, ListBuilds, RunBuild, UpdateBuild,
},
requests::api::*,
};
use mungos::mongodb::bson::{doc, to_bson};
use periphery_client::{
@@ -112,7 +110,84 @@ impl Resolve<CreateBuild, RequestUser> for State {
let build_id = self
.db
.builds
.create_one(&build)
.create_one(build)
.await
.context("failed to add build to db")?;
let build = self.get_build(&build_id).await?;
let update = Update {
target: UpdateTarget::Build(build_id),
operation: Operation::CreateBuild,
start_ts,
end_ts: Some(monitor_timestamp()),
operator: user.id.clone(),
success: true,
logs: vec![
Log::simple(
"create build",
format!("created build\nid: {}\nname: {}", build.id, build.name),
),
Log::simple("config", format!("{:#?}", build.config)),
],
..Default::default()
};
self.add_update(update).await?;
Ok(build)
}
}
#[async_trait]
impl Resolve<CopyBuild, RequestUser> for State {
async fn resolve(
&self,
CopyBuild { name, id }: CopyBuild,
user: RequestUser,
) -> anyhow::Result<Build> {
let Build {
config,
description,
..
} = self
.get_build_check_permissions(&id, &user, PermissionLevel::Update)
.await?;
match &config.builder {
BuildBuilderConfig::Server { server_id } => {
self.get_server_check_permissions(
server_id,
&user,
PermissionLevel::Update,
)
.await
.context("cannot create build on this server. user must have update permissions on the server.")?;
}
BuildBuilderConfig::Builder { builder_id } => {
self.get_builder_check_permissions(
builder_id,
&user,
PermissionLevel::Read,
)
.await
.context("cannot create build using this builder. user must have at least read permissions on the builder.")?;
}
}
let start_ts = monitor_timestamp();
let build = Build {
id: Default::default(),
name,
created_at: start_ts,
updated_at: start_ts,
last_built_at: 0,
permissions: [(user.id.clone(), PermissionLevel::Update)]
.into_iter()
.collect(),
description,
config,
};
let build_id = self
.db
.builds
.create_one(build)
.await
.context("failed to add build to db")?;
let build = self.get_build(&build_id).await?;
+82 -10
View File
@@ -10,10 +10,7 @@ use monitor_types::{
},
get_image_name, monitor_timestamp,
permissioned::Permissioned,
requests::api::{
CreateDeployment, DeleteDeployment, Deploy, GetDeployment, ListDeployments,
RemoveContainer, RenameDeployment, StartContainer, StopContainer, UpdateDeployment,
},
requests::api::*,
to_monitor_name,
};
use mungos::mongodb::bson::{doc, to_bson};
@@ -71,14 +68,18 @@ impl Resolve<CreateDeployment, RequestUser> for State {
user: RequestUser,
) -> anyhow::Result<Deployment> {
if let Some(server_id) = &config.server_id {
self.get_server_check_permissions(server_id, &user, PermissionLevel::Update)
.await
.context("cannot create deployment on this server. user must have update permissions on the server to perform this action.")?;
if !server_id.is_empty() {
self.get_server_check_permissions(server_id, &user, PermissionLevel::Update)
.await
.context("cannot create deployment on this server. user must have update permissions on the server to perform this action.")?;
}
}
if let Some(DeploymentImage::Build { build_id, .. }) = &config.image {
self.get_build_check_permissions(build_id, &user, PermissionLevel::Read)
.await
.context("cannot create deployment with this build attached. user must have at least read permissions on the build to perform this action.")?;
if !build_id.is_empty() {
self.get_build_check_permissions(build_id, &user, PermissionLevel::Read)
.await
.context("cannot create deployment with this build attached. user must have at least read permissions on the build to perform this action.")?;
}
}
let start_ts = monitor_timestamp();
let deployment = Deployment {
@@ -125,6 +126,77 @@ impl Resolve<CreateDeployment, RequestUser> for State {
}
}
#[async_trait]
impl Resolve<CopyDeployment, RequestUser> for State {
async fn resolve(
&self,
CopyDeployment { name, id }: CopyDeployment,
user: RequestUser,
) -> anyhow::Result<Deployment> {
let Deployment {
config,
description,
..
} = self
.get_deployment_check_permissions(&id, &user, PermissionLevel::Update)
.await?;
if !config.server_id.is_empty() {
self.get_server_check_permissions(&config.server_id, &user, PermissionLevel::Update)
.await
.context("cannot create deployment on this server. user must have update permissions on the server to perform this action.")?;
}
if let DeploymentImage::Build { build_id, .. } = &config.image {
if !build_id.is_empty() {
self.get_build_check_permissions(build_id, &user, PermissionLevel::Read)
.await
.context("cannot create deployment with this build attached. user must have at least read permissions on the build to perform this action.")?;
}
}
let start_ts = monitor_timestamp();
let deployment = Deployment {
id: Default::default(),
name,
created_at: start_ts,
updated_at: start_ts,
permissions: [(user.id.clone(), PermissionLevel::Update)]
.into_iter()
.collect(),
description,
config,
};
let deployment_id = self
.db
.deployments
.create_one(&deployment)
.await
.context("failed to add deployment to db")?;
let deployment = self.get_deployment(&deployment_id).await?;
let update = Update {
target: UpdateTarget::Deployment(deployment_id),
operation: Operation::CreateDeployment,
start_ts,
end_ts: Some(monitor_timestamp()),
operator: user.id.clone(),
success: true,
logs: vec![
Log::simple(
"create deployment",
format!(
"created deployment\nid: {}\nname: {}",
deployment.id, deployment.name
),
),
Log::simple("config", format!("{:#?}", deployment.config)),
],
..Default::default()
};
self.add_update(update).await?;
Ok(deployment)
}
}
#[async_trait]
impl Resolve<DeleteDeployment, RequestUser> for State {
async fn resolve(
+19 -11
View File
@@ -15,10 +15,10 @@ use crate::{
state::{State, StateExtension},
};
mod build;
mod deployment;
mod secret;
mod server;
mod build;
#[typeshare]
#[derive(Serialize, Deserialize, Debug, Clone, Resolver)]
@@ -70,7 +70,7 @@ pub enum ApiRequest {
// ==== DEPLOYMENT ====
//
GetDeployment(GetDeployment),
ListDeployments(ListDeployments),
ListDeployments(ListDeployments),
// CRUD
CreateDeployment(CreateDeployment),
DeleteDeployment(DeleteDeployment),
@@ -86,7 +86,7 @@ pub enum ApiRequest {
// ==== BUILD ====
//
GetBuild(GetBuild),
ListBuilds(ListBuilds),
ListBuilds(ListBuilds),
// CRUD
CreateBuild(CreateBuild),
DeleteBuild(DeleteBuild),
@@ -105,18 +105,26 @@ pub fn router() -> Router {
Json(request): Json<ApiRequest>| async move {
let timer = Instant::now();
let req_id = Uuid::new_v4();
info!("/auth request {req_id} | {request:?}");
let res = state
.resolve_request(request, user)
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")));
info!("/api request {req_id} | {request:?}");
let res = tokio::spawn(async move {
state
.resolve_request(request, user)
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")))
})
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")));
if let Err(e) = &res {
info!("/auth request {req_id} ERROR: {e:?}");
info!("/api request {req_id} SPAWN ERROR: {e:?}");
}
let res = res?;
if let Err(e) = &res {
info!("/api request {req_id} ERROR: {e:?}");
}
let res = res?;
let elapsed = timer.elapsed();
info!("/auth request {req_id} | resolve time: {elapsed:?}");
debug!("/auth request {req_id} RESPONSE: {res}");
info!("/api request {req_id} | resolve time: {elapsed:?}");
debug!("/api request {req_id} RESPONSE: {res}");
Result::<_, (StatusCode, String)>::Ok((TypedHeader(ContentType::json()), res))
},
),
+1 -1
View File
@@ -1,8 +1,8 @@
use anyhow::{anyhow, Context};
use async_trait::async_trait;
use monitor_types::{
monitor_timestamp,
entities::user::ApiSecret,
monitor_timestamp,
requests::api::{CreateLoginSecret, CreateLoginSecretResponse, DeleteLoginSecret},
};
use mungos::{
+1 -7
View File
@@ -12,13 +12,7 @@ use monitor_types::{
},
monitor_timestamp,
permissioned::Permissioned,
requests::api::{
CreateServer, DeleteServer, GetAllSystemStats, GetBasicSystemStats, GetCpuUsage,
GetDiskUsage, GetDockerContainers, GetDockerImages, GetDockerNetworks, GetNetworkUsage,
GetPeripheryVersion, GetPeripheryVersionResponse, GetServer, GetSystemComponents,
GetSystemInformation, GetSystemProcesses, ListServers, PruneDockerContainers,
PruneDockerImages, PruneDockerNetworks, RenameServer, UpdateServer,
},
requests::api::*,
};
use mungos::mongodb::bson::{doc, to_bson};
use periphery_client::requests;
+4 -2
View File
@@ -1,4 +1,6 @@
use crate::entities::{server::ServerActionState, deployment::DeploymentActionState, build::BuildActionState};
use crate::entities::{
build::BuildActionState, deployment::DeploymentActionState, server::ServerActionState,
};
pub trait Busy {
fn busy(&self) -> bool;
@@ -27,4 +29,4 @@ impl Busy for BuildActionState {
fn busy(&self) -> bool {
self.building || self.updating
}
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ use partial_derive2::Partial;
use serde::{Deserialize, Serialize};
use typeshare::typeshare;
use crate::{I64, i64_is_zero};
use crate::{i64_is_zero, I64};
use super::PermissionsMap;
+1 -1
View File
@@ -3,7 +3,7 @@ use mungos::MungosIndexed;
use serde::{Deserialize, Serialize};
use typeshare::typeshare;
use crate::{I64, i64_is_zero};
use crate::{i64_is_zero, I64};
#[typeshare]
#[derive(Serialize, Deserialize, Debug, Clone, Default, MungosIndexed)]
+5 -2
View File
@@ -1,4 +1,7 @@
use crate::entities::{PermissionsMap, PermissionLevel, deployment::Deployment, build::Build, server::Server, builder::Builder};
use crate::entities::{
build::Build, builder::Builder, deployment::Deployment, server::Server, PermissionLevel,
PermissionsMap,
};
pub trait Permissioned {
fn permissions_map(&self) -> &PermissionsMap;
@@ -30,4 +33,4 @@ impl Permissioned for Builder {
fn permissions_map(&self) -> &PermissionsMap {
&self.permissions
}
}
}
+10
View File
@@ -38,6 +38,16 @@ pub struct CreateBuild {
//
#[typeshare]
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
#[response(Build)]
pub struct CopyBuild {
pub name: String,
pub id: String,
}
//
#[typeshare]
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
#[response(Build)]
+1 -3
View File
@@ -8,6 +8,4 @@
// MongoDocument,
// };
// derive_crud_requests!(Builder);
// derive_crud_requests!(Builder);
+10
View File
@@ -40,6 +40,16 @@ pub struct CreateDeployment {
//
#[typeshare]
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
#[response(Deployment)]
pub struct CopyDeployment {
pub name: String,
pub id: String,
}
//
#[typeshare]
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
#[response(Deployment)]
+12 -4
View File
@@ -36,10 +36,18 @@ async fn app() -> anyhow::Result<()> {
let timer = Instant::now();
let req_id = Uuid::new_v4();
info!("request {req_id} | {request:?}");
let res = state
.resolve_request(request, ())
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")));
let res = tokio::spawn(async move {
state
.resolve_request(request, ())
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")))
})
.await
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")));
if let Err(e) = &res {
debug!("request {req_id} SPAWN ERROR: {e:?}");
}
let res = res?;
if let Err(e) = &res {
debug!("request {req_id} ERROR: {e:?}");
}
+4 -1
View File
@@ -1,5 +1,8 @@
use async_trait::async_trait;
use monitor_types::{entities::{server::docker_image::ImageSummary, update::Log}, optional_string};
use monitor_types::{
entities::{server::docker_image::ImageSummary, update::Log},
optional_string,
};
use resolver_api::{derive::Request, Resolve};
use serde::{Deserialize, Serialize};
+4 -1
View File
@@ -1,4 +1,7 @@
use monitor_types::{entities::{update::Log, CloneArgs, SystemCommand}, to_monitor_name};
use monitor_types::{
entities::{update::Log, CloneArgs, SystemCommand},
to_monitor_name,
};
use resolver_api::{derive::Request, Resolve};
use serde::{Deserialize, Serialize};