Files
komodo/bin/core/src/stack/execute.rs
T
98d72fc908 1.19.4 (#812)
* start 1.19.4

* deploy 1.19.4-dev-1

* try smaller binaries with cargo strip

* deploy 1.19.4-dev-2

* smaller binaries with cargo strip

* Fix Submit Dialog Button Behavior with 500 Errors on Duplicate Names (#819)

* Implement enhanced error handling and messaging for resource creation

* Implement improved error handling for resource creation across alerter, build, and sync

* Implement error handling improvements for resource copying and validation feedback

* Adjust error handling for resource creation to distinguish validation errors from unexpected system errors

* Refactor resource creation error handling by removing redundant match statements and simplifying the error propagation in multiple API modules.

* fmt

* bump indexmap

* fix account selector showing empty when account no longer found

* clean up theme logic, ensure monaco and others get up to date current theme

* enforce disable_non_admin_create for tags. Clean up status code responses

* update server cache concurrency controller

* deploy 1.19.4-dev-3

* Allow signing in by pressing enter (#830)

* Improve dialog overflow handling to prevent clipping of content (#828)

* Add Email notification entry to community.md (#824)

* Add clickable file path to show/hide file contents in StackInfo (#827)

* add clickable file path to show/hide file contents in StackInfo

Also added CopyButton due to the new functionality making the file path not selectable.

* Move clicking interaction to CardHeader

* Avoid sync edge cases of having toggle show function capturing showContents from outside

Co-authored-by: Maxwell Becker <49575486+mbecker20@users.noreply.github.com>

* Format previous change

* Add `default_show_contents` to `handleToggleShow`

---------

Co-authored-by: Maxwell Becker <49575486+mbecker20@users.noreply.github.com>

* deploy 1.19.4-dev-4

* avoid stake info ShowHideButton double toggle

* Allow multiple simultaneous Action runs for use with Args

* deploy 1.19.4-dev-5

* feat: persist all table sorting states including unsorted (#832)

- Always save sorting state to localStorage, even when empty/unsorted
- Fixes issue where 'unsorted' state was not persisted across page reloads
- Ensures consistent and predictable sorting behavior for all DataTable components

* autofocus on login username field (#837)

* Fix unnecessary auth queries flooding console on login page (#842)

* Refactor authentication error handling to use serror::Result and status codes

* Enable user query only when JWT is present

* Enable query execution in useRead only if JWT is present

* Revert backend auth changes - keep PR focused on frontend only

* Fix unnecessary API queries to unreachable servers flooding console (#843)

* Implement server availability checks in various components

* Refactor server availability check to ensure only healthy servers are identified

* cargo fmt

* fmt

* Auth error handling with status codes (#841)

* Refactor authentication error handling to use serror::Result and status codes

* Refactor error messages

* Refactor authentication error handling to include status codes and improve error messages

* clean up

* clean

* fmt

* invalid user id also UNAUTHORIZED

* deploy 1.19.4-dev-6

* deploy 1.19.4-dev-7

---------

Co-authored-by: Marcel Pfennig <82059270+MP-Tool@users.noreply.github.com>
Co-authored-by: jack <45038833+jackra1n@users.noreply.github.com>
Co-authored-by: Guten <ywzhaifei@gmail.com>
Co-authored-by: Paulo Roberto Albuquerque <paulora2405@gmail.com>
Co-authored-by: Lorenzo Farnararo <2814802+baldarn@users.noreply.github.com>
2025-09-14 12:32:06 -07:00

215 lines
5.0 KiB
Rust

use komodo_client::{
api::execute::*,
entities::{
permission::PermissionLevel,
stack::{Stack, StackActionState},
update::{Log, Update},
user::User,
},
};
use periphery_client::{PeripheryClient, api::compose::*};
use crate::{
helpers::{periphery_client, update::update_update},
monitor::update_cache_for_server,
state::action_states,
};
use super::get_stack_and_server;
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),
mut update: Update,
extras: T::Extras,
) -> anyhow::Result<Update> {
let (stack, server) = get_stack_and_server(
stack,
user,
PermissionLevel::Execute.into(),
true,
)
.await?;
// 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 frontend to recheck action state
update_update(update.clone()).await?;
let periphery = periphery_client(&server)?;
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()
}
}