forked from github-starred/komodo
crud for builder
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -1913,9 +1913,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mungos"
|
name = "mungos"
|
||||||
version = "0.4.4"
|
version = "0.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78e0e07595834795a2884abf009363c3884f3e5ca0ed63748e586aa62efcd26b"
|
checksum = "606e6fe66f9507be4814a6ee50508650c4563ecd21904713cf5eda650cf4dd42"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
|||||||
@@ -63,6 +63,6 @@ partial_derive2 = "0.1.4"
|
|||||||
make_option = "0.1.3"
|
make_option = "0.1.3"
|
||||||
resolver_api = "0.1.5"
|
resolver_api = "0.1.5"
|
||||||
parse_csl = "0.1.0"
|
parse_csl = "0.1.0"
|
||||||
mungos = "0.4.4"
|
mungos = "0.4.5"
|
||||||
svi = "0.1.4"
|
svi = "0.1.4"
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ use anyhow::{anyhow, Context};
|
|||||||
use async_timing_util::unix_timestamp_ms;
|
use async_timing_util::unix_timestamp_ms;
|
||||||
use axum::async_trait;
|
use axum::async_trait;
|
||||||
use monitor_types::requests::auth::{LoginWithSecret, LoginWithSecretResponse};
|
use monitor_types::requests::auth::{LoginWithSecret, LoginWithSecretResponse};
|
||||||
use mungos::{
|
use mungos::{mongodb::bson::doc, Update};
|
||||||
mongodb::bson::{doc, Document},
|
|
||||||
Update,
|
|
||||||
};
|
|
||||||
use resolver_api::Resolve;
|
use resolver_api::Resolve;
|
||||||
|
|
||||||
use crate::state::State;
|
use crate::state::State;
|
||||||
@@ -30,7 +27,7 @@ impl Resolve<LoginWithSecret> for State {
|
|||||||
if expires < ts {
|
if expires < ts {
|
||||||
self.db
|
self.db
|
||||||
.users
|
.users
|
||||||
.update_one::<Document>(
|
.update_one(
|
||||||
&user.id,
|
&user.id,
|
||||||
Update::Custom(doc! { "$pull": { "secrets": { "name": s.name } } }),
|
Update::Custom(doc! { "$pull": { "secrets": { "name": s.name } } }),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ impl Resolve<UpdateBuild, RequestUser> for State {
|
|||||||
.builds
|
.builds
|
||||||
.update_one(
|
.update_one(
|
||||||
&id,
|
&id,
|
||||||
mungos::Update::<()>::Set(doc! { "config": to_bson(&config)? }),
|
mungos::Update::Set(doc! { "config": to_bson(&config)? }),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.context("failed to update build on database")?;
|
.context("failed to update build on database")?;
|
||||||
@@ -447,7 +447,7 @@ impl Resolve<RunBuild, RequestUser> for State {
|
|||||||
let _ = self
|
let _ = self
|
||||||
.db
|
.db
|
||||||
.builds
|
.builds
|
||||||
.update_one::<Build>(
|
.update_one(
|
||||||
&build.id,
|
&build.id,
|
||||||
mungos::Update::Set(doc! {
|
mungos::Update::Set(doc! {
|
||||||
"version": to_bson(&build.config.version)
|
"version": to_bson(&build.config.version)
|
||||||
|
|||||||
254
core/src/requests/api/builder.rs
Normal file
254
core/src/requests/api/builder.rs
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
use anyhow::Context;
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use monitor_types::{
|
||||||
|
entities::{
|
||||||
|
builder::Builder,
|
||||||
|
update::{Log, ResourceTarget, Update},
|
||||||
|
Operation, PermissionLevel,
|
||||||
|
},
|
||||||
|
monitor_timestamp,
|
||||||
|
permissioned::Permissioned,
|
||||||
|
requests::api::*,
|
||||||
|
};
|
||||||
|
use mungos::mongodb::bson::{doc, to_bson};
|
||||||
|
use resolver_api::Resolve;
|
||||||
|
|
||||||
|
use crate::{auth::RequestUser, state::State};
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Resolve<GetBuilder, RequestUser> for State {
|
||||||
|
async fn resolve(
|
||||||
|
&self,
|
||||||
|
GetBuilder { id }: GetBuilder,
|
||||||
|
user: RequestUser,
|
||||||
|
) -> anyhow::Result<Builder> {
|
||||||
|
self.get_builder_check_permissions(&id, &user, PermissionLevel::Read)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Resolve<ListBuilders, RequestUser> for State {
|
||||||
|
async fn resolve(
|
||||||
|
&self,
|
||||||
|
ListBuilders { query }: ListBuilders,
|
||||||
|
user: RequestUser,
|
||||||
|
) -> anyhow::Result<Vec<Builder>> {
|
||||||
|
let builders = self
|
||||||
|
.db
|
||||||
|
.builders
|
||||||
|
.get_some(query, None)
|
||||||
|
.await
|
||||||
|
.context("failed to pull builders from mongo")?;
|
||||||
|
|
||||||
|
let builders = if user.is_admin {
|
||||||
|
builders
|
||||||
|
} else {
|
||||||
|
builders
|
||||||
|
.into_iter()
|
||||||
|
.filter(|builder| builder.get_user_permissions(&user.id) > PermissionLevel::None)
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(builders)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Resolve<CreateBuilder, RequestUser> for State {
|
||||||
|
async fn resolve(
|
||||||
|
&self,
|
||||||
|
CreateBuilder { name, config }: CreateBuilder,
|
||||||
|
user: RequestUser,
|
||||||
|
) -> anyhow::Result<Builder> {
|
||||||
|
let start_ts = monitor_timestamp();
|
||||||
|
let builder = Builder {
|
||||||
|
id: Default::default(),
|
||||||
|
name,
|
||||||
|
created_at: start_ts,
|
||||||
|
updated_at: start_ts,
|
||||||
|
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
description: Default::default(),
|
||||||
|
config: config.into(),
|
||||||
|
};
|
||||||
|
let builder_id = self
|
||||||
|
.db
|
||||||
|
.builders
|
||||||
|
.create_one(builder)
|
||||||
|
.await
|
||||||
|
.context("failed to add build to db")?;
|
||||||
|
let builder = self.get_builder(&builder_id).await?;
|
||||||
|
let update = Update {
|
||||||
|
target: ResourceTarget::Builder(builder_id),
|
||||||
|
operation: Operation::CreateBuilder,
|
||||||
|
start_ts,
|
||||||
|
end_ts: Some(monitor_timestamp()),
|
||||||
|
operator: user.id.clone(),
|
||||||
|
success: true,
|
||||||
|
logs: vec![
|
||||||
|
Log::simple(
|
||||||
|
"create builder",
|
||||||
|
format!(
|
||||||
|
"created builder\nid: {}\nname: {}",
|
||||||
|
builder.id, builder.name
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Log::simple("config", format!("{:#?}", builder.config)),
|
||||||
|
],
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
self.add_update(update).await?;
|
||||||
|
|
||||||
|
Ok(builder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Resolve<CopyBuilder, RequestUser> for State {
|
||||||
|
async fn resolve(
|
||||||
|
&self,
|
||||||
|
CopyBuilder { name, id }: CopyBuilder,
|
||||||
|
user: RequestUser,
|
||||||
|
) -> anyhow::Result<Builder> {
|
||||||
|
let Builder {
|
||||||
|
config,
|
||||||
|
description,
|
||||||
|
..
|
||||||
|
} = self
|
||||||
|
.get_builder_check_permissions(&id, &user, PermissionLevel::Update)
|
||||||
|
.await?;
|
||||||
|
let start_ts = monitor_timestamp();
|
||||||
|
let builder = Builder {
|
||||||
|
id: Default::default(),
|
||||||
|
name,
|
||||||
|
created_at: start_ts,
|
||||||
|
updated_at: start_ts,
|
||||||
|
permissions: [(user.id.clone(), PermissionLevel::Update)]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
description,
|
||||||
|
config,
|
||||||
|
};
|
||||||
|
let builder_id = self
|
||||||
|
.db
|
||||||
|
.builders
|
||||||
|
.create_one(builder)
|
||||||
|
.await
|
||||||
|
.context("failed to add builder to db")?;
|
||||||
|
let builder = self.get_builder(&builder_id).await?;
|
||||||
|
let update = Update {
|
||||||
|
target: ResourceTarget::Builder(builder_id),
|
||||||
|
operation: Operation::CreateBuilder,
|
||||||
|
start_ts,
|
||||||
|
end_ts: Some(monitor_timestamp()),
|
||||||
|
operator: user.id.clone(),
|
||||||
|
success: true,
|
||||||
|
logs: vec![
|
||||||
|
Log::simple(
|
||||||
|
"create builder",
|
||||||
|
format!(
|
||||||
|
"created builder\nid: {}\nname: {}",
|
||||||
|
builder.id, builder.name
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Log::simple("config", format!("{:#?}", builder.config)),
|
||||||
|
],
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
self.add_update(update).await?;
|
||||||
|
|
||||||
|
Ok(builder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Resolve<DeleteBuilder, RequestUser> for State {
|
||||||
|
async fn resolve(
|
||||||
|
&self,
|
||||||
|
DeleteBuilder { id }: DeleteBuilder,
|
||||||
|
user: RequestUser,
|
||||||
|
) -> anyhow::Result<Builder> {
|
||||||
|
let builder = self
|
||||||
|
.get_builder_check_permissions(&id, &user, PermissionLevel::Update)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let start_ts = monitor_timestamp();
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.builds
|
||||||
|
.update_many(
|
||||||
|
doc! { "config.builder.params.builder_id": &id },
|
||||||
|
doc! { "$set": { "config.builder.params.builder_id": "" } },
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.builds
|
||||||
|
.delete_one(&id)
|
||||||
|
.await
|
||||||
|
.context("failed to delete build from database")?;
|
||||||
|
|
||||||
|
let mut update = Update {
|
||||||
|
target: ResourceTarget::Builder(id.clone()),
|
||||||
|
operation: Operation::DeleteBuilder,
|
||||||
|
start_ts,
|
||||||
|
operator: user.id.clone(),
|
||||||
|
logs: vec![Log::simple(
|
||||||
|
"delete builder",
|
||||||
|
format!("deleted builder {}", builder.name),
|
||||||
|
)],
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
update.finalize();
|
||||||
|
self.add_update(update).await?;
|
||||||
|
|
||||||
|
Ok(builder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl Resolve<UpdateBuilder, RequestUser> for State {
|
||||||
|
async fn resolve(
|
||||||
|
&self,
|
||||||
|
UpdateBuilder { id, config }: UpdateBuilder,
|
||||||
|
user: RequestUser,
|
||||||
|
) -> anyhow::Result<Builder> {
|
||||||
|
let builder = self
|
||||||
|
.get_builder_check_permissions(&id, &user, PermissionLevel::Update)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut update = Update {
|
||||||
|
target: ResourceTarget::Builder(id.clone()),
|
||||||
|
operation: Operation::UpdateBuilder,
|
||||||
|
start_ts: monitor_timestamp(),
|
||||||
|
logs: vec![Log::simple(
|
||||||
|
"builder update",
|
||||||
|
serde_json::to_string_pretty(&config).unwrap(),
|
||||||
|
)],
|
||||||
|
operator: user.id.clone(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let config = builder.config.merge_partial(config);
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.builders
|
||||||
|
.update_one(
|
||||||
|
&id,
|
||||||
|
mungos::Update::Set(doc! { "config": to_bson(&config)? }),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let builder = self.get_builder(&id).await?;
|
||||||
|
|
||||||
|
update.finalize();
|
||||||
|
self.add_update(update).await?;
|
||||||
|
|
||||||
|
Ok(builder)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -487,7 +487,7 @@ impl Resolve<UpdateDeployment, RequestUser> for State {
|
|||||||
.deployments
|
.deployments
|
||||||
.update_one(
|
.update_one(
|
||||||
&id,
|
&id,
|
||||||
mungos::Update::<()>::Set(doc! { "config": to_bson(&config)? }),
|
mungos::Update::Set(doc! { "config": to_bson(&config)? }),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.context("failed to update server on mongo")?;
|
.context("failed to update server on mongo")?;
|
||||||
@@ -583,7 +583,7 @@ impl Resolve<RenameDeployment, RequestUser> for State {
|
|||||||
.deployments
|
.deployments
|
||||||
.update_one(
|
.update_one(
|
||||||
&deployment.id,
|
&deployment.id,
|
||||||
mungos::Update::<()>::Set(
|
mungos::Update::Set(
|
||||||
doc! { "name": &name, "updated_at": monitor_timestamp() },
|
doc! { "name": &name, "updated_at": monitor_timestamp() },
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
mod build;
|
mod build;
|
||||||
|
mod builder;
|
||||||
mod deployment;
|
mod deployment;
|
||||||
mod permissions;
|
mod permissions;
|
||||||
mod repo;
|
mod repo;
|
||||||
@@ -33,6 +34,10 @@ pub enum ApiRequest {
|
|||||||
CreateLoginSecret(CreateLoginSecret),
|
CreateLoginSecret(CreateLoginSecret),
|
||||||
DeleteLoginSecret(DeleteLoginSecret),
|
DeleteLoginSecret(DeleteLoginSecret),
|
||||||
|
|
||||||
|
// ==== PERMISSIONS ====
|
||||||
|
UpdateUserPerimissions(UpdateUserPermissions),
|
||||||
|
UpdateUserPermissionsOnTarget(UpdateUserPermissionsOnTarget),
|
||||||
|
|
||||||
// ==== SERVER ====
|
// ==== SERVER ====
|
||||||
GetPeripheryVersion(GetPeripheryVersion),
|
GetPeripheryVersion(GetPeripheryVersion),
|
||||||
GetSystemInformation(GetSystemInformation),
|
GetSystemInformation(GetSystemInformation),
|
||||||
@@ -89,7 +94,17 @@ pub enum ApiRequest {
|
|||||||
UpdateBuild(UpdateBuild),
|
UpdateBuild(UpdateBuild),
|
||||||
// ACTIONS
|
// ACTIONS
|
||||||
RunBuild(RunBuild),
|
RunBuild(RunBuild),
|
||||||
// ==== PERMISSIONS ====
|
|
||||||
|
// ==== REPO ====
|
||||||
|
GetRepo(GetRepo),
|
||||||
|
ListRepos(ListRepos),
|
||||||
|
// CRUD
|
||||||
|
CreateRepo(CreateRepo),
|
||||||
|
UpdateRepo(UpdateRepo),
|
||||||
|
DeleteRepo(DeleteRepo),
|
||||||
|
// ACTIONS
|
||||||
|
CloneRepo(CloneRepo),
|
||||||
|
PullRepo(PullRepo),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn router() -> Router {
|
pub fn router() -> Router {
|
||||||
|
|||||||
@@ -2,11 +2,6 @@ use anyhow::{anyhow, Context};
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use monitor_types::{
|
use monitor_types::{
|
||||||
entities::{
|
entities::{
|
||||||
build::Build,
|
|
||||||
builder::Builder,
|
|
||||||
deployment::Deployment,
|
|
||||||
repo::Repo,
|
|
||||||
server::Server,
|
|
||||||
update::{Log, ResourceTarget, Update, UpdateStatus},
|
update::{Log, ResourceTarget, Update, UpdateStatus},
|
||||||
Operation,
|
Operation,
|
||||||
},
|
},
|
||||||
@@ -58,7 +53,7 @@ impl Resolve<UpdateUserPermissions, RequestUser> for State {
|
|||||||
}
|
}
|
||||||
self.db
|
self.db
|
||||||
.users
|
.users
|
||||||
.update_one::<Document>(&user_id, mungos::Update::Set(update_doc))
|
.update_one(&user_id, mungos::Update::Set(update_doc))
|
||||||
.await?;
|
.await?;
|
||||||
let end_ts = monitor_timestamp();
|
let end_ts = monitor_timestamp();
|
||||||
let mut update = Update {
|
let mut update = Update {
|
||||||
@@ -127,7 +122,7 @@ impl Resolve<UpdateUserPermissionsOnTarget, RequestUser> for State {
|
|||||||
.ok_or(anyhow!("failed to find a build with id {id}"))?;
|
.ok_or(anyhow!("failed to find a build with id {id}"))?;
|
||||||
self.db
|
self.db
|
||||||
.builds
|
.builds
|
||||||
.update_one::<Build>(
|
.update_one(
|
||||||
id,
|
id,
|
||||||
mungos::Update::Set(doc! {
|
mungos::Update::Set(doc! {
|
||||||
format!("permissions.{}", user_id): permission.to_string()
|
format!("permissions.{}", user_id): permission.to_string()
|
||||||
@@ -149,7 +144,7 @@ impl Resolve<UpdateUserPermissionsOnTarget, RequestUser> for State {
|
|||||||
.ok_or(anyhow!("failed to find a builder with id {id}"))?;
|
.ok_or(anyhow!("failed to find a builder with id {id}"))?;
|
||||||
self.db
|
self.db
|
||||||
.builders
|
.builders
|
||||||
.update_one::<Builder>(
|
.update_one(
|
||||||
id,
|
id,
|
||||||
mungos::Update::Set(doc! {
|
mungos::Update::Set(doc! {
|
||||||
format!("permissions.{}", user_id): permission.to_string()
|
format!("permissions.{}", user_id): permission.to_string()
|
||||||
@@ -171,7 +166,7 @@ impl Resolve<UpdateUserPermissionsOnTarget, RequestUser> for State {
|
|||||||
.ok_or(anyhow!("failed to find a deployment with id {id}"))?;
|
.ok_or(anyhow!("failed to find a deployment with id {id}"))?;
|
||||||
self.db
|
self.db
|
||||||
.deployments
|
.deployments
|
||||||
.update_one::<Deployment>(
|
.update_one(
|
||||||
id,
|
id,
|
||||||
mungos::Update::Set(doc! {
|
mungos::Update::Set(doc! {
|
||||||
format!("permissions.{}", user_id): permission.to_string()
|
format!("permissions.{}", user_id): permission.to_string()
|
||||||
@@ -193,7 +188,7 @@ impl Resolve<UpdateUserPermissionsOnTarget, RequestUser> for State {
|
|||||||
.ok_or(anyhow!("failed to find a server with id {id}"))?;
|
.ok_or(anyhow!("failed to find a server with id {id}"))?;
|
||||||
self.db
|
self.db
|
||||||
.servers
|
.servers
|
||||||
.update_one::<Server>(
|
.update_one(
|
||||||
id,
|
id,
|
||||||
mungos::Update::Set(doc! {
|
mungos::Update::Set(doc! {
|
||||||
format!("permissions.{}", user_id): permission.to_string()
|
format!("permissions.{}", user_id): permission.to_string()
|
||||||
@@ -215,7 +210,7 @@ impl Resolve<UpdateUserPermissionsOnTarget, RequestUser> for State {
|
|||||||
.ok_or(anyhow!("failed to find a repo with id {id}"))?;
|
.ok_or(anyhow!("failed to find a repo with id {id}"))?;
|
||||||
self.db
|
self.db
|
||||||
.repos
|
.repos
|
||||||
.update_one::<Repo>(
|
.update_one(
|
||||||
id,
|
id,
|
||||||
mungos::Update::Set(doc! {
|
mungos::Update::Set(doc! {
|
||||||
format!("permissions.{}", user_id): permission.to_string()
|
format!("permissions.{}", user_id): permission.to_string()
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ impl Resolve<UpdateRepo, RequestUser> for State {
|
|||||||
.repos
|
.repos
|
||||||
.update_one(
|
.update_one(
|
||||||
&repo.id,
|
&repo.id,
|
||||||
mungos::Update::<()>::Set(doc! { "config": to_bson(&config)? }),
|
mungos::Update::Set(doc! { "config": to_bson(&config)? }),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.context("failed to update repo on database")?;
|
.context("failed to update repo on database")?;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use monitor_types::{
|
|||||||
requests::api::{CreateLoginSecret, CreateLoginSecretResponse, DeleteLoginSecret},
|
requests::api::{CreateLoginSecret, CreateLoginSecretResponse, DeleteLoginSecret},
|
||||||
};
|
};
|
||||||
use mungos::{
|
use mungos::{
|
||||||
mongodb::bson::{doc, to_bson, Document},
|
mongodb::bson::{doc, to_bson},
|
||||||
Update,
|
Update,
|
||||||
};
|
};
|
||||||
use resolver_api::Resolve;
|
use resolver_api::Resolve;
|
||||||
@@ -42,7 +42,7 @@ impl Resolve<CreateLoginSecret, RequestUser> for State {
|
|||||||
};
|
};
|
||||||
self.db
|
self.db
|
||||||
.users
|
.users
|
||||||
.update_one::<Document>(
|
.update_one(
|
||||||
&user.id,
|
&user.id,
|
||||||
Update::Custom(doc! {
|
Update::Custom(doc! {
|
||||||
"$push": {
|
"$push": {
|
||||||
@@ -65,7 +65,7 @@ impl Resolve<DeleteLoginSecret, RequestUser> for State {
|
|||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
self.db
|
self.db
|
||||||
.users
|
.users
|
||||||
.update_one::<Document>(
|
.update_one(
|
||||||
&user.id,
|
&user.id,
|
||||||
Update::Custom(doc! {
|
Update::Custom(doc! {
|
||||||
"$pull": {
|
"$pull": {
|
||||||
|
|||||||
@@ -126,49 +126,70 @@ impl Resolve<CreateServer, RequestUser> for State {
|
|||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Resolve<DeleteServer, RequestUser> for State {
|
impl Resolve<DeleteServer, RequestUser> for State {
|
||||||
async fn resolve(&self, req: DeleteServer, user: RequestUser) -> anyhow::Result<Server> {
|
async fn resolve(
|
||||||
if self.action_states.server.busy(&req.id).await {
|
&self,
|
||||||
|
DeleteServer { id }: DeleteServer,
|
||||||
|
user: RequestUser,
|
||||||
|
) -> anyhow::Result<Server> {
|
||||||
|
if self.action_states.server.busy(&id).await {
|
||||||
return Err(anyhow!("server busy"));
|
return Err(anyhow!("server busy"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let server = self
|
let server = self
|
||||||
.get_server_check_permissions(&req.id, &user, PermissionLevel::Update)
|
.get_server_check_permissions(&id, &user, PermissionLevel::Update)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let start_ts = monitor_timestamp();
|
let start_ts = monitor_timestamp();
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.builds
|
||||||
|
.update_many(
|
||||||
|
doc! { "config.builder.params.server_id": &id },
|
||||||
|
doc! { "$set": { "config.builder.params.server_id": "" } },
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.context("failed to detach server from builds")?;
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.deployments
|
||||||
|
.update_many(
|
||||||
|
doc! { "config.server_id": &id },
|
||||||
|
doc! { "$set": { "config.server_id": "" } },
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.context("failed to detach server from deployments")?;
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.repos
|
||||||
|
.update_many(
|
||||||
|
doc! { "config.server_id": &id },
|
||||||
|
doc! { "$set": { "config.server_id": "" } },
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.context("failed to detach server from repos")?;
|
||||||
|
|
||||||
|
self.db
|
||||||
|
.servers
|
||||||
|
.delete_one(&id)
|
||||||
|
.await
|
||||||
|
.context("failed to delete server from mongo")?;
|
||||||
|
|
||||||
let mut update = Update {
|
let mut update = Update {
|
||||||
target: ResourceTarget::Server(req.id.clone()),
|
target: ResourceTarget::Server(id.clone()),
|
||||||
operation: Operation::DeleteServer,
|
operation: Operation::DeleteServer,
|
||||||
start_ts,
|
start_ts,
|
||||||
operator: user.id.clone(),
|
operator: user.id.clone(),
|
||||||
success: true,
|
logs: vec![Log::simple(
|
||||||
status: UpdateStatus::InProgress,
|
"delete server",
|
||||||
|
format!("deleted server {}", server.name),
|
||||||
|
)],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
update.id = self.add_update(update.clone()).await?;
|
update.finalize();
|
||||||
|
self.add_update(update).await?;
|
||||||
|
|
||||||
let res = self
|
self.server_status_cache.remove(&id).await;
|
||||||
.db
|
|
||||||
.servers
|
|
||||||
.delete_one(&req.id)
|
|
||||||
.await
|
|
||||||
.context("failed to delete server from mongo");
|
|
||||||
|
|
||||||
let log = match res {
|
|
||||||
Ok(_) => Log::simple("delete server", format!("deleted server {}", server.name)),
|
|
||||||
Err(e) => Log::error("delete server", format!("failed to delete server\n{e:#?}")),
|
|
||||||
};
|
|
||||||
|
|
||||||
update.end_ts = Some(monitor_timestamp());
|
|
||||||
update.status = UpdateStatus::Complete;
|
|
||||||
update.success = log.success;
|
|
||||||
update.logs.push(log);
|
|
||||||
|
|
||||||
self.update_update(update).await?;
|
|
||||||
|
|
||||||
self.server_status_cache.remove(&req.id).await;
|
|
||||||
|
|
||||||
Ok(server)
|
Ok(server)
|
||||||
}
|
}
|
||||||
@@ -191,7 +212,7 @@ impl Resolve<UpdateServer, RequestUser> for State {
|
|||||||
.servers
|
.servers
|
||||||
.update_one(
|
.update_one(
|
||||||
&id,
|
&id,
|
||||||
mungos::Update::<()>::Set(doc! { "config": to_bson(&config)? }),
|
mungos::Update::Set(doc! { "config": to_bson(&config)? }),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.context("failed to update server on mongo")?;
|
.context("failed to update server on mongo")?;
|
||||||
@@ -235,9 +256,7 @@ impl Resolve<RenameServer, RequestUser> for State {
|
|||||||
.updates
|
.updates
|
||||||
.update_one(
|
.update_one(
|
||||||
&id,
|
&id,
|
||||||
mungos::Update::<Server>::Set(
|
mungos::Update::Set(doc! { "name": &name, "updated_at": monitor_timestamp() }),
|
||||||
doc! { "name": &name, "updated_at": monitor_timestamp() },
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let mut update = Update {
|
let mut update = Update {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use bson::serde_helpers::hex_string_as_object_id;
|
use bson::serde_helpers::hex_string_as_object_id;
|
||||||
use derive_builder::Builder;
|
use derive_builder::Builder;
|
||||||
use mungos::MungosIndexed;
|
use mungos::MungosIndexed;
|
||||||
|
use partial_derive2::Partial;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use typeshare::typeshare;
|
use typeshare::typeshare;
|
||||||
|
|
||||||
@@ -50,18 +51,58 @@ pub enum BuilderConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[typeshare]
|
#[typeshare]
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, MungosIndexed)]
|
#[derive(Serialize, Deserialize, Debug, Clone, MungosIndexed)]
|
||||||
|
#[serde(tag = "type", content = "params")]
|
||||||
|
pub enum PartialBuilderConfig {
|
||||||
|
AwsBuilder(PartialAwsBuilder),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PartialBuilderConfig> for BuilderConfig {
|
||||||
|
fn from(value: PartialBuilderConfig) -> BuilderConfig {
|
||||||
|
match value {
|
||||||
|
PartialBuilderConfig::AwsBuilder(builder) => BuilderConfig::AwsBuilder(builder.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuilderConfig {
|
||||||
|
pub fn merge_partial(self, partial: PartialBuilderConfig) -> BuilderConfig {
|
||||||
|
match partial {
|
||||||
|
PartialBuilderConfig::AwsBuilder(partial) => match self {
|
||||||
|
BuilderConfig::AwsBuilder(config) => {
|
||||||
|
let config = AwsBuilder {
|
||||||
|
region: partial.region.unwrap_or(config.region),
|
||||||
|
instance_type: partial.instance_type.unwrap_or(config.instance_type),
|
||||||
|
volume_gb: partial.volume_gb.unwrap_or(config.volume_gb),
|
||||||
|
ami_id: partial.ami_id.unwrap_or(config.ami_id),
|
||||||
|
subnet_id: partial.subnet_id.unwrap_or(config.subnet_id),
|
||||||
|
security_group_ids: partial.security_group_ids.unwrap_or(config.security_group_ids),
|
||||||
|
key_pair_name: partial.key_pair_name.unwrap_or(config.key_pair_name),
|
||||||
|
assign_public_ip: partial.assign_public_ip.unwrap_or(config.assign_public_ip),
|
||||||
|
};
|
||||||
|
BuilderConfig::AwsBuilder(config)
|
||||||
|
}
|
||||||
|
// _ => BuilderConfig::AwsBuilder(partial.into()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[typeshare]
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial)]
|
||||||
|
#[partial_derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[skip_serializing_none]
|
||||||
pub struct AwsBuilder {
|
pub struct AwsBuilder {
|
||||||
#[serde(default = "default_region")]
|
#[serde(default = "aws_default_region")]
|
||||||
#[builder(default = "default_region()")]
|
#[builder(default = "aws_default_region()")]
|
||||||
pub region: String,
|
pub region: String,
|
||||||
|
|
||||||
#[serde(default = "default_instance_type")]
|
#[serde(default = "aws_default_instance_type")]
|
||||||
#[builder(default = "default_instance_type()")]
|
#[builder(default = "aws_default_instance_type()")]
|
||||||
pub instance_type: String,
|
pub instance_type: String,
|
||||||
|
|
||||||
#[serde(default = "default_volume_gb")]
|
#[serde(default = "aws_default_volume_gb")]
|
||||||
#[builder(default = "default_volume_gb()")]
|
#[builder(default = "aws_default_volume_gb()")]
|
||||||
pub volume_gb: i32,
|
pub volume_gb: i32,
|
||||||
|
|
||||||
pub ami_id: String,
|
pub ami_id: String,
|
||||||
@@ -71,14 +112,29 @@ pub struct AwsBuilder {
|
|||||||
pub assign_public_ip: bool,
|
pub assign_public_ip: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_region() -> String {
|
fn aws_default_region() -> String {
|
||||||
String::from("us-east-1")
|
String::from("us-east-1")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_instance_type() -> String {
|
fn aws_default_instance_type() -> String {
|
||||||
String::from("c5.2xlarge")
|
String::from("c5.2xlarge")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_volume_gb() -> i32 {
|
fn aws_default_volume_gb() -> i32 {
|
||||||
20
|
20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<PartialAwsBuilder> for AwsBuilder {
|
||||||
|
fn from(value: PartialAwsBuilder) -> AwsBuilder {
|
||||||
|
AwsBuilder {
|
||||||
|
region: value.region.unwrap_or(aws_default_region()),
|
||||||
|
instance_type: value.instance_type.unwrap_or(aws_default_instance_type()),
|
||||||
|
volume_gb: value.volume_gb.unwrap_or(aws_default_volume_gb()),
|
||||||
|
ami_id: value.ami_id.unwrap_or_default(),
|
||||||
|
subnet_id: value.subnet_id.unwrap_or_default(),
|
||||||
|
security_group_ids: value.security_group_ids.unwrap_or_default(),
|
||||||
|
key_pair_name: value.key_pair_name.unwrap_or_default(),
|
||||||
|
assign_public_ip: value.assign_public_ip.unwrap_or_default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,65 @@
|
|||||||
// use monitor_macros::derive_crud_requests;
|
use resolver_api::derive::Request;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use typeshare::typeshare;
|
||||||
|
|
||||||
// use crate::{
|
use crate::{
|
||||||
// entities::{
|
entities::builder::{Builder, PartialBuilderConfig},
|
||||||
// builder::{Builder},
|
MongoDocument,
|
||||||
// update::Update,
|
};
|
||||||
// },
|
|
||||||
// MongoDocument,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// derive_crud_requests!(Builder);
|
//
|
||||||
|
|
||||||
|
#[typeshare]
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||||
|
#[response(Builder)]
|
||||||
|
pub struct GetBuilder {
|
||||||
|
pub id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#[typeshare]
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||||
|
#[response(Vec<Builder>)]
|
||||||
|
pub struct ListBuilders {
|
||||||
|
pub query: Option<MongoDocument>,
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#[typeshare]
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||||
|
#[response(Builder)]
|
||||||
|
pub struct CreateBuilder {
|
||||||
|
pub name: String,
|
||||||
|
pub config: PartialBuilderConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#[typeshare]
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||||
|
#[response(Builder)]
|
||||||
|
pub struct CopyBuilder {
|
||||||
|
pub name: String,
|
||||||
|
pub id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#[typeshare]
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||||
|
#[response(Builder)]
|
||||||
|
pub struct DeleteBuilder {
|
||||||
|
pub id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
#[typeshare]
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, Request)]
|
||||||
|
#[response(Builder)]
|
||||||
|
pub struct UpdateBuilder {
|
||||||
|
pub id: String,
|
||||||
|
pub config: PartialBuilderConfig,
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user