Files
komodo/bin/core/src/stack/execute.rs
T
Maxwell Becker 96c4ae9fc5 2.0.0 UI (#1220)
* new ui using mantine

* resources page

* prog on resource page

* resources and resource layouts

* confirm button and modal

* tweaks

* update details

* topbar updates

* add skeletons for resource implementations

* add resource tables

* add tags to recents cards

* resource page table scrolling

* table component + tags filter

* export toml

* New Resource button

* Fix update details capture closing

* tweaks

* omni search

* refine config

* config tweaks

* implement more configs / resource selector

* add profile page

* provider / account selectors

* container table page

* build config

* deployment config

* fix deployment build version selector

* fix secrets selector

* resource sync config

* mobile topbar and updates

* update details fz sm

* stack config

* terminals page

* create terminal in prog

* create terminal menu

* finish create terminal menu

* terminal pages working

* stack tabs / info

* add executions

* add server header info

* confirm pubkey modal

* improve resource header styling

* FileSource component

* stack service table, move icons.ts

* basic procedure config

* tweak procedure config

* container / image pages

* network / volume pages

* clean up docker resource pages

*  basic log / terminal ui

* reusable log section

* styling

* clean up resource components

* delete in resource header

* log auto select stderr

* fix some bgs

* stack logs with service selector

* stack terminals

* add deployment executions

* use correct icon

* useResource hooks

* build info

* build info

* tweaks

* server tabs

* fix terminal section target

* prog on server tabs

* server stats

* light theme

* start on historical stats

* stack service page

* resource sync tabs

* sync tabs

* more topbar icons

* add settings basic

* add topbar alerts

* tweak stream selector behavior

* tweak alert icon topbar

* improve styling smaller screen

* schedules page and other progress

* onboarding keys

* improve schedule page descriptions

* improve update notifications

* schedule timezone selector

* tag color selector

* finish settings / providers

* use shared-text-update component so settings tables aren't janky

* updates page

* refine updates page

* alert page

* standardize borders

* theme and swarm

* swarm tabs

* swarm node page

* swarm config page

* swarm pages

* swarm task and secret pages

* swarm stack page

* fix stack log service selector in swarm mode

* standard inspect section

* swarm inspect tab

* server and swarm resources tab

* add disable confirm dialog (modal) option for executions

* stack update available indicator

* deployment update available

* add template switch to resource headers

* ResourceHeader + rename

* set editing name onclick

* repo tabs

* server stats table

* refine a bit

* refine deployment / stack header info

* show server stats dashboard. dashboard tables

* action last run in config

* SettingsUsers page

* user page etc

* manage api key

* user base permissions

* color the table multi select

* user group page

* UserAddUserGroup

* active includes deployments / stacks

* improve small screen view

* fix docker pages execution showing

* clean up

* rename frontend to UI

* align profile page styling

* config maintenance windows

* finish maintenance windows

* builder config

* add batch execute dropdown / confirm menu

* batch execute styling

* deploy 2.0.0-dev-117

* improve stats card light theme

* add update page

* improve mobile

* terminal group nowrap

* mobile improvements

* allow unused again

* improve mobile font sizing

* improve mobile updates / alerts

* mobile tabs

* alert page

* add server version mismatch color

* new resource, clearable selector

* Fix build show info tab

* copy resources

* keyboard shortcuts

* server resource header version mismatch

* fix type errors

* container page server multi select

* confirm button clear timeout

* hash compare force uses first 8 for short hash

* fix log height

* copy webhooks

* responsive tweaks

* add icons to server stat sections

* add historical server stats charts

* server stat current card shows usage numbers

* refine current stats more

* fix shortcuts interfering with monaco brave

* clean up unused

* remove v1 frontend
2026-02-25 15:28:23 -08:00

245 lines
5.7 KiB
Rust

use anyhow::anyhow;
use komodo_client::{
api::execute::*,
entities::{
SwarmOrServer,
permission::PermissionLevel,
server::Server,
stack::{Stack, StackActionState},
update::{Log, Update},
user::User,
},
};
use periphery_client::api::compose::*;
use crate::{
helpers::{periphery_client, update::update_update},
monitor::update_cache_for_server,
periphery::PeripheryClient,
state::action_states,
};
use super::setup_stack_execution;
pub trait ExecuteCompose {
type Extras;
async fn execute(
periphery: PeripheryClient,
stack: Stack,
services: Vec<String>,
extras: Self::Extras,
) -> anyhow::Result<Log>;
}
pub async fn execute_compose<T: ExecuteCompose>(
stack: &str,
services: Vec<String>,
user: &User,
set_in_progress: impl Fn(&mut StackActionState),
update: Update,
extras: T::Extras,
) -> anyhow::Result<Update> {
let (stack, swarm_or_server) = setup_stack_execution(
stack,
user,
PermissionLevel::Execute.into(),
)
.await?;
let SwarmOrServer::Server(server) = swarm_or_server else {
return Err(anyhow!(
"Compose executions (Start, Stop, Restart) should not be called for Stack in Swarm Mode"
));
};
execute_compose_with_stack_and_server::<T>(
stack,
server,
services,
set_in_progress,
update,
extras,
)
.await
}
pub async fn execute_compose_with_stack_and_server<
T: ExecuteCompose,
>(
stack: Stack,
server: Server,
services: Vec<String>,
set_in_progress: impl Fn(&mut StackActionState),
mut update: Update,
extras: T::Extras,
) -> anyhow::Result<Update> {
// get the action state for the stack (or insert default).
let action_state =
action_states().stack.get_or_insert_default(&stack.id).await;
// Will check to ensure stack not already busy before updating, and return Err if so.
// The returned guard will set the action state back to default when dropped.
let _action_guard = action_state.update(set_in_progress)?;
// Send update here for UI to recheck action state
update_update(update.clone()).await?;
let periphery = periphery_client(&server).await?;
if !services.is_empty() {
update.logs.push(Log::simple(
"Service/s",
format!(
"Execution requested for Stack service/s {}",
services.join(", ")
),
))
}
update
.logs
.push(T::execute(periphery, stack, services, extras).await?);
// Ensure cached stack state up to date by updating server cache
update_cache_for_server(&server, true).await;
update.finalize();
update_update(update.clone()).await?;
Ok(update)
}
fn service_args(services: &[String]) -> String {
if !services.is_empty() {
format!(" {}", services.join(" "))
} else {
String::new()
}
}
impl ExecuteCompose for StartStack {
type Extras = ();
async fn execute(
periphery: PeripheryClient,
stack: Stack,
services: Vec<String>,
_: Self::Extras,
) -> anyhow::Result<Log> {
let service_args = service_args(&services);
periphery
.request(ComposeExecution {
project: stack.project_name(false),
command: format!("start{service_args}"),
})
.await
}
}
impl ExecuteCompose for RestartStack {
type Extras = ();
async fn execute(
periphery: PeripheryClient,
stack: Stack,
services: Vec<String>,
_: Self::Extras,
) -> anyhow::Result<Log> {
let service_args = service_args(&services);
periphery
.request(ComposeExecution {
project: stack.project_name(false),
command: format!("restart{service_args}"),
})
.await
}
}
impl ExecuteCompose for PauseStack {
type Extras = ();
async fn execute(
periphery: PeripheryClient,
stack: Stack,
services: Vec<String>,
_: Self::Extras,
) -> anyhow::Result<Log> {
let service_args = service_args(&services);
periphery
.request(ComposeExecution {
project: stack.project_name(false),
command: format!("pause{service_args}"),
})
.await
}
}
impl ExecuteCompose for UnpauseStack {
type Extras = ();
async fn execute(
periphery: PeripheryClient,
stack: Stack,
services: Vec<String>,
_: Self::Extras,
) -> anyhow::Result<Log> {
let service_args = service_args(&services);
periphery
.request(ComposeExecution {
project: stack.project_name(false),
command: format!("unpause{service_args}"),
})
.await
}
}
impl ExecuteCompose for StopStack {
type Extras = Option<i32>;
async fn execute(
periphery: PeripheryClient,
stack: Stack,
services: Vec<String>,
timeout: Self::Extras,
) -> anyhow::Result<Log> {
let service_args = service_args(&services);
let maybe_timeout = maybe_timeout(timeout);
periphery
.request(ComposeExecution {
project: stack.project_name(false),
command: format!("stop{maybe_timeout}{service_args}"),
})
.await
}
}
impl ExecuteCompose for DestroyStack {
type Extras = (Option<i32>, bool);
async fn execute(
periphery: PeripheryClient,
stack: Stack,
services: Vec<String>,
(timeout, remove_orphans): Self::Extras,
) -> anyhow::Result<Log> {
let service_args = service_args(&services);
let maybe_timeout = maybe_timeout(timeout);
let maybe_remove_orphans = if remove_orphans {
" --remove-orphans"
} else {
""
};
periphery
.request(ComposeExecution {
project: stack.project_name(false),
command: format!(
"down{maybe_timeout}{maybe_remove_orphans}{service_args}"
),
})
.await
}
}
pub fn maybe_timeout(timeout: Option<i32>) -> String {
if let Some(timeout) = timeout {
format!(" --timeout {timeout}")
} else {
String::new()
}
}