mirror of
https://github.com/moghtech/komodo.git
synced 2025-12-05 19:17:36 -06:00
prog on swarm
This commit is contained in:
40
Cargo.lock
generated
40
Cargo.lock
generated
@@ -908,7 +908,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cache"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"tokio",
|
||||
@@ -1100,7 +1100,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "command"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"komodo_client",
|
||||
"shlex",
|
||||
@@ -1127,7 +1127,7 @@ checksum = "3a9b614a5787ef0c8802a55766480563cb3a93b435898c422ed2a359cf811582"
|
||||
|
||||
[[package]]
|
||||
name = "config"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"indexmap 2.12.0",
|
||||
@@ -1449,7 +1449,7 @@ checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
|
||||
|
||||
[[package]]
|
||||
name = "database"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-compression",
|
||||
@@ -1748,7 +1748,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "encoding"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -1790,7 +1790,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "environment"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"formatting",
|
||||
@@ -1800,7 +1800,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "environment_file"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"thiserror 2.0.17",
|
||||
]
|
||||
@@ -1902,7 +1902,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "formatting"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"serror",
|
||||
]
|
||||
@@ -2068,7 +2068,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "git"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cache",
|
||||
@@ -2702,7 +2702,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "interpolate"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"komodo_client",
|
||||
@@ -2824,7 +2824,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "komodo_cli"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
@@ -2852,7 +2852,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "komodo_client"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async_timing_util",
|
||||
@@ -2888,7 +2888,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "komodo_core"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
@@ -2962,7 +2962,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "komodo_periphery"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
@@ -3083,7 +3083,7 @@ checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
|
||||
[[package]]
|
||||
name = "logger"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"komodo_client",
|
||||
@@ -3375,7 +3375,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "noise"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
@@ -3799,7 +3799,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
|
||||
[[package]]
|
||||
name = "periphery_client"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"derive_variants",
|
||||
@@ -4280,7 +4280,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "response"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -4550,7 +4550,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "secret_file"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"tokio",
|
||||
]
|
||||
@@ -5583,7 +5583,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "transport"
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
|
||||
@@ -8,7 +8,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "2.0.0-dev-90"
|
||||
version = "2.0.0-dev-91"
|
||||
edition = "2024"
|
||||
authors = ["mbecker20 <becker.maxh@gmail.com>"]
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
@@ -142,13 +142,13 @@ pub enum ExecuteRequest {
|
||||
RunAction(RunAction),
|
||||
BatchRunAction(BatchRunAction),
|
||||
|
||||
// ==== SYNC ====
|
||||
RunSync(RunSync),
|
||||
|
||||
// ==== ALERTER ====
|
||||
TestAlerter(TestAlerter),
|
||||
SendAlert(SendAlert),
|
||||
|
||||
// ==== SYNC ====
|
||||
RunSync(RunSync),
|
||||
|
||||
// ==== MAINTENANCE ====
|
||||
ClearRepoCache(ClearRepoCache),
|
||||
BackupCoreDatabase(BackupCoreDatabase),
|
||||
|
||||
@@ -49,6 +49,7 @@ mod repo;
|
||||
mod schedule;
|
||||
mod server;
|
||||
mod stack;
|
||||
mod swarm;
|
||||
mod sync;
|
||||
mod tag;
|
||||
mod terminal;
|
||||
@@ -75,36 +76,12 @@ enum ReadRequest {
|
||||
ListGitProvidersFromConfig(ListGitProvidersFromConfig),
|
||||
ListDockerRegistriesFromConfig(ListDockerRegistriesFromConfig),
|
||||
|
||||
// ==== USER ====
|
||||
GetUsername(GetUsername),
|
||||
GetPermission(GetPermission),
|
||||
FindUser(FindUser),
|
||||
ListUsers(ListUsers),
|
||||
ListApiKeys(ListApiKeys),
|
||||
ListApiKeysForServiceUser(ListApiKeysForServiceUser),
|
||||
ListPermissions(ListPermissions),
|
||||
ListUserTargetPermissions(ListUserTargetPermissions),
|
||||
|
||||
// ==== USER GROUP ====
|
||||
GetUserGroup(GetUserGroup),
|
||||
ListUserGroups(ListUserGroups),
|
||||
|
||||
// ==== PROCEDURE ====
|
||||
GetProceduresSummary(GetProceduresSummary),
|
||||
GetProcedure(GetProcedure),
|
||||
GetProcedureActionState(GetProcedureActionState),
|
||||
ListProcedures(ListProcedures),
|
||||
ListFullProcedures(ListFullProcedures),
|
||||
|
||||
// ==== ACTION ====
|
||||
GetActionsSummary(GetActionsSummary),
|
||||
GetAction(GetAction),
|
||||
GetActionActionState(GetActionActionState),
|
||||
ListActions(ListActions),
|
||||
ListFullActions(ListFullActions),
|
||||
|
||||
// ==== SCHEDULE ====
|
||||
ListSchedules(ListSchedules),
|
||||
// ==== SWARM ====
|
||||
GetSwarmsSummary(GetSwarmsSummary),
|
||||
GetSwarm(GetSwarm),
|
||||
GetSwarmActionState(GetSwarmActionState),
|
||||
ListSwarms(ListSwarms),
|
||||
ListFullSwarms(ListFullSwarms),
|
||||
|
||||
// ==== SERVER ====
|
||||
GetServersSummary(GetServersSummary),
|
||||
@@ -112,7 +89,6 @@ enum ReadRequest {
|
||||
GetServerState(GetServerState),
|
||||
GetPeripheryInformation(GetPeripheryInformation),
|
||||
GetServerActionState(GetServerActionState),
|
||||
GetHistoricalServerStats(GetHistoricalServerStats),
|
||||
ListServers(ListServers),
|
||||
ListFullServers(ListFullServers),
|
||||
|
||||
@@ -139,6 +115,7 @@ enum ReadRequest {
|
||||
// ==== SERVER STATS ====
|
||||
GetSystemInformation(GetSystemInformation),
|
||||
GetSystemStats(GetSystemStats),
|
||||
GetHistoricalServerStats(GetHistoricalServerStats),
|
||||
ListSystemProcesses(ListSystemProcesses),
|
||||
|
||||
// ==== STACK ====
|
||||
@@ -184,6 +161,23 @@ enum ReadRequest {
|
||||
ListRepos(ListRepos),
|
||||
ListFullRepos(ListFullRepos),
|
||||
|
||||
// ==== PROCEDURE ====
|
||||
GetProceduresSummary(GetProceduresSummary),
|
||||
GetProcedure(GetProcedure),
|
||||
GetProcedureActionState(GetProcedureActionState),
|
||||
ListProcedures(ListProcedures),
|
||||
ListFullProcedures(ListFullProcedures),
|
||||
|
||||
// ==== ACTION ====
|
||||
GetActionsSummary(GetActionsSummary),
|
||||
GetAction(GetAction),
|
||||
GetActionActionState(GetActionActionState),
|
||||
ListActions(ListActions),
|
||||
ListFullActions(ListFullActions),
|
||||
|
||||
// ==== SCHEDULE ====
|
||||
ListSchedules(ListSchedules),
|
||||
|
||||
// ==== SYNC ====
|
||||
GetResourceSyncsSummary(GetResourceSyncsSummary),
|
||||
GetResourceSync(GetResourceSync),
|
||||
@@ -211,6 +205,20 @@ enum ReadRequest {
|
||||
GetTag(GetTag),
|
||||
ListTags(ListTags),
|
||||
|
||||
// ==== USER ====
|
||||
GetUsername(GetUsername),
|
||||
GetPermission(GetPermission),
|
||||
FindUser(FindUser),
|
||||
ListUsers(ListUsers),
|
||||
ListApiKeys(ListApiKeys),
|
||||
ListApiKeysForServiceUser(ListApiKeysForServiceUser),
|
||||
ListPermissions(ListPermissions),
|
||||
ListUserTargetPermissions(ListUserTargetPermissions),
|
||||
|
||||
// ==== USER GROUP ====
|
||||
GetUserGroup(GetUserGroup),
|
||||
ListUserGroups(ListUserGroups),
|
||||
|
||||
// ==== UPDATE ====
|
||||
GetUpdate(GetUpdate),
|
||||
ListUpdates(ListUpdates),
|
||||
|
||||
@@ -383,8 +383,8 @@ impl Resolve<ReadArgs> for ListDockerContainers {
|
||||
let cache = server_status_cache()
|
||||
.get_or_insert_default(&server.id)
|
||||
.await;
|
||||
if let Some(containers) = &cache.containers {
|
||||
Ok(containers.clone())
|
||||
if let Some(docker) = &cache.docker {
|
||||
Ok(docker.containers.clone())
|
||||
} else {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
@@ -410,10 +410,11 @@ impl Resolve<ReadArgs> for ListAllDockerContainers {
|
||||
let cache = server_status_cache()
|
||||
.get_or_insert_default(&server.id)
|
||||
.await;
|
||||
let Some(more) = &cache.containers else {
|
||||
let Some(docker) = &cache.docker else {
|
||||
continue;
|
||||
};
|
||||
let more = more
|
||||
let more = docker
|
||||
.containers
|
||||
.iter()
|
||||
.filter(|container| {
|
||||
self.containers.is_empty()
|
||||
@@ -448,8 +449,8 @@ impl Resolve<ReadArgs> for GetDockerContainersSummary {
|
||||
.get_or_insert_default(&server.id)
|
||||
.await;
|
||||
|
||||
if let Some(containers) = &cache.containers {
|
||||
for container in containers {
|
||||
if let Some(docker) = &cache.docker {
|
||||
for container in &docker.containers {
|
||||
res.total += 1;
|
||||
match container.state {
|
||||
ContainerStateStatusEnum::Created
|
||||
@@ -641,8 +642,8 @@ impl Resolve<ReadArgs> for ListDockerNetworks {
|
||||
let cache = server_status_cache()
|
||||
.get_or_insert_default(&server.id)
|
||||
.await;
|
||||
if let Some(networks) = &cache.networks {
|
||||
Ok(networks.clone())
|
||||
if let Some(docker) = &cache.docker {
|
||||
Ok(docker.networks.clone())
|
||||
} else {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
@@ -694,8 +695,8 @@ impl Resolve<ReadArgs> for ListDockerImages {
|
||||
let cache = server_status_cache()
|
||||
.get_or_insert_default(&server.id)
|
||||
.await;
|
||||
if let Some(images) = &cache.images {
|
||||
Ok(images.clone())
|
||||
if let Some(docker) = &cache.docker {
|
||||
Ok(docker.images.clone())
|
||||
} else {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
@@ -775,8 +776,8 @@ impl Resolve<ReadArgs> for ListDockerVolumes {
|
||||
let cache = server_status_cache()
|
||||
.get_or_insert_default(&server.id)
|
||||
.await;
|
||||
if let Some(volumes) = &cache.volumes {
|
||||
Ok(volumes.clone())
|
||||
if let Some(docker) = &cache.docker {
|
||||
Ok(docker.volumes.clone())
|
||||
} else {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
@@ -825,8 +826,8 @@ impl Resolve<ReadArgs> for ListComposeProjects {
|
||||
let cache = server_status_cache()
|
||||
.get_or_insert_default(&server.id)
|
||||
.await;
|
||||
if let Some(projects) = &cache.projects {
|
||||
Ok(projects.clone())
|
||||
if let Some(docker) = &cache.docker {
|
||||
Ok(docker.projects.clone())
|
||||
} else {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
140
bin/core/src/api/read/swarm.rs
Normal file
140
bin/core/src/api/read/swarm.rs
Normal file
@@ -0,0 +1,140 @@
|
||||
use anyhow::Context;
|
||||
use komodo_client::{
|
||||
api::read::*,
|
||||
entities::{
|
||||
permission::PermissionLevel,
|
||||
swarm::{Swarm, SwarmActionState, SwarmListItem, SwarmState},
|
||||
},
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{
|
||||
helpers::query::get_all_tags, permission::get_check_permissions,
|
||||
resource, state::{action_states, swarm_status_cache},
|
||||
};
|
||||
|
||||
use super::ReadArgs;
|
||||
|
||||
impl Resolve<ReadArgs> for GetSwarm {
|
||||
async fn resolve(
|
||||
self,
|
||||
ReadArgs { user }: &ReadArgs,
|
||||
) -> serror::Result<Swarm> {
|
||||
Ok(
|
||||
get_check_permissions::<Swarm>(
|
||||
&self.swarm,
|
||||
user,
|
||||
PermissionLevel::Read.into(),
|
||||
)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolve<ReadArgs> for ListSwarms {
|
||||
async fn resolve(
|
||||
self,
|
||||
ReadArgs { user }: &ReadArgs,
|
||||
) -> serror::Result<Vec<SwarmListItem>> {
|
||||
let all_tags = if self.query.tags.is_empty() {
|
||||
vec![]
|
||||
} else {
|
||||
get_all_tags(None).await?
|
||||
};
|
||||
Ok(
|
||||
resource::list_for_user::<Swarm>(
|
||||
self.query,
|
||||
user,
|
||||
PermissionLevel::Read.into(),
|
||||
&all_tags,
|
||||
)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolve<ReadArgs> for ListFullSwarms {
|
||||
async fn resolve(
|
||||
self,
|
||||
ReadArgs { user }: &ReadArgs,
|
||||
) -> serror::Result<ListFullSwarmsResponse> {
|
||||
let all_tags = if self.query.tags.is_empty() {
|
||||
vec![]
|
||||
} else {
|
||||
get_all_tags(None).await?
|
||||
};
|
||||
Ok(
|
||||
resource::list_full_for_user::<Swarm>(
|
||||
self.query,
|
||||
user,
|
||||
PermissionLevel::Read.into(),
|
||||
&all_tags,
|
||||
)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolve<ReadArgs> for GetSwarmActionState {
|
||||
async fn resolve(
|
||||
self,
|
||||
ReadArgs { user }: &ReadArgs,
|
||||
) -> serror::Result<SwarmActionState> {
|
||||
let swarm = get_check_permissions::<Swarm>(
|
||||
&self.swarm,
|
||||
user,
|
||||
PermissionLevel::Read.into(),
|
||||
)
|
||||
.await?;
|
||||
let action_state = action_states()
|
||||
.swarm
|
||||
.get(&swarm.id)
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
.get()?;
|
||||
Ok(action_state)
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolve<ReadArgs> for GetSwarmsSummary {
|
||||
async fn resolve(
|
||||
self,
|
||||
ReadArgs { user }: &ReadArgs,
|
||||
) -> serror::Result<GetSwarmsSummaryResponse> {
|
||||
let swarms = resource::list_full_for_user::<Swarm>(
|
||||
Default::default(),
|
||||
user,
|
||||
PermissionLevel::Read.into(),
|
||||
&[],
|
||||
)
|
||||
.await
|
||||
.context("failed to get swarms from db")?;
|
||||
|
||||
let mut res = GetSwarmsSummaryResponse::default();
|
||||
|
||||
let cache = swarm_status_cache();
|
||||
|
||||
for swarm in swarms {
|
||||
res.total += 1;
|
||||
|
||||
match cache
|
||||
.get(&swarm.id)
|
||||
.await
|
||||
.map(|status| status.state)
|
||||
.unwrap_or_default()
|
||||
{
|
||||
SwarmState::Unknown => {
|
||||
res.unknown += 1;
|
||||
}
|
||||
SwarmState::Healthy => {
|
||||
res.healthy += 1;
|
||||
}
|
||||
SwarmState::Unhealthy => {
|
||||
res.unhealthy += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ mod resource;
|
||||
mod server;
|
||||
mod service_user;
|
||||
mod stack;
|
||||
mod swarm;
|
||||
mod sync;
|
||||
mod tag;
|
||||
mod terminal;
|
||||
@@ -53,36 +54,16 @@ pub struct WriteArgs {
|
||||
#[error(serror::Error)]
|
||||
#[serde(tag = "type", content = "params")]
|
||||
pub enum WriteRequest {
|
||||
// ==== USER ====
|
||||
CreateLocalUser(CreateLocalUser),
|
||||
UpdateUserUsername(UpdateUserUsername),
|
||||
UpdateUserPassword(UpdateUserPassword),
|
||||
DeleteUser(DeleteUser),
|
||||
|
||||
// ==== SERVICE USER ====
|
||||
CreateServiceUser(CreateServiceUser),
|
||||
UpdateServiceUserDescription(UpdateServiceUserDescription),
|
||||
CreateApiKeyForServiceUser(CreateApiKeyForServiceUser),
|
||||
DeleteApiKeyForServiceUser(DeleteApiKeyForServiceUser),
|
||||
|
||||
// ==== USER GROUP ====
|
||||
CreateUserGroup(CreateUserGroup),
|
||||
RenameUserGroup(RenameUserGroup),
|
||||
DeleteUserGroup(DeleteUserGroup),
|
||||
AddUserToUserGroup(AddUserToUserGroup),
|
||||
RemoveUserFromUserGroup(RemoveUserFromUserGroup),
|
||||
SetUsersInUserGroup(SetUsersInUserGroup),
|
||||
SetEveryoneUserGroup(SetEveryoneUserGroup),
|
||||
|
||||
// ==== PERMISSIONS ====
|
||||
UpdateUserAdmin(UpdateUserAdmin),
|
||||
UpdateUserBasePermissions(UpdateUserBasePermissions),
|
||||
UpdatePermissionOnResourceType(UpdatePermissionOnResourceType),
|
||||
UpdatePermissionOnTarget(UpdatePermissionOnTarget),
|
||||
|
||||
// ==== RESOURCE ====
|
||||
UpdateResourceMeta(UpdateResourceMeta),
|
||||
|
||||
// ==== SWARM ====
|
||||
CreateSwarm(CreateSwarm),
|
||||
CopySwarm(CopySwarm),
|
||||
DeleteSwarm(DeleteSwarm),
|
||||
UpdateSwarm(UpdateSwarm),
|
||||
RenameSwarm(RenameSwarm),
|
||||
|
||||
// ==== SERVER ====
|
||||
CreateServer(CreateServer),
|
||||
CopyServer(CopyServer),
|
||||
@@ -93,6 +74,12 @@ pub enum WriteRequest {
|
||||
UpdateServerPublicKey(UpdateServerPublicKey),
|
||||
RotateServerKeys(RotateServerKeys),
|
||||
|
||||
// ==== TERMINAL ====
|
||||
CreateTerminal(CreateTerminal),
|
||||
DeleteTerminal(DeleteTerminal),
|
||||
DeleteAllTerminals(DeleteAllTerminals),
|
||||
BatchDeleteAllTerminals(BatchDeleteAllTerminals),
|
||||
|
||||
// ==== STACK ====
|
||||
CreateStack(CreateStack),
|
||||
CopyStack(CopyStack),
|
||||
@@ -119,13 +106,6 @@ pub enum WriteRequest {
|
||||
WriteBuildFileContents(WriteBuildFileContents),
|
||||
RefreshBuildCache(RefreshBuildCache),
|
||||
|
||||
// ==== BUILDER ====
|
||||
CreateBuilder(CreateBuilder),
|
||||
CopyBuilder(CopyBuilder),
|
||||
DeleteBuilder(DeleteBuilder),
|
||||
UpdateBuilder(UpdateBuilder),
|
||||
RenameBuilder(RenameBuilder),
|
||||
|
||||
// ==== REPO ====
|
||||
CreateRepo(CreateRepo),
|
||||
CopyRepo(CopyRepo),
|
||||
@@ -134,13 +114,6 @@ pub enum WriteRequest {
|
||||
RenameRepo(RenameRepo),
|
||||
RefreshRepoCache(RefreshRepoCache),
|
||||
|
||||
// ==== ALERTER ====
|
||||
CreateAlerter(CreateAlerter),
|
||||
CopyAlerter(CopyAlerter),
|
||||
DeleteAlerter(DeleteAlerter),
|
||||
UpdateAlerter(UpdateAlerter),
|
||||
RenameAlerter(RenameAlerter),
|
||||
|
||||
// ==== PROCEDURE ====
|
||||
CreateProcedure(CreateProcedure),
|
||||
CopyProcedure(CopyProcedure),
|
||||
@@ -165,11 +138,51 @@ pub enum WriteRequest {
|
||||
CommitSync(CommitSync),
|
||||
RefreshResourceSyncPending(RefreshResourceSyncPending),
|
||||
|
||||
// ==== TERMINAL ====
|
||||
CreateTerminal(CreateTerminal),
|
||||
DeleteTerminal(DeleteTerminal),
|
||||
DeleteAllTerminals(DeleteAllTerminals),
|
||||
BatchDeleteAllTerminals(BatchDeleteAllTerminals),
|
||||
// ==== BUILDER ====
|
||||
CreateBuilder(CreateBuilder),
|
||||
CopyBuilder(CopyBuilder),
|
||||
DeleteBuilder(DeleteBuilder),
|
||||
UpdateBuilder(UpdateBuilder),
|
||||
RenameBuilder(RenameBuilder),
|
||||
|
||||
// ==== ALERTER ====
|
||||
CreateAlerter(CreateAlerter),
|
||||
CopyAlerter(CopyAlerter),
|
||||
DeleteAlerter(DeleteAlerter),
|
||||
UpdateAlerter(UpdateAlerter),
|
||||
RenameAlerter(RenameAlerter),
|
||||
|
||||
// ==== ONBOARDING KEY ====
|
||||
CreateOnboardingKey(CreateOnboardingKey),
|
||||
UpdateOnboardingKey(UpdateOnboardingKey),
|
||||
DeleteOnboardingKey(DeleteOnboardingKey),
|
||||
|
||||
// ==== USER ====
|
||||
CreateLocalUser(CreateLocalUser),
|
||||
UpdateUserUsername(UpdateUserUsername),
|
||||
UpdateUserPassword(UpdateUserPassword),
|
||||
DeleteUser(DeleteUser),
|
||||
|
||||
// ==== SERVICE USER ====
|
||||
CreateServiceUser(CreateServiceUser),
|
||||
UpdateServiceUserDescription(UpdateServiceUserDescription),
|
||||
CreateApiKeyForServiceUser(CreateApiKeyForServiceUser),
|
||||
DeleteApiKeyForServiceUser(DeleteApiKeyForServiceUser),
|
||||
|
||||
// ==== USER GROUP ====
|
||||
CreateUserGroup(CreateUserGroup),
|
||||
RenameUserGroup(RenameUserGroup),
|
||||
DeleteUserGroup(DeleteUserGroup),
|
||||
AddUserToUserGroup(AddUserToUserGroup),
|
||||
RemoveUserFromUserGroup(RemoveUserFromUserGroup),
|
||||
SetUsersInUserGroup(SetUsersInUserGroup),
|
||||
SetEveryoneUserGroup(SetEveryoneUserGroup),
|
||||
|
||||
// ==== PERMISSIONS ====
|
||||
UpdateUserAdmin(UpdateUserAdmin),
|
||||
UpdateUserBasePermissions(UpdateUserBasePermissions),
|
||||
UpdatePermissionOnResourceType(UpdatePermissionOnResourceType),
|
||||
UpdatePermissionOnTarget(UpdatePermissionOnTarget),
|
||||
|
||||
// ==== TAG ====
|
||||
CreateTag(CreateTag),
|
||||
@@ -192,11 +205,6 @@ pub enum WriteRequest {
|
||||
UpdateDockerRegistryAccount(UpdateDockerRegistryAccount),
|
||||
DeleteDockerRegistryAccount(DeleteDockerRegistryAccount),
|
||||
|
||||
// ==== ONBOARDING KEY ====
|
||||
CreateOnboardingKey(CreateOnboardingKey),
|
||||
UpdateOnboardingKey(UpdateOnboardingKey),
|
||||
DeleteOnboardingKey(DeleteOnboardingKey),
|
||||
|
||||
// ==== ALERT ====
|
||||
CloseAlert(CloseAlert),
|
||||
}
|
||||
|
||||
108
bin/core/src/api/write/swarm.rs
Normal file
108
bin/core/src/api/write/swarm.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
use komodo_client::{
|
||||
api::write::*,
|
||||
entities::{
|
||||
permission::PermissionLevel, swarm::Swarm, update::Update,
|
||||
},
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{permission::get_check_permissions, resource};
|
||||
|
||||
use super::WriteArgs;
|
||||
|
||||
impl Resolve<WriteArgs> for CreateSwarm {
|
||||
#[instrument(
|
||||
"CreateSwarm",
|
||||
skip_all,
|
||||
fields(
|
||||
operator = user.id,
|
||||
swarm = self.name,
|
||||
config = serde_json::to_string(&self.config).unwrap(),
|
||||
)
|
||||
)]
|
||||
async fn resolve(
|
||||
self,
|
||||
WriteArgs { user }: &WriteArgs,
|
||||
) -> serror::Result<Swarm> {
|
||||
resource::create::<Swarm>(&self.name, self.config, None, user)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolve<WriteArgs> for CopySwarm {
|
||||
#[instrument(
|
||||
"CopySwarm",
|
||||
skip_all,
|
||||
fields(
|
||||
operator = user.id,
|
||||
swarm = self.name,
|
||||
copy_swarm = self.id,
|
||||
)
|
||||
)]
|
||||
async fn resolve(
|
||||
self,
|
||||
WriteArgs { user }: &WriteArgs,
|
||||
) -> serror::Result<Swarm> {
|
||||
let Swarm { config, .. } = get_check_permissions::<Swarm>(
|
||||
&self.id,
|
||||
user,
|
||||
PermissionLevel::Read.into(),
|
||||
)
|
||||
.await?;
|
||||
resource::create::<Swarm>(&self.name, config.into(), None, user)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolve<WriteArgs> for DeleteSwarm {
|
||||
#[instrument(
|
||||
"DeleteSwarm",
|
||||
skip_all,
|
||||
fields(
|
||||
operator = user.id,
|
||||
swarm = self.id,
|
||||
)
|
||||
)]
|
||||
async fn resolve(
|
||||
self,
|
||||
WriteArgs { user }: &WriteArgs,
|
||||
) -> serror::Result<Swarm> {
|
||||
Ok(resource::delete::<Swarm>(&self.id, user).await?)
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolve<WriteArgs> for UpdateSwarm {
|
||||
#[instrument(
|
||||
"UpdateSwarm",
|
||||
skip_all,
|
||||
fields(
|
||||
operator = user.id,
|
||||
swarm = self.id,
|
||||
update = serde_json::to_string(&self.config).unwrap()
|
||||
)
|
||||
)]
|
||||
async fn resolve(
|
||||
self,
|
||||
WriteArgs { user }: &WriteArgs,
|
||||
) -> serror::Result<Swarm> {
|
||||
Ok(resource::update::<Swarm>(&self.id, self.config, user).await?)
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolve<WriteArgs> for RenameSwarm {
|
||||
#[instrument(
|
||||
"RenameSwarm",
|
||||
skip_all,
|
||||
fields(
|
||||
operator = user.id,
|
||||
swarm = self.id,
|
||||
new_name = self.name
|
||||
)
|
||||
)]
|
||||
async fn resolve(
|
||||
self,
|
||||
WriteArgs { user }: &WriteArgs,
|
||||
) -> serror::Result<Update> {
|
||||
Ok(resource::rename::<Swarm>(&self.id, &self.name, user).await?)
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,6 @@ impl PeripheryConnectionArgs<'_> {
|
||||
periphery_connections().insert(id.clone(), self).await;
|
||||
|
||||
let responses = connection.responses.clone();
|
||||
let terminals = connection.terminals.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
@@ -94,7 +93,6 @@ impl PeripheryConnectionArgs<'_> {
|
||||
Ok(PeripheryClient {
|
||||
id,
|
||||
responses,
|
||||
terminals,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,13 @@ use komodo_client::{
|
||||
deployment::DeploymentActionState,
|
||||
procedure::ProcedureActionState, repo::RepoActionState,
|
||||
server::ServerActionState, stack::StackActionState,
|
||||
sync::ResourceSyncActionState,
|
||||
swarm::SwarmActionState, sync::ResourceSyncActionState,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ActionStates {
|
||||
pub swarm: CloneCache<String, Arc<ActionState<SwarmActionState>>>,
|
||||
pub server: CloneCache<String, Arc<ActionState<ServerActionState>>>,
|
||||
pub stack: CloneCache<String, Arc<ActionState<StackActionState>>>,
|
||||
pub deployment:
|
||||
|
||||
@@ -76,7 +76,7 @@ async fn app() -> anyhow::Result<()> {
|
||||
startup::on_startup().await;
|
||||
|
||||
// Spawn background tasks
|
||||
monitor::spawn_monitor_loop();
|
||||
monitor::spawn_monitoring_loops();
|
||||
resource::spawn_resource_refresh_loop();
|
||||
resource::spawn_all_resources_cache_refresh_loop();
|
||||
resource::spawn_build_state_refresh_loop();
|
||||
|
||||
@@ -1,29 +1,73 @@
|
||||
use komodo_client::entities::{
|
||||
alert::SeverityLevel,
|
||||
deployment::{Deployment, DeploymentState},
|
||||
docker::{
|
||||
container::ContainerListItem, image::ImageListItem,
|
||||
network::NetworkListItem, volume::VolumeListItem,
|
||||
},
|
||||
docker::DockerLists,
|
||||
repo::Repo,
|
||||
server::{
|
||||
PeripheryInformation, Server, ServerConfig, ServerHealth,
|
||||
ServerHealthState, ServerState,
|
||||
},
|
||||
stack::{ComposeProject, Stack, StackState},
|
||||
stack::{Stack, StackState},
|
||||
stats::{SingleDiskUsage, SystemInformation, SystemStats},
|
||||
};
|
||||
use serror::Serror;
|
||||
|
||||
use crate::state::{
|
||||
deployment_status_cache, repo_status_cache, server_status_cache,
|
||||
stack_status_cache,
|
||||
CachedDeploymentStatus, CachedRepoStatus, CachedServerStatus,
|
||||
CachedStackStatus, History, deployment_status_cache,
|
||||
repo_status_cache, server_status_cache, stack_status_cache,
|
||||
};
|
||||
|
||||
use super::{
|
||||
CachedDeploymentStatus, CachedRepoStatus, CachedServerStatus,
|
||||
CachedStackStatus, History,
|
||||
};
|
||||
pub async fn insert_server_status(
|
||||
server: &Server,
|
||||
state: ServerState,
|
||||
periphery_info: Option<PeripheryInformation>,
|
||||
system_info: Option<SystemInformation>,
|
||||
system_stats: Option<SystemStats>,
|
||||
docker: Option<DockerLists>,
|
||||
err: impl Into<Option<Serror>>,
|
||||
) {
|
||||
let health =
|
||||
system_stats.as_ref().map(|s| get_server_health(server, s));
|
||||
server_status_cache()
|
||||
.insert(
|
||||
server.id.clone(),
|
||||
CachedServerStatus {
|
||||
id: server.id.clone(),
|
||||
state,
|
||||
periphery_info,
|
||||
system_info,
|
||||
system_stats,
|
||||
health,
|
||||
docker,
|
||||
err: err.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
pub async fn insert_stacks_status_unknown(stacks: Vec<Stack>) {
|
||||
let status_cache = stack_status_cache();
|
||||
for stack in stacks {
|
||||
let prev =
|
||||
status_cache.get(&stack.id).await.map(|s| s.curr.state);
|
||||
status_cache
|
||||
.insert(
|
||||
stack.id.clone(),
|
||||
History {
|
||||
curr: CachedStackStatus {
|
||||
id: stack.id,
|
||||
state: StackState::Unknown,
|
||||
services: Vec::new(),
|
||||
},
|
||||
prev,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn insert_deployments_status_unknown(
|
||||
deployments: Vec<Deployment>,
|
||||
@@ -66,69 +110,6 @@ pub async fn insert_repos_status_unknown(repos: Vec<Repo>) {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn insert_stacks_status_unknown(stacks: Vec<Stack>) {
|
||||
let status_cache = stack_status_cache();
|
||||
for stack in stacks {
|
||||
let prev =
|
||||
status_cache.get(&stack.id).await.map(|s| s.curr.state);
|
||||
status_cache
|
||||
.insert(
|
||||
stack.id.clone(),
|
||||
History {
|
||||
curr: CachedStackStatus {
|
||||
id: stack.id,
|
||||
state: StackState::Unknown,
|
||||
services: Vec::new(),
|
||||
},
|
||||
prev,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
type DockerLists = (
|
||||
Option<Vec<ContainerListItem>>,
|
||||
Option<Vec<NetworkListItem>>,
|
||||
Option<Vec<ImageListItem>>,
|
||||
Option<Vec<VolumeListItem>>,
|
||||
Option<Vec<ComposeProject>>,
|
||||
);
|
||||
|
||||
pub async fn insert_server_status(
|
||||
server: &Server,
|
||||
state: ServerState,
|
||||
periphery_info: Option<PeripheryInformation>,
|
||||
system_info: Option<SystemInformation>,
|
||||
system_stats: Option<SystemStats>,
|
||||
(containers, networks, images, volumes, projects): DockerLists,
|
||||
err: impl Into<Option<Serror>>,
|
||||
) {
|
||||
let health =
|
||||
system_stats.as_ref().map(|s| get_server_health(server, s));
|
||||
server_status_cache()
|
||||
.insert(
|
||||
server.id.clone(),
|
||||
CachedServerStatus {
|
||||
id: server.id.clone(),
|
||||
state,
|
||||
periphery_info,
|
||||
system_info,
|
||||
system_stats,
|
||||
health,
|
||||
containers,
|
||||
networks,
|
||||
images,
|
||||
volumes,
|
||||
projects,
|
||||
err: err.into(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
const ALERT_PERCENTAGE_THRESHOLD: f32 = 5.0;
|
||||
|
||||
fn get_server_health(
|
||||
|
||||
@@ -7,19 +7,15 @@ use futures_util::future::join_all;
|
||||
use helpers::insert_stacks_status_unknown;
|
||||
use komodo_client::entities::{
|
||||
build::Build,
|
||||
deployment::{Deployment, DeploymentState},
|
||||
docker::{
|
||||
container::ContainerListItem, image::ImageListItem,
|
||||
network::NetworkListItem, volume::VolumeListItem,
|
||||
},
|
||||
deployment::Deployment,
|
||||
komodo_timestamp, optional_string,
|
||||
repo::Repo,
|
||||
server::{PeripheryInformation, Server, ServerHealth, ServerState},
|
||||
stack::{ComposeProject, Stack, StackService, StackState},
|
||||
stats::{SystemInformation, SystemStats},
|
||||
server::{Server, ServerState},
|
||||
stack::Stack,
|
||||
stats::SystemStats,
|
||||
};
|
||||
use periphery_client::api::{
|
||||
self, PollStatusResponse, git::GetLatestCommit,
|
||||
self, git::GetLatestCommit, poll::PollStatusResponse,
|
||||
};
|
||||
use serror::Serror;
|
||||
use tokio::sync::Mutex;
|
||||
@@ -29,8 +25,8 @@ use crate::{
|
||||
helpers::periphery_client,
|
||||
monitor::{alert::check_alerts, record::record_server_stats},
|
||||
state::{
|
||||
db_client, deployment_status_cache, periphery_connections,
|
||||
repo_status_cache,
|
||||
CachedRepoStatus, db_client, deployment_status_cache,
|
||||
periphery_connections, repo_status_cache,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -43,62 +39,24 @@ mod alert;
|
||||
mod helpers;
|
||||
mod record;
|
||||
mod resources;
|
||||
mod swarm;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct History<Curr: Default, Prev> {
|
||||
pub curr: Curr,
|
||||
pub prev: Option<Prev>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct CachedServerStatus {
|
||||
pub id: String,
|
||||
pub state: ServerState,
|
||||
pub health: Option<ServerHealth>,
|
||||
pub periphery_info: Option<PeripheryInformation>,
|
||||
pub system_info: Option<SystemInformation>,
|
||||
pub system_stats: Option<SystemStats>,
|
||||
pub containers: Option<Vec<ContainerListItem>>,
|
||||
pub networks: Option<Vec<NetworkListItem>>,
|
||||
pub images: Option<Vec<ImageListItem>>,
|
||||
pub volumes: Option<Vec<VolumeListItem>>,
|
||||
pub projects: Option<Vec<ComposeProject>>,
|
||||
/// Store the error in reaching periphery
|
||||
pub err: Option<serror::Serror>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct CachedDeploymentStatus {
|
||||
/// The deployment id
|
||||
pub id: String,
|
||||
pub state: DeploymentState,
|
||||
pub container: Option<ContainerListItem>,
|
||||
pub update_available: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct CachedRepoStatus {
|
||||
pub latest_hash: Option<String>,
|
||||
pub latest_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct CachedStackStatus {
|
||||
/// The stack id
|
||||
pub id: String,
|
||||
/// The stack state
|
||||
pub state: StackState,
|
||||
/// The services connected to the stack
|
||||
pub services: Vec<StackService>,
|
||||
}
|
||||
pub use swarm::update_cache_for_swarm;
|
||||
|
||||
const ADDITIONAL_MS: u128 = 500;
|
||||
|
||||
pub fn spawn_monitor_loop() {
|
||||
let interval: async_timing_util::Timelength = core_config()
|
||||
pub fn spawn_monitoring_loops() {
|
||||
let interval = core_config()
|
||||
.monitoring_interval
|
||||
.try_into()
|
||||
.expect("Invalid monitoring interval");
|
||||
spawn_server_monitoring_loop(interval);
|
||||
swarm::spawn_swarm_monitoring_loop(interval);
|
||||
}
|
||||
|
||||
fn spawn_server_monitoring_loop(
|
||||
interval: async_timing_util::Timelength,
|
||||
) {
|
||||
tokio::spawn(async move {
|
||||
refresh_server_cache(komodo_timestamp()).await;
|
||||
loop {
|
||||
@@ -115,7 +73,7 @@ async fn refresh_server_cache(ts: i64) {
|
||||
Ok(servers) => servers,
|
||||
Err(e) => {
|
||||
error!(
|
||||
"failed to get server list (manage status cache) | {e:#}"
|
||||
"Failed to get server list (refresh server cache) | {e:#}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -172,7 +130,7 @@ pub async fn update_cache_for_server(server: &Server, force: bool) {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
(None, None, None, None, None),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
@@ -190,7 +148,7 @@ pub async fn update_cache_for_server(server: &Server, force: bool) {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
(None, None, None, None, None),
|
||||
None,
|
||||
Serror::from(&e),
|
||||
)
|
||||
.await;
|
||||
@@ -202,14 +160,11 @@ pub async fn update_cache_for_server(server: &Server, force: bool) {
|
||||
periphery_info,
|
||||
system_info,
|
||||
system_stats,
|
||||
mut containers,
|
||||
networks,
|
||||
images,
|
||||
volumes,
|
||||
projects,
|
||||
mut docker,
|
||||
} = match periphery
|
||||
.request(api::PollStatus {
|
||||
.request(api::poll::PollStatus {
|
||||
include_stats: server.config.stats_monitoring,
|
||||
include_docker: true,
|
||||
})
|
||||
.await
|
||||
{
|
||||
@@ -222,7 +177,7 @@ pub async fn update_cache_for_server(server: &Server, force: bool) {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
(None, None, None, None, None),
|
||||
None,
|
||||
Serror::from(&e),
|
||||
)
|
||||
.await;
|
||||
@@ -230,37 +185,44 @@ pub async fn update_cache_for_server(server: &Server, force: bool) {
|
||||
}
|
||||
};
|
||||
|
||||
containers.iter_mut().for_each(|container| {
|
||||
container.server_id = Some(server.id.clone())
|
||||
});
|
||||
if let Some(docker) = &mut docker {
|
||||
docker.containers.iter_mut().for_each(|container| {
|
||||
container.server_id = Some(server.id.clone())
|
||||
});
|
||||
}
|
||||
|
||||
let containers = docker
|
||||
.as_ref()
|
||||
.map(|docker| docker.containers.as_slice())
|
||||
.unwrap_or(&[]);
|
||||
let images = docker
|
||||
.as_ref()
|
||||
.map(|docker| docker.images.as_slice())
|
||||
.unwrap_or(&[]);
|
||||
|
||||
tokio::join!(
|
||||
resources::update_deployment_cache(
|
||||
server.name.clone(),
|
||||
resources.deployments,
|
||||
&containers,
|
||||
&images,
|
||||
containers,
|
||||
images,
|
||||
&resources.builds,
|
||||
),
|
||||
resources::update_stack_cache(
|
||||
server.name.clone(),
|
||||
resources.stacks,
|
||||
&containers,
|
||||
&images
|
||||
containers,
|
||||
images
|
||||
),
|
||||
);
|
||||
|
||||
insert_server_status(
|
||||
server,
|
||||
ServerState::Ok,
|
||||
Some(periphery_info),
|
||||
Some(system_info),
|
||||
system_stats.map(|stats| filter_volumes(server, stats)),
|
||||
(
|
||||
Some(containers.clone()),
|
||||
Some(networks),
|
||||
Some(images),
|
||||
Some(volumes),
|
||||
Some(projects),
|
||||
),
|
||||
docker,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -30,200 +30,12 @@ use crate::{
|
||||
services::extract_services_from_stack,
|
||||
},
|
||||
state::{
|
||||
CachedDeploymentStatus, CachedStackStatus, History,
|
||||
action_states, db_client, deployment_status_cache,
|
||||
stack_status_cache,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{CachedDeploymentStatus, CachedStackStatus, History};
|
||||
|
||||
fn deployment_alert_sent_cache() -> &'static Mutex<HashSet<String>> {
|
||||
static CACHE: OnceLock<Mutex<HashSet<String>>> = OnceLock::new();
|
||||
CACHE.get_or_init(Default::default)
|
||||
}
|
||||
|
||||
pub async fn update_deployment_cache(
|
||||
server_name: String,
|
||||
deployments: Vec<Deployment>,
|
||||
containers: &[ContainerListItem],
|
||||
images: &[ImageListItem],
|
||||
builds: &[Build],
|
||||
) {
|
||||
let deployment_status_cache = deployment_status_cache();
|
||||
for deployment in deployments {
|
||||
let container = containers
|
||||
.iter()
|
||||
.find(|container| container.name == deployment.name)
|
||||
.cloned();
|
||||
let prev = deployment_status_cache
|
||||
.get(&deployment.id)
|
||||
.await
|
||||
.map(|s| s.curr.state);
|
||||
let state = container
|
||||
.as_ref()
|
||||
.map(|c| c.state.into())
|
||||
.unwrap_or(DeploymentState::NotDeployed);
|
||||
let image = match deployment.config.image {
|
||||
DeploymentImage::Build { build_id, version } => {
|
||||
let (build_name, build_version) = builds
|
||||
.iter()
|
||||
.find(|build| build.id == build_id)
|
||||
.map(|b| (b.name.as_ref(), b.config.version))
|
||||
.unwrap_or(("Unknown", Default::default()));
|
||||
let version = if version.is_none() {
|
||||
build_version.to_string()
|
||||
} else {
|
||||
version.to_string()
|
||||
};
|
||||
format!("{build_name}:{version}")
|
||||
}
|
||||
DeploymentImage::Image { image } => {
|
||||
// If image already has tag, leave it,
|
||||
// otherwise default the tag to latest
|
||||
if image.contains(':') {
|
||||
image.to_string()
|
||||
} else {
|
||||
format!("{image}:latest")
|
||||
}
|
||||
}
|
||||
};
|
||||
let update_available = if let Some(ContainerListItem {
|
||||
image_id: Some(curr_image_id),
|
||||
..
|
||||
}) = &container
|
||||
{
|
||||
// Docker will automatically strip `docker.io` from incoming image names re #468.
|
||||
// Need to strip it in order to match by image name and find available updates.
|
||||
let image = image.strip_prefix("docker.io/").unwrap_or(&image);
|
||||
images
|
||||
.iter()
|
||||
.find(|i| i.name == image)
|
||||
.map(|i| &i.id != curr_image_id)
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if update_available {
|
||||
if deployment.config.auto_update {
|
||||
if state == DeploymentState::Running
|
||||
&& !action_states()
|
||||
.deployment
|
||||
.get_or_insert_default(&deployment.id)
|
||||
.await
|
||||
.busy()
|
||||
.unwrap_or(true)
|
||||
{
|
||||
let id = deployment.id.clone();
|
||||
let server_name = server_name.clone();
|
||||
tokio::spawn(async move {
|
||||
match execute::inner_handler(
|
||||
ExecuteRequest::Deploy(Deploy {
|
||||
deployment: deployment.name.clone(),
|
||||
stop_time: None,
|
||||
stop_signal: None,
|
||||
}),
|
||||
auto_redeploy_user().to_owned(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
let ts = komodo_timestamp();
|
||||
let alert = Alert {
|
||||
id: Default::default(),
|
||||
ts,
|
||||
resolved: true,
|
||||
resolved_ts: ts.into(),
|
||||
level: SeverityLevel::Ok,
|
||||
target: ResourceTarget::Deployment(id.clone()),
|
||||
data: AlertData::DeploymentAutoUpdated {
|
||||
id,
|
||||
name: deployment.name,
|
||||
server_name,
|
||||
server_id: deployment.config.server_id,
|
||||
image,
|
||||
},
|
||||
};
|
||||
let res = db_client().alerts.insert_one(&alert).await;
|
||||
if let Err(e) = res {
|
||||
error!(
|
||||
"Failed to record DeploymentAutoUpdated to db | {e:#}"
|
||||
);
|
||||
}
|
||||
send_alerts(&[alert]).await;
|
||||
}
|
||||
Err(e) => {
|
||||
warn!(
|
||||
"Failed to auto update Deployment {} | {e:#}",
|
||||
deployment.name
|
||||
)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if state == DeploymentState::Running
|
||||
&& deployment.config.send_alerts
|
||||
&& !deployment_alert_sent_cache()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.contains(&deployment.id)
|
||||
{
|
||||
// Add that it is already sent to the cache, so another alert won't be sent.
|
||||
deployment_alert_sent_cache()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(deployment.id.clone());
|
||||
let ts = komodo_timestamp();
|
||||
let alert = Alert {
|
||||
id: Default::default(),
|
||||
ts,
|
||||
resolved: true,
|
||||
resolved_ts: ts.into(),
|
||||
level: SeverityLevel::Ok,
|
||||
target: ResourceTarget::Deployment(deployment.id.clone()),
|
||||
data: AlertData::DeploymentImageUpdateAvailable {
|
||||
id: deployment.id.clone(),
|
||||
name: deployment.name,
|
||||
server_name: server_name.clone(),
|
||||
server_id: deployment.config.server_id,
|
||||
image,
|
||||
},
|
||||
};
|
||||
let res = db_client().alerts.insert_one(&alert).await;
|
||||
if let Err(e) = res {
|
||||
error!(
|
||||
"Failed to record DeploymentImageUpdateAvailable to db | {e:#}"
|
||||
);
|
||||
}
|
||||
send_alerts(&[alert]).await;
|
||||
}
|
||||
} else {
|
||||
// If it sees there is no longer update available, remove
|
||||
// from the sent cache, so on next `update_available = true`
|
||||
// the cache is empty and a fresh alert will be sent.
|
||||
deployment_alert_sent_cache()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.remove(&deployment.id);
|
||||
}
|
||||
deployment_status_cache
|
||||
.insert(
|
||||
deployment.id.clone(),
|
||||
History {
|
||||
curr: CachedDeploymentStatus {
|
||||
id: deployment.id,
|
||||
state,
|
||||
container,
|
||||
update_available,
|
||||
},
|
||||
prev,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
/// (StackId, Service)
|
||||
fn stack_alert_sent_cache()
|
||||
-> &'static Mutex<HashSet<(String, String)>> {
|
||||
@@ -425,3 +237,190 @@ pub async fn update_stack_cache(
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
fn deployment_alert_sent_cache() -> &'static Mutex<HashSet<String>> {
|
||||
static CACHE: OnceLock<Mutex<HashSet<String>>> = OnceLock::new();
|
||||
CACHE.get_or_init(Default::default)
|
||||
}
|
||||
|
||||
pub async fn update_deployment_cache(
|
||||
server_name: String,
|
||||
deployments: Vec<Deployment>,
|
||||
containers: &[ContainerListItem],
|
||||
images: &[ImageListItem],
|
||||
builds: &[Build],
|
||||
) {
|
||||
let deployment_status_cache = deployment_status_cache();
|
||||
for deployment in deployments {
|
||||
let container = containers
|
||||
.iter()
|
||||
.find(|container| container.name == deployment.name)
|
||||
.cloned();
|
||||
let prev = deployment_status_cache
|
||||
.get(&deployment.id)
|
||||
.await
|
||||
.map(|s| s.curr.state);
|
||||
let state = container
|
||||
.as_ref()
|
||||
.map(|c| c.state.into())
|
||||
.unwrap_or(DeploymentState::NotDeployed);
|
||||
let image = match deployment.config.image {
|
||||
DeploymentImage::Build { build_id, version } => {
|
||||
let (build_name, build_version) = builds
|
||||
.iter()
|
||||
.find(|build| build.id == build_id)
|
||||
.map(|b| (b.name.as_ref(), b.config.version))
|
||||
.unwrap_or(("Unknown", Default::default()));
|
||||
let version = if version.is_none() {
|
||||
build_version.to_string()
|
||||
} else {
|
||||
version.to_string()
|
||||
};
|
||||
format!("{build_name}:{version}")
|
||||
}
|
||||
DeploymentImage::Image { image } => {
|
||||
// If image already has tag, leave it,
|
||||
// otherwise default the tag to latest
|
||||
if image.contains(':') {
|
||||
image.to_string()
|
||||
} else {
|
||||
format!("{image}:latest")
|
||||
}
|
||||
}
|
||||
};
|
||||
let update_available = if let Some(ContainerListItem {
|
||||
image_id: Some(curr_image_id),
|
||||
..
|
||||
}) = &container
|
||||
{
|
||||
// Docker will automatically strip `docker.io` from incoming image names re #468.
|
||||
// Need to strip it in order to match by image name and find available updates.
|
||||
let image = image.strip_prefix("docker.io/").unwrap_or(&image);
|
||||
images
|
||||
.iter()
|
||||
.find(|i| i.name == image)
|
||||
.map(|i| &i.id != curr_image_id)
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if update_available {
|
||||
if deployment.config.auto_update {
|
||||
if state == DeploymentState::Running
|
||||
&& !action_states()
|
||||
.deployment
|
||||
.get_or_insert_default(&deployment.id)
|
||||
.await
|
||||
.busy()
|
||||
.unwrap_or(true)
|
||||
{
|
||||
let id = deployment.id.clone();
|
||||
let server_name = server_name.clone();
|
||||
tokio::spawn(async move {
|
||||
match execute::inner_handler(
|
||||
ExecuteRequest::Deploy(Deploy {
|
||||
deployment: deployment.name.clone(),
|
||||
stop_time: None,
|
||||
stop_signal: None,
|
||||
}),
|
||||
auto_redeploy_user().to_owned(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(_) => {
|
||||
let ts = komodo_timestamp();
|
||||
let alert = Alert {
|
||||
id: Default::default(),
|
||||
ts,
|
||||
resolved: true,
|
||||
resolved_ts: ts.into(),
|
||||
level: SeverityLevel::Ok,
|
||||
target: ResourceTarget::Deployment(id.clone()),
|
||||
data: AlertData::DeploymentAutoUpdated {
|
||||
id,
|
||||
name: deployment.name,
|
||||
server_name,
|
||||
server_id: deployment.config.server_id,
|
||||
image,
|
||||
},
|
||||
};
|
||||
let res = db_client().alerts.insert_one(&alert).await;
|
||||
if let Err(e) = res {
|
||||
error!(
|
||||
"Failed to record DeploymentAutoUpdated to db | {e:#}"
|
||||
);
|
||||
}
|
||||
send_alerts(&[alert]).await;
|
||||
}
|
||||
Err(e) => {
|
||||
warn!(
|
||||
"Failed to auto update Deployment {} | {e:#}",
|
||||
deployment.name
|
||||
)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if state == DeploymentState::Running
|
||||
&& deployment.config.send_alerts
|
||||
&& !deployment_alert_sent_cache()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.contains(&deployment.id)
|
||||
{
|
||||
// Add that it is already sent to the cache, so another alert won't be sent.
|
||||
deployment_alert_sent_cache()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(deployment.id.clone());
|
||||
let ts = komodo_timestamp();
|
||||
let alert = Alert {
|
||||
id: Default::default(),
|
||||
ts,
|
||||
resolved: true,
|
||||
resolved_ts: ts.into(),
|
||||
level: SeverityLevel::Ok,
|
||||
target: ResourceTarget::Deployment(deployment.id.clone()),
|
||||
data: AlertData::DeploymentImageUpdateAvailable {
|
||||
id: deployment.id.clone(),
|
||||
name: deployment.name,
|
||||
server_name: server_name.clone(),
|
||||
server_id: deployment.config.server_id,
|
||||
image,
|
||||
},
|
||||
};
|
||||
let res = db_client().alerts.insert_one(&alert).await;
|
||||
if let Err(e) = res {
|
||||
error!(
|
||||
"Failed to record DeploymentImageUpdateAvailable to db | {e:#}"
|
||||
);
|
||||
}
|
||||
send_alerts(&[alert]).await;
|
||||
}
|
||||
} else {
|
||||
// If it sees there is no longer update available, remove
|
||||
// from the sent cache, so on next `update_available = true`
|
||||
// the cache is empty and a fresh alert will be sent.
|
||||
deployment_alert_sent_cache()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.remove(&deployment.id);
|
||||
}
|
||||
deployment_status_cache
|
||||
.insert(
|
||||
deployment.id.clone(),
|
||||
History {
|
||||
curr: CachedDeploymentStatus {
|
||||
id: deployment.id,
|
||||
state,
|
||||
container,
|
||||
update_available,
|
||||
},
|
||||
prev,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
186
bin/core/src/monitor/swarm.rs
Normal file
186
bin/core/src/monitor/swarm.rs
Normal file
@@ -0,0 +1,186 @@
|
||||
use std::{
|
||||
sync::{Arc, OnceLock},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use async_timing_util::wait_until_timelength;
|
||||
use cache::CloneCache;
|
||||
use database::mungos::find::find_collect;
|
||||
use futures_util::future::join_all;
|
||||
use komodo_client::entities::{
|
||||
docker::node::NodeState,
|
||||
komodo_timestamp,
|
||||
server::Server,
|
||||
swarm::{Swarm, SwarmState},
|
||||
};
|
||||
use periphery_client::api::swarm::{
|
||||
PollSwarmStatus, PollSwarmStatusResponse,
|
||||
};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::{
|
||||
helpers::periphery_client,
|
||||
resource,
|
||||
state::{CachedSwarmStatus, db_client, swarm_status_cache},
|
||||
};
|
||||
|
||||
const ADDITIONAL_MS: u128 = 1000;
|
||||
|
||||
pub fn spawn_swarm_monitoring_loop(
|
||||
interval: async_timing_util::Timelength,
|
||||
) {
|
||||
tokio::spawn(async move {
|
||||
refresh_swarm_cache(komodo_timestamp()).await;
|
||||
loop {
|
||||
let ts = (wait_until_timelength(interval, ADDITIONAL_MS).await
|
||||
- ADDITIONAL_MS) as i64;
|
||||
refresh_swarm_cache(ts).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async fn refresh_swarm_cache(_ts: i64) {
|
||||
let swarms =
|
||||
match find_collect(&db_client().swarms, None, None).await {
|
||||
Ok(swarms) => swarms,
|
||||
Err(e) => {
|
||||
error!(
|
||||
"Failed to get swarm list (refresh swarm cache) | {e:#}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let futures = swarms.into_iter().map(|swarm| async move {
|
||||
update_cache_for_swarm(&swarm, false).await;
|
||||
});
|
||||
join_all(futures).await;
|
||||
// tokio::join!(check_alerts(ts), record_swarm_stats(ts));
|
||||
}
|
||||
|
||||
/// Makes sure cache for swarm doesn't update too frequently / simultaneously.
|
||||
/// If forced, will still block against simultaneous update.
|
||||
fn update_cache_for_swarm_controller()
|
||||
-> &'static CloneCache<String, Arc<Mutex<i64>>> {
|
||||
static CACHE: OnceLock<CloneCache<String, Arc<Mutex<i64>>>> =
|
||||
OnceLock::new();
|
||||
CACHE.get_or_init(Default::default)
|
||||
}
|
||||
|
||||
/// The background loop will call this with force: false,
|
||||
/// which exits early if the lock is busy or it was completed too recently.
|
||||
/// If force is true, it will wait on simultaneous calls, and will
|
||||
/// ignore the restriction on being completed too recently.
|
||||
pub async fn update_cache_for_swarm(swarm: &Swarm, force: bool) {
|
||||
// Concurrency controller to ensure it isn't done too often
|
||||
// when it happens in other contexts.
|
||||
let controller = update_cache_for_swarm_controller()
|
||||
.get_or_insert_default(&swarm.id)
|
||||
.await;
|
||||
let mut lock = match controller.try_lock() {
|
||||
Ok(lock) => lock,
|
||||
Err(_) if force => controller.lock().await,
|
||||
Err(_) => return,
|
||||
};
|
||||
|
||||
let now = komodo_timestamp();
|
||||
|
||||
// early return if called again sooner than 1s.
|
||||
if !force && *lock > now - 1_000 {
|
||||
return;
|
||||
}
|
||||
|
||||
*lock = now;
|
||||
|
||||
if swarm.config.server_ids.is_empty() {
|
||||
swarm_status_cache()
|
||||
.insert(
|
||||
swarm.id.clone(),
|
||||
CachedSwarmStatus {
|
||||
state: SwarmState::Unknown,
|
||||
inspect: None,
|
||||
lists: None,
|
||||
err: Some(
|
||||
anyhow!("No Servers configured as manager nodes").into(),
|
||||
),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
|
||||
let PollSwarmStatusResponse { inspect, lists } =
|
||||
match poll_swarm_inspect_info(&swarm.config.server_ids).await {
|
||||
Ok(info) => info,
|
||||
Err(e) => {
|
||||
swarm_status_cache()
|
||||
.insert(
|
||||
swarm.id.clone(),
|
||||
CachedSwarmStatus {
|
||||
state: SwarmState::Unknown,
|
||||
inspect: None,
|
||||
lists: None,
|
||||
err: Some(e.into()),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let mut state = SwarmState::Healthy;
|
||||
|
||||
for node in &lists.nodes {
|
||||
let node_state = node
|
||||
.status
|
||||
.as_ref()
|
||||
.and_then(|status| status.state)
|
||||
.unwrap_or_default();
|
||||
if !matches!(node_state, NodeState::READY) {
|
||||
state = SwarmState::Unhealthy;
|
||||
}
|
||||
}
|
||||
|
||||
swarm_status_cache()
|
||||
.insert(
|
||||
swarm.id.clone(),
|
||||
CachedSwarmStatus {
|
||||
state,
|
||||
inspect,
|
||||
lists: Some(lists),
|
||||
err: None,
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn poll_swarm_inspect_info(
|
||||
servers: &[String],
|
||||
) -> anyhow::Result<PollSwarmStatusResponse> {
|
||||
let mut err = Option::<anyhow::Error>::None;
|
||||
for server in servers {
|
||||
match poll_swarm_inspect_info_from_server(server).await {
|
||||
Ok(res) => return Ok(res),
|
||||
Err(e) => err = Some(e),
|
||||
}
|
||||
}
|
||||
Err(err.unwrap_or_else(|| {
|
||||
anyhow!("Failed to poll swarm inspect info with unknown error")
|
||||
}))
|
||||
}
|
||||
|
||||
async fn poll_swarm_inspect_info_from_server(
|
||||
server: &str,
|
||||
) -> anyhow::Result<PollSwarmStatusResponse> {
|
||||
let server = resource::get::<Server>(server).await?;
|
||||
let periphery = periphery_client(&server).await?;
|
||||
periphery
|
||||
.request_custom_timeout(
|
||||
PollSwarmStatus {},
|
||||
Duration::from_secs(1),
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -12,7 +12,6 @@ use uuid::Uuid;
|
||||
use crate::{
|
||||
connection::{
|
||||
PeripheryConnection, PeripheryConnectionArgs, ResponseChannels,
|
||||
TerminalChannels,
|
||||
},
|
||||
state::periphery_connections,
|
||||
};
|
||||
@@ -24,7 +23,6 @@ pub struct PeripheryClient {
|
||||
/// Usually the server id
|
||||
pub id: String,
|
||||
pub responses: Arc<ResponseChannels>,
|
||||
pub terminals: Arc<TerminalChannels>,
|
||||
}
|
||||
|
||||
impl PeripheryClient {
|
||||
@@ -51,7 +49,6 @@ impl PeripheryClient {
|
||||
return Ok(PeripheryClient {
|
||||
id,
|
||||
responses: connection.responses.clone(),
|
||||
terminals: connection.terminals.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -68,7 +65,6 @@ impl PeripheryClient {
|
||||
Ok(PeripheryClient {
|
||||
id,
|
||||
responses: connection.responses.clone(),
|
||||
terminals: connection.terminals.clone(),
|
||||
})
|
||||
} else {
|
||||
// Core -> Periphery connection
|
||||
@@ -89,6 +85,20 @@ impl PeripheryClient {
|
||||
&self,
|
||||
request: T,
|
||||
) -> anyhow::Result<T::Response>
|
||||
where
|
||||
T: std::fmt::Debug + Serialize + HasResponse,
|
||||
T::Response: DeserializeOwned,
|
||||
{
|
||||
self
|
||||
.request_custom_timeout(request, Duration::from_secs(10))
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn request_custom_timeout<T>(
|
||||
&self,
|
||||
request: T,
|
||||
timeout: Duration,
|
||||
) -> anyhow::Result<T::Response>
|
||||
where
|
||||
T: std::fmt::Debug + Serialize + HasResponse,
|
||||
T::Response: DeserializeOwned,
|
||||
@@ -117,24 +127,28 @@ impl PeripheryClient {
|
||||
.await
|
||||
.context("Failed to send request over channel")
|
||||
{
|
||||
// cleanup
|
||||
self.terminals.remove(&channel_id).await;
|
||||
self.responses.remove(&channel_id).await;
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
// Poll for the associated response
|
||||
loop {
|
||||
let message = response_receiever
|
||||
.recv()
|
||||
.with_timeout(Duration::from_secs(10))
|
||||
.await?;
|
||||
let res = async {
|
||||
// Poll for the associated response
|
||||
loop {
|
||||
let message =
|
||||
response_receiever.recv().with_timeout(timeout).await?;
|
||||
|
||||
// Still in progress, sent to avoid timeout.
|
||||
let Some(message) = message.decode()? else {
|
||||
continue;
|
||||
};
|
||||
// Still in progress, sent to avoid timeout.
|
||||
let Some(message) = message.decode()? else {
|
||||
continue;
|
||||
};
|
||||
|
||||
return message.decode();
|
||||
return message.decode();
|
||||
}
|
||||
}
|
||||
.await;
|
||||
|
||||
self.responses.remove(&channel_id).await;
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,8 +147,9 @@ impl super::KomodoResource for Stack {
|
||||
.await
|
||||
.as_ref()
|
||||
{
|
||||
if let Some(projects) = &status.projects {
|
||||
if let Some(project) = projects
|
||||
if let Some(docker) = &status.docker {
|
||||
if let Some(project) = docker
|
||||
.projects
|
||||
.iter()
|
||||
.find(|project| project.name == project_name)
|
||||
{
|
||||
|
||||
@@ -8,13 +8,16 @@ use komodo_client::entities::{
|
||||
swarm::{
|
||||
PartialSwarmConfig, Swarm, SwarmConfig, SwarmConfigDiff,
|
||||
SwarmInfo, SwarmListItem, SwarmListItemInfo, SwarmQuerySpecifics,
|
||||
SwarmState,
|
||||
},
|
||||
update::Update,
|
||||
user::User,
|
||||
};
|
||||
|
||||
use crate::{config::core_config, state::db_client};
|
||||
use crate::{
|
||||
config::core_config,
|
||||
monitor::update_cache_for_swarm,
|
||||
state::{db_client, swarm_status_cache},
|
||||
};
|
||||
|
||||
use super::get_check_permissions;
|
||||
|
||||
@@ -42,6 +45,11 @@ impl super::KomodoResource for Swarm {
|
||||
async fn to_list_item(
|
||||
swarm: Resource<Self::Config, Self::Info>,
|
||||
) -> Self::ListItem {
|
||||
let state = swarm_status_cache()
|
||||
.get(&swarm.id)
|
||||
.await
|
||||
.map(|status| status.state)
|
||||
.unwrap_or_default();
|
||||
SwarmListItem {
|
||||
name: swarm.name,
|
||||
id: swarm.id,
|
||||
@@ -50,18 +58,12 @@ impl super::KomodoResource for Swarm {
|
||||
resource_type: ResourceTargetVariant::Swarm,
|
||||
info: SwarmListItemInfo {
|
||||
server_ids: swarm.config.server_ids,
|
||||
state: SwarmState::Unknown,
|
||||
state,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
async fn busy(id: &String) -> anyhow::Result<bool> {
|
||||
// action_states()
|
||||
// .swarm
|
||||
// .get(id)
|
||||
// .await
|
||||
// .unwrap_or_default()
|
||||
// .busy()
|
||||
async fn busy(_id: &String) -> anyhow::Result<bool> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
@@ -83,10 +85,10 @@ impl super::KomodoResource for Swarm {
|
||||
}
|
||||
|
||||
async fn post_create(
|
||||
_created: &Resource<Self::Config, Self::Info>,
|
||||
created: &Self,
|
||||
_update: &mut Update,
|
||||
) -> anyhow::Result<()> {
|
||||
// refresh_swarm_state_cache().await;
|
||||
update_cache_for_swarm(created, true).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -105,10 +107,10 @@ impl super::KomodoResource for Swarm {
|
||||
}
|
||||
|
||||
async fn post_update(
|
||||
_updated: &Self,
|
||||
updated: &Self,
|
||||
_update: &mut Update,
|
||||
) -> anyhow::Result<()> {
|
||||
// refresh_swarm_state_cache().await;
|
||||
update_cache_for_swarm(updated, true).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -125,18 +127,17 @@ impl super::KomodoResource for Swarm {
|
||||
}
|
||||
|
||||
async fn pre_delete(
|
||||
_swarm: &Resource<Self::Config, Self::Info>,
|
||||
_swarm: &Self,
|
||||
_update: &mut Update,
|
||||
) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn post_delete(
|
||||
_swarm: &Resource<Self::Config, Self::Info>,
|
||||
swarm: &Self,
|
||||
_update: &mut Update,
|
||||
) -> anyhow::Result<()> {
|
||||
// swarm_state_cache().remove(&swarm.id).await;
|
||||
|
||||
swarm_status_cache().remove(&swarm.id).await;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,19 @@ use anyhow::Context;
|
||||
use arc_swap::ArcSwap;
|
||||
use cache::CloneCache;
|
||||
use komodo_client::entities::{
|
||||
action::ActionState, build::BuildState,
|
||||
deployment::DeploymentState, procedure::ProcedureState,
|
||||
repo::RepoState, stack::StackState,
|
||||
action::ActionState,
|
||||
build::BuildState,
|
||||
deployment::DeploymentState,
|
||||
docker::{
|
||||
DockerLists, SwarmLists, container::ContainerListItem,
|
||||
swarm::SwarmInspectInfo,
|
||||
},
|
||||
procedure::ProcedureState,
|
||||
repo::RepoState,
|
||||
server::{PeripheryInformation, ServerHealth, ServerState},
|
||||
stack::{StackService, StackState},
|
||||
stats::{SystemInformation, SystemStats},
|
||||
swarm::SwarmState,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -16,10 +26,6 @@ use crate::{
|
||||
helpers::{
|
||||
action_state::ActionStates, all_resources::AllResourcesById,
|
||||
},
|
||||
monitor::{
|
||||
CachedDeploymentStatus, CachedRepoStatus, CachedServerStatus,
|
||||
CachedStackStatus, History,
|
||||
},
|
||||
};
|
||||
|
||||
static DB_CLIENT: OnceLock<database::Client> = OnceLock::new();
|
||||
@@ -64,6 +70,43 @@ pub fn action_states() -> &'static ActionStates {
|
||||
ACTION_STATES.get_or_init(ActionStates::default)
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct History<Curr: Default, Prev> {
|
||||
pub curr: Curr,
|
||||
pub prev: Option<Prev>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct CachedSwarmStatus {
|
||||
pub state: SwarmState,
|
||||
pub inspect: Option<SwarmInspectInfo>,
|
||||
pub lists: Option<SwarmLists>,
|
||||
/// Store the error in communicating with Swarm
|
||||
pub err: Option<serror::Serror>,
|
||||
}
|
||||
|
||||
pub type SwarmStatusCache =
|
||||
CloneCache<String, Arc<CachedSwarmStatus>>;
|
||||
|
||||
pub fn swarm_status_cache() -> &'static SwarmStatusCache {
|
||||
static SWARM_STATUS_CACHE: OnceLock<SwarmStatusCache> =
|
||||
OnceLock::new();
|
||||
SWARM_STATUS_CACHE.get_or_init(Default::default)
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct CachedServerStatus {
|
||||
pub id: String,
|
||||
pub state: ServerState,
|
||||
pub health: Option<ServerHealth>,
|
||||
pub periphery_info: Option<PeripheryInformation>,
|
||||
pub system_info: Option<SystemInformation>,
|
||||
pub system_stats: Option<SystemStats>,
|
||||
pub docker: Option<DockerLists>,
|
||||
/// Store the error in reaching periphery
|
||||
pub err: Option<serror::Serror>,
|
||||
}
|
||||
|
||||
pub type ServerStatusCache =
|
||||
CloneCache<String, Arc<CachedServerStatus>>;
|
||||
|
||||
@@ -73,6 +116,16 @@ pub fn server_status_cache() -> &'static ServerStatusCache {
|
||||
SERVER_STATUS_CACHE.get_or_init(Default::default)
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct CachedStackStatus {
|
||||
/// The stack id
|
||||
pub id: String,
|
||||
/// The stack state
|
||||
pub state: StackState,
|
||||
/// The services connected to the stack
|
||||
pub services: Vec<StackService>,
|
||||
}
|
||||
|
||||
pub type StackStatusCache =
|
||||
CloneCache<String, Arc<History<CachedStackStatus, StackState>>>;
|
||||
|
||||
@@ -82,6 +135,15 @@ pub fn stack_status_cache() -> &'static StackStatusCache {
|
||||
STACK_STATUS_CACHE.get_or_init(Default::default)
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct CachedDeploymentStatus {
|
||||
/// The deployment id
|
||||
pub id: String,
|
||||
pub state: DeploymentState,
|
||||
pub container: Option<ContainerListItem>,
|
||||
pub update_available: bool,
|
||||
}
|
||||
|
||||
/// Cache of ids to status
|
||||
pub type DeploymentStatusCache = CloneCache<
|
||||
String,
|
||||
@@ -103,6 +165,12 @@ pub fn build_state_cache() -> &'static BuildStateCache {
|
||||
BUILD_STATE_CACHE.get_or_init(Default::default)
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct CachedRepoStatus {
|
||||
pub latest_hash: Option<String>,
|
||||
pub latest_message: Option<String>,
|
||||
}
|
||||
|
||||
pub type RepoStatusCache = CloneCache<String, Arc<CachedRepoStatus>>;
|
||||
|
||||
pub fn repo_status_cache() -> &'static RepoStatusCache {
|
||||
|
||||
@@ -1,28 +1,20 @@
|
||||
use command::run_komodo_standard_command;
|
||||
use derive_variants::EnumVariants;
|
||||
use encoding::{EncodedJsonMessage, EncodedResponse};
|
||||
use futures_util::FutureExt;
|
||||
use komodo_client::entities::{
|
||||
config::{DockerRegistry, GitProvider},
|
||||
server::PeripheryInformation,
|
||||
stats::SystemProcess,
|
||||
update::Log,
|
||||
};
|
||||
use periphery_client::api::{
|
||||
build::*, compose::*, container::*, docker::*, git::*, keys::*,
|
||||
stats::*, swarm::*, terminal::*, *,
|
||||
poll::*, stats::*, swarm::*, terminal::*, *,
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
api::compose::list_compose_projects,
|
||||
config::periphery_config,
|
||||
state::{
|
||||
docker_client, host_public_ip, periphery_keys, stats_client,
|
||||
},
|
||||
};
|
||||
use crate::{config::periphery_config, state::stats_client};
|
||||
|
||||
pub mod terminal;
|
||||
|
||||
@@ -33,6 +25,7 @@ mod deploy;
|
||||
mod docker;
|
||||
mod git;
|
||||
mod keys;
|
||||
mod poll;
|
||||
mod swarm;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -144,6 +137,7 @@ pub enum PeripheryRequest {
|
||||
PruneSystem(PruneSystem),
|
||||
|
||||
// Swarm
|
||||
GetSwarmLists(PollSwarmStatus),
|
||||
InspectSwarmNode(InspectSwarmNode),
|
||||
InspectSwarmService(InspectSwarmService),
|
||||
InspectSwarmTask(InspectSwarmTask),
|
||||
@@ -191,78 +185,6 @@ impl Resolve<Args> for GetVersion {
|
||||
|
||||
//
|
||||
|
||||
impl Resolve<Args> for PollStatus {
|
||||
async fn resolve(
|
||||
self,
|
||||
_: &Args,
|
||||
) -> anyhow::Result<PollStatusResponse> {
|
||||
// Docker lists
|
||||
let docker_lists = async {
|
||||
let client = docker_client().load();
|
||||
let Some(client) = client.iter().next() else {
|
||||
return Default::default();
|
||||
};
|
||||
let containers =
|
||||
client.list_containers().await.unwrap_or_default();
|
||||
// Todo: handle errors better
|
||||
(
|
||||
tokio::join!(
|
||||
client
|
||||
.list_networks(&containers)
|
||||
.map(Result::unwrap_or_default),
|
||||
client
|
||||
.list_images(&containers)
|
||||
.map(Result::unwrap_or_default),
|
||||
client
|
||||
.list_volumes(&containers)
|
||||
.map(Result::unwrap_or_default)
|
||||
),
|
||||
containers,
|
||||
)
|
||||
};
|
||||
|
||||
let (
|
||||
((networks, images, volumes), containers),
|
||||
projects,
|
||||
stats_client,
|
||||
) = tokio::join!(
|
||||
docker_lists,
|
||||
list_compose_projects().map(Result::unwrap_or_default),
|
||||
stats_client().read(),
|
||||
);
|
||||
|
||||
let system_stats = if self.include_stats {
|
||||
Some(stats_client.stats.clone())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let config = periphery_config();
|
||||
|
||||
Ok(PollStatusResponse {
|
||||
periphery_info: PeripheryInformation {
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
public_key: periphery_keys().load().public.to_string(),
|
||||
terminals_disabled: config.disable_terminals,
|
||||
container_terminals_disabled: config
|
||||
.disable_container_terminals,
|
||||
stats_polling_rate: config.stats_polling_rate,
|
||||
docker_connected: docker_client().load().is_some(),
|
||||
public_ip: host_public_ip().await.cloned(),
|
||||
},
|
||||
system_info: stats_client.info.clone(),
|
||||
system_stats,
|
||||
containers,
|
||||
networks,
|
||||
images,
|
||||
volumes,
|
||||
projects,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
impl Resolve<Args> for GetSystemProcesses {
|
||||
async fn resolve(
|
||||
self,
|
||||
|
||||
84
bin/periphery/src/api/poll.rs
Normal file
84
bin/periphery/src/api/poll.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use futures_util::FutureExt;
|
||||
use komodo_client::entities::{
|
||||
docker::DockerLists, server::PeripheryInformation,
|
||||
};
|
||||
use periphery_client::api::poll::{PollStatus, PollStatusResponse};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{
|
||||
api::compose::list_compose_projects,
|
||||
config::periphery_config,
|
||||
docker::DockerClient,
|
||||
state::{
|
||||
docker_client, host_public_ip, periphery_keys, stats_client,
|
||||
},
|
||||
};
|
||||
|
||||
impl Resolve<super::Args> for PollStatus {
|
||||
async fn resolve(
|
||||
self,
|
||||
_: &super::Args,
|
||||
) -> anyhow::Result<PollStatusResponse> {
|
||||
let stats_client = stats_client().read().await;
|
||||
|
||||
let system_stats = if self.include_stats {
|
||||
Some(stats_client.stats.clone())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let docker = if self.include_docker {
|
||||
let client = docker_client().load();
|
||||
if let Some(client) = client.iter().next() {
|
||||
Some(docker_lists(client).await)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(PollStatusResponse {
|
||||
periphery_info: periphery_information().await,
|
||||
system_info: stats_client.info.clone(),
|
||||
system_stats,
|
||||
docker,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async fn periphery_information() -> PeripheryInformation {
|
||||
let config = periphery_config();
|
||||
PeripheryInformation {
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
public_key: periphery_keys().load().public.to_string(),
|
||||
terminals_disabled: config.disable_terminals,
|
||||
container_terminals_disabled: config.disable_container_terminals,
|
||||
stats_polling_rate: config.stats_polling_rate,
|
||||
docker_connected: docker_client().load().is_some(),
|
||||
public_ip: host_public_ip().await.cloned(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn docker_lists(client: &DockerClient) -> DockerLists {
|
||||
let containers = client.list_containers().await.unwrap_or_default();
|
||||
let (networks, images, volumes, projects) = tokio::join!(
|
||||
client
|
||||
.list_networks(&containers)
|
||||
.map(Result::unwrap_or_default),
|
||||
client
|
||||
.list_images(&containers)
|
||||
.map(Result::unwrap_or_default),
|
||||
client
|
||||
.list_volumes(&containers)
|
||||
.map(Result::unwrap_or_default),
|
||||
list_compose_projects().map(Result::unwrap_or_default),
|
||||
);
|
||||
DockerLists {
|
||||
containers,
|
||||
networks,
|
||||
images,
|
||||
volumes,
|
||||
projects,
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,45 @@
|
||||
use anyhow::Context as _;
|
||||
use komodo_client::entities::docker::{
|
||||
node::SwarmNode, secret::SwarmSecret, service::SwarmService,
|
||||
task::SwarmTask,
|
||||
SwarmLists, node::SwarmNode, secret::SwarmSecret,
|
||||
service::SwarmService, task::SwarmTask,
|
||||
};
|
||||
use periphery_client::api::swarm::{
|
||||
InspectSwarmNode, InspectSwarmSecret, InspectSwarmService,
|
||||
InspectSwarmTask,
|
||||
InspectSwarmTask, PollSwarmStatus, PollSwarmStatusResponse,
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::state::docker_client;
|
||||
|
||||
impl Resolve<super::Args> for PollSwarmStatus {
|
||||
async fn resolve(
|
||||
self,
|
||||
_: &super::Args,
|
||||
) -> anyhow::Result<PollSwarmStatusResponse> {
|
||||
let client = docker_client().load();
|
||||
let client = client
|
||||
.iter()
|
||||
.next()
|
||||
.context("Could not connect to docker client")?;
|
||||
let (inspect, nodes, services, tasks, secrets) = tokio::join!(
|
||||
client.inspect_swarm(),
|
||||
client.list_swarm_nodes(),
|
||||
client.list_swarm_services(),
|
||||
client.list_swarm_tasks(),
|
||||
client.list_swarm_secrets(),
|
||||
);
|
||||
Ok(PollSwarmStatusResponse {
|
||||
inspect: inspect.ok(),
|
||||
lists: SwarmLists {
|
||||
nodes: nodes.unwrap_or_default(),
|
||||
services: services.unwrap_or_default(),
|
||||
tasks: tasks.unwrap_or_default(),
|
||||
secrets: secrets.unwrap_or_default(),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ======
|
||||
// Node
|
||||
// ======
|
||||
|
||||
@@ -15,6 +15,7 @@ mod network;
|
||||
mod node;
|
||||
mod secret;
|
||||
mod service;
|
||||
mod swarm;
|
||||
mod task;
|
||||
mod volume;
|
||||
|
||||
@@ -463,3 +464,11 @@ fn convert_task_spec_container_spec(
|
||||
ulimits: spec.ulimits.map(|ulimits| ulimits.into_iter().map(convert_resources_ulimits).collect()),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_tls_info(tls_info: bollard::models::TlsInfo) -> TlsInfo {
|
||||
TlsInfo {
|
||||
trust_root: tls_info.trust_root,
|
||||
cert_issuer_subject: tls_info.cert_issuer_subject,
|
||||
cert_issuer_public_key: tls_info.cert_issuer_public_key,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ use super::{
|
||||
|
||||
impl DockerClient {
|
||||
/// Lists swarm nodes
|
||||
pub async fn list_swarm_nodes(&self) -> anyhow::Result<Vec<SwarmNode>> {
|
||||
pub async fn list_swarm_nodes(
|
||||
&self,
|
||||
) -> anyhow::Result<Vec<SwarmNode>> {
|
||||
let nodes = self
|
||||
.docker
|
||||
.list_nodes(Option::<ListNodesOptions>::None)
|
||||
@@ -93,11 +95,7 @@ fn convert_node(node: bollard::models::Node) -> SwarmNode {
|
||||
.collect()
|
||||
}),
|
||||
}),
|
||||
tls_info: description.tls_info.map(|tls_info| TlsInfo {
|
||||
trust_root: tls_info.trust_root,
|
||||
cert_issuer_subject: tls_info.cert_issuer_subject,
|
||||
cert_issuer_public_key: tls_info.cert_issuer_public_key,
|
||||
}),
|
||||
tls_info: description.tls_info.map(super::convert_tls_info),
|
||||
}
|
||||
}),
|
||||
status: node.status.map(|status| NodeStatus {
|
||||
|
||||
96
bin/periphery/src/docker/swarm.rs
Normal file
96
bin/periphery/src/docker/swarm.rs
Normal file
@@ -0,0 +1,96 @@
|
||||
use anyhow::Context;
|
||||
use komodo_client::entities::docker::swarm::{
|
||||
JoinTokens, SwarmInspectInfo, SwarmSpec, SwarmSpecCaConfig,
|
||||
SwarmSpecCaConfigExternalCas,
|
||||
SwarmSpecCaConfigExternalCasProtocolEnum, SwarmSpecDispatcher,
|
||||
SwarmSpecEncryptionConfig, SwarmSpecOrchestration, SwarmSpecRaft,
|
||||
SwarmSpecTaskDefaults, SwarmSpecTaskDefaultsLogDriver,
|
||||
};
|
||||
|
||||
use super::DockerClient;
|
||||
|
||||
impl DockerClient {
|
||||
/// Inspect swarm info
|
||||
pub async fn inspect_swarm(
|
||||
&self,
|
||||
) -> anyhow::Result<SwarmInspectInfo> {
|
||||
self
|
||||
.docker
|
||||
.inspect_swarm()
|
||||
.await
|
||||
.map(convert_swarm_info)
|
||||
.context("Failed to query for swarm info")
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_swarm_info(
|
||||
swarm: bollard::models::Swarm,
|
||||
) -> SwarmInspectInfo {
|
||||
SwarmInspectInfo {
|
||||
id: swarm.id,
|
||||
version: swarm.version.map(super::convert_object_version),
|
||||
created_at: swarm.created_at,
|
||||
updated_at: swarm.updated_at,
|
||||
spec: swarm.spec.map(|spec| SwarmSpec {
|
||||
name: spec.name,
|
||||
labels: spec.labels,
|
||||
orchestration: spec.orchestration.map(|orchestration| {
|
||||
SwarmSpecOrchestration {
|
||||
task_history_retention_limit: orchestration
|
||||
.task_history_retention_limit,
|
||||
}
|
||||
}),
|
||||
raft: spec.raft.map(|raft| SwarmSpecRaft {
|
||||
snapshot_interval: raft.snapshot_interval,
|
||||
keep_old_snapshots: raft.keep_old_snapshots,
|
||||
log_entries_for_slow_followers: raft
|
||||
.log_entries_for_slow_followers,
|
||||
election_tick: raft.election_tick,
|
||||
heartbeat_tick: raft.heartbeat_tick,
|
||||
}),
|
||||
dispatcher: spec.dispatcher.map(|dispatcher| {
|
||||
SwarmSpecDispatcher {
|
||||
heartbeat_period: dispatcher.heartbeat_period,
|
||||
}
|
||||
}),
|
||||
ca_config: spec.ca_config.map(|config| SwarmSpecCaConfig {
|
||||
node_cert_expiry: config.node_cert_expiry,
|
||||
external_cas: config.external_cas.map(|cas| {
|
||||
cas
|
||||
.into_iter()
|
||||
.map(|cas| SwarmSpecCaConfigExternalCas {
|
||||
protocol: cas.protocol.map(|protocol| match protocol {
|
||||
bollard::secret::SwarmSpecCaConfigExternalCasProtocolEnum::EMPTY => SwarmSpecCaConfigExternalCasProtocolEnum::EMPTY,
|
||||
bollard::secret::SwarmSpecCaConfigExternalCasProtocolEnum::CFSSL => SwarmSpecCaConfigExternalCasProtocolEnum::CFSSL,
|
||||
}),
|
||||
url: cas.url,
|
||||
options: cas.options,
|
||||
ca_cert: cas.ca_cert,
|
||||
})
|
||||
.collect()
|
||||
}),
|
||||
signing_ca_cert: config.signing_ca_cert,
|
||||
signing_ca_key: config.signing_ca_key,
|
||||
force_rotate: config.force_rotate,
|
||||
}),
|
||||
encryption_config: spec.encryption_config.map(|config| SwarmSpecEncryptionConfig {
|
||||
auto_lock_managers: config.auto_lock_managers,
|
||||
}),
|
||||
task_defaults: spec.task_defaults.map(|defaults| SwarmSpecTaskDefaults {
|
||||
log_driver: defaults.log_driver.map(|driver| SwarmSpecTaskDefaultsLogDriver {
|
||||
name: driver.name,
|
||||
options: driver.options,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
tls_info: swarm.tls_info.map(super::convert_tls_info),
|
||||
root_rotation_in_progress: swarm.root_rotation_in_progress,
|
||||
data_path_port: swarm.data_path_port,
|
||||
default_addr_pool: swarm.default_addr_pool,
|
||||
subnet_size: swarm.subnet_size,
|
||||
join_tokens: swarm.join_tokens.map(|tokens| JoinTokens {
|
||||
worker: tokens.worker,
|
||||
manager: tokens.manager,
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,6 @@ pub struct GetSwarmsSummaryResponse {
|
||||
pub healthy: u32,
|
||||
/// The number of Swarms with Unhealthy state
|
||||
pub unhealthy: u32,
|
||||
/// The number of Swarms with Offline state
|
||||
pub offline: u32,
|
||||
/// The number of Swarms with Unknown state
|
||||
pub unknown: u32,
|
||||
}
|
||||
|
||||
@@ -2,13 +2,20 @@ use crate::entities::{
|
||||
action::ActionActionState, build::BuildActionState,
|
||||
deployment::DeploymentActionState, procedure::ProcedureActionState,
|
||||
repo::RepoActionState, server::ServerActionState,
|
||||
stack::StackActionState, sync::ResourceSyncActionState,
|
||||
stack::StackActionState, swarm::SwarmActionState,
|
||||
sync::ResourceSyncActionState,
|
||||
};
|
||||
|
||||
pub trait Busy {
|
||||
fn busy(&self) -> bool;
|
||||
}
|
||||
|
||||
impl Busy for SwarmActionState {
|
||||
fn busy(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Busy for ServerActionState {
|
||||
fn busy(&self) -> bool {
|
||||
self.pruning_containers
|
||||
|
||||
@@ -3,6 +3,15 @@ use std::collections::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::entities::{
|
||||
docker::{
|
||||
container::ContainerListItem, image::ImageListItem,
|
||||
network::NetworkListItem, node::SwarmNode, secret::SwarmSecret,
|
||||
service::SwarmService, task::SwarmTask, volume::VolumeListItem,
|
||||
},
|
||||
stack::ComposeProject,
|
||||
};
|
||||
|
||||
use super::{I64, U64};
|
||||
|
||||
pub mod container;
|
||||
@@ -12,9 +21,32 @@ pub mod node;
|
||||
pub mod secret;
|
||||
pub mod service;
|
||||
pub mod stats;
|
||||
pub mod swarm;
|
||||
pub mod task;
|
||||
pub mod volume;
|
||||
|
||||
/// Swarm lists available from a manager node.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SwarmLists {
|
||||
pub nodes: Vec<SwarmNode>,
|
||||
pub services: Vec<SwarmService>,
|
||||
pub tasks: Vec<SwarmTask>,
|
||||
pub secrets: Vec<SwarmSecret>,
|
||||
}
|
||||
|
||||
/// Standard docker lists available from a Server.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct DockerLists {
|
||||
pub containers: Vec<ContainerListItem>,
|
||||
pub networks: Vec<NetworkListItem>,
|
||||
pub images: Vec<ImageListItem>,
|
||||
pub volumes: Vec<VolumeListItem>,
|
||||
pub projects: Vec<ComposeProject>,
|
||||
}
|
||||
|
||||
/// PortBinding represents a binding between a host IP address and a host port.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
@@ -565,3 +597,22 @@ pub enum EndpointPortConfigPublishModeEnum {
|
||||
#[serde(rename = "host")]
|
||||
HOST,
|
||||
}
|
||||
|
||||
/// Information about the issuer of leaf TLS certificates and the trusted root CA certificate.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct TlsInfo {
|
||||
/// The root CA certificate(s) that are used to validate leaf TLS certificates.
|
||||
#[serde(rename = "TrustRoot")]
|
||||
pub trust_root: Option<String>,
|
||||
|
||||
/// The base64-url-safe-encoded raw subject bytes of the issuer.
|
||||
#[serde(rename = "CertIssuerSubject")]
|
||||
pub cert_issuer_subject: Option<String>,
|
||||
|
||||
/// The base64-url-safe-encoded raw public key bytes of the issuer.
|
||||
#[serde(rename = "CertIssuerPublicKey")]
|
||||
pub cert_issuer_public_key: Option<String>,
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct NetworkListItem {
|
||||
pub name: Option<String>,
|
||||
pub id: Option<String>,
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::collections::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use super::{ObjectVersion, Platform, ResourceObject};
|
||||
use super::*;
|
||||
|
||||
/// Swarm node details.
|
||||
#[typeshare]
|
||||
@@ -159,25 +159,6 @@ pub struct EngineDescriptionPlugins {
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
/// Information about the issuer of leaf TLS certificates and the trusted root CA certificate.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct TlsInfo {
|
||||
/// The root CA certificate(s) that are used to validate leaf TLS certificates.
|
||||
#[serde(rename = "TrustRoot")]
|
||||
pub trust_root: Option<String>,
|
||||
|
||||
/// The base64-url-safe-encoded raw subject bytes of the issuer.
|
||||
#[serde(rename = "CertIssuerSubject")]
|
||||
pub cert_issuer_subject: Option<String>,
|
||||
|
||||
/// The base64-url-safe-encoded raw public key bytes of the issuer.
|
||||
#[serde(rename = "CertIssuerPublicKey")]
|
||||
pub cert_issuer_public_key: Option<String>,
|
||||
}
|
||||
|
||||
/// NodeStatus represents the status of a node. It provides the current status of the node, as seen by the manager.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use super::{Driver, ObjectVersion};
|
||||
use super::*;
|
||||
|
||||
/// Swarm secret details.
|
||||
#[typeshare]
|
||||
|
||||
257
client/core/rs/src/entities/docker/swarm.rs
Normal file
257
client/core/rs/src/entities/docker/swarm.rs
Normal file
@@ -0,0 +1,257 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Docker-level information about the Swarm.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct SwarmInspectInfo {
|
||||
/// The (Docker) ID of the swarm.
|
||||
#[serde(rename = "ID")]
|
||||
pub id: Option<String>,
|
||||
|
||||
#[serde(rename = "Version")]
|
||||
pub version: Option<ObjectVersion>,
|
||||
|
||||
/// Date and time at which the swarm was initialised in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds.
|
||||
#[serde(rename = "CreatedAt")]
|
||||
pub created_at: Option<String>,
|
||||
|
||||
/// Date and time at which the swarm was last updated in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds.
|
||||
#[serde(rename = "UpdatedAt")]
|
||||
pub updated_at: Option<String>,
|
||||
|
||||
#[serde(rename = "Spec")]
|
||||
pub spec: Option<SwarmSpec>,
|
||||
|
||||
#[serde(rename = "TLSInfo")]
|
||||
pub tls_info: Option<TlsInfo>,
|
||||
|
||||
/// Whether there is currently a root CA rotation in progress for the swarm
|
||||
#[serde(rename = "RootRotationInProgress")]
|
||||
pub root_rotation_in_progress: Option<bool>,
|
||||
|
||||
/// DataPathPort specifies the data path port number for data traffic. Acceptable port range is 1024 to 49151. If no port is set or is set to 0, the default port (4789) is used.
|
||||
#[serde(rename = "DataPathPort")]
|
||||
pub data_path_port: Option<u32>,
|
||||
|
||||
/// Default Address Pool specifies default subnet pools for global scope networks.
|
||||
#[serde(rename = "DefaultAddrPool")]
|
||||
pub default_addr_pool: Option<Vec<String>>,
|
||||
|
||||
/// SubnetSize specifies the subnet size of the networks created from the default subnet pool.
|
||||
#[serde(rename = "SubnetSize")]
|
||||
pub subnet_size: Option<u32>,
|
||||
|
||||
#[serde(rename = "JoinTokens")]
|
||||
pub join_tokens: Option<JoinTokens>,
|
||||
}
|
||||
|
||||
/// User modifiable swarm configuration.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct SwarmSpec {
|
||||
/// Name of the swarm.
|
||||
#[serde(rename = "Name")]
|
||||
pub name: Option<String>,
|
||||
|
||||
/// User-defined key/value metadata.
|
||||
#[serde(rename = "Labels")]
|
||||
pub labels: Option<HashMap<String, String>>,
|
||||
|
||||
#[serde(rename = "Orchestration")]
|
||||
pub orchestration: Option<SwarmSpecOrchestration>,
|
||||
|
||||
#[serde(rename = "Raft")]
|
||||
pub raft: Option<SwarmSpecRaft>,
|
||||
|
||||
#[serde(rename = "Dispatcher")]
|
||||
pub dispatcher: Option<SwarmSpecDispatcher>,
|
||||
|
||||
#[serde(rename = "CAConfig")]
|
||||
pub ca_config: Option<SwarmSpecCaConfig>,
|
||||
|
||||
#[serde(rename = "EncryptionConfig")]
|
||||
pub encryption_config: Option<SwarmSpecEncryptionConfig>,
|
||||
|
||||
#[serde(rename = "TaskDefaults")]
|
||||
pub task_defaults: Option<SwarmSpecTaskDefaults>,
|
||||
}
|
||||
|
||||
/// Orchestration configuration.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct SwarmSpecOrchestration {
|
||||
/// The number of historic tasks to keep per instance or node.
|
||||
/// If negative, never remove completed or failed tasks.
|
||||
#[serde(rename = "TaskHistoryRetentionLimit")]
|
||||
pub task_history_retention_limit: Option<I64>,
|
||||
}
|
||||
|
||||
/// Raft configuration.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct SwarmSpecRaft {
|
||||
/// The number of log entries between snapshots.
|
||||
#[serde(rename = "SnapshotInterval")]
|
||||
pub snapshot_interval: Option<U64>,
|
||||
|
||||
/// The number of snapshots to keep beyond the current snapshot.
|
||||
#[serde(rename = "KeepOldSnapshots")]
|
||||
pub keep_old_snapshots: Option<U64>,
|
||||
|
||||
/// The number of log entries to keep around to sync up slow followers after a snapshot is created.
|
||||
#[serde(rename = "LogEntriesForSlowFollowers")]
|
||||
pub log_entries_for_slow_followers: Option<U64>,
|
||||
|
||||
/// The number of ticks that a follower will wait for a message from the leader before becoming a candidate and starting an election. `ElectionTick` must be greater than `HeartbeatTick`. A tick currently defaults to one second, so these translate directly to seconds currently, but this is NOT guaranteed.
|
||||
#[serde(rename = "ElectionTick")]
|
||||
pub election_tick: Option<I64>,
|
||||
|
||||
/// The number of ticks between heartbeats.
|
||||
/// Every HeartbeatTick ticks, the leader will send a heartbeat to the followers.
|
||||
/// A tick currently defaults to one second, so these translate directly to seconds currently, but this is NOT guaranteed.
|
||||
#[serde(rename = "HeartbeatTick")]
|
||||
pub heartbeat_tick: Option<I64>,
|
||||
}
|
||||
|
||||
/// Dispatcher configuration.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct SwarmSpecDispatcher {
|
||||
/// The delay for an agent to send a heartbeat to the dispatcher.
|
||||
#[serde(rename = "HeartbeatPeriod")]
|
||||
pub heartbeat_period: Option<I64>,
|
||||
}
|
||||
|
||||
/// CA configuration.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct SwarmSpecCaConfig {
|
||||
/// The duration node certificates are issued for.
|
||||
#[serde(rename = "NodeCertExpiry")]
|
||||
pub node_cert_expiry: Option<I64>,
|
||||
|
||||
/// Configuration for forwarding signing requests to an external certificate authority.
|
||||
#[serde(rename = "ExternalCAs")]
|
||||
pub external_cas: Option<Vec<SwarmSpecCaConfigExternalCas>>,
|
||||
|
||||
/// The desired signing CA certificate for all swarm node TLS leaf certificates, in PEM format.
|
||||
#[serde(rename = "SigningCACert")]
|
||||
pub signing_ca_cert: Option<String>,
|
||||
|
||||
/// The desired signing CA key for all swarm node TLS leaf certificates, in PEM format.
|
||||
#[serde(rename = "SigningCAKey")]
|
||||
pub signing_ca_key: Option<String>,
|
||||
|
||||
/// An integer whose purpose is to force swarm to generate a new signing CA certificate and key, if none have been specified in `SigningCACert` and `SigningCAKey`
|
||||
#[serde(rename = "ForceRotate")]
|
||||
pub force_rotate: Option<U64>,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct SwarmSpecCaConfigExternalCas {
|
||||
/// Protocol for communication with the external CA (currently only `cfssl` is supported).
|
||||
#[serde(rename = "Protocol")]
|
||||
pub protocol: Option<SwarmSpecCaConfigExternalCasProtocolEnum>,
|
||||
|
||||
/// URL where certificate signing requests should be sent.
|
||||
#[serde(rename = "URL")]
|
||||
pub url: Option<String>,
|
||||
|
||||
/// An object with key/value pairs that are interpreted as protocol-specific options for the external CA driver.
|
||||
#[serde(rename = "Options")]
|
||||
pub options: Option<HashMap<String, String>>,
|
||||
|
||||
/// The root CA certificate (in PEM format) this external CA uses to issue TLS certificates (assumed to be to the current swarm root CA certificate if not provided).
|
||||
#[serde(rename = "CACert")]
|
||||
pub ca_cert: Option<String>,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Default,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
pub enum SwarmSpecCaConfigExternalCasProtocolEnum {
|
||||
#[default]
|
||||
#[serde(rename = "")]
|
||||
EMPTY,
|
||||
#[serde(rename = "cfssl")]
|
||||
CFSSL,
|
||||
}
|
||||
|
||||
/// Parameters related to encryption-at-rest.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct SwarmSpecEncryptionConfig {
|
||||
/// If set, generate a key and use it to lock data stored on the managers.
|
||||
#[serde(rename = "AutoLockManagers")]
|
||||
pub auto_lock_managers: Option<bool>,
|
||||
}
|
||||
|
||||
/// Defaults for creating tasks in this cluster.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct SwarmSpecTaskDefaults {
|
||||
#[serde(rename = "LogDriver")]
|
||||
pub log_driver: Option<SwarmSpecTaskDefaultsLogDriver>,
|
||||
}
|
||||
|
||||
/// The log driver to use for tasks created in the orchestrator if unspecified by a service. Updating this value only affects new tasks. Existing tasks continue to use their previously configured log driver until recreated.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct SwarmSpecTaskDefaultsLogDriver {
|
||||
/// The log driver to use as a default for new tasks.
|
||||
#[serde(rename = "Name")]
|
||||
pub name: Option<String>,
|
||||
|
||||
/// Driver-specific options for the selected log driver, specified as key/value pairs.
|
||||
#[serde(rename = "Options")]
|
||||
pub options: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
||||
/// JoinTokens contains the tokens workers and managers need to join the swarm.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct JoinTokens {
|
||||
/// The token workers can use to join the swarm.
|
||||
#[serde(rename = "Worker")]
|
||||
pub worker: Option<String>,
|
||||
|
||||
/// The token managers can use to join the swarm.
|
||||
#[serde(rename = "Manager")]
|
||||
pub manager: Option<String>,
|
||||
}
|
||||
@@ -655,7 +655,9 @@ impl Default for StackConfig {
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
pub struct ComposeProject {
|
||||
/// The compose project name.
|
||||
pub name: String,
|
||||
|
||||
@@ -6,6 +6,10 @@ use serde::{Deserialize, Serialize};
|
||||
use strum::Display;
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::deserializers::{
|
||||
option_string_list_deserializer, string_list_deserializer,
|
||||
};
|
||||
|
||||
use super::resource::{Resource, ResourceListItem, ResourceQuery};
|
||||
|
||||
#[typeshare]
|
||||
@@ -32,8 +36,6 @@ pub enum SwarmState {
|
||||
Healthy,
|
||||
/// The Swarm is unhealthy
|
||||
Unhealthy,
|
||||
/// Servers are reachable, but Swarm is not running on any of them.
|
||||
Offline,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
@@ -58,12 +60,22 @@ pub struct SwarmConfig {
|
||||
#[partial_attr(serde(alias = "servers"))]
|
||||
#[builder(default)]
|
||||
pub server_ids: Vec<String>,
|
||||
|
||||
/// Configure quick links that are displayed in the resource header
|
||||
#[serde(default, deserialize_with = "string_list_deserializer")]
|
||||
#[partial_attr(serde(
|
||||
default,
|
||||
deserialize_with = "option_string_list_deserializer"
|
||||
))]
|
||||
#[builder(default)]
|
||||
pub links: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for SwarmConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
server_ids: Default::default(),
|
||||
links: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,36 +22,12 @@ export type ReadResponses = {
|
||||
ListGitProvidersFromConfig: Types.ListGitProvidersFromConfigResponse;
|
||||
ListDockerRegistriesFromConfig: Types.ListDockerRegistriesFromConfigResponse;
|
||||
|
||||
// ==== USER ====
|
||||
GetUsername: Types.GetUsernameResponse;
|
||||
GetPermission: Types.GetPermissionResponse;
|
||||
FindUser: Types.FindUserResponse;
|
||||
ListUsers: Types.ListUsersResponse;
|
||||
ListApiKeys: Types.ListApiKeysResponse;
|
||||
ListApiKeysForServiceUser: Types.ListApiKeysForServiceUserResponse;
|
||||
ListPermissions: Types.ListPermissionsResponse;
|
||||
ListUserTargetPermissions: Types.ListUserTargetPermissionsResponse;
|
||||
|
||||
// ==== USER GROUP ====
|
||||
GetUserGroup: Types.GetUserGroupResponse;
|
||||
ListUserGroups: Types.ListUserGroupsResponse;
|
||||
|
||||
// ==== PROCEDURE ====
|
||||
GetProceduresSummary: Types.GetProceduresSummaryResponse;
|
||||
GetProcedure: Types.GetProcedureResponse;
|
||||
GetProcedureActionState: Types.GetProcedureActionStateResponse;
|
||||
ListProcedures: Types.ListProceduresResponse;
|
||||
ListFullProcedures: Types.ListFullProceduresResponse;
|
||||
|
||||
// ==== ACTION ====
|
||||
GetActionsSummary: Types.GetActionsSummaryResponse;
|
||||
GetAction: Types.GetActionResponse;
|
||||
GetActionActionState: Types.GetActionActionStateResponse;
|
||||
ListActions: Types.ListActionsResponse;
|
||||
ListFullActions: Types.ListFullActionsResponse;
|
||||
|
||||
// ==== SCHEDULE ====
|
||||
ListSchedules: Types.ListSchedulesResponse;
|
||||
// ==== SWARM ====
|
||||
GetSwarmsSummary: Types.GetSwarmsSummaryResponse;
|
||||
GetSwarm: Types.GetSwarmResponse;
|
||||
GetSwarmActionState: Types.GetSwarmActionStateResponse;
|
||||
ListSwarms: Types.ListSwarmsResponse;
|
||||
ListFullSwarms: Types.ListFullSwarmsResponse;
|
||||
|
||||
// ==== SERVER ====
|
||||
GetServersSummary: Types.GetServersSummaryResponse;
|
||||
@@ -59,9 +35,10 @@ export type ReadResponses = {
|
||||
GetServerState: Types.GetServerStateResponse;
|
||||
GetPeripheryInformation: Types.GetPeripheryInformationResponse;
|
||||
GetServerActionState: Types.GetServerActionStateResponse;
|
||||
GetHistoricalServerStats: Types.GetHistoricalServerStatsResponse;
|
||||
ListServers: Types.ListServersResponse;
|
||||
ListFullServers: Types.ListFullServersResponse;
|
||||
|
||||
// ==== TERMINAL ====
|
||||
ListTerminals: Types.ListTerminalsResponse;
|
||||
|
||||
// ==== DOCKER ====
|
||||
@@ -81,6 +58,12 @@ export type ReadResponses = {
|
||||
ListDockerVolumes: Types.ListDockerVolumesResponse;
|
||||
InspectDockerVolume: Types.InspectDockerVolumeResponse;
|
||||
|
||||
// ==== SERVER STATS ====
|
||||
GetSystemInformation: Types.GetSystemInformationResponse;
|
||||
GetSystemStats: Types.GetSystemStatsResponse;
|
||||
GetHistoricalServerStats: Types.GetHistoricalServerStatsResponse;
|
||||
ListSystemProcesses: Types.ListSystemProcessesResponse;
|
||||
|
||||
// ==== STACK ====
|
||||
GetStacksSummary: Types.GetStacksSummaryResponse;
|
||||
GetStack: Types.GetStackResponse;
|
||||
@@ -124,6 +107,23 @@ export type ReadResponses = {
|
||||
ListRepos: Types.ListReposResponse;
|
||||
ListFullRepos: Types.ListFullReposResponse;
|
||||
|
||||
// ==== PROCEDURE ====
|
||||
GetProceduresSummary: Types.GetProceduresSummaryResponse;
|
||||
GetProcedure: Types.GetProcedureResponse;
|
||||
GetProcedureActionState: Types.GetProcedureActionStateResponse;
|
||||
ListProcedures: Types.ListProceduresResponse;
|
||||
ListFullProcedures: Types.ListFullProceduresResponse;
|
||||
|
||||
// ==== ACTION ====
|
||||
GetActionsSummary: Types.GetActionsSummaryResponse;
|
||||
GetAction: Types.GetActionResponse;
|
||||
GetActionActionState: Types.GetActionActionStateResponse;
|
||||
ListActions: Types.ListActionsResponse;
|
||||
ListFullActions: Types.ListFullActionsResponse;
|
||||
|
||||
// ==== SCHEDULE ====
|
||||
ListSchedules: Types.ListSchedulesResponse;
|
||||
|
||||
// ==== SYNC ====
|
||||
GetResourceSyncsSummary: Types.GetResourceSyncsSummaryResponse;
|
||||
GetResourceSync: Types.GetResourceSyncResponse;
|
||||
@@ -151,6 +151,20 @@ export type ReadResponses = {
|
||||
GetTag: Types.GetTagResponse;
|
||||
ListTags: Types.ListTagsResponse;
|
||||
|
||||
// ==== USER ====
|
||||
GetUsername: Types.GetUsernameResponse;
|
||||
GetPermission: Types.GetPermissionResponse;
|
||||
FindUser: Types.FindUserResponse;
|
||||
ListUsers: Types.ListUsersResponse;
|
||||
ListApiKeys: Types.ListApiKeysResponse;
|
||||
ListApiKeysForServiceUser: Types.ListApiKeysForServiceUserResponse;
|
||||
ListPermissions: Types.ListPermissionsResponse;
|
||||
ListUserTargetPermissions: Types.ListUserTargetPermissionsResponse;
|
||||
|
||||
// ==== USER GROUP ====
|
||||
GetUserGroup: Types.GetUserGroupResponse;
|
||||
ListUserGroups: Types.ListUserGroupsResponse;
|
||||
|
||||
// ==== UPDATE ====
|
||||
GetUpdate: Types.GetUpdateResponse;
|
||||
ListUpdates: Types.ListUpdatesResponse;
|
||||
@@ -159,11 +173,6 @@ export type ReadResponses = {
|
||||
ListAlerts: Types.ListAlertsResponse;
|
||||
GetAlert: Types.GetAlertResponse;
|
||||
|
||||
// ==== SERVER STATS ====
|
||||
GetSystemInformation: Types.GetSystemInformationResponse;
|
||||
GetSystemStats: Types.GetSystemStatsResponse;
|
||||
ListSystemProcesses: Types.ListSystemProcessesResponse;
|
||||
|
||||
// ==== VARIABLE ====
|
||||
GetVariable: Types.GetVariableResponse;
|
||||
ListVariables: Types.ListVariablesResponse;
|
||||
@@ -179,36 +188,16 @@ export type ReadResponses = {
|
||||
};
|
||||
|
||||
export type WriteResponses = {
|
||||
// ==== USER ====
|
||||
CreateLocalUser: Types.CreateLocalUserResponse;
|
||||
UpdateUserUsername: Types.UpdateUserUsernameResponse;
|
||||
UpdateUserPassword: Types.UpdateUserPasswordResponse;
|
||||
DeleteUser: Types.DeleteUserResponse;
|
||||
|
||||
// ==== SERVICE USER ====
|
||||
CreateServiceUser: Types.CreateServiceUserResponse;
|
||||
UpdateServiceUserDescription: Types.UpdateServiceUserDescriptionResponse;
|
||||
CreateApiKeyForServiceUser: Types.CreateApiKeyForServiceUserResponse;
|
||||
DeleteApiKeyForServiceUser: Types.DeleteApiKeyForServiceUserResponse;
|
||||
|
||||
// ==== USER GROUP ====
|
||||
CreateUserGroup: Types.UserGroup;
|
||||
RenameUserGroup: Types.UserGroup;
|
||||
DeleteUserGroup: Types.UserGroup;
|
||||
AddUserToUserGroup: Types.UserGroup;
|
||||
RemoveUserFromUserGroup: Types.UserGroup;
|
||||
SetUsersInUserGroup: Types.UserGroup;
|
||||
SetEveryoneUserGroup: Types.UserGroup;
|
||||
|
||||
// ==== PERMISSIONS ====
|
||||
UpdateUserAdmin: Types.UpdateUserAdminResponse;
|
||||
UpdateUserBasePermissions: Types.UpdateUserBasePermissionsResponse;
|
||||
UpdatePermissionOnResourceType: Types.UpdatePermissionOnResourceTypeResponse;
|
||||
UpdatePermissionOnTarget: Types.UpdatePermissionOnTargetResponse;
|
||||
|
||||
// ==== RESOURCE ====
|
||||
UpdateResourceMeta: Types.UpdateResourceMetaResponse;
|
||||
|
||||
// ==== SWARM ====
|
||||
CreateSwarm: Types.Swarm;
|
||||
CopySwarm: Types.Swarm;
|
||||
DeleteSwarm: Types.Swarm;
|
||||
UpdateSwarm: Types.Swarm;
|
||||
RenameSwarm: Types.Update;
|
||||
|
||||
// ==== SERVER ====
|
||||
CreateServer: Types.Server;
|
||||
CopyServer: Types.Server;
|
||||
@@ -219,6 +208,12 @@ export type WriteResponses = {
|
||||
UpdateServerPublicKey: Types.Update;
|
||||
RotateServerKeys: Types.Update;
|
||||
|
||||
// ==== TERMINAL ====
|
||||
CreateTerminal: Types.NoData;
|
||||
DeleteTerminal: Types.NoData;
|
||||
DeleteAllTerminals: Types.NoData;
|
||||
BatchDeleteAllTerminals: Types.NoData;
|
||||
|
||||
// ==== STACK ====
|
||||
CreateStack: Types.Stack;
|
||||
CopyStack: Types.Stack;
|
||||
@@ -245,13 +240,6 @@ export type WriteResponses = {
|
||||
WriteBuildFileContents: Types.Update;
|
||||
RefreshBuildCache: Types.NoData;
|
||||
|
||||
// ==== BUILDER ====
|
||||
CreateBuilder: Types.Builder;
|
||||
CopyBuilder: Types.Builder;
|
||||
DeleteBuilder: Types.Builder;
|
||||
UpdateBuilder: Types.Builder;
|
||||
RenameBuilder: Types.Update;
|
||||
|
||||
// ==== REPO ====
|
||||
CreateRepo: Types.Repo;
|
||||
CopyRepo: Types.Repo;
|
||||
@@ -260,13 +248,6 @@ export type WriteResponses = {
|
||||
RenameRepo: Types.Update;
|
||||
RefreshRepoCache: Types.NoData;
|
||||
|
||||
// ==== ALERTER ====
|
||||
CreateAlerter: Types.Alerter;
|
||||
CopyAlerter: Types.Alerter;
|
||||
DeleteAlerter: Types.Alerter;
|
||||
UpdateAlerter: Types.Alerter;
|
||||
RenameAlerter: Types.Update;
|
||||
|
||||
// ==== PROCEDURE ====
|
||||
CreateProcedure: Types.Procedure;
|
||||
CopyProcedure: Types.Procedure;
|
||||
@@ -291,11 +272,51 @@ export type WriteResponses = {
|
||||
WriteSyncFileContents: Types.Update;
|
||||
RefreshResourceSyncPending: Types.ResourceSync;
|
||||
|
||||
// ==== TERMINAL ====
|
||||
CreateTerminal: Types.NoData;
|
||||
DeleteTerminal: Types.NoData;
|
||||
DeleteAllTerminals: Types.NoData;
|
||||
BatchDeleteAllTerminals: Types.NoData;
|
||||
// ==== BUILDER ====
|
||||
CreateBuilder: Types.Builder;
|
||||
CopyBuilder: Types.Builder;
|
||||
DeleteBuilder: Types.Builder;
|
||||
UpdateBuilder: Types.Builder;
|
||||
RenameBuilder: Types.Update;
|
||||
|
||||
// ==== ALERTER ====
|
||||
CreateAlerter: Types.Alerter;
|
||||
CopyAlerter: Types.Alerter;
|
||||
DeleteAlerter: Types.Alerter;
|
||||
UpdateAlerter: Types.Alerter;
|
||||
RenameAlerter: Types.Update;
|
||||
|
||||
// ==== ONBOARDING KEY ====
|
||||
CreateOnboardingKey: Types.CreateOnboardingKeyResponse;
|
||||
UpdateOnboardingKey: Types.UpdateOnboardingKeyResponse;
|
||||
DeleteOnboardingKey: Types.DeleteOnboardingKeyResponse;
|
||||
|
||||
// ==== USER ====
|
||||
CreateLocalUser: Types.CreateLocalUserResponse;
|
||||
UpdateUserUsername: Types.UpdateUserUsernameResponse;
|
||||
UpdateUserPassword: Types.UpdateUserPasswordResponse;
|
||||
DeleteUser: Types.DeleteUserResponse;
|
||||
|
||||
// ==== SERVICE USER ====
|
||||
CreateServiceUser: Types.CreateServiceUserResponse;
|
||||
UpdateServiceUserDescription: Types.UpdateServiceUserDescriptionResponse;
|
||||
CreateApiKeyForServiceUser: Types.CreateApiKeyForServiceUserResponse;
|
||||
DeleteApiKeyForServiceUser: Types.DeleteApiKeyForServiceUserResponse;
|
||||
|
||||
// ==== USER GROUP ====
|
||||
CreateUserGroup: Types.UserGroup;
|
||||
RenameUserGroup: Types.UserGroup;
|
||||
DeleteUserGroup: Types.UserGroup;
|
||||
AddUserToUserGroup: Types.UserGroup;
|
||||
RemoveUserFromUserGroup: Types.UserGroup;
|
||||
SetUsersInUserGroup: Types.UserGroup;
|
||||
SetEveryoneUserGroup: Types.UserGroup;
|
||||
|
||||
// ==== PERMISSIONS ====
|
||||
UpdateUserAdmin: Types.UpdateUserAdminResponse;
|
||||
UpdateUserBasePermissions: Types.UpdateUserBasePermissionsResponse;
|
||||
UpdatePermissionOnResourceType: Types.UpdatePermissionOnResourceTypeResponse;
|
||||
UpdatePermissionOnTarget: Types.UpdatePermissionOnTargetResponse;
|
||||
|
||||
// ==== TAG ====
|
||||
CreateTag: Types.Tag;
|
||||
@@ -310,7 +331,7 @@ export type WriteResponses = {
|
||||
UpdateVariableIsSecret: Types.UpdateVariableIsSecretResponse;
|
||||
DeleteVariable: Types.DeleteVariableResponse;
|
||||
|
||||
// ==== PROVIDERS ====
|
||||
// ==== PROVIDER ====
|
||||
CreateGitProviderAccount: Types.CreateGitProviderAccountResponse;
|
||||
UpdateGitProviderAccount: Types.UpdateGitProviderAccountResponse;
|
||||
DeleteGitProviderAccount: Types.DeleteGitProviderAccountResponse;
|
||||
@@ -318,11 +339,6 @@ export type WriteResponses = {
|
||||
UpdateDockerRegistryAccount: Types.UpdateDockerRegistryAccountResponse;
|
||||
DeleteDockerRegistryAccount: Types.DeleteDockerRegistryAccountResponse;
|
||||
|
||||
// ==== ONBOARDING KEY ====
|
||||
CreateOnboardingKey: Types.CreateOnboardingKeyResponse;
|
||||
UpdateOnboardingKey: Types.UpdateOnboardingKeyResponse;
|
||||
DeleteOnboardingKey: Types.DeleteOnboardingKeyResponse;
|
||||
|
||||
// ==== ALERT ====
|
||||
CloseAlert: Types.NoData;
|
||||
};
|
||||
@@ -365,6 +381,7 @@ export type ExecuteResponses = {
|
||||
UnpauseStack: Types.Update;
|
||||
DestroyStack: Types.Update;
|
||||
BatchDestroyStack: Types.BatchExecutionResponse;
|
||||
RunStackService: Types.Update;
|
||||
|
||||
// ==== DEPLOYMENT ====
|
||||
Deploy: Types.Update;
|
||||
@@ -403,16 +420,6 @@ export type ExecuteResponses = {
|
||||
// ==== SYNC ====
|
||||
RunSync: Types.Update;
|
||||
|
||||
// ==== STACK Service ====
|
||||
DeployStackService: Types.Update;
|
||||
StartStackService: Types.Update;
|
||||
RestartStackService: Types.Update;
|
||||
StopStackService: Types.Update;
|
||||
PauseStackService: Types.Update;
|
||||
UnpauseStackService: Types.Update;
|
||||
DestroyStackService: Types.Update;
|
||||
RunStackService: Types.Update;
|
||||
|
||||
// ==== ALERTER ====
|
||||
TestAlerter: Types.Update;
|
||||
SendAlert: Types.Update;
|
||||
|
||||
@@ -2564,6 +2564,8 @@ export interface SwarmConfig {
|
||||
* tries the next Server.
|
||||
*/
|
||||
server_ids?: string[];
|
||||
/** Configure quick links that are displayed in the resource header */
|
||||
links?: string[];
|
||||
}
|
||||
|
||||
export interface SwarmInfo {
|
||||
@@ -4144,8 +4146,6 @@ export enum SwarmState {
|
||||
Healthy = "Healthy",
|
||||
/** The Swarm is unhealthy */
|
||||
Unhealthy = "Unhealthy",
|
||||
/** Servers are reachable, but Swarm is not running on any of them. */
|
||||
Offline = "Offline",
|
||||
}
|
||||
|
||||
export interface SwarmListItemInfo {
|
||||
@@ -5800,6 +5800,15 @@ export interface DiscordAlerterEndpoint {
|
||||
url: string;
|
||||
}
|
||||
|
||||
/** Standard docker lists available from a Server. */
|
||||
export interface DockerLists {
|
||||
containers: ContainerListItem[];
|
||||
networks: NetworkListItem[];
|
||||
images: ImageListItem[];
|
||||
volumes: VolumeListItem[];
|
||||
projects: ComposeProject[];
|
||||
}
|
||||
|
||||
/** Driver represents a driver (network, logging, secrets). */
|
||||
export interface Driver {
|
||||
/** Name of the driver. */
|
||||
@@ -6637,8 +6646,8 @@ export interface GetSwarmsSummaryResponse {
|
||||
healthy: number;
|
||||
/** The number of Swarms with Unhealthy state */
|
||||
unhealthy: number;
|
||||
/** The number of Swarms with Offline state */
|
||||
offline: number;
|
||||
/** The number of Swarms with Unknown state */
|
||||
unknown: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6798,6 +6807,14 @@ export interface InspectStackContainer {
|
||||
service: string;
|
||||
}
|
||||
|
||||
/** JoinTokens contains the tokens workers and managers need to join the swarm. */
|
||||
export interface JoinTokens {
|
||||
/** The token workers can use to join the swarm. */
|
||||
Worker?: string;
|
||||
/** The token managers can use to join the swarm. */
|
||||
Manager?: string;
|
||||
}
|
||||
|
||||
export interface LatestCommit {
|
||||
hash: string;
|
||||
message: string;
|
||||
@@ -8804,6 +8821,124 @@ export interface StopStack {
|
||||
services?: string[];
|
||||
}
|
||||
|
||||
/** Orchestration configuration. */
|
||||
export interface SwarmSpecOrchestration {
|
||||
/**
|
||||
* The number of historic tasks to keep per instance or node.
|
||||
* If negative, never remove completed or failed tasks.
|
||||
*/
|
||||
TaskHistoryRetentionLimit?: I64;
|
||||
}
|
||||
|
||||
/** Raft configuration. */
|
||||
export interface SwarmSpecRaft {
|
||||
/** The number of log entries between snapshots. */
|
||||
SnapshotInterval?: U64;
|
||||
/** The number of snapshots to keep beyond the current snapshot. */
|
||||
KeepOldSnapshots?: U64;
|
||||
/** The number of log entries to keep around to sync up slow followers after a snapshot is created. */
|
||||
LogEntriesForSlowFollowers?: U64;
|
||||
/** The number of ticks that a follower will wait for a message from the leader before becoming a candidate and starting an election. `ElectionTick` must be greater than `HeartbeatTick`. A tick currently defaults to one second, so these translate directly to seconds currently, but this is NOT guaranteed. */
|
||||
ElectionTick?: I64;
|
||||
/**
|
||||
* The number of ticks between heartbeats.
|
||||
* Every HeartbeatTick ticks, the leader will send a heartbeat to the followers.
|
||||
* A tick currently defaults to one second, so these translate directly to seconds currently, but this is NOT guaranteed.
|
||||
*/
|
||||
HeartbeatTick?: I64;
|
||||
}
|
||||
|
||||
/** Dispatcher configuration. */
|
||||
export interface SwarmSpecDispatcher {
|
||||
/** The delay for an agent to send a heartbeat to the dispatcher. */
|
||||
HeartbeatPeriod?: I64;
|
||||
}
|
||||
|
||||
export enum SwarmSpecCaConfigExternalCasProtocolEnum {
|
||||
EMPTY = "",
|
||||
CFSSL = "cfssl",
|
||||
}
|
||||
|
||||
export interface SwarmSpecCaConfigExternalCas {
|
||||
/** Protocol for communication with the external CA (currently only `cfssl` is supported). */
|
||||
Protocol?: SwarmSpecCaConfigExternalCasProtocolEnum;
|
||||
/** URL where certificate signing requests should be sent. */
|
||||
URL?: string;
|
||||
/** An object with key/value pairs that are interpreted as protocol-specific options for the external CA driver. */
|
||||
Options?: Record<string, string>;
|
||||
/** The root CA certificate (in PEM format) this external CA uses to issue TLS certificates (assumed to be to the current swarm root CA certificate if not provided). */
|
||||
CACert?: string;
|
||||
}
|
||||
|
||||
/** CA configuration. */
|
||||
export interface SwarmSpecCaConfig {
|
||||
/** The duration node certificates are issued for. */
|
||||
NodeCertExpiry?: I64;
|
||||
/** Configuration for forwarding signing requests to an external certificate authority. */
|
||||
ExternalCAs?: SwarmSpecCaConfigExternalCas[];
|
||||
/** The desired signing CA certificate for all swarm node TLS leaf certificates, in PEM format. */
|
||||
SigningCACert?: string;
|
||||
/** The desired signing CA key for all swarm node TLS leaf certificates, in PEM format. */
|
||||
SigningCAKey?: string;
|
||||
/** An integer whose purpose is to force swarm to generate a new signing CA certificate and key, if none have been specified in `SigningCACert` and `SigningCAKey` */
|
||||
ForceRotate?: U64;
|
||||
}
|
||||
|
||||
/** Parameters related to encryption-at-rest. */
|
||||
export interface SwarmSpecEncryptionConfig {
|
||||
/** If set, generate a key and use it to lock data stored on the managers. */
|
||||
AutoLockManagers?: boolean;
|
||||
}
|
||||
|
||||
/** The log driver to use for tasks created in the orchestrator if unspecified by a service. Updating this value only affects new tasks. Existing tasks continue to use their previously configured log driver until recreated. */
|
||||
export interface SwarmSpecTaskDefaultsLogDriver {
|
||||
/** The log driver to use as a default for new tasks. */
|
||||
Name?: string;
|
||||
/** Driver-specific options for the selected log driver, specified as key/value pairs. */
|
||||
Options?: Record<string, string>;
|
||||
}
|
||||
|
||||
/** Defaults for creating tasks in this cluster. */
|
||||
export interface SwarmSpecTaskDefaults {
|
||||
LogDriver?: SwarmSpecTaskDefaultsLogDriver;
|
||||
}
|
||||
|
||||
/** User modifiable swarm configuration. */
|
||||
export interface SwarmSpec {
|
||||
/** Name of the swarm. */
|
||||
Name?: string;
|
||||
/** User-defined key/value metadata. */
|
||||
Labels?: Record<string, string>;
|
||||
Orchestration?: SwarmSpecOrchestration;
|
||||
Raft?: SwarmSpecRaft;
|
||||
Dispatcher?: SwarmSpecDispatcher;
|
||||
CAConfig?: SwarmSpecCaConfig;
|
||||
EncryptionConfig?: SwarmSpecEncryptionConfig;
|
||||
TaskDefaults?: SwarmSpecTaskDefaults;
|
||||
}
|
||||
|
||||
/** Docker-level information about the Swarm. */
|
||||
export interface SwarmInspectInfo {
|
||||
/** The (Docker) ID of the swarm. */
|
||||
ID?: string;
|
||||
Version?: ObjectVersion;
|
||||
/** Date and time at which the swarm was initialised in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. */
|
||||
CreatedAt?: string;
|
||||
/** Date and time at which the swarm was last updated in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. */
|
||||
UpdatedAt?: string;
|
||||
Spec?: SwarmSpec;
|
||||
TLSInfo?: TlsInfo;
|
||||
/** Whether there is currently a root CA rotation in progress for the swarm */
|
||||
RootRotationInProgress?: boolean;
|
||||
/** DataPathPort specifies the data path port number for data traffic. Acceptable port range is 1024 to 49151. If no port is set or is set to 0, the default port (4789) is used. */
|
||||
DataPathPort?: number;
|
||||
/** Default Address Pool specifies default subnet pools for global scope networks. */
|
||||
DefaultAddrPool?: string[];
|
||||
/** SubnetSize specifies the subnet size of the networks created from the default subnet pool. */
|
||||
SubnetSize?: number;
|
||||
JoinTokens?: JoinTokens;
|
||||
}
|
||||
|
||||
/** Swarm node details. */
|
||||
export interface SwarmNode {
|
||||
ID?: string;
|
||||
@@ -9486,9 +9621,9 @@ export type ExecuteRequest =
|
||||
| { type: "BatchRunProcedure", params: BatchRunProcedure }
|
||||
| { type: "RunAction", params: RunAction }
|
||||
| { type: "BatchRunAction", params: BatchRunAction }
|
||||
| { type: "RunSync", params: RunSync }
|
||||
| { type: "TestAlerter", params: TestAlerter }
|
||||
| { type: "SendAlert", params: SendAlert }
|
||||
| { type: "RunSync", params: RunSync }
|
||||
| { type: "ClearRepoCache", params: ClearRepoCache }
|
||||
| { type: "BackupCoreDatabase", params: BackupCoreDatabase }
|
||||
| { type: "GlobalAutoUpdate", params: GlobalAutoUpdate }
|
||||
@@ -9587,33 +9722,16 @@ export type ReadRequest =
|
||||
| { type: "ListSecrets", params: ListSecrets }
|
||||
| { type: "ListGitProvidersFromConfig", params: ListGitProvidersFromConfig }
|
||||
| { type: "ListDockerRegistriesFromConfig", params: ListDockerRegistriesFromConfig }
|
||||
| { type: "GetUsername", params: GetUsername }
|
||||
| { type: "GetPermission", params: GetPermission }
|
||||
| { type: "FindUser", params: FindUser }
|
||||
| { type: "ListUsers", params: ListUsers }
|
||||
| { type: "ListApiKeys", params: ListApiKeys }
|
||||
| { type: "ListApiKeysForServiceUser", params: ListApiKeysForServiceUser }
|
||||
| { type: "ListPermissions", params: ListPermissions }
|
||||
| { type: "ListUserTargetPermissions", params: ListUserTargetPermissions }
|
||||
| { type: "GetUserGroup", params: GetUserGroup }
|
||||
| { type: "ListUserGroups", params: ListUserGroups }
|
||||
| { type: "GetProceduresSummary", params: GetProceduresSummary }
|
||||
| { type: "GetProcedure", params: GetProcedure }
|
||||
| { type: "GetProcedureActionState", params: GetProcedureActionState }
|
||||
| { type: "ListProcedures", params: ListProcedures }
|
||||
| { type: "ListFullProcedures", params: ListFullProcedures }
|
||||
| { type: "GetActionsSummary", params: GetActionsSummary }
|
||||
| { type: "GetAction", params: GetAction }
|
||||
| { type: "GetActionActionState", params: GetActionActionState }
|
||||
| { type: "ListActions", params: ListActions }
|
||||
| { type: "ListFullActions", params: ListFullActions }
|
||||
| { type: "ListSchedules", params: ListSchedules }
|
||||
| { type: "GetSwarmsSummary", params: GetSwarmsSummary }
|
||||
| { type: "GetSwarm", params: GetSwarm }
|
||||
| { type: "GetSwarmActionState", params: GetSwarmActionState }
|
||||
| { type: "ListSwarms", params: ListSwarms }
|
||||
| { type: "ListFullSwarms", params: ListFullSwarms }
|
||||
| { type: "GetServersSummary", params: GetServersSummary }
|
||||
| { type: "GetServer", params: GetServer }
|
||||
| { type: "GetServerState", params: GetServerState }
|
||||
| { type: "GetPeripheryInformation", params: GetPeripheryInformation }
|
||||
| { type: "GetServerActionState", params: GetServerActionState }
|
||||
| { type: "GetHistoricalServerStats", params: GetHistoricalServerStats }
|
||||
| { type: "ListServers", params: ListServers }
|
||||
| { type: "ListFullServers", params: ListFullServers }
|
||||
| { type: "ListTerminals", params: ListTerminals }
|
||||
@@ -9634,6 +9752,7 @@ export type ReadRequest =
|
||||
| { type: "InspectDockerVolume", params: InspectDockerVolume }
|
||||
| { type: "GetSystemInformation", params: GetSystemInformation }
|
||||
| { type: "GetSystemStats", params: GetSystemStats }
|
||||
| { type: "GetHistoricalServerStats", params: GetHistoricalServerStats }
|
||||
| { type: "ListSystemProcesses", params: ListSystemProcesses }
|
||||
| { type: "GetStacksSummary", params: GetStacksSummary }
|
||||
| { type: "GetStack", params: GetStack }
|
||||
@@ -9670,6 +9789,17 @@ export type ReadRequest =
|
||||
| { type: "GetRepoActionState", params: GetRepoActionState }
|
||||
| { type: "ListRepos", params: ListRepos }
|
||||
| { type: "ListFullRepos", params: ListFullRepos }
|
||||
| { type: "GetProceduresSummary", params: GetProceduresSummary }
|
||||
| { type: "GetProcedure", params: GetProcedure }
|
||||
| { type: "GetProcedureActionState", params: GetProcedureActionState }
|
||||
| { type: "ListProcedures", params: ListProcedures }
|
||||
| { type: "ListFullProcedures", params: ListFullProcedures }
|
||||
| { type: "GetActionsSummary", params: GetActionsSummary }
|
||||
| { type: "GetAction", params: GetAction }
|
||||
| { type: "GetActionActionState", params: GetActionActionState }
|
||||
| { type: "ListActions", params: ListActions }
|
||||
| { type: "ListFullActions", params: ListFullActions }
|
||||
| { type: "ListSchedules", params: ListSchedules }
|
||||
| { type: "GetResourceSyncsSummary", params: GetResourceSyncsSummary }
|
||||
| { type: "GetResourceSync", params: GetResourceSync }
|
||||
| { type: "GetResourceSyncActionState", params: GetResourceSyncActionState }
|
||||
@@ -9687,6 +9817,16 @@ export type ReadRequest =
|
||||
| { type: "ExportResourcesToToml", params: ExportResourcesToToml }
|
||||
| { type: "GetTag", params: GetTag }
|
||||
| { type: "ListTags", params: ListTags }
|
||||
| { type: "GetUsername", params: GetUsername }
|
||||
| { type: "GetPermission", params: GetPermission }
|
||||
| { type: "FindUser", params: FindUser }
|
||||
| { type: "ListUsers", params: ListUsers }
|
||||
| { type: "ListApiKeys", params: ListApiKeys }
|
||||
| { type: "ListApiKeysForServiceUser", params: ListApiKeysForServiceUser }
|
||||
| { type: "ListPermissions", params: ListPermissions }
|
||||
| { type: "ListUserTargetPermissions", params: ListUserTargetPermissions }
|
||||
| { type: "GetUserGroup", params: GetUserGroup }
|
||||
| { type: "ListUserGroups", params: ListUserGroups }
|
||||
| { type: "GetUpdate", params: GetUpdate }
|
||||
| { type: "ListUpdates", params: ListUpdates }
|
||||
| { type: "ListAlerts", params: ListAlerts }
|
||||
@@ -9761,26 +9901,12 @@ export type UserRequest =
|
||||
| { type: "DeleteApiKey", params: DeleteApiKey };
|
||||
|
||||
export type WriteRequest =
|
||||
| { type: "CreateLocalUser", params: CreateLocalUser }
|
||||
| { type: "UpdateUserUsername", params: UpdateUserUsername }
|
||||
| { type: "UpdateUserPassword", params: UpdateUserPassword }
|
||||
| { type: "DeleteUser", params: DeleteUser }
|
||||
| { type: "CreateServiceUser", params: CreateServiceUser }
|
||||
| { type: "UpdateServiceUserDescription", params: UpdateServiceUserDescription }
|
||||
| { type: "CreateApiKeyForServiceUser", params: CreateApiKeyForServiceUser }
|
||||
| { type: "DeleteApiKeyForServiceUser", params: DeleteApiKeyForServiceUser }
|
||||
| { type: "CreateUserGroup", params: CreateUserGroup }
|
||||
| { type: "RenameUserGroup", params: RenameUserGroup }
|
||||
| { type: "DeleteUserGroup", params: DeleteUserGroup }
|
||||
| { type: "AddUserToUserGroup", params: AddUserToUserGroup }
|
||||
| { type: "RemoveUserFromUserGroup", params: RemoveUserFromUserGroup }
|
||||
| { type: "SetUsersInUserGroup", params: SetUsersInUserGroup }
|
||||
| { type: "SetEveryoneUserGroup", params: SetEveryoneUserGroup }
|
||||
| { type: "UpdateUserAdmin", params: UpdateUserAdmin }
|
||||
| { type: "UpdateUserBasePermissions", params: UpdateUserBasePermissions }
|
||||
| { type: "UpdatePermissionOnResourceType", params: UpdatePermissionOnResourceType }
|
||||
| { type: "UpdatePermissionOnTarget", params: UpdatePermissionOnTarget }
|
||||
| { type: "UpdateResourceMeta", params: UpdateResourceMeta }
|
||||
| { type: "CreateSwarm", params: CreateSwarm }
|
||||
| { type: "CopySwarm", params: CopySwarm }
|
||||
| { type: "DeleteSwarm", params: DeleteSwarm }
|
||||
| { type: "UpdateSwarm", params: UpdateSwarm }
|
||||
| { type: "RenameSwarm", params: RenameSwarm }
|
||||
| { type: "CreateServer", params: CreateServer }
|
||||
| { type: "CopyServer", params: CopyServer }
|
||||
| { type: "DeleteServer", params: DeleteServer }
|
||||
@@ -9789,6 +9915,10 @@ export type WriteRequest =
|
||||
| { type: "CreateNetwork", params: CreateNetwork }
|
||||
| { type: "UpdateServerPublicKey", params: UpdateServerPublicKey }
|
||||
| { type: "RotateServerKeys", params: RotateServerKeys }
|
||||
| { type: "CreateTerminal", params: CreateTerminal }
|
||||
| { type: "DeleteTerminal", params: DeleteTerminal }
|
||||
| { type: "DeleteAllTerminals", params: DeleteAllTerminals }
|
||||
| { type: "BatchDeleteAllTerminals", params: BatchDeleteAllTerminals }
|
||||
| { type: "CreateStack", params: CreateStack }
|
||||
| { type: "CopyStack", params: CopyStack }
|
||||
| { type: "DeleteStack", params: DeleteStack }
|
||||
@@ -9809,22 +9939,12 @@ export type WriteRequest =
|
||||
| { type: "RenameBuild", params: RenameBuild }
|
||||
| { type: "WriteBuildFileContents", params: WriteBuildFileContents }
|
||||
| { type: "RefreshBuildCache", params: RefreshBuildCache }
|
||||
| { type: "CreateBuilder", params: CreateBuilder }
|
||||
| { type: "CopyBuilder", params: CopyBuilder }
|
||||
| { type: "DeleteBuilder", params: DeleteBuilder }
|
||||
| { type: "UpdateBuilder", params: UpdateBuilder }
|
||||
| { type: "RenameBuilder", params: RenameBuilder }
|
||||
| { type: "CreateRepo", params: CreateRepo }
|
||||
| { type: "CopyRepo", params: CopyRepo }
|
||||
| { type: "DeleteRepo", params: DeleteRepo }
|
||||
| { type: "UpdateRepo", params: UpdateRepo }
|
||||
| { type: "RenameRepo", params: RenameRepo }
|
||||
| { type: "RefreshRepoCache", params: RefreshRepoCache }
|
||||
| { type: "CreateAlerter", params: CreateAlerter }
|
||||
| { type: "CopyAlerter", params: CopyAlerter }
|
||||
| { type: "DeleteAlerter", params: DeleteAlerter }
|
||||
| { type: "UpdateAlerter", params: UpdateAlerter }
|
||||
| { type: "RenameAlerter", params: RenameAlerter }
|
||||
| { type: "CreateProcedure", params: CreateProcedure }
|
||||
| { type: "CopyProcedure", params: CopyProcedure }
|
||||
| { type: "DeleteProcedure", params: DeleteProcedure }
|
||||
@@ -9843,10 +9963,38 @@ export type WriteRequest =
|
||||
| { type: "WriteSyncFileContents", params: WriteSyncFileContents }
|
||||
| { type: "CommitSync", params: CommitSync }
|
||||
| { type: "RefreshResourceSyncPending", params: RefreshResourceSyncPending }
|
||||
| { type: "CreateTerminal", params: CreateTerminal }
|
||||
| { type: "DeleteTerminal", params: DeleteTerminal }
|
||||
| { type: "DeleteAllTerminals", params: DeleteAllTerminals }
|
||||
| { type: "BatchDeleteAllTerminals", params: BatchDeleteAllTerminals }
|
||||
| { type: "CreateBuilder", params: CreateBuilder }
|
||||
| { type: "CopyBuilder", params: CopyBuilder }
|
||||
| { type: "DeleteBuilder", params: DeleteBuilder }
|
||||
| { type: "UpdateBuilder", params: UpdateBuilder }
|
||||
| { type: "RenameBuilder", params: RenameBuilder }
|
||||
| { type: "CreateAlerter", params: CreateAlerter }
|
||||
| { type: "CopyAlerter", params: CopyAlerter }
|
||||
| { type: "DeleteAlerter", params: DeleteAlerter }
|
||||
| { type: "UpdateAlerter", params: UpdateAlerter }
|
||||
| { type: "RenameAlerter", params: RenameAlerter }
|
||||
| { type: "CreateOnboardingKey", params: CreateOnboardingKey }
|
||||
| { type: "UpdateOnboardingKey", params: UpdateOnboardingKey }
|
||||
| { type: "DeleteOnboardingKey", params: DeleteOnboardingKey }
|
||||
| { type: "CreateLocalUser", params: CreateLocalUser }
|
||||
| { type: "UpdateUserUsername", params: UpdateUserUsername }
|
||||
| { type: "UpdateUserPassword", params: UpdateUserPassword }
|
||||
| { type: "DeleteUser", params: DeleteUser }
|
||||
| { type: "CreateServiceUser", params: CreateServiceUser }
|
||||
| { type: "UpdateServiceUserDescription", params: UpdateServiceUserDescription }
|
||||
| { type: "CreateApiKeyForServiceUser", params: CreateApiKeyForServiceUser }
|
||||
| { type: "DeleteApiKeyForServiceUser", params: DeleteApiKeyForServiceUser }
|
||||
| { type: "CreateUserGroup", params: CreateUserGroup }
|
||||
| { type: "RenameUserGroup", params: RenameUserGroup }
|
||||
| { type: "DeleteUserGroup", params: DeleteUserGroup }
|
||||
| { type: "AddUserToUserGroup", params: AddUserToUserGroup }
|
||||
| { type: "RemoveUserFromUserGroup", params: RemoveUserFromUserGroup }
|
||||
| { type: "SetUsersInUserGroup", params: SetUsersInUserGroup }
|
||||
| { type: "SetEveryoneUserGroup", params: SetEveryoneUserGroup }
|
||||
| { type: "UpdateUserAdmin", params: UpdateUserAdmin }
|
||||
| { type: "UpdateUserBasePermissions", params: UpdateUserBasePermissions }
|
||||
| { type: "UpdatePermissionOnResourceType", params: UpdatePermissionOnResourceType }
|
||||
| { type: "UpdatePermissionOnTarget", params: UpdatePermissionOnTarget }
|
||||
| { type: "CreateTag", params: CreateTag }
|
||||
| { type: "DeleteTag", params: DeleteTag }
|
||||
| { type: "RenameTag", params: RenameTag }
|
||||
@@ -9862,9 +10010,6 @@ export type WriteRequest =
|
||||
| { type: "CreateDockerRegistryAccount", params: CreateDockerRegistryAccount }
|
||||
| { type: "UpdateDockerRegistryAccount", params: UpdateDockerRegistryAccount }
|
||||
| { type: "DeleteDockerRegistryAccount", params: DeleteDockerRegistryAccount }
|
||||
| { type: "CreateOnboardingKey", params: CreateOnboardingKey }
|
||||
| { type: "UpdateOnboardingKey", params: UpdateOnboardingKey }
|
||||
| { type: "DeleteOnboardingKey", params: DeleteOnboardingKey }
|
||||
| { type: "CloseAlert", params: CloseAlert };
|
||||
|
||||
export type WsLoginMessage =
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
use komodo_client::entities::{
|
||||
config::{DockerRegistry, GitProvider},
|
||||
docker::{
|
||||
container::ContainerListItem, image::ImageListItem,
|
||||
network::NetworkListItem, volume::VolumeListItem,
|
||||
},
|
||||
server::PeripheryInformation,
|
||||
stack::ComposeProject,
|
||||
stats::{SystemInformation, SystemStats},
|
||||
update::Log,
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
@@ -18,6 +11,7 @@ pub mod container;
|
||||
pub mod docker;
|
||||
pub mod git;
|
||||
pub mod keys;
|
||||
pub mod poll;
|
||||
pub mod stats;
|
||||
pub mod swarm;
|
||||
pub mod terminal;
|
||||
@@ -60,33 +54,6 @@ pub struct GetVersionResponse {
|
||||
|
||||
//
|
||||
|
||||
/// This is the data Core uses to update all Server-related status caches.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Resolve)]
|
||||
#[response(PollStatusResponse)]
|
||||
#[error(anyhow::Error)]
|
||||
pub struct PollStatus {
|
||||
/// Some servers have stats monitoring disabled.
|
||||
pub include_stats: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct PollStatusResponse {
|
||||
pub periphery_info: PeripheryInformation,
|
||||
/// Basic system information
|
||||
pub system_info: SystemInformation,
|
||||
/// Current System Stats (Cpu, Mem, Disk)
|
||||
pub system_stats: Option<SystemStats>,
|
||||
|
||||
// Docker lists
|
||||
pub containers: Vec<ContainerListItem>,
|
||||
pub networks: Vec<NetworkListItem>,
|
||||
pub images: Vec<ImageListItem>,
|
||||
pub volumes: Vec<VolumeListItem>,
|
||||
pub projects: Vec<ComposeProject>,
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Resolve)]
|
||||
#[response(ListGitProvidersResponse)]
|
||||
#[error(anyhow::Error)]
|
||||
|
||||
29
client/periphery/rs/src/api/poll.rs
Normal file
29
client/periphery/rs/src/api/poll.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
use komodo_client::entities::{
|
||||
docker::DockerLists,
|
||||
server::PeripheryInformation,
|
||||
stats::{SystemInformation, SystemStats},
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// This is the data Core uses to update all Server-related status caches.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Resolve)]
|
||||
#[response(PollStatusResponse)]
|
||||
#[error(anyhow::Error)]
|
||||
pub struct PollStatus {
|
||||
/// Include system stats
|
||||
pub include_stats: bool,
|
||||
/// Include docker info
|
||||
pub include_docker: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PollStatusResponse {
|
||||
pub periphery_info: PeripheryInformation,
|
||||
/// Basic system information
|
||||
pub system_info: SystemInformation,
|
||||
/// Current System Stats (Cpu, Mem, Disk)
|
||||
pub system_stats: Option<SystemStats>,
|
||||
/// Docker lists
|
||||
pub docker: Option<DockerLists>,
|
||||
}
|
||||
@@ -1,10 +1,22 @@
|
||||
use komodo_client::entities::docker::{
|
||||
node::SwarmNode, secret::SwarmSecret, service::SwarmService,
|
||||
task::SwarmTask,
|
||||
SwarmLists, node::SwarmNode, secret::SwarmSecret,
|
||||
service::SwarmService, swarm::SwarmInspectInfo, task::SwarmTask,
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Resolve)]
|
||||
#[response(PollSwarmStatusResponse)]
|
||||
#[error(anyhow::Error)]
|
||||
pub struct PollSwarmStatus {}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct PollSwarmStatusResponse {
|
||||
/// Inspect swarm response
|
||||
pub inspect: Option<SwarmInspectInfo>,
|
||||
pub lists: SwarmLists,
|
||||
}
|
||||
|
||||
// ======
|
||||
// Node
|
||||
// ======
|
||||
|
||||
141
frontend/public/client/responses.d.ts
vendored
141
frontend/public/client/responses.d.ts
vendored
@@ -18,33 +18,16 @@ export type ReadResponses = {
|
||||
ListSecrets: Types.ListSecretsResponse;
|
||||
ListGitProvidersFromConfig: Types.ListGitProvidersFromConfigResponse;
|
||||
ListDockerRegistriesFromConfig: Types.ListDockerRegistriesFromConfigResponse;
|
||||
GetUsername: Types.GetUsernameResponse;
|
||||
GetPermission: Types.GetPermissionResponse;
|
||||
FindUser: Types.FindUserResponse;
|
||||
ListUsers: Types.ListUsersResponse;
|
||||
ListApiKeys: Types.ListApiKeysResponse;
|
||||
ListApiKeysForServiceUser: Types.ListApiKeysForServiceUserResponse;
|
||||
ListPermissions: Types.ListPermissionsResponse;
|
||||
ListUserTargetPermissions: Types.ListUserTargetPermissionsResponse;
|
||||
GetUserGroup: Types.GetUserGroupResponse;
|
||||
ListUserGroups: Types.ListUserGroupsResponse;
|
||||
GetProceduresSummary: Types.GetProceduresSummaryResponse;
|
||||
GetProcedure: Types.GetProcedureResponse;
|
||||
GetProcedureActionState: Types.GetProcedureActionStateResponse;
|
||||
ListProcedures: Types.ListProceduresResponse;
|
||||
ListFullProcedures: Types.ListFullProceduresResponse;
|
||||
GetActionsSummary: Types.GetActionsSummaryResponse;
|
||||
GetAction: Types.GetActionResponse;
|
||||
GetActionActionState: Types.GetActionActionStateResponse;
|
||||
ListActions: Types.ListActionsResponse;
|
||||
ListFullActions: Types.ListFullActionsResponse;
|
||||
ListSchedules: Types.ListSchedulesResponse;
|
||||
GetSwarmsSummary: Types.GetSwarmsSummaryResponse;
|
||||
GetSwarm: Types.GetSwarmResponse;
|
||||
GetSwarmActionState: Types.GetSwarmActionStateResponse;
|
||||
ListSwarms: Types.ListSwarmsResponse;
|
||||
ListFullSwarms: Types.ListFullSwarmsResponse;
|
||||
GetServersSummary: Types.GetServersSummaryResponse;
|
||||
GetServer: Types.GetServerResponse;
|
||||
GetServerState: Types.GetServerStateResponse;
|
||||
GetPeripheryInformation: Types.GetPeripheryInformationResponse;
|
||||
GetServerActionState: Types.GetServerActionStateResponse;
|
||||
GetHistoricalServerStats: Types.GetHistoricalServerStatsResponse;
|
||||
ListServers: Types.ListServersResponse;
|
||||
ListFullServers: Types.ListFullServersResponse;
|
||||
ListTerminals: Types.ListTerminalsResponse;
|
||||
@@ -63,6 +46,10 @@ export type ReadResponses = {
|
||||
ListDockerImageHistory: Types.ListDockerImageHistoryResponse;
|
||||
ListDockerVolumes: Types.ListDockerVolumesResponse;
|
||||
InspectDockerVolume: Types.InspectDockerVolumeResponse;
|
||||
GetSystemInformation: Types.GetSystemInformationResponse;
|
||||
GetSystemStats: Types.GetSystemStatsResponse;
|
||||
GetHistoricalServerStats: Types.GetHistoricalServerStatsResponse;
|
||||
ListSystemProcesses: Types.ListSystemProcessesResponse;
|
||||
GetStacksSummary: Types.GetStacksSummaryResponse;
|
||||
GetStack: Types.GetStackResponse;
|
||||
GetStackActionState: Types.GetStackActionStateResponse;
|
||||
@@ -98,6 +85,17 @@ export type ReadResponses = {
|
||||
GetRepoActionState: Types.GetRepoActionStateResponse;
|
||||
ListRepos: Types.ListReposResponse;
|
||||
ListFullRepos: Types.ListFullReposResponse;
|
||||
GetProceduresSummary: Types.GetProceduresSummaryResponse;
|
||||
GetProcedure: Types.GetProcedureResponse;
|
||||
GetProcedureActionState: Types.GetProcedureActionStateResponse;
|
||||
ListProcedures: Types.ListProceduresResponse;
|
||||
ListFullProcedures: Types.ListFullProceduresResponse;
|
||||
GetActionsSummary: Types.GetActionsSummaryResponse;
|
||||
GetAction: Types.GetActionResponse;
|
||||
GetActionActionState: Types.GetActionActionStateResponse;
|
||||
ListActions: Types.ListActionsResponse;
|
||||
ListFullActions: Types.ListFullActionsResponse;
|
||||
ListSchedules: Types.ListSchedulesResponse;
|
||||
GetResourceSyncsSummary: Types.GetResourceSyncsSummaryResponse;
|
||||
GetResourceSync: Types.GetResourceSyncResponse;
|
||||
GetResourceSyncActionState: Types.GetResourceSyncActionStateResponse;
|
||||
@@ -115,13 +113,20 @@ export type ReadResponses = {
|
||||
ExportResourcesToToml: Types.ExportResourcesToTomlResponse;
|
||||
GetTag: Types.GetTagResponse;
|
||||
ListTags: Types.ListTagsResponse;
|
||||
GetUsername: Types.GetUsernameResponse;
|
||||
GetPermission: Types.GetPermissionResponse;
|
||||
FindUser: Types.FindUserResponse;
|
||||
ListUsers: Types.ListUsersResponse;
|
||||
ListApiKeys: Types.ListApiKeysResponse;
|
||||
ListApiKeysForServiceUser: Types.ListApiKeysForServiceUserResponse;
|
||||
ListPermissions: Types.ListPermissionsResponse;
|
||||
ListUserTargetPermissions: Types.ListUserTargetPermissionsResponse;
|
||||
GetUserGroup: Types.GetUserGroupResponse;
|
||||
ListUserGroups: Types.ListUserGroupsResponse;
|
||||
GetUpdate: Types.GetUpdateResponse;
|
||||
ListUpdates: Types.ListUpdatesResponse;
|
||||
ListAlerts: Types.ListAlertsResponse;
|
||||
GetAlert: Types.GetAlertResponse;
|
||||
GetSystemInformation: Types.GetSystemInformationResponse;
|
||||
GetSystemStats: Types.GetSystemStatsResponse;
|
||||
ListSystemProcesses: Types.ListSystemProcessesResponse;
|
||||
GetVariable: Types.GetVariableResponse;
|
||||
ListVariables: Types.ListVariablesResponse;
|
||||
GetGitProviderAccount: Types.GetGitProviderAccountResponse;
|
||||
@@ -131,26 +136,12 @@ export type ReadResponses = {
|
||||
ListOnboardingKeys: Types.ListOnboardingKeysResponse;
|
||||
};
|
||||
export type WriteResponses = {
|
||||
CreateLocalUser: Types.CreateLocalUserResponse;
|
||||
UpdateUserUsername: Types.UpdateUserUsernameResponse;
|
||||
UpdateUserPassword: Types.UpdateUserPasswordResponse;
|
||||
DeleteUser: Types.DeleteUserResponse;
|
||||
CreateServiceUser: Types.CreateServiceUserResponse;
|
||||
UpdateServiceUserDescription: Types.UpdateServiceUserDescriptionResponse;
|
||||
CreateApiKeyForServiceUser: Types.CreateApiKeyForServiceUserResponse;
|
||||
DeleteApiKeyForServiceUser: Types.DeleteApiKeyForServiceUserResponse;
|
||||
CreateUserGroup: Types.UserGroup;
|
||||
RenameUserGroup: Types.UserGroup;
|
||||
DeleteUserGroup: Types.UserGroup;
|
||||
AddUserToUserGroup: Types.UserGroup;
|
||||
RemoveUserFromUserGroup: Types.UserGroup;
|
||||
SetUsersInUserGroup: Types.UserGroup;
|
||||
SetEveryoneUserGroup: Types.UserGroup;
|
||||
UpdateUserAdmin: Types.UpdateUserAdminResponse;
|
||||
UpdateUserBasePermissions: Types.UpdateUserBasePermissionsResponse;
|
||||
UpdatePermissionOnResourceType: Types.UpdatePermissionOnResourceTypeResponse;
|
||||
UpdatePermissionOnTarget: Types.UpdatePermissionOnTargetResponse;
|
||||
UpdateResourceMeta: Types.UpdateResourceMetaResponse;
|
||||
CreateSwarm: Types.Swarm;
|
||||
CopySwarm: Types.Swarm;
|
||||
DeleteSwarm: Types.Swarm;
|
||||
UpdateSwarm: Types.Swarm;
|
||||
RenameSwarm: Types.Update;
|
||||
CreateServer: Types.Server;
|
||||
CopyServer: Types.Server;
|
||||
DeleteServer: Types.Server;
|
||||
@@ -159,6 +150,10 @@ export type WriteResponses = {
|
||||
CreateNetwork: Types.Update;
|
||||
UpdateServerPublicKey: Types.Update;
|
||||
RotateServerKeys: Types.Update;
|
||||
CreateTerminal: Types.NoData;
|
||||
DeleteTerminal: Types.NoData;
|
||||
DeleteAllTerminals: Types.NoData;
|
||||
BatchDeleteAllTerminals: Types.NoData;
|
||||
CreateStack: Types.Stack;
|
||||
CopyStack: Types.Stack;
|
||||
DeleteStack: Types.Stack;
|
||||
@@ -179,22 +174,12 @@ export type WriteResponses = {
|
||||
RenameBuild: Types.Update;
|
||||
WriteBuildFileContents: Types.Update;
|
||||
RefreshBuildCache: Types.NoData;
|
||||
CreateBuilder: Types.Builder;
|
||||
CopyBuilder: Types.Builder;
|
||||
DeleteBuilder: Types.Builder;
|
||||
UpdateBuilder: Types.Builder;
|
||||
RenameBuilder: Types.Update;
|
||||
CreateRepo: Types.Repo;
|
||||
CopyRepo: Types.Repo;
|
||||
DeleteRepo: Types.Repo;
|
||||
UpdateRepo: Types.Repo;
|
||||
RenameRepo: Types.Update;
|
||||
RefreshRepoCache: Types.NoData;
|
||||
CreateAlerter: Types.Alerter;
|
||||
CopyAlerter: Types.Alerter;
|
||||
DeleteAlerter: Types.Alerter;
|
||||
UpdateAlerter: Types.Alerter;
|
||||
RenameAlerter: Types.Update;
|
||||
CreateProcedure: Types.Procedure;
|
||||
CopyProcedure: Types.Procedure;
|
||||
DeleteProcedure: Types.Procedure;
|
||||
@@ -213,10 +198,38 @@ export type WriteResponses = {
|
||||
CommitSync: Types.Update;
|
||||
WriteSyncFileContents: Types.Update;
|
||||
RefreshResourceSyncPending: Types.ResourceSync;
|
||||
CreateTerminal: Types.NoData;
|
||||
DeleteTerminal: Types.NoData;
|
||||
DeleteAllTerminals: Types.NoData;
|
||||
BatchDeleteAllTerminals: Types.NoData;
|
||||
CreateBuilder: Types.Builder;
|
||||
CopyBuilder: Types.Builder;
|
||||
DeleteBuilder: Types.Builder;
|
||||
UpdateBuilder: Types.Builder;
|
||||
RenameBuilder: Types.Update;
|
||||
CreateAlerter: Types.Alerter;
|
||||
CopyAlerter: Types.Alerter;
|
||||
DeleteAlerter: Types.Alerter;
|
||||
UpdateAlerter: Types.Alerter;
|
||||
RenameAlerter: Types.Update;
|
||||
CreateOnboardingKey: Types.CreateOnboardingKeyResponse;
|
||||
UpdateOnboardingKey: Types.UpdateOnboardingKeyResponse;
|
||||
DeleteOnboardingKey: Types.DeleteOnboardingKeyResponse;
|
||||
CreateLocalUser: Types.CreateLocalUserResponse;
|
||||
UpdateUserUsername: Types.UpdateUserUsernameResponse;
|
||||
UpdateUserPassword: Types.UpdateUserPasswordResponse;
|
||||
DeleteUser: Types.DeleteUserResponse;
|
||||
CreateServiceUser: Types.CreateServiceUserResponse;
|
||||
UpdateServiceUserDescription: Types.UpdateServiceUserDescriptionResponse;
|
||||
CreateApiKeyForServiceUser: Types.CreateApiKeyForServiceUserResponse;
|
||||
DeleteApiKeyForServiceUser: Types.DeleteApiKeyForServiceUserResponse;
|
||||
CreateUserGroup: Types.UserGroup;
|
||||
RenameUserGroup: Types.UserGroup;
|
||||
DeleteUserGroup: Types.UserGroup;
|
||||
AddUserToUserGroup: Types.UserGroup;
|
||||
RemoveUserFromUserGroup: Types.UserGroup;
|
||||
SetUsersInUserGroup: Types.UserGroup;
|
||||
SetEveryoneUserGroup: Types.UserGroup;
|
||||
UpdateUserAdmin: Types.UpdateUserAdminResponse;
|
||||
UpdateUserBasePermissions: Types.UpdateUserBasePermissionsResponse;
|
||||
UpdatePermissionOnResourceType: Types.UpdatePermissionOnResourceTypeResponse;
|
||||
UpdatePermissionOnTarget: Types.UpdatePermissionOnTargetResponse;
|
||||
CreateTag: Types.Tag;
|
||||
DeleteTag: Types.Tag;
|
||||
RenameTag: Types.Tag;
|
||||
@@ -232,9 +245,6 @@ export type WriteResponses = {
|
||||
CreateDockerRegistryAccount: Types.CreateDockerRegistryAccountResponse;
|
||||
UpdateDockerRegistryAccount: Types.UpdateDockerRegistryAccountResponse;
|
||||
DeleteDockerRegistryAccount: Types.DeleteDockerRegistryAccountResponse;
|
||||
CreateOnboardingKey: Types.CreateOnboardingKeyResponse;
|
||||
UpdateOnboardingKey: Types.UpdateOnboardingKeyResponse;
|
||||
DeleteOnboardingKey: Types.DeleteOnboardingKeyResponse;
|
||||
CloseAlert: Types.NoData;
|
||||
};
|
||||
export type ExecuteResponses = {
|
||||
@@ -272,6 +282,7 @@ export type ExecuteResponses = {
|
||||
UnpauseStack: Types.Update;
|
||||
DestroyStack: Types.Update;
|
||||
BatchDestroyStack: Types.BatchExecutionResponse;
|
||||
RunStackService: Types.Update;
|
||||
Deploy: Types.Update;
|
||||
BatchDeploy: Types.BatchExecutionResponse;
|
||||
PullDeployment: Types.Update;
|
||||
@@ -297,14 +308,6 @@ export type ExecuteResponses = {
|
||||
RunAction: Types.Update;
|
||||
BatchRunAction: Types.BatchExecutionResponse;
|
||||
RunSync: Types.Update;
|
||||
DeployStackService: Types.Update;
|
||||
StartStackService: Types.Update;
|
||||
RestartStackService: Types.Update;
|
||||
StopStackService: Types.Update;
|
||||
PauseStackService: Types.Update;
|
||||
UnpauseStackService: Types.Update;
|
||||
DestroyStackService: Types.Update;
|
||||
RunStackService: Types.Update;
|
||||
TestAlerter: Types.Update;
|
||||
SendAlert: Types.Update;
|
||||
ClearRepoCache: Types.Update;
|
||||
|
||||
498
frontend/public/client/types.d.ts
vendored
498
frontend/public/client/types.d.ts
vendored
@@ -2684,6 +2684,8 @@ export interface SwarmConfig {
|
||||
* tries the next Server.
|
||||
*/
|
||||
server_ids?: string[];
|
||||
/** Configure quick links that are displayed in the resource header */
|
||||
links?: string[];
|
||||
}
|
||||
export interface SwarmInfo {
|
||||
}
|
||||
@@ -4108,9 +4110,7 @@ export declare enum SwarmState {
|
||||
/** The Swarm is healthy, all nodes OK */
|
||||
Healthy = "Healthy",
|
||||
/** The Swarm is unhealthy */
|
||||
Unhealthy = "Unhealthy",
|
||||
/** Servers are reachable, but Swarm is not running on any of them. */
|
||||
Offline = "Offline"
|
||||
Unhealthy = "Unhealthy"
|
||||
}
|
||||
export interface SwarmListItemInfo {
|
||||
/** Servers part of the swarm */
|
||||
@@ -5601,6 +5601,14 @@ export interface DiscordAlerterEndpoint {
|
||||
/** The Discord webhook url */
|
||||
url: string;
|
||||
}
|
||||
/** Standard docker lists available from a Server. */
|
||||
export interface DockerLists {
|
||||
containers: ContainerListItem[];
|
||||
networks: NetworkListItem[];
|
||||
images: ImageListItem[];
|
||||
volumes: VolumeListItem[];
|
||||
projects: ComposeProject[];
|
||||
}
|
||||
/** Driver represents a driver (network, logging, secrets). */
|
||||
export interface Driver {
|
||||
/** Name of the driver. */
|
||||
@@ -6356,8 +6364,8 @@ export interface GetSwarmsSummaryResponse {
|
||||
healthy: number;
|
||||
/** The number of Swarms with Unhealthy state */
|
||||
unhealthy: number;
|
||||
/** The number of Swarms with Offline state */
|
||||
offline: number;
|
||||
/** The number of Swarms with Unknown state */
|
||||
unknown: number;
|
||||
}
|
||||
/**
|
||||
* Get the system information of the target server.
|
||||
@@ -6498,6 +6506,13 @@ export interface InspectStackContainer {
|
||||
/** The service name to inspect */
|
||||
service: string;
|
||||
}
|
||||
/** JoinTokens contains the tokens workers and managers need to join the swarm. */
|
||||
export interface JoinTokens {
|
||||
/** The token workers can use to join the swarm. */
|
||||
Worker?: string;
|
||||
/** The token managers can use to join the swarm. */
|
||||
Manager?: string;
|
||||
}
|
||||
export interface LatestCommit {
|
||||
hash: string;
|
||||
message: string;
|
||||
@@ -8312,6 +8327,113 @@ export interface StopStack {
|
||||
*/
|
||||
services?: string[];
|
||||
}
|
||||
/** Orchestration configuration. */
|
||||
export interface SwarmSpecOrchestration {
|
||||
/**
|
||||
* The number of historic tasks to keep per instance or node.
|
||||
* If negative, never remove completed or failed tasks.
|
||||
*/
|
||||
TaskHistoryRetentionLimit?: I64;
|
||||
}
|
||||
/** Raft configuration. */
|
||||
export interface SwarmSpecRaft {
|
||||
/** The number of log entries between snapshots. */
|
||||
SnapshotInterval?: U64;
|
||||
/** The number of snapshots to keep beyond the current snapshot. */
|
||||
KeepOldSnapshots?: U64;
|
||||
/** The number of log entries to keep around to sync up slow followers after a snapshot is created. */
|
||||
LogEntriesForSlowFollowers?: U64;
|
||||
/** The number of ticks that a follower will wait for a message from the leader before becoming a candidate and starting an election. `ElectionTick` must be greater than `HeartbeatTick`. A tick currently defaults to one second, so these translate directly to seconds currently, but this is NOT guaranteed. */
|
||||
ElectionTick?: I64;
|
||||
/**
|
||||
* The number of ticks between heartbeats.
|
||||
* Every HeartbeatTick ticks, the leader will send a heartbeat to the followers.
|
||||
* A tick currently defaults to one second, so these translate directly to seconds currently, but this is NOT guaranteed.
|
||||
*/
|
||||
HeartbeatTick?: I64;
|
||||
}
|
||||
/** Dispatcher configuration. */
|
||||
export interface SwarmSpecDispatcher {
|
||||
/** The delay for an agent to send a heartbeat to the dispatcher. */
|
||||
HeartbeatPeriod?: I64;
|
||||
}
|
||||
export declare enum SwarmSpecCaConfigExternalCasProtocolEnum {
|
||||
EMPTY = "",
|
||||
CFSSL = "cfssl"
|
||||
}
|
||||
export interface SwarmSpecCaConfigExternalCas {
|
||||
/** Protocol for communication with the external CA (currently only `cfssl` is supported). */
|
||||
Protocol?: SwarmSpecCaConfigExternalCasProtocolEnum;
|
||||
/** URL where certificate signing requests should be sent. */
|
||||
URL?: string;
|
||||
/** An object with key/value pairs that are interpreted as protocol-specific options for the external CA driver. */
|
||||
Options?: Record<string, string>;
|
||||
/** The root CA certificate (in PEM format) this external CA uses to issue TLS certificates (assumed to be to the current swarm root CA certificate if not provided). */
|
||||
CACert?: string;
|
||||
}
|
||||
/** CA configuration. */
|
||||
export interface SwarmSpecCaConfig {
|
||||
/** The duration node certificates are issued for. */
|
||||
NodeCertExpiry?: I64;
|
||||
/** Configuration for forwarding signing requests to an external certificate authority. */
|
||||
ExternalCAs?: SwarmSpecCaConfigExternalCas[];
|
||||
/** The desired signing CA certificate for all swarm node TLS leaf certificates, in PEM format. */
|
||||
SigningCACert?: string;
|
||||
/** The desired signing CA key for all swarm node TLS leaf certificates, in PEM format. */
|
||||
SigningCAKey?: string;
|
||||
/** An integer whose purpose is to force swarm to generate a new signing CA certificate and key, if none have been specified in `SigningCACert` and `SigningCAKey` */
|
||||
ForceRotate?: U64;
|
||||
}
|
||||
/** Parameters related to encryption-at-rest. */
|
||||
export interface SwarmSpecEncryptionConfig {
|
||||
/** If set, generate a key and use it to lock data stored on the managers. */
|
||||
AutoLockManagers?: boolean;
|
||||
}
|
||||
/** The log driver to use for tasks created in the orchestrator if unspecified by a service. Updating this value only affects new tasks. Existing tasks continue to use their previously configured log driver until recreated. */
|
||||
export interface SwarmSpecTaskDefaultsLogDriver {
|
||||
/** The log driver to use as a default for new tasks. */
|
||||
Name?: string;
|
||||
/** Driver-specific options for the selected log driver, specified as key/value pairs. */
|
||||
Options?: Record<string, string>;
|
||||
}
|
||||
/** Defaults for creating tasks in this cluster. */
|
||||
export interface SwarmSpecTaskDefaults {
|
||||
LogDriver?: SwarmSpecTaskDefaultsLogDriver;
|
||||
}
|
||||
/** User modifiable swarm configuration. */
|
||||
export interface SwarmSpec {
|
||||
/** Name of the swarm. */
|
||||
Name?: string;
|
||||
/** User-defined key/value metadata. */
|
||||
Labels?: Record<string, string>;
|
||||
Orchestration?: SwarmSpecOrchestration;
|
||||
Raft?: SwarmSpecRaft;
|
||||
Dispatcher?: SwarmSpecDispatcher;
|
||||
CAConfig?: SwarmSpecCaConfig;
|
||||
EncryptionConfig?: SwarmSpecEncryptionConfig;
|
||||
TaskDefaults?: SwarmSpecTaskDefaults;
|
||||
}
|
||||
/** Docker-level information about the Swarm. */
|
||||
export interface SwarmInspectInfo {
|
||||
/** The (Docker) ID of the swarm. */
|
||||
ID?: string;
|
||||
Version?: ObjectVersion;
|
||||
/** Date and time at which the swarm was initialised in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. */
|
||||
CreatedAt?: string;
|
||||
/** Date and time at which the swarm was last updated in [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. */
|
||||
UpdatedAt?: string;
|
||||
Spec?: SwarmSpec;
|
||||
TLSInfo?: TlsInfo;
|
||||
/** Whether there is currently a root CA rotation in progress for the swarm */
|
||||
RootRotationInProgress?: boolean;
|
||||
/** DataPathPort specifies the data path port number for data traffic. Acceptable port range is 1024 to 49151. If no port is set or is set to 0, the default port (4789) is used. */
|
||||
DataPathPort?: number;
|
||||
/** Default Address Pool specifies default subnet pools for global scope networks. */
|
||||
DefaultAddrPool?: string[];
|
||||
/** SubnetSize specifies the subnet size of the networks created from the default subnet pool. */
|
||||
SubnetSize?: number;
|
||||
JoinTokens?: JoinTokens;
|
||||
}
|
||||
/** Swarm node details. */
|
||||
export interface SwarmNode {
|
||||
ID?: string;
|
||||
@@ -9074,15 +9196,15 @@ export type ExecuteRequest = {
|
||||
} | {
|
||||
type: "BatchRunAction";
|
||||
params: BatchRunAction;
|
||||
} | {
|
||||
type: "RunSync";
|
||||
params: RunSync;
|
||||
} | {
|
||||
type: "TestAlerter";
|
||||
params: TestAlerter;
|
||||
} | {
|
||||
type: "SendAlert";
|
||||
params: SendAlert;
|
||||
} | {
|
||||
type: "RunSync";
|
||||
params: RunSync;
|
||||
} | {
|
||||
type: "ClearRepoCache";
|
||||
params: ClearRepoCache;
|
||||
@@ -9200,68 +9322,20 @@ export type ReadRequest = {
|
||||
type: "ListDockerRegistriesFromConfig";
|
||||
params: ListDockerRegistriesFromConfig;
|
||||
} | {
|
||||
type: "GetUsername";
|
||||
params: GetUsername;
|
||||
type: "GetSwarmsSummary";
|
||||
params: GetSwarmsSummary;
|
||||
} | {
|
||||
type: "GetPermission";
|
||||
params: GetPermission;
|
||||
type: "GetSwarm";
|
||||
params: GetSwarm;
|
||||
} | {
|
||||
type: "FindUser";
|
||||
params: FindUser;
|
||||
type: "GetSwarmActionState";
|
||||
params: GetSwarmActionState;
|
||||
} | {
|
||||
type: "ListUsers";
|
||||
params: ListUsers;
|
||||
type: "ListSwarms";
|
||||
params: ListSwarms;
|
||||
} | {
|
||||
type: "ListApiKeys";
|
||||
params: ListApiKeys;
|
||||
} | {
|
||||
type: "ListApiKeysForServiceUser";
|
||||
params: ListApiKeysForServiceUser;
|
||||
} | {
|
||||
type: "ListPermissions";
|
||||
params: ListPermissions;
|
||||
} | {
|
||||
type: "ListUserTargetPermissions";
|
||||
params: ListUserTargetPermissions;
|
||||
} | {
|
||||
type: "GetUserGroup";
|
||||
params: GetUserGroup;
|
||||
} | {
|
||||
type: "ListUserGroups";
|
||||
params: ListUserGroups;
|
||||
} | {
|
||||
type: "GetProceduresSummary";
|
||||
params: GetProceduresSummary;
|
||||
} | {
|
||||
type: "GetProcedure";
|
||||
params: GetProcedure;
|
||||
} | {
|
||||
type: "GetProcedureActionState";
|
||||
params: GetProcedureActionState;
|
||||
} | {
|
||||
type: "ListProcedures";
|
||||
params: ListProcedures;
|
||||
} | {
|
||||
type: "ListFullProcedures";
|
||||
params: ListFullProcedures;
|
||||
} | {
|
||||
type: "GetActionsSummary";
|
||||
params: GetActionsSummary;
|
||||
} | {
|
||||
type: "GetAction";
|
||||
params: GetAction;
|
||||
} | {
|
||||
type: "GetActionActionState";
|
||||
params: GetActionActionState;
|
||||
} | {
|
||||
type: "ListActions";
|
||||
params: ListActions;
|
||||
} | {
|
||||
type: "ListFullActions";
|
||||
params: ListFullActions;
|
||||
} | {
|
||||
type: "ListSchedules";
|
||||
params: ListSchedules;
|
||||
type: "ListFullSwarms";
|
||||
params: ListFullSwarms;
|
||||
} | {
|
||||
type: "GetServersSummary";
|
||||
params: GetServersSummary;
|
||||
@@ -9277,9 +9351,6 @@ export type ReadRequest = {
|
||||
} | {
|
||||
type: "GetServerActionState";
|
||||
params: GetServerActionState;
|
||||
} | {
|
||||
type: "GetHistoricalServerStats";
|
||||
params: GetHistoricalServerStats;
|
||||
} | {
|
||||
type: "ListServers";
|
||||
params: ListServers;
|
||||
@@ -9340,6 +9411,9 @@ export type ReadRequest = {
|
||||
} | {
|
||||
type: "GetSystemStats";
|
||||
params: GetSystemStats;
|
||||
} | {
|
||||
type: "GetHistoricalServerStats";
|
||||
params: GetHistoricalServerStats;
|
||||
} | {
|
||||
type: "ListSystemProcesses";
|
||||
params: ListSystemProcesses;
|
||||
@@ -9448,6 +9522,39 @@ export type ReadRequest = {
|
||||
} | {
|
||||
type: "ListFullRepos";
|
||||
params: ListFullRepos;
|
||||
} | {
|
||||
type: "GetProceduresSummary";
|
||||
params: GetProceduresSummary;
|
||||
} | {
|
||||
type: "GetProcedure";
|
||||
params: GetProcedure;
|
||||
} | {
|
||||
type: "GetProcedureActionState";
|
||||
params: GetProcedureActionState;
|
||||
} | {
|
||||
type: "ListProcedures";
|
||||
params: ListProcedures;
|
||||
} | {
|
||||
type: "ListFullProcedures";
|
||||
params: ListFullProcedures;
|
||||
} | {
|
||||
type: "GetActionsSummary";
|
||||
params: GetActionsSummary;
|
||||
} | {
|
||||
type: "GetAction";
|
||||
params: GetAction;
|
||||
} | {
|
||||
type: "GetActionActionState";
|
||||
params: GetActionActionState;
|
||||
} | {
|
||||
type: "ListActions";
|
||||
params: ListActions;
|
||||
} | {
|
||||
type: "ListFullActions";
|
||||
params: ListFullActions;
|
||||
} | {
|
||||
type: "ListSchedules";
|
||||
params: ListSchedules;
|
||||
} | {
|
||||
type: "GetResourceSyncsSummary";
|
||||
params: GetResourceSyncsSummary;
|
||||
@@ -9499,6 +9606,36 @@ export type ReadRequest = {
|
||||
} | {
|
||||
type: "ListTags";
|
||||
params: ListTags;
|
||||
} | {
|
||||
type: "GetUsername";
|
||||
params: GetUsername;
|
||||
} | {
|
||||
type: "GetPermission";
|
||||
params: GetPermission;
|
||||
} | {
|
||||
type: "FindUser";
|
||||
params: FindUser;
|
||||
} | {
|
||||
type: "ListUsers";
|
||||
params: ListUsers;
|
||||
} | {
|
||||
type: "ListApiKeys";
|
||||
params: ListApiKeys;
|
||||
} | {
|
||||
type: "ListApiKeysForServiceUser";
|
||||
params: ListApiKeysForServiceUser;
|
||||
} | {
|
||||
type: "ListPermissions";
|
||||
params: ListPermissions;
|
||||
} | {
|
||||
type: "ListUserTargetPermissions";
|
||||
params: ListUserTargetPermissions;
|
||||
} | {
|
||||
type: "GetUserGroup";
|
||||
params: GetUserGroup;
|
||||
} | {
|
||||
type: "ListUserGroups";
|
||||
params: ListUserGroups;
|
||||
} | {
|
||||
type: "GetUpdate";
|
||||
params: GetUpdate;
|
||||
@@ -9598,65 +9735,23 @@ export type UserRequest = {
|
||||
params: DeleteApiKey;
|
||||
};
|
||||
export type WriteRequest = {
|
||||
type: "CreateLocalUser";
|
||||
params: CreateLocalUser;
|
||||
} | {
|
||||
type: "UpdateUserUsername";
|
||||
params: UpdateUserUsername;
|
||||
} | {
|
||||
type: "UpdateUserPassword";
|
||||
params: UpdateUserPassword;
|
||||
} | {
|
||||
type: "DeleteUser";
|
||||
params: DeleteUser;
|
||||
} | {
|
||||
type: "CreateServiceUser";
|
||||
params: CreateServiceUser;
|
||||
} | {
|
||||
type: "UpdateServiceUserDescription";
|
||||
params: UpdateServiceUserDescription;
|
||||
} | {
|
||||
type: "CreateApiKeyForServiceUser";
|
||||
params: CreateApiKeyForServiceUser;
|
||||
} | {
|
||||
type: "DeleteApiKeyForServiceUser";
|
||||
params: DeleteApiKeyForServiceUser;
|
||||
} | {
|
||||
type: "CreateUserGroup";
|
||||
params: CreateUserGroup;
|
||||
} | {
|
||||
type: "RenameUserGroup";
|
||||
params: RenameUserGroup;
|
||||
} | {
|
||||
type: "DeleteUserGroup";
|
||||
params: DeleteUserGroup;
|
||||
} | {
|
||||
type: "AddUserToUserGroup";
|
||||
params: AddUserToUserGroup;
|
||||
} | {
|
||||
type: "RemoveUserFromUserGroup";
|
||||
params: RemoveUserFromUserGroup;
|
||||
} | {
|
||||
type: "SetUsersInUserGroup";
|
||||
params: SetUsersInUserGroup;
|
||||
} | {
|
||||
type: "SetEveryoneUserGroup";
|
||||
params: SetEveryoneUserGroup;
|
||||
} | {
|
||||
type: "UpdateUserAdmin";
|
||||
params: UpdateUserAdmin;
|
||||
} | {
|
||||
type: "UpdateUserBasePermissions";
|
||||
params: UpdateUserBasePermissions;
|
||||
} | {
|
||||
type: "UpdatePermissionOnResourceType";
|
||||
params: UpdatePermissionOnResourceType;
|
||||
} | {
|
||||
type: "UpdatePermissionOnTarget";
|
||||
params: UpdatePermissionOnTarget;
|
||||
} | {
|
||||
type: "UpdateResourceMeta";
|
||||
params: UpdateResourceMeta;
|
||||
} | {
|
||||
type: "CreateSwarm";
|
||||
params: CreateSwarm;
|
||||
} | {
|
||||
type: "CopySwarm";
|
||||
params: CopySwarm;
|
||||
} | {
|
||||
type: "DeleteSwarm";
|
||||
params: DeleteSwarm;
|
||||
} | {
|
||||
type: "UpdateSwarm";
|
||||
params: UpdateSwarm;
|
||||
} | {
|
||||
type: "RenameSwarm";
|
||||
params: RenameSwarm;
|
||||
} | {
|
||||
type: "CreateServer";
|
||||
params: CreateServer;
|
||||
@@ -9681,6 +9776,18 @@ export type WriteRequest = {
|
||||
} | {
|
||||
type: "RotateServerKeys";
|
||||
params: RotateServerKeys;
|
||||
} | {
|
||||
type: "CreateTerminal";
|
||||
params: CreateTerminal;
|
||||
} | {
|
||||
type: "DeleteTerminal";
|
||||
params: DeleteTerminal;
|
||||
} | {
|
||||
type: "DeleteAllTerminals";
|
||||
params: DeleteAllTerminals;
|
||||
} | {
|
||||
type: "BatchDeleteAllTerminals";
|
||||
params: BatchDeleteAllTerminals;
|
||||
} | {
|
||||
type: "CreateStack";
|
||||
params: CreateStack;
|
||||
@@ -9741,21 +9848,6 @@ export type WriteRequest = {
|
||||
} | {
|
||||
type: "RefreshBuildCache";
|
||||
params: RefreshBuildCache;
|
||||
} | {
|
||||
type: "CreateBuilder";
|
||||
params: CreateBuilder;
|
||||
} | {
|
||||
type: "CopyBuilder";
|
||||
params: CopyBuilder;
|
||||
} | {
|
||||
type: "DeleteBuilder";
|
||||
params: DeleteBuilder;
|
||||
} | {
|
||||
type: "UpdateBuilder";
|
||||
params: UpdateBuilder;
|
||||
} | {
|
||||
type: "RenameBuilder";
|
||||
params: RenameBuilder;
|
||||
} | {
|
||||
type: "CreateRepo";
|
||||
params: CreateRepo;
|
||||
@@ -9774,21 +9866,6 @@ export type WriteRequest = {
|
||||
} | {
|
||||
type: "RefreshRepoCache";
|
||||
params: RefreshRepoCache;
|
||||
} | {
|
||||
type: "CreateAlerter";
|
||||
params: CreateAlerter;
|
||||
} | {
|
||||
type: "CopyAlerter";
|
||||
params: CopyAlerter;
|
||||
} | {
|
||||
type: "DeleteAlerter";
|
||||
params: DeleteAlerter;
|
||||
} | {
|
||||
type: "UpdateAlerter";
|
||||
params: UpdateAlerter;
|
||||
} | {
|
||||
type: "RenameAlerter";
|
||||
params: RenameAlerter;
|
||||
} | {
|
||||
type: "CreateProcedure";
|
||||
params: CreateProcedure;
|
||||
@@ -9844,17 +9921,101 @@ export type WriteRequest = {
|
||||
type: "RefreshResourceSyncPending";
|
||||
params: RefreshResourceSyncPending;
|
||||
} | {
|
||||
type: "CreateTerminal";
|
||||
params: CreateTerminal;
|
||||
type: "CreateBuilder";
|
||||
params: CreateBuilder;
|
||||
} | {
|
||||
type: "DeleteTerminal";
|
||||
params: DeleteTerminal;
|
||||
type: "CopyBuilder";
|
||||
params: CopyBuilder;
|
||||
} | {
|
||||
type: "DeleteAllTerminals";
|
||||
params: DeleteAllTerminals;
|
||||
type: "DeleteBuilder";
|
||||
params: DeleteBuilder;
|
||||
} | {
|
||||
type: "BatchDeleteAllTerminals";
|
||||
params: BatchDeleteAllTerminals;
|
||||
type: "UpdateBuilder";
|
||||
params: UpdateBuilder;
|
||||
} | {
|
||||
type: "RenameBuilder";
|
||||
params: RenameBuilder;
|
||||
} | {
|
||||
type: "CreateAlerter";
|
||||
params: CreateAlerter;
|
||||
} | {
|
||||
type: "CopyAlerter";
|
||||
params: CopyAlerter;
|
||||
} | {
|
||||
type: "DeleteAlerter";
|
||||
params: DeleteAlerter;
|
||||
} | {
|
||||
type: "UpdateAlerter";
|
||||
params: UpdateAlerter;
|
||||
} | {
|
||||
type: "RenameAlerter";
|
||||
params: RenameAlerter;
|
||||
} | {
|
||||
type: "CreateOnboardingKey";
|
||||
params: CreateOnboardingKey;
|
||||
} | {
|
||||
type: "UpdateOnboardingKey";
|
||||
params: UpdateOnboardingKey;
|
||||
} | {
|
||||
type: "DeleteOnboardingKey";
|
||||
params: DeleteOnboardingKey;
|
||||
} | {
|
||||
type: "CreateLocalUser";
|
||||
params: CreateLocalUser;
|
||||
} | {
|
||||
type: "UpdateUserUsername";
|
||||
params: UpdateUserUsername;
|
||||
} | {
|
||||
type: "UpdateUserPassword";
|
||||
params: UpdateUserPassword;
|
||||
} | {
|
||||
type: "DeleteUser";
|
||||
params: DeleteUser;
|
||||
} | {
|
||||
type: "CreateServiceUser";
|
||||
params: CreateServiceUser;
|
||||
} | {
|
||||
type: "UpdateServiceUserDescription";
|
||||
params: UpdateServiceUserDescription;
|
||||
} | {
|
||||
type: "CreateApiKeyForServiceUser";
|
||||
params: CreateApiKeyForServiceUser;
|
||||
} | {
|
||||
type: "DeleteApiKeyForServiceUser";
|
||||
params: DeleteApiKeyForServiceUser;
|
||||
} | {
|
||||
type: "CreateUserGroup";
|
||||
params: CreateUserGroup;
|
||||
} | {
|
||||
type: "RenameUserGroup";
|
||||
params: RenameUserGroup;
|
||||
} | {
|
||||
type: "DeleteUserGroup";
|
||||
params: DeleteUserGroup;
|
||||
} | {
|
||||
type: "AddUserToUserGroup";
|
||||
params: AddUserToUserGroup;
|
||||
} | {
|
||||
type: "RemoveUserFromUserGroup";
|
||||
params: RemoveUserFromUserGroup;
|
||||
} | {
|
||||
type: "SetUsersInUserGroup";
|
||||
params: SetUsersInUserGroup;
|
||||
} | {
|
||||
type: "SetEveryoneUserGroup";
|
||||
params: SetEveryoneUserGroup;
|
||||
} | {
|
||||
type: "UpdateUserAdmin";
|
||||
params: UpdateUserAdmin;
|
||||
} | {
|
||||
type: "UpdateUserBasePermissions";
|
||||
params: UpdateUserBasePermissions;
|
||||
} | {
|
||||
type: "UpdatePermissionOnResourceType";
|
||||
params: UpdatePermissionOnResourceType;
|
||||
} | {
|
||||
type: "UpdatePermissionOnTarget";
|
||||
params: UpdatePermissionOnTarget;
|
||||
} | {
|
||||
type: "CreateTag";
|
||||
params: CreateTag;
|
||||
@@ -9900,15 +10061,6 @@ export type WriteRequest = {
|
||||
} | {
|
||||
type: "DeleteDockerRegistryAccount";
|
||||
params: DeleteDockerRegistryAccount;
|
||||
} | {
|
||||
type: "CreateOnboardingKey";
|
||||
params: CreateOnboardingKey;
|
||||
} | {
|
||||
type: "UpdateOnboardingKey";
|
||||
params: UpdateOnboardingKey;
|
||||
} | {
|
||||
type: "DeleteOnboardingKey";
|
||||
params: DeleteOnboardingKey;
|
||||
} | {
|
||||
type: "CloseAlert";
|
||||
params: CloseAlert;
|
||||
|
||||
@@ -580,8 +580,6 @@ export var SwarmState;
|
||||
SwarmState["Healthy"] = "Healthy";
|
||||
/** The Swarm is unhealthy */
|
||||
SwarmState["Unhealthy"] = "Unhealthy";
|
||||
/** Servers are reachable, but Swarm is not running on any of them. */
|
||||
SwarmState["Offline"] = "Offline";
|
||||
})(SwarmState || (SwarmState = {}));
|
||||
/**
|
||||
* Configures the behavior of [CreateTerminal] if the
|
||||
@@ -734,6 +732,11 @@ export var ServiceUpdateStatusStateEnum;
|
||||
ServiceUpdateStatusStateEnum["ROLLBACK_PAUSED"] = "rollback_paused";
|
||||
ServiceUpdateStatusStateEnum["ROLLBACK_COMPLETED"] = "rollback_completed";
|
||||
})(ServiceUpdateStatusStateEnum || (ServiceUpdateStatusStateEnum = {}));
|
||||
export var SwarmSpecCaConfigExternalCasProtocolEnum;
|
||||
(function (SwarmSpecCaConfigExternalCasProtocolEnum) {
|
||||
SwarmSpecCaConfigExternalCasProtocolEnum["EMPTY"] = "";
|
||||
SwarmSpecCaConfigExternalCasProtocolEnum["CFSSL"] = "cfssl";
|
||||
})(SwarmSpecCaConfigExternalCasProtocolEnum || (SwarmSpecCaConfigExternalCasProtocolEnum = {}));
|
||||
export var TaskState;
|
||||
(function (TaskState) {
|
||||
TaskState["NEW"] = "new";
|
||||
|
||||
@@ -46,7 +46,7 @@ export const BuildComponents: RequiredResourceComponents = {
|
||||
list_item: (id) => useBuild(id),
|
||||
resource_links: (resource) => (resource.config as Types.BuildConfig).links,
|
||||
|
||||
Description: () => <>Build docker images.</>,
|
||||
Description: () => <>Build container images.</>,
|
||||
|
||||
Dashboard: () => {
|
||||
const summary = useRead("GetBuildsSummary", {}).data;
|
||||
|
||||
@@ -299,6 +299,7 @@ export const ResourceSelector = ({
|
||||
placeholder,
|
||||
targetClassName,
|
||||
state,
|
||||
exclude_ids,
|
||||
}: {
|
||||
type: UsableResource;
|
||||
selected: string | undefined;
|
||||
@@ -309,6 +310,7 @@ export const ResourceSelector = ({
|
||||
placeholder?: string;
|
||||
targetClassName?: string;
|
||||
state?: unknown;
|
||||
exclude_ids?: string[];
|
||||
}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [search, setSearch] = useState("");
|
||||
@@ -321,7 +323,11 @@ export const ResourceSelector = ({
|
||||
: () => true;
|
||||
const resources = useRead(`List${type}s`, {})
|
||||
.data?.filter(templateFilterFn)
|
||||
.filter((r) => !state || (r.info as any).state === state);
|
||||
.filter(
|
||||
(r) =>
|
||||
(!state || (r.info as any).state === state) &&
|
||||
(!exclude_ids || r.id === selected || !exclude_ids?.includes(r.id))
|
||||
);
|
||||
const name = resources?.find((r) => r.id === selected)?.name;
|
||||
|
||||
if (!resources) return null;
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
import { RequiredResourceComponents, UsableResource } from "@types";
|
||||
import { AlerterComponents } from "./alerter";
|
||||
import { BuildComponents } from "./build";
|
||||
import { BuilderComponents } from "./builder";
|
||||
import { DeploymentComponents } from "./deployment";
|
||||
import { RepoComponents } from "./repo";
|
||||
import { SwarmComponents } from "./swarm";
|
||||
import { ServerComponents } from "./server";
|
||||
import { ProcedureComponents } from "./procedure/index";
|
||||
import { ResourceSyncComponents } from "./sync";
|
||||
import { StackComponents } from "./stack";
|
||||
import { DeploymentComponents } from "./deployment";
|
||||
import { BuildComponents } from "./build";
|
||||
import { RepoComponents } from "./repo";
|
||||
import { ProcedureComponents } from "./procedure/index";
|
||||
import { ActionComponents } from "./action";
|
||||
import { BuilderComponents } from "./builder";
|
||||
import { AlerterComponents } from "./alerter";
|
||||
import { ResourceSyncComponents } from "./sync";
|
||||
|
||||
export const ResourceComponents: {
|
||||
[key in UsableResource]: RequiredResourceComponents;
|
||||
} = {
|
||||
Swarm: SwarmComponents,
|
||||
Server: ServerComponents,
|
||||
Stack: StackComponents,
|
||||
Deployment: DeploymentComponents,
|
||||
|
||||
107
frontend/src/components/resources/swarm/config.tsx
Normal file
107
frontend/src/components/resources/swarm/config.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
import { Config } from "@components/config";
|
||||
import { ConfigItem } from "@components/config/util";
|
||||
import { useLocalStorage, usePermissions, useRead, useWrite } from "@lib/hooks";
|
||||
import { Types } from "komodo_client";
|
||||
import { ResourceSelector } from "../common";
|
||||
import { Button } from "@ui/button";
|
||||
import { MinusCircle, PlusCircle } from "lucide-react";
|
||||
|
||||
export const SwarmConfig = ({ id }: { id: string }) => {
|
||||
const { canWrite } = usePermissions({ type: "Swarm", id });
|
||||
const swarm = useRead("GetSwarm", { swarm: id }).data;
|
||||
const config = swarm?.config;
|
||||
const global_disabled =
|
||||
useRead("GetCoreInfo", {}).data?.ui_write_disabled ?? false;
|
||||
const [update, set] = useLocalStorage<Partial<Types.SwarmConfig>>(
|
||||
`swarm-${id}-update-v1`,
|
||||
{}
|
||||
);
|
||||
const { mutateAsync } = useWrite("UpdateSwarm");
|
||||
|
||||
if (!config) return null;
|
||||
|
||||
const disabled = global_disabled || !canWrite;
|
||||
|
||||
return (
|
||||
<Config
|
||||
disabled={disabled}
|
||||
original={config}
|
||||
update={update}
|
||||
set={set}
|
||||
onSave={async () => {
|
||||
await mutateAsync({ id, config: update });
|
||||
}}
|
||||
components={{
|
||||
"": [
|
||||
{
|
||||
label: "Managers",
|
||||
labelHidden: true,
|
||||
components: {
|
||||
server_ids: (server_ids, set) => {
|
||||
return (
|
||||
<ConfigItem
|
||||
label="Manager Nodes"
|
||||
description="Select the Servers which have joined the Swarm as Manager Nodes."
|
||||
>
|
||||
<div className="flex flex-col gap-4 w-full">
|
||||
{server_ids?.map((server_id, index) => (
|
||||
<div key={index} className="w-full flex gap-4">
|
||||
<ResourceSelector
|
||||
type="Server"
|
||||
exclude_ids={server_ids}
|
||||
selected={server_id}
|
||||
onSelect={(server_id) =>
|
||||
set({
|
||||
server_ids: [
|
||||
...server_ids.map((id, i) =>
|
||||
i === index ? server_id : id
|
||||
),
|
||||
],
|
||||
})
|
||||
}
|
||||
disabled={disabled}
|
||||
align="start"
|
||||
/>
|
||||
{!disabled && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() =>
|
||||
set({
|
||||
server_ids: [
|
||||
...server_ids?.filter(
|
||||
(_, i) => i !== index
|
||||
),
|
||||
],
|
||||
})
|
||||
}
|
||||
>
|
||||
<MinusCircle className="w-4 h-4" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{!disabled && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() =>
|
||||
set({
|
||||
server_ids: [...(server_ids ?? []), ""],
|
||||
})
|
||||
}
|
||||
className="flex items-center gap-2 w-[200px]"
|
||||
>
|
||||
<PlusCircle className="w-4 h-4" />
|
||||
Add Server
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</ConfigItem>
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
101
frontend/src/components/resources/swarm/index.tsx
Normal file
101
frontend/src/components/resources/swarm/index.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import { useRead } from "@lib/hooks";
|
||||
import { RequiredResourceComponents } from "@types";
|
||||
import { Boxes } from "lucide-react";
|
||||
import { SwarmConfig } from "./config";
|
||||
import { DeleteResource, NewResource, ResourcePageHeader } from "../common";
|
||||
import { SwarmTable } from "./table";
|
||||
import {
|
||||
swarm_state_intention,
|
||||
stroke_color_class_by_intention,
|
||||
} from "@lib/color";
|
||||
import { cn } from "@lib/utils";
|
||||
import { Types } from "komodo_client";
|
||||
import { DashboardPieChart } from "@components/util";
|
||||
import { StatusBadge } from "@components/util";
|
||||
import { GroupActions } from "@components/group-actions";
|
||||
|
||||
export const useSwarm = (id?: string) =>
|
||||
useRead("ListSwarms", {}, { refetchInterval: 10_000 }).data?.find(
|
||||
(d) => d.id === id
|
||||
);
|
||||
|
||||
export const useFullSwarm = (id: string) =>
|
||||
useRead("GetSwarm", { swarm: id }, { refetchInterval: 10_000 }).data;
|
||||
|
||||
const SwarmIcon = ({ id, size }: { id?: string; size: number }) => {
|
||||
const state = useSwarm(id)?.info.state;
|
||||
const color = stroke_color_class_by_intention(swarm_state_intention(state));
|
||||
return <Boxes className={cn(`w-${size} h-${size}`, state && color)} />;
|
||||
};
|
||||
|
||||
export const SwarmComponents: RequiredResourceComponents = {
|
||||
list_item: (id) => useSwarm(id),
|
||||
resource_links: (resource) => (resource.config as Types.SwarmConfig).links,
|
||||
|
||||
Description: () => <>Control and monitor docker swarms.</>,
|
||||
|
||||
Dashboard: () => {
|
||||
const summary = useRead("GetSwarmsSummary", {}).data;
|
||||
return (
|
||||
<DashboardPieChart
|
||||
data={[
|
||||
{ intention: "Good", value: summary?.healthy ?? 0, title: "Healthy" },
|
||||
{
|
||||
intention: "Critical",
|
||||
value: summary?.unhealthy ?? 0,
|
||||
title: "Unhealthy",
|
||||
},
|
||||
{
|
||||
intention: "Unknown",
|
||||
value: summary?.unknown ?? 0,
|
||||
title: "Unknown",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
New: () => <NewResource type="Swarm" />,
|
||||
|
||||
GroupActions: () => <GroupActions type="Swarm" actions={[]} />,
|
||||
|
||||
Table: ({ resources }) => (
|
||||
<SwarmTable swarms={resources as Types.SwarmListItem[]} />
|
||||
),
|
||||
|
||||
Icon: ({ id }) => <SwarmIcon id={id} size={4} />,
|
||||
BigIcon: ({ id }) => <SwarmIcon id={id} size={8} />,
|
||||
|
||||
State: ({ id }) => {
|
||||
const state = useSwarm(id)?.info.state;
|
||||
return <StatusBadge text={state} intent={swarm_state_intention(state)} />;
|
||||
},
|
||||
|
||||
Info: {},
|
||||
|
||||
Status: {},
|
||||
|
||||
Actions: {},
|
||||
|
||||
Page: {},
|
||||
|
||||
Config: SwarmConfig,
|
||||
|
||||
DangerZone: ({ id }) => <DeleteResource type="Swarm" id={id} />,
|
||||
|
||||
ResourcePageHeader: ({ id }) => {
|
||||
const swarm = useSwarm(id);
|
||||
|
||||
return (
|
||||
<ResourcePageHeader
|
||||
intent={swarm_state_intention(swarm?.info.state)}
|
||||
icon={<SwarmIcon id={id} size={8} />}
|
||||
type="Swarm"
|
||||
id={id}
|
||||
resource={swarm}
|
||||
state={swarm?.info.state}
|
||||
status=""
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
43
frontend/src/components/resources/swarm/table.tsx
Normal file
43
frontend/src/components/resources/swarm/table.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { DataTable, SortableHeader } from "@ui/data-table";
|
||||
import { ResourceLink } from "../common";
|
||||
import { TableTags } from "@components/tags";
|
||||
import { SwarmComponents } from ".";
|
||||
import { Types } from "komodo_client";
|
||||
import { useSelectedResources } from "@lib/hooks";
|
||||
|
||||
export const SwarmTable = ({ swarms }: { swarms: Types.SwarmListItem[] }) => {
|
||||
const [_, setSelectedResources] = useSelectedResources("Swarm");
|
||||
|
||||
return (
|
||||
<DataTable
|
||||
tableKey="swarms"
|
||||
data={swarms}
|
||||
selectOptions={{
|
||||
selectKey: ({ name }) => name,
|
||||
onSelect: setSelectedResources,
|
||||
}}
|
||||
columns={[
|
||||
{
|
||||
header: ({ column }) => (
|
||||
<SortableHeader column={column} title="Name" />
|
||||
),
|
||||
accessorKey: "name",
|
||||
cell: ({ row }) => <ResourceLink type="Swarm" id={row.original.id} />,
|
||||
size: 200,
|
||||
},
|
||||
{
|
||||
header: ({ column }) => (
|
||||
<SortableHeader column={column} title="State" />
|
||||
),
|
||||
accessorKey: "info.state",
|
||||
cell: ({ row }) => <SwarmComponents.State id={row.original.id} />,
|
||||
size: 120,
|
||||
},
|
||||
{
|
||||
header: "Tags",
|
||||
cell: ({ row }) => <TableTags tag_ids={row.original.tags} />,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -129,6 +129,23 @@ export const soft_text_color_class_by_intention = (
|
||||
}
|
||||
};
|
||||
|
||||
export const swarm_state_intention: (
|
||||
state?: Types.SwarmState,
|
||||
hasVersionMismatch?: boolean
|
||||
) => ColorIntention = (state, hasVersionMismatch) => {
|
||||
switch (state) {
|
||||
case Types.SwarmState.Healthy:
|
||||
// If there's a version mismatch and the server is "Ok", show warning instead
|
||||
return hasVersionMismatch ? "Warning" : "Good";
|
||||
case Types.SwarmState.Unhealthy:
|
||||
return "Critical";
|
||||
case Types.SwarmState.Unknown:
|
||||
return "Neutral";
|
||||
case undefined:
|
||||
return "None";
|
||||
}
|
||||
};
|
||||
|
||||
export const server_state_intention: (
|
||||
state?: Types.ServerState,
|
||||
hasVersionMismatch?: boolean
|
||||
@@ -146,6 +163,29 @@ export const server_state_intention: (
|
||||
}
|
||||
};
|
||||
|
||||
export const stack_state_intention = (state?: Types.StackState) => {
|
||||
switch (state) {
|
||||
case undefined:
|
||||
return "None";
|
||||
case Types.StackState.Deploying:
|
||||
return "Warning";
|
||||
case Types.StackState.Running:
|
||||
return "Good";
|
||||
case Types.StackState.Paused:
|
||||
return "Warning";
|
||||
case Types.StackState.Stopped:
|
||||
return "Critical";
|
||||
case Types.StackState.Restarting:
|
||||
return "Critical";
|
||||
case Types.StackState.Down:
|
||||
return "Neutral";
|
||||
case Types.StackState.Unknown:
|
||||
return "Unknown";
|
||||
default:
|
||||
return "Critical";
|
||||
}
|
||||
};
|
||||
|
||||
export const deployment_state_intention: (
|
||||
state?: Types.DeploymentState
|
||||
) => ColorIntention = (state) => {
|
||||
@@ -222,29 +262,6 @@ export const repo_state_intention = (state?: Types.RepoState) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const stack_state_intention = (state?: Types.StackState) => {
|
||||
switch (state) {
|
||||
case undefined:
|
||||
return "None";
|
||||
case Types.StackState.Deploying:
|
||||
return "Warning";
|
||||
case Types.StackState.Running:
|
||||
return "Good";
|
||||
case Types.StackState.Paused:
|
||||
return "Warning";
|
||||
case Types.StackState.Stopped:
|
||||
return "Critical";
|
||||
case Types.StackState.Restarting:
|
||||
return "Critical";
|
||||
case Types.StackState.Down:
|
||||
return "Neutral";
|
||||
case Types.StackState.Unknown:
|
||||
return "Unknown";
|
||||
default:
|
||||
return "Critical";
|
||||
}
|
||||
};
|
||||
|
||||
export const procedure_state_intention = (status?: Types.ProcedureState) => {
|
||||
switch (status) {
|
||||
case undefined:
|
||||
|
||||
@@ -364,6 +364,7 @@ type ResourceMap = {
|
||||
|
||||
export const useAllResources = (): ResourceMap => {
|
||||
return {
|
||||
Swarm: useRead("ListSwarms", {}).data,
|
||||
Server: useRead("ListServers", {}).data,
|
||||
Stack: useRead("ListStacks", {}).data,
|
||||
Deployment: useRead("ListDeployments", {}).data,
|
||||
|
||||
@@ -126,12 +126,14 @@ const on_update = (
|
||||
// Invalidate these every time
|
||||
invalidate(["ListUpdates"]);
|
||||
invalidate(["GetUpdate", { id: update.id }]);
|
||||
if (update.target.type === "Deployment") {
|
||||
invalidate(["GetDeploymentActionState", { deployment: update.target.id }]);
|
||||
} else if (update.target.type === "Stack") {
|
||||
invalidate(["GetStackActionState", { stack: update.target.id }]);
|
||||
if (update.target.type === "Swarm") {
|
||||
invalidate(["GetSwarmActionState", { swarm: update.target.id }]);
|
||||
} else if (update.target.type === "Server") {
|
||||
invalidate(["GetServerActionState", { server: update.target.id }]);
|
||||
} else if (update.target.type === "Stack") {
|
||||
invalidate(["GetStackActionState", { stack: update.target.id }]);
|
||||
} else if (update.target.type === "Deployment") {
|
||||
invalidate(["GetDeploymentActionState", { deployment: update.target.id }]);
|
||||
} else if (update.target.type === "Build") {
|
||||
invalidate(["GetBuildActionState", { build: update.target.id }]);
|
||||
} else if (update.target.type === "Repo") {
|
||||
@@ -144,7 +146,7 @@ const on_update = (
|
||||
invalidate(["GetResourceSyncActionState", { sync: update.target.id }]);
|
||||
}
|
||||
|
||||
// Invalidate lists for execution updates - update status
|
||||
// Invalidate lists for execution updates - this updates status
|
||||
if (update.operation === Types.Operation.RunBuild) {
|
||||
invalidate(["ListBuilds"]);
|
||||
} else if (
|
||||
@@ -180,18 +182,23 @@ const on_update = (
|
||||
);
|
||||
}
|
||||
|
||||
if (update.target.type === "Deployment") {
|
||||
if (update.target.type === "Swarm") {
|
||||
invalidate(
|
||||
["ListDeployments"],
|
||||
["GetDeploymentsSummary"],
|
||||
["ListDockerContainers"],
|
||||
["ListDockerNetworks"],
|
||||
["ListDockerImages"],
|
||||
["GetDeployment"],
|
||||
["GetDeploymentLog", { deployment: update.target.id }],
|
||||
["SearchDeploymentLog", { deployment: update.target.id }],
|
||||
["GetDeploymentContainer"],
|
||||
["GetResourceMatchingContainer"]
|
||||
["ListSwarms"],
|
||||
["ListFullSwarms"],
|
||||
["GetSwarmsSummary"],
|
||||
["GetSwarm"]
|
||||
);
|
||||
}
|
||||
|
||||
if (update.target.type === "Server") {
|
||||
invalidate(
|
||||
["ListServers"],
|
||||
["ListFullServers"],
|
||||
["GetServersSummary"],
|
||||
["GetServer"],
|
||||
["GetServerState"],
|
||||
["GetHistoricalServerStats"]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -213,14 +220,18 @@ const on_update = (
|
||||
);
|
||||
}
|
||||
|
||||
if (update.target.type === "Server") {
|
||||
if (update.target.type === "Deployment") {
|
||||
invalidate(
|
||||
["ListServers"],
|
||||
["ListFullServers"],
|
||||
["GetServersSummary"],
|
||||
["GetServer"],
|
||||
["GetServerState"],
|
||||
["GetHistoricalServerStats"]
|
||||
["ListDeployments"],
|
||||
["GetDeploymentsSummary"],
|
||||
["ListDockerContainers"],
|
||||
["ListDockerNetworks"],
|
||||
["ListDockerImages"],
|
||||
["GetDeployment"],
|
||||
["GetDeploymentLog", { deployment: update.target.id }],
|
||||
["SearchDeploymentLog", { deployment: update.target.id }],
|
||||
["GetDeploymentContainer"],
|
||||
["GetResourceMatchingContainer"]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -264,6 +275,15 @@ const on_update = (
|
||||
);
|
||||
}
|
||||
|
||||
if (update.target.type === "ResourceSync") {
|
||||
invalidate(
|
||||
["ListResourceSyncs"],
|
||||
["ListFullResourceSyncs"],
|
||||
["GetResourceSyncsSummary"],
|
||||
["GetResourceSync"]
|
||||
);
|
||||
}
|
||||
|
||||
if (update.target.type === "Builder") {
|
||||
invalidate(
|
||||
["ListBuilders"],
|
||||
@@ -282,15 +302,6 @@ const on_update = (
|
||||
);
|
||||
}
|
||||
|
||||
if (update.target.type === "ResourceSync") {
|
||||
invalidate(
|
||||
["ListResourceSyncs"],
|
||||
["ListFullResourceSyncs"],
|
||||
["GetResourceSyncsSummary"],
|
||||
["GetResourceSync"]
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
update.target.type === "System" &&
|
||||
update.operation.includes("Variable")
|
||||
|
||||
@@ -14,6 +14,7 @@ export const object_keys = <T extends object>(o: T): (keyof T)[] =>
|
||||
Object.keys(o) as (keyof T)[];
|
||||
|
||||
export const RESOURCE_TARGETS: UsableResource[] = [
|
||||
"Swarm",
|
||||
"Server",
|
||||
"Stack",
|
||||
"Deployment",
|
||||
|
||||
Reference in New Issue
Block a user