mirror of
https://github.com/moghtech/komodo.git
synced 2026-08-10 01:29:51 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a246eaf35a | ||
|
|
0d462fb2e0 | ||
|
|
ca01407090 | ||
|
|
20b9d16d4b | ||
|
|
7c95823eb0 | ||
|
|
254622078e | ||
|
|
38421d6719 | ||
|
|
0f96794559 | ||
|
|
d79fefff17 | ||
|
|
4626b4a477 | ||
|
|
150a8a160d | ||
|
|
5b3bb9b8bb | ||
|
|
79831f29af | ||
|
|
b68f5abd25 | ||
|
|
2325899ebf | ||
|
|
23fd208f0f | ||
|
|
19904e00b9 | ||
|
|
8880b1c948 | ||
|
|
e47c8d2b62 | ||
|
|
1addb8fccd |
+4
-1
@@ -1,2 +1,5 @@
|
||||
[alias]
|
||||
xtask = "run --package xtask --"
|
||||
|
||||
[build]
|
||||
rustflags = ["-Wunused-crate-dependencies"]
|
||||
rustflags = ["-Wunused-crate-dependencies"]
|
||||
|
||||
+10
-10
@@ -22,16 +22,16 @@ jobs:
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
target
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-
|
||||
# - name: Cache cargo registry
|
||||
# uses: actions/cache@v4
|
||||
# with:
|
||||
# path: |
|
||||
# ~/.cargo/registry
|
||||
# ~/.cargo/git
|
||||
# target
|
||||
# key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-cargo-
|
||||
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
|
||||
Generated
+1688
-852
File diff suppressed because it is too large
Load Diff
+33
-31
@@ -3,21 +3,19 @@ resolver = "2"
|
||||
members = [
|
||||
"bin/*",
|
||||
"lib/*",
|
||||
"xtask",
|
||||
"client/core/rs",
|
||||
"client/periphery/rs",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "2.0.0"
|
||||
version = "2.2.0"
|
||||
edition = "2024"
|
||||
authors = ["mbecker20 <becker.maxh@gmail.com>"]
|
||||
license = "GPL-3.0-or-later"
|
||||
repository = "https://github.com/moghtech/komodo"
|
||||
homepage = "https://komo.do"
|
||||
|
||||
[profile.release]
|
||||
strip = "debuginfo"
|
||||
|
||||
[workspace.dependencies]
|
||||
# LOCAL
|
||||
komodo_client = { path = "client/core/rs" }
|
||||
@@ -33,29 +31,29 @@ git = { path = "lib/git" }
|
||||
|
||||
# MOGH
|
||||
slack = { version = "2.0.0", package = "slack_client_rs", default-features = false, features = ["rustls"] }
|
||||
mogh_error = { version = "1.0.3", default-features = false }
|
||||
mogh_error = { version = "1.0.4", default-features = false }
|
||||
derive_default_builder = "0.1.8"
|
||||
async_timing_util = "1.1.0"
|
||||
mogh_auth_client = "1.2.2"
|
||||
mogh_auth_server = "1.2.13"
|
||||
mogh_auth_client = "1.5.0"
|
||||
mogh_auth_server = "1.5.0"
|
||||
mogh_secret_file = "1.0.1"
|
||||
mogh_validations = "1.0.1"
|
||||
mogh_rate_limit = "1.0.1"
|
||||
partial_derive2 = "0.4.5"
|
||||
partial_derive2 = "0.5.0"
|
||||
mongo_indexed = "2.0.2"
|
||||
mogh_resolver = "1.0.0"
|
||||
mogh_config = "1.0.4"
|
||||
mogh_logger = "1.3.2"
|
||||
mogh_server = "1.4.5"
|
||||
mogh_config = "1.1.0"
|
||||
mogh_logger = "1.3.3"
|
||||
mogh_server = "1.5.0"
|
||||
toml_pretty = "2.0.0"
|
||||
mogh_cache = "1.1.1"
|
||||
mogh_cache = "1.1.2"
|
||||
mogh_pki = "1.1.3"
|
||||
mungos = "3.2.2"
|
||||
svi = "1.2.0"
|
||||
|
||||
# ASYNC
|
||||
reqwest = { version = "0.13.2", default-features = false, features = ["json", "stream", "form", "query", "rustls"] }
|
||||
tokio = { version = "1.50.0", features = ["full"] }
|
||||
reqwest = { version = "0.13.3", default-features = false, features = ["json", "stream", "form", "query", "rustls"] }
|
||||
tokio = { version = "1.52.2", features = ["full"] }
|
||||
tokio-util = { version = "0.7.18", features = ["io", "codec"] }
|
||||
tokio-stream = { version = "0.1.18", features = ["sync"] }
|
||||
pin-project-lite = "0.2.17"
|
||||
@@ -64,20 +62,20 @@ arc-swap = "1.9.0"
|
||||
|
||||
# SERVER
|
||||
tokio-tungstenite = { version = "0.29.0", features = ["rustls-tls-native-roots"] }
|
||||
axum = { version = "0.8.8", features = ["ws", "json", "macros"] }
|
||||
axum-extra = { version = "0.12.5", features = ["typed-header"] }
|
||||
axum = { version = "0.8.9", features = ["ws", "json", "macros"] }
|
||||
axum-extra = { version = "0.12.6", features = ["typed-header"] }
|
||||
|
||||
# OPENAPI
|
||||
utoipa-scalar = { version = "0.3.0", features = ["axum"] }
|
||||
utoipa = "5.4.0"
|
||||
utoipa = "5.5.0"
|
||||
|
||||
# SER/DE
|
||||
ipnetwork = { version = "0.21.1", features = ["serde"] }
|
||||
indexmap = { version = "2.13.0", features = ["serde"] }
|
||||
indexmap = { version = "2.14.0", features = ["serde"] }
|
||||
serde = { version = "1.0.227", features = ["derive"] }
|
||||
strum = { version = "0.28.0", features = ["derive"] }
|
||||
bson = { version = "2.15.0" } # must keep in sync with mongodb version
|
||||
toml = "1.1.0"
|
||||
toml = "1.1.2"
|
||||
serde_yaml_ng = "0.10.0"
|
||||
serde_json = "1.0.149"
|
||||
serde_qs = "1.1.0"
|
||||
@@ -91,34 +89,34 @@ thiserror = "2.0.18"
|
||||
tracing = "0.1.44"
|
||||
|
||||
# CONFIG
|
||||
clap = { version = "4.5.60", features = ["derive"] }
|
||||
clap = { version = "4.6.1", features = ["derive"] }
|
||||
dotenvy = "0.15.7"
|
||||
envy = "0.4.2"
|
||||
|
||||
# CRYPTO / AUTH
|
||||
uuid = { version = "1.21.0", features = ["v4", "fast-rng", "serde"] }
|
||||
rustls = { version = "0.23.37", features = ["aws-lc-rs"] }
|
||||
uuid = { version = "1.23.1", features = ["v4", "fast-rng", "serde"] }
|
||||
rustls = { version = "0.23.40", features = ["aws-lc-rs"] }
|
||||
data-encoding = "2.10.0"
|
||||
urlencoding = "2.1.3"
|
||||
bcrypt = "0.19.0"
|
||||
hmac = "0.12.1"
|
||||
sha1 = "0.10.6"
|
||||
sha2 = "0.10.9"
|
||||
rand = "0.10.0"
|
||||
hmac = "0.13.0"
|
||||
sha1 = "0.11.0"
|
||||
sha2 = "0.11.0"
|
||||
rand = "0.10.1"
|
||||
hex = "0.4.3"
|
||||
|
||||
# SYSTEM
|
||||
hickory-resolver = "0.25.2"
|
||||
hickory-resolver = "0.26.1"
|
||||
portable-pty = "0.9.0"
|
||||
shell-escape = "0.1.5"
|
||||
crossterm = "0.29.0"
|
||||
bollard = "0.20.2"
|
||||
bollard = "0.21.0"
|
||||
sysinfo = "0.38.4"
|
||||
shlex = "1.3.0"
|
||||
|
||||
# CLOUD
|
||||
aws-config = "1.8.15"
|
||||
aws-sdk-ec2 = "1.220.0"
|
||||
aws-config = "1.8.16"
|
||||
aws-sdk-ec2 = "1.224.0"
|
||||
aws-credential-types = "1.2.14"
|
||||
|
||||
## CRON
|
||||
@@ -128,7 +126,8 @@ chrono = "0.4.44"
|
||||
croner = "3.0.1"
|
||||
|
||||
# MISC
|
||||
async-compression = { version = "0.4.41", features = ["tokio", "gzip"] }
|
||||
async-compression = { version = "0.4.42", features = ["tokio", "gzip"] }
|
||||
schemars = { version = "1.2.1", features = ["indexmap2"] }
|
||||
derive_builder = "0.20.2"
|
||||
comfy-table = "7.2.2"
|
||||
typeshare = "1.0.5"
|
||||
@@ -136,3 +135,6 @@ wildcard = "0.3.0"
|
||||
colored = "3.1.1"
|
||||
bytes = "1.11.1"
|
||||
regex = "1.12.3"
|
||||
|
||||
[profile.release]
|
||||
strip = "debuginfo"
|
||||
@@ -1,7 +1,7 @@
|
||||
## Builds the Komodo Core, Periphery, and Util binaries
|
||||
## for a specific architecture. Requires OpenSSL 3 or later.
|
||||
|
||||
FROM rust:1.94.0-bookworm AS builder
|
||||
FROM rust:1.95.0-bookworm AS builder
|
||||
RUN cargo install cargo-strip
|
||||
|
||||
WORKDIR /builder
|
||||
@@ -12,6 +12,7 @@ COPY ./client/periphery ./client/periphery
|
||||
COPY ./bin/core ./bin/core
|
||||
COPY ./bin/periphery ./bin/periphery
|
||||
COPY ./bin/cli ./bin/cli
|
||||
COPY ./xtask ./xtask
|
||||
|
||||
# Compile bin
|
||||
RUN \
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
## Uses chef for dependency caching to help speed up back-to-back builds.
|
||||
|
||||
FROM lukemathwalker/cargo-chef:latest-rust-1.94.0-bookworm AS chef
|
||||
FROM lukemathwalker/cargo-chef:latest-rust-1.95.0-bookworm AS chef
|
||||
WORKDIR /builder
|
||||
|
||||
# Plan just the RECIPE to see if things have changed
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM rust:1.94.0-bullseye AS builder
|
||||
FROM rust:1.95.0-trixie AS builder
|
||||
RUN cargo install cargo-strip
|
||||
|
||||
WORKDIR /builder
|
||||
|
||||
@@ -9,7 +9,7 @@ ARG AARCH64_BINARIES=${BINARIES_IMAGE}-aarch64
|
||||
FROM ${X86_64_BINARIES} AS x86_64
|
||||
FROM ${AARCH64_BINARIES} AS aarch64
|
||||
|
||||
FROM debian:bullseye-slim
|
||||
FROM debian:trixie-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
||||
+131
-550
@@ -28,558 +28,139 @@ pub async fn handle(
|
||||
}
|
||||
|
||||
println!("\n{}: Execution", "Mode".dimmed());
|
||||
match execution {
|
||||
Execution::None(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RunAction(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BatchRunAction(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RunProcedure(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BatchRunProcedure(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RunBuild(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BatchRunBuild(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::CancelBuild(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::Deploy(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BatchDeploy(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PullDeployment(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::StartDeployment(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RestartDeployment(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PauseDeployment(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::UnpauseDeployment(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::StopDeployment(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::DestroyDeployment(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BatchDestroyDeployment(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::CloneRepo(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BatchCloneRepo(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PullRepo(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BatchPullRepo(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BuildRepo(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BatchBuildRepo(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::CancelRepoBuild(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::StartContainer(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RestartContainer(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PauseContainer(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::UnpauseContainer(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::StopContainer(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::DestroyContainer(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::StartAllContainers(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RestartAllContainers(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PauseAllContainers(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::UnpauseAllContainers(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::StopAllContainers(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PruneContainers(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::DeleteNetwork(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PruneNetworks(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::DeleteImage(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PruneImages(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::DeleteVolume(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PruneVolumes(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PruneDockerBuilders(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PruneBuildx(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PruneSystem(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RunSync(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::CommitSync(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::DeployStack(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BatchDeployStack(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::DeployStackIfChanged(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BatchDeployStackIfChanged(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PullStack(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BatchPullStack(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::StartStack(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RestartStack(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::PauseStack(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::UnpauseStack(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::StopStack(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::DestroyStack(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BatchDestroyStack(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RunStackService(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::TestAlerter(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::SendAlert(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RemoveSwarmNodes(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RemoveSwarmStacks(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RemoveSwarmServices(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::CreateSwarmConfig(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RotateSwarmConfig(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RemoveSwarmConfigs(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::CreateSwarmSecret(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RotateSwarmSecret(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RemoveSwarmSecrets(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::ClearRepoCache(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::BackupCoreDatabase(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::GlobalAutoUpdate(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RotateAllServerKeys(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::RotateCoreKeys(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
Execution::Sleep(data) => {
|
||||
println!("{}: {data:?}", "Data".dimmed())
|
||||
}
|
||||
|
||||
macro_rules! handle_execution {
|
||||
(
|
||||
execute: [$($ExecVariant:ident),* $(,)?],
|
||||
batch: [$($BatchVariant:ident),* $(,)?],
|
||||
) => {{
|
||||
// Print data
|
||||
match execution {
|
||||
$(Execution::$ExecVariant(data) => println!("{}: {data:?}", "Data".dimmed()),)*
|
||||
$(Execution::$BatchVariant(data) => println!("{}: {data:?}", "Data".dimmed()),)*
|
||||
Execution::CommitSync(data) => println!("{}: {data:?}", "Data".dimmed()),
|
||||
Execution::Sleep(data) => println!("{}: {data:?}", "Data".dimmed()),
|
||||
Execution::None(data) => println!("{}: {data:?}", "Data".dimmed()),
|
||||
}
|
||||
|
||||
$crate::command::wait_for_enter("run execution", yes)?;
|
||||
|
||||
info!("Running Execution...");
|
||||
|
||||
let client = $crate::command::komodo_client().await?;
|
||||
|
||||
// Execute and get result
|
||||
match execution.clone() {
|
||||
$(
|
||||
Execution::$ExecVariant(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
)*
|
||||
$(
|
||||
Execution::$BatchVariant(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
)*
|
||||
Execution::CommitSync(request) => client
|
||||
.write(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::Sleep(request) => {
|
||||
let duration =
|
||||
Duration::from_millis(request.duration_ms as u64);
|
||||
tokio::time::sleep(duration).await;
|
||||
println!("Finished sleeping!");
|
||||
std::process::exit(0)
|
||||
}
|
||||
Execution::None(_) => unreachable!(),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
super::wait_for_enter("run execution", yes)?;
|
||||
|
||||
info!("Running Execution...");
|
||||
|
||||
let client = super::komodo_client().await?;
|
||||
|
||||
let res = match execution.clone() {
|
||||
Execution::RunAction(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BatchRunAction(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
Execution::RunProcedure(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BatchRunProcedure(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
Execution::RunBuild(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BatchRunBuild(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
Execution::CancelBuild(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::Deploy(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BatchDeploy(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
Execution::PullDeployment(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::StartDeployment(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RestartDeployment(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::PauseDeployment(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::UnpauseDeployment(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::StopDeployment(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::DestroyDeployment(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BatchDestroyDeployment(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
Execution::CloneRepo(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BatchCloneRepo(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
Execution::PullRepo(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BatchPullRepo(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
Execution::BuildRepo(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BatchBuildRepo(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
Execution::CancelRepoBuild(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::StartContainer(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RestartContainer(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::PauseContainer(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::UnpauseContainer(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::StopContainer(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::DestroyContainer(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::StartAllContainers(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RestartAllContainers(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::PauseAllContainers(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::UnpauseAllContainers(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::StopAllContainers(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::PruneContainers(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::DeleteNetwork(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::PruneNetworks(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::DeleteImage(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::PruneImages(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::DeleteVolume(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::PruneVolumes(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::PruneDockerBuilders(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::PruneBuildx(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::PruneSystem(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RunSync(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::CommitSync(request) => client
|
||||
.write(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::DeployStack(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BatchDeployStack(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
Execution::DeployStackIfChanged(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BatchDeployStackIfChanged(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
Execution::PullStack(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BatchPullStack(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
Execution::StartStack(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RestartStack(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::PauseStack(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::UnpauseStack(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::StopStack(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::DestroyStack(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BatchDestroyStack(request) => {
|
||||
client.execute(request).await.map(ExecutionResult::Batch)
|
||||
}
|
||||
Execution::RunStackService(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::TestAlerter(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::SendAlert(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RemoveSwarmNodes(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RemoveSwarmStacks(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RemoveSwarmServices(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::CreateSwarmConfig(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RotateSwarmConfig(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RemoveSwarmConfigs(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::CreateSwarmSecret(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RotateSwarmSecret(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RemoveSwarmSecrets(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::ClearRepoCache(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::BackupCoreDatabase(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::GlobalAutoUpdate(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RotateAllServerKeys(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::RotateCoreKeys(request) => client
|
||||
.execute(request)
|
||||
.await
|
||||
.map(|u| ExecutionResult::Single(u.into())),
|
||||
Execution::Sleep(request) => {
|
||||
let duration =
|
||||
Duration::from_millis(request.duration_ms as u64);
|
||||
tokio::time::sleep(duration).await;
|
||||
println!("Finished sleeping!");
|
||||
std::process::exit(0)
|
||||
}
|
||||
Execution::None(_) => unreachable!(),
|
||||
};
|
||||
let res = handle_execution!(
|
||||
execute: [
|
||||
RunAction,
|
||||
RunProcedure,
|
||||
RunBuild,
|
||||
CancelBuild,
|
||||
Deploy,
|
||||
PullDeployment,
|
||||
StartDeployment,
|
||||
RestartDeployment,
|
||||
PauseDeployment,
|
||||
UnpauseDeployment,
|
||||
StopDeployment,
|
||||
DestroyDeployment,
|
||||
CloneRepo,
|
||||
PullRepo,
|
||||
BuildRepo,
|
||||
CancelRepoBuild,
|
||||
StartContainer,
|
||||
RestartContainer,
|
||||
PauseContainer,
|
||||
UnpauseContainer,
|
||||
StopContainer,
|
||||
DestroyContainer,
|
||||
StartAllContainers,
|
||||
RestartAllContainers,
|
||||
PauseAllContainers,
|
||||
UnpauseAllContainers,
|
||||
StopAllContainers,
|
||||
PruneContainers,
|
||||
DeleteNetwork,
|
||||
PruneNetworks,
|
||||
DeleteImage,
|
||||
PruneImages,
|
||||
DeleteVolume,
|
||||
PruneVolumes,
|
||||
PruneDockerBuilders,
|
||||
PruneBuildx,
|
||||
PruneSystem,
|
||||
RunSync,
|
||||
DeployStack,
|
||||
DeployStackIfChanged,
|
||||
PullStack,
|
||||
StartStack,
|
||||
RestartStack,
|
||||
PauseStack,
|
||||
UnpauseStack,
|
||||
StopStack,
|
||||
DestroyStack,
|
||||
RunStackService,
|
||||
TestAlerter,
|
||||
SendAlert,
|
||||
RemoveSwarmNodes,
|
||||
UpdateSwarmNode,
|
||||
RemoveSwarmStacks,
|
||||
RemoveSwarmServices,
|
||||
CreateSwarmConfig,
|
||||
RotateSwarmConfig,
|
||||
RemoveSwarmConfigs,
|
||||
CreateSwarmSecret,
|
||||
RotateSwarmSecret,
|
||||
RemoveSwarmSecrets,
|
||||
ClearRepoCache,
|
||||
BackupCoreDatabase,
|
||||
GlobalAutoUpdate,
|
||||
RotateAllServerKeys,
|
||||
RotateCoreKeys,
|
||||
],
|
||||
batch: [
|
||||
BatchRunAction,
|
||||
BatchRunProcedure,
|
||||
BatchRunBuild,
|
||||
BatchDeploy,
|
||||
BatchDestroyDeployment,
|
||||
BatchCloneRepo,
|
||||
BatchPullRepo,
|
||||
BatchBuildRepo,
|
||||
BatchDeployStack,
|
||||
BatchDeployStackIfChanged,
|
||||
BatchPullStack,
|
||||
BatchDestroyStack,
|
||||
],
|
||||
);
|
||||
|
||||
match res {
|
||||
Ok(ExecutionResult::Single(update)) => {
|
||||
|
||||
@@ -2,7 +2,7 @@ use anyhow::{Context, anyhow};
|
||||
use colored::Colorize;
|
||||
use komodo_client::{
|
||||
api::{
|
||||
read::{ListAllDockerContainers, ListServers},
|
||||
read::{GetServer, ListAllDockerContainers, ListServers},
|
||||
terminal::InitTerminal,
|
||||
},
|
||||
entities::{
|
||||
@@ -138,11 +138,14 @@ async fn get_server(
|
||||
}
|
||||
|
||||
if containers.len() == 1 {
|
||||
return containers
|
||||
let server_id = containers
|
||||
.pop()
|
||||
.context("Shouldn't happen")?
|
||||
.server_id
|
||||
.context("Container doesn't have server_id");
|
||||
.context("Container doesn't have server_id")?;
|
||||
let server_name =
|
||||
client.read(GetServer { server: server_id }).await?.name;
|
||||
return Ok(server_name);
|
||||
}
|
||||
|
||||
let servers = containers
|
||||
|
||||
@@ -264,6 +264,9 @@ pub fn cli_config() -> &'static CliConfig {
|
||||
ansi: env
|
||||
.komodo_cli_logging_ansi
|
||||
.unwrap_or(config.cli_logging.ansi),
|
||||
timestamps: env
|
||||
.komodo_cli_logging_timestamps
|
||||
.unwrap_or(config.cli_logging.timestamps),
|
||||
otlp_endpoint: env
|
||||
.komodo_cli_logging_otlp_endpoint
|
||||
.unwrap_or(config.cli_logging.otlp_endpoint),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## All in one, multi stage compile + runtime Docker build for your architecture.
|
||||
|
||||
# Build Core
|
||||
FROM rust:1.94.0-trixie AS core-builder
|
||||
FROM rust:1.95.0-trixie AS core-builder
|
||||
RUN cargo install cargo-strip
|
||||
|
||||
WORKDIR /builder
|
||||
@@ -11,6 +11,7 @@ COPY ./client/core/rs ./client/core/rs
|
||||
COPY ./client/periphery ./client/periphery
|
||||
COPY ./bin/core ./bin/core
|
||||
COPY ./bin/cli ./bin/cli
|
||||
COPY ./xtask ./xtask
|
||||
|
||||
# Compile app
|
||||
RUN cargo build -p komodo_core --release && \
|
||||
@@ -58,7 +59,8 @@ ENV KOMODO_CLI_CONFIG_PATHS="/config"
|
||||
# This ensures any `komodo.cli.*` takes precedence over the Core `/config/*config.*`
|
||||
ENV KOMODO_CLI_CONFIG_KEYWORDS="*config.*,*komodo.cli*.*"
|
||||
|
||||
CMD [ "/bin/bash", "-c", "update-ca-certificates && core" ]
|
||||
ENTRYPOINT [ "entrypoint.sh" ]
|
||||
CMD [ "core" ]
|
||||
|
||||
# Label to prevent Komodo from stopping with StopAllContainers
|
||||
LABEL komodo.skip="true"
|
||||
|
||||
@@ -27,7 +27,7 @@ pub async fn send_alert(
|
||||
SeverityLevel::Critical => {
|
||||
let err = err
|
||||
.as_ref()
|
||||
.map(|e| format!("\n**error**: {e}"))
|
||||
.map(|e| format!("\n**error**: {e:#?}"))
|
||||
.unwrap_or_default();
|
||||
format!(
|
||||
"{level} | Swarm **{name}** is **unhealthy** ❌\n{link}{err}"
|
||||
@@ -36,28 +36,6 @@ pub async fn send_alert(
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
AlertData::ServerVersionMismatch {
|
||||
id,
|
||||
name,
|
||||
region,
|
||||
server_version,
|
||||
core_version,
|
||||
} => {
|
||||
let region = fmt_region(region);
|
||||
let link = resource_link(ResourceTargetVariant::Server, id);
|
||||
match alert.level {
|
||||
SeverityLevel::Ok => {
|
||||
format!(
|
||||
"{level} | **{name}**{region} | Periphery version now matches Core version ✅\n{link}"
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
format!(
|
||||
"{level} | **{name}**{region} | Version mismatch detected ⚠️\nPeriphery: **{server_version}** | Core: **{core_version}**\n{link}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
AlertData::ServerUnreachable {
|
||||
id,
|
||||
name,
|
||||
@@ -84,6 +62,28 @@ pub async fn send_alert(
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
AlertData::ServerVersionMismatch {
|
||||
id,
|
||||
name,
|
||||
region,
|
||||
server_version,
|
||||
core_version,
|
||||
} => {
|
||||
let region = fmt_region(region);
|
||||
let link = resource_link(ResourceTargetVariant::Server, id);
|
||||
match alert.level {
|
||||
SeverityLevel::Ok => {
|
||||
format!(
|
||||
"{level} | **{name}**{region} | Periphery version now matches Core version ✅\n{link}"
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
format!(
|
||||
"{level} | **{name}**{region} | Version mismatch detected ⚠️\nPeriphery: **{server_version}** | Core: **{core_version}**\n{link}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
AlertData::ServerCpu {
|
||||
id,
|
||||
name,
|
||||
|
||||
+25
-25
@@ -260,7 +260,7 @@ fn standard_alert_content(alert: &Alert) -> String {
|
||||
SeverityLevel::Critical => {
|
||||
let err = err
|
||||
.as_ref()
|
||||
.map(|e| format!("\nerror: {e}"))
|
||||
.map(|e| format!("\nerror: {e:#?}"))
|
||||
.unwrap_or_default();
|
||||
format!(
|
||||
"{level} | Swarm {name} is unhealthy ❌\n{link}{err}"
|
||||
@@ -269,6 +269,30 @@ fn standard_alert_content(alert: &Alert) -> String {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
AlertData::ServerUnreachable {
|
||||
id,
|
||||
name,
|
||||
region,
|
||||
err,
|
||||
} => {
|
||||
let region = fmt_region(region);
|
||||
let link = resource_link(ResourceTargetVariant::Server, id);
|
||||
match alert.level {
|
||||
SeverityLevel::Ok => {
|
||||
format!("{level} | {name}{region} is now connected\n{link}")
|
||||
}
|
||||
SeverityLevel::Critical => {
|
||||
let err = err
|
||||
.as_ref()
|
||||
.map(|e| format!("\nerror: {e:#?}"))
|
||||
.unwrap_or_default();
|
||||
format!(
|
||||
"{level} | {name}{region} is unreachable ❌\n{link}{err}"
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
AlertData::ServerVersionMismatch {
|
||||
id,
|
||||
name,
|
||||
@@ -291,30 +315,6 @@ fn standard_alert_content(alert: &Alert) -> String {
|
||||
}
|
||||
}
|
||||
}
|
||||
AlertData::ServerUnreachable {
|
||||
id,
|
||||
name,
|
||||
region,
|
||||
err,
|
||||
} => {
|
||||
let region = fmt_region(region);
|
||||
let link = resource_link(ResourceTargetVariant::Server, id);
|
||||
match alert.level {
|
||||
SeverityLevel::Ok => {
|
||||
format!("{level} | {name}{region} is now connected\n{link}")
|
||||
}
|
||||
SeverityLevel::Critical => {
|
||||
let err = err
|
||||
.as_ref()
|
||||
.map(|e| format!("\nerror: {e:#?}"))
|
||||
.unwrap_or_default();
|
||||
format!(
|
||||
"{level} | {name}{region} is unreachable ❌\n{link}{err}"
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
AlertData::ServerCpu {
|
||||
id,
|
||||
name,
|
||||
|
||||
+30
-30
@@ -42,7 +42,7 @@ pub async fn send_alert(
|
||||
format!("{level} | Swarm *{name}* is *unhealthy* ❌");
|
||||
let err = err
|
||||
.as_ref()
|
||||
.map(|e| format!("\nerror: {e}"))
|
||||
.map(|e| format!("\nerror: {e:#?}"))
|
||||
.unwrap_or_default();
|
||||
let blocks = vec![
|
||||
Block::header(level),
|
||||
@@ -59,35 +59,6 @@ pub async fn send_alert(
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
AlertData::ServerVersionMismatch {
|
||||
id,
|
||||
name,
|
||||
region,
|
||||
server_version,
|
||||
core_version,
|
||||
} => {
|
||||
let region = fmt_region(region);
|
||||
let text = match alert.level {
|
||||
SeverityLevel::Ok => {
|
||||
format!(
|
||||
"{level} | *{name}*{region} | Periphery version now matches Core version ✅"
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
format!(
|
||||
"{level} | *{name}*{region} | Version mismatch detected ⚠️\nPeriphery: {server_version} | Core: {core_version}"
|
||||
)
|
||||
}
|
||||
};
|
||||
let blocks = vec![
|
||||
Block::header(text.clone()),
|
||||
Block::section(resource_link(
|
||||
ResourceTargetVariant::Server,
|
||||
id,
|
||||
)),
|
||||
];
|
||||
(text, blocks.into())
|
||||
}
|
||||
AlertData::ServerUnreachable {
|
||||
id,
|
||||
name,
|
||||
@@ -129,6 +100,35 @@ pub async fn send_alert(
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
AlertData::ServerVersionMismatch {
|
||||
id,
|
||||
name,
|
||||
region,
|
||||
server_version,
|
||||
core_version,
|
||||
} => {
|
||||
let region = fmt_region(region);
|
||||
let text = match alert.level {
|
||||
SeverityLevel::Ok => {
|
||||
format!(
|
||||
"{level} | *{name}*{region} | Periphery version now matches Core version ✅"
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
format!(
|
||||
"{level} | *{name}*{region} | Version mismatch detected ⚠️\nPeriphery: {server_version} | Core: {core_version}"
|
||||
)
|
||||
}
|
||||
};
|
||||
let blocks = vec![
|
||||
Block::header(text.clone()),
|
||||
Block::section(resource_link(
|
||||
ResourceTargetVariant::Server,
|
||||
id,
|
||||
)),
|
||||
];
|
||||
(text, blocks.into())
|
||||
}
|
||||
AlertData::ServerCpu {
|
||||
id,
|
||||
name,
|
||||
|
||||
@@ -509,10 +509,10 @@ pub async fn validate_cancel_build(
|
||||
)?;
|
||||
|
||||
match (latest_build, latest_cancel) {
|
||||
(Some(build), Some(cancel)) => {
|
||||
if cancel.start_ts > build.start_ts {
|
||||
return Err(anyhow!("Build has already been cancelled"));
|
||||
}
|
||||
(Some(build), Some(cancel))
|
||||
if cancel.start_ts > build.start_ts =>
|
||||
{
|
||||
return Err(anyhow!("Build has already been cancelled"));
|
||||
}
|
||||
(None, _) => return Err(anyhow!("No build in progress")),
|
||||
_ => {}
|
||||
|
||||
@@ -15,7 +15,7 @@ use komodo_client::{
|
||||
},
|
||||
entities::{
|
||||
SwarmOrServer, deployment::DeploymentState, server::ServerState,
|
||||
stack::StackState,
|
||||
stack::StackState, swarm::SwarmState,
|
||||
},
|
||||
};
|
||||
use mogh_error::AddStatusCodeError;
|
||||
@@ -39,7 +39,7 @@ use crate::{
|
||||
resource::rotate_server_keys,
|
||||
state::{
|
||||
db_client, deployment_status_cache, server_status_cache,
|
||||
stack_status_cache,
|
||||
stack_status_cache, swarm_status_cache,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -244,6 +244,7 @@ impl Resolve<ExecuteArgs> for GlobalAutoUpdate {
|
||||
.context("Failed to query for stacks from database")?;
|
||||
|
||||
let server_status_cache = server_status_cache();
|
||||
let swarm_status_cache = swarm_status_cache();
|
||||
let stack_status_cache = stack_status_cache();
|
||||
|
||||
// Will be edited later at update.logs[0]
|
||||
@@ -255,7 +256,7 @@ impl Resolve<ExecuteArgs> for GlobalAutoUpdate {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Only pull running stacks.
|
||||
// Only check running stacks.
|
||||
if !matches!(status.curr.state, StackState::Running) {
|
||||
continue;
|
||||
}
|
||||
@@ -267,43 +268,58 @@ impl Resolve<ExecuteArgs> for GlobalAutoUpdate {
|
||||
&servers,
|
||||
)?;
|
||||
|
||||
if let SwarmOrServer::None = &swarm_or_server {
|
||||
continue;
|
||||
// Ensure server / swarm is reachable
|
||||
match &swarm_or_server {
|
||||
SwarmOrServer::None => continue,
|
||||
SwarmOrServer::Server(server) => {
|
||||
if !server_status_cache
|
||||
.get(&server.id)
|
||||
.await
|
||||
.map(|s| matches!(s.state, ServerState::Ok))
|
||||
.unwrap_or_default()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
SwarmOrServer::Swarm(swarm) => {
|
||||
if !swarm_status_cache
|
||||
.get(&swarm.id)
|
||||
.await
|
||||
.map(|s| {
|
||||
matches!(
|
||||
s.state,
|
||||
SwarmState::Healthy | SwarmState::Unhealthy
|
||||
)
|
||||
})
|
||||
.unwrap_or_default()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(server) =
|
||||
servers.iter().find(|s| s.id == stack.config.server_id)
|
||||
// This check is probably redundant along with running check
|
||||
// but shouldn't hurt
|
||||
&& server_status_cache
|
||||
.get(&server.id)
|
||||
.await
|
||||
.map(|s| matches!(s.state, ServerState::Ok))
|
||||
.unwrap_or_default()
|
||||
if let Err(e) = check_stack_for_update_inner(
|
||||
stack.id,
|
||||
&swarm_or_server,
|
||||
self.skip_auto_update,
|
||||
true,
|
||||
false,
|
||||
)
|
||||
.await
|
||||
{
|
||||
if let Err(e) = check_stack_for_update_inner(
|
||||
stack.id,
|
||||
&swarm_or_server,
|
||||
self.skip_auto_update,
|
||||
true,
|
||||
false,
|
||||
)
|
||||
.await
|
||||
{
|
||||
update.push_error_log(
|
||||
&format!("Check Stack {}", stack.name),
|
||||
format_serror(&e.into()),
|
||||
);
|
||||
} else {
|
||||
if !update.logs[0].stdout.is_empty() {
|
||||
update.logs[0].stdout.push('\n');
|
||||
}
|
||||
|
||||
update.logs[0].stdout.push_str(&format!(
|
||||
"Checked Stack {} ✅",
|
||||
bold(&stack.name)
|
||||
));
|
||||
update.push_error_log(
|
||||
&format!("Check Stack {}", stack.name),
|
||||
format_serror(&e.into()),
|
||||
);
|
||||
} else {
|
||||
if !update.logs[0].stdout.is_empty() {
|
||||
update.logs[0].stdout.push('\n');
|
||||
}
|
||||
|
||||
update.logs[0].stdout.push_str(&format!(
|
||||
"Checked Stack {} ✅",
|
||||
bold(&stack.name)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +336,7 @@ impl Resolve<ExecuteArgs> for GlobalAutoUpdate {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Only pull running deployments.
|
||||
// Only check running deployments.
|
||||
if !matches!(status.curr.state, DeploymentState::Running) {
|
||||
continue;
|
||||
}
|
||||
@@ -332,8 +348,34 @@ impl Resolve<ExecuteArgs> for GlobalAutoUpdate {
|
||||
&servers,
|
||||
)?;
|
||||
|
||||
if let SwarmOrServer::None = &swarm_or_server {
|
||||
continue;
|
||||
// Ensure server / swarm is reachable
|
||||
match &swarm_or_server {
|
||||
SwarmOrServer::None => continue,
|
||||
SwarmOrServer::Server(server) => {
|
||||
if !server_status_cache
|
||||
.get(&server.id)
|
||||
.await
|
||||
.map(|s| matches!(s.state, ServerState::Ok))
|
||||
.unwrap_or_default()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
SwarmOrServer::Swarm(swarm) => {
|
||||
if !swarm_status_cache
|
||||
.get(&swarm.id)
|
||||
.await
|
||||
.map(|s| {
|
||||
matches!(
|
||||
s.state,
|
||||
SwarmState::Healthy | SwarmState::Unhealthy
|
||||
)
|
||||
})
|
||||
.unwrap_or_default()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let name = deployment.name.clone();
|
||||
|
||||
@@ -148,6 +148,7 @@ pub enum ExecuteRequest {
|
||||
|
||||
// ==== SWARM ====
|
||||
RemoveSwarmNodes(RemoveSwarmNodes),
|
||||
UpdateSwarmNode(UpdateSwarmNode),
|
||||
RemoveSwarmStacks(RemoveSwarmStacks),
|
||||
RemoveSwarmServices(RemoveSwarmServices),
|
||||
CreateSwarmConfig(CreateSwarmConfig),
|
||||
|
||||
@@ -698,13 +698,12 @@ pub async fn validate_cancel_repo_build(
|
||||
)?;
|
||||
|
||||
match (latest_build, latest_cancel) {
|
||||
(Some(build), Some(cancel)) => {
|
||||
if cancel.start_ts > build.start_ts {
|
||||
return Err(anyhow!(
|
||||
"Repo build has already been cancelled"
|
||||
));
|
||||
}
|
||||
(Some(build), Some(cancel))
|
||||
if cancel.start_ts > build.start_ts =>
|
||||
{
|
||||
return Err(anyhow!("Repo build has already been cancelled"));
|
||||
}
|
||||
|
||||
(None, _) => return Err(anyhow!("No repo build in progress")),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
use formatting::format_serror;
|
||||
use komodo_client::{
|
||||
api::execute::{
|
||||
CreateSwarmConfig, CreateSwarmSecret, RemoveSwarmConfigs,
|
||||
RemoveSwarmNodes, RemoveSwarmSecrets, RemoveSwarmServices,
|
||||
RemoveSwarmStacks, RotateSwarmConfig, RotateSwarmSecret,
|
||||
},
|
||||
api::execute::*,
|
||||
entities::{permission::PermissionLevel, swarm::Swarm},
|
||||
};
|
||||
use mogh_resolver::Resolve;
|
||||
@@ -76,6 +72,72 @@ impl Resolve<ExecuteArgs> for RemoveSwarmNodes {
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolve<ExecuteArgs> for UpdateSwarmNode {
|
||||
#[instrument(
|
||||
"UpdateSwarmNode",
|
||||
skip_all,
|
||||
fields(
|
||||
task_id = task_id.to_string(),
|
||||
operator = user.id,
|
||||
update_id = update.id,
|
||||
swarm = self.swarm,
|
||||
node = self.node,
|
||||
availability = format!("{:?}", self.availability),
|
||||
label_add = format!("{:?}", self.label_add),
|
||||
label_rm = format!("{:?}", self.label_rm),
|
||||
role = format!("{:?}", self.role),
|
||||
)
|
||||
)]
|
||||
async fn resolve(
|
||||
self,
|
||||
ExecuteArgs {
|
||||
user,
|
||||
update,
|
||||
task_id,
|
||||
}: &ExecuteArgs,
|
||||
) -> Result<Self::Response, Self::Error> {
|
||||
let swarm = get_check_permissions::<Swarm>(
|
||||
&self.swarm,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
update_update(update.clone()).await?;
|
||||
|
||||
let mut update = update.clone();
|
||||
|
||||
match swarm_request(
|
||||
&swarm.config.server_ids,
|
||||
periphery_client::api::swarm::UpdateSwarmNode {
|
||||
node: self.node,
|
||||
availability: self.availability,
|
||||
label_add: self.label_add,
|
||||
label_rm: self.label_rm,
|
||||
role: self.role,
|
||||
},
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(log) => {
|
||||
update.logs.push(log);
|
||||
refresh_swarm_cache(&swarm, true).await;
|
||||
}
|
||||
Err(e) => update.push_error_log(
|
||||
"Update Swarm Node",
|
||||
format_serror(
|
||||
&e.context("Failed to update swarm node").into(),
|
||||
),
|
||||
),
|
||||
};
|
||||
|
||||
update.finalize();
|
||||
update_update(update.clone()).await?;
|
||||
|
||||
Ok(update)
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolve<ExecuteArgs> for RemoveSwarmStacks {
|
||||
#[instrument(
|
||||
"RemoveSwarmStacks",
|
||||
|
||||
@@ -283,6 +283,7 @@ impl Resolve<ExecuteArgs> for RunSync {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
// New resource types need to be added here manually.
|
||||
if deploy_cache.is_empty()
|
||||
&& resource_sync_deltas.no_changes()
|
||||
&& server_deltas.no_changes()
|
||||
@@ -339,10 +340,7 @@ impl Resolve<ExecuteArgs> for RunSync {
|
||||
)
|
||||
.await,
|
||||
);
|
||||
maybe_extend(
|
||||
&mut update.logs,
|
||||
ResourceSync::execute_sync_updates(resource_sync_deltas).await,
|
||||
);
|
||||
|
||||
maybe_extend(
|
||||
&mut update.logs,
|
||||
Server::execute_sync_updates(server_deltas).await,
|
||||
@@ -356,38 +354,43 @@ impl Resolve<ExecuteArgs> for RunSync {
|
||||
Action::execute_sync_updates(action_deltas).await,
|
||||
);
|
||||
|
||||
// Dependent on server
|
||||
// Depends on server
|
||||
maybe_extend(
|
||||
&mut update.logs,
|
||||
Swarm::execute_sync_updates(swarm_deltas).await,
|
||||
);
|
||||
// Depends on server
|
||||
maybe_extend(
|
||||
&mut update.logs,
|
||||
Builder::execute_sync_updates(builder_deltas).await,
|
||||
);
|
||||
// Depends on server / builder
|
||||
maybe_extend(
|
||||
&mut update.logs,
|
||||
Repo::execute_sync_updates(repo_deltas).await,
|
||||
);
|
||||
|
||||
// Dependant on builder
|
||||
// Depends on builder / repo
|
||||
maybe_extend(
|
||||
&mut update.logs,
|
||||
Build::execute_sync_updates(build_deltas).await,
|
||||
);
|
||||
|
||||
// Dependant on server / build
|
||||
maybe_extend(
|
||||
&mut update.logs,
|
||||
Deployment::execute_sync_updates(deployment_deltas).await,
|
||||
);
|
||||
// stack only depends on server, but maybe will depend on build later.
|
||||
// Depends on server / repo
|
||||
maybe_extend(
|
||||
&mut update.logs,
|
||||
Stack::execute_sync_updates(stack_deltas).await,
|
||||
);
|
||||
|
||||
// Dependant on everything
|
||||
// Depends on repo
|
||||
maybe_extend(
|
||||
&mut update.logs,
|
||||
ResourceSync::execute_sync_updates(resource_sync_deltas).await,
|
||||
);
|
||||
// Depends on server / build
|
||||
maybe_extend(
|
||||
&mut update.logs,
|
||||
Deployment::execute_sync_updates(deployment_deltas).await,
|
||||
);
|
||||
// Depends on everything
|
||||
maybe_extend(
|
||||
&mut update.logs,
|
||||
Procedure::execute_sync_updates(procedure_deltas).await,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use anyhow::{Context, anyhow};
|
||||
use axum::http::HeaderMap;
|
||||
use hex::ToHex;
|
||||
use hmac::{Hmac, Mac};
|
||||
use hmac::{Hmac, KeyInit as _, Mac};
|
||||
use serde::Deserialize;
|
||||
use sha2::Sha256;
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
use anyhow::Context;
|
||||
use database::mungos::find::find_collect;
|
||||
use database::{
|
||||
bson::doc,
|
||||
mungos::{find::find_collect, mongodb::options::FindOptions},
|
||||
};
|
||||
use komodo_client::{
|
||||
api::read::{
|
||||
ExportAllResourcesToToml, ExportAllResourcesToTomlResponse,
|
||||
@@ -215,18 +218,21 @@ impl Resolve<ReadArgs> for ExportResourcesToToml {
|
||||
.context("failed to add user groups")?;
|
||||
|
||||
if include_variables {
|
||||
res.variables =
|
||||
find_collect(&db_client().variables, None, None)
|
||||
.await
|
||||
.context("failed to get variables from db")?
|
||||
.into_iter()
|
||||
.map(|mut variable| {
|
||||
if !user.admin && variable.is_secret {
|
||||
variable.value = "#".repeat(variable.value.len())
|
||||
}
|
||||
variable
|
||||
})
|
||||
.collect();
|
||||
res.variables = find_collect(
|
||||
&db_client().variables,
|
||||
None,
|
||||
FindOptions::builder().sort(doc! { "name": 1 }).build(),
|
||||
)
|
||||
.await
|
||||
.context("failed to get variables from db")?
|
||||
.into_iter()
|
||||
.map(|mut variable| {
|
||||
if !user.admin && variable.is_secret {
|
||||
variable.value = "#".repeat(variable.value.len())
|
||||
}
|
||||
variable
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
|
||||
let toml = serialize_resources_toml(res)
|
||||
|
||||
@@ -555,8 +555,9 @@ impl Resolve<WriteArgs> for RefreshStackCache {
|
||||
&mut services,
|
||||
) {
|
||||
warn!(
|
||||
"failed to extract stack services, things won't works correctly. stack: {} | {e:#}",
|
||||
stack.name
|
||||
stack = stack.id,
|
||||
stack_name = stack.name,
|
||||
"Failed to extract stack services | {e:#}",
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -775,7 +776,13 @@ pub async fn check_stack_for_update_inner(
|
||||
|
||||
if image.is_empty() ||
|
||||
// Images with a hardcoded digest can't have update.
|
||||
image.contains('@')
|
||||
image.contains('@') ||
|
||||
// Services explicitly excluded from global auto-update checks.
|
||||
// Manual checks should still evaluate all services.
|
||||
(wait_for_auto_update &&
|
||||
stack.config.auto_update_skip_services.contains(
|
||||
&service.service_name,
|
||||
))
|
||||
{
|
||||
service.image_digest = None;
|
||||
continue;
|
||||
@@ -939,7 +946,10 @@ pub async fn check_stack_for_update_inner(
|
||||
.retain(|(stack_id, _)| stack_id != &stack.id)
|
||||
.await;
|
||||
|
||||
let deploy_services = if stack.config.auto_update_all_services {
|
||||
let deploy_services = if stack.config.auto_update_all_services
|
||||
// Swarm stacks don't support individual service deploy
|
||||
|| !stack.config.swarm_id.is_empty()
|
||||
{
|
||||
Vec::new()
|
||||
} else {
|
||||
services_with_update
|
||||
|
||||
@@ -205,6 +205,20 @@ impl AuthImpl for KomodoAuthImpl {
|
||||
core_config().disable_user_registration
|
||||
}
|
||||
|
||||
fn local_registration_disabled(&self) -> bool {
|
||||
let config = core_config();
|
||||
config
|
||||
.disable_local_user_registration
|
||||
.unwrap_or(config.disable_user_registration)
|
||||
}
|
||||
|
||||
fn oidc_registration_disabled(&self) -> bool {
|
||||
let config = core_config();
|
||||
config
|
||||
.disable_oidc_user_registration
|
||||
.unwrap_or(config.disable_user_registration)
|
||||
}
|
||||
|
||||
fn validate_username(
|
||||
&self,
|
||||
username: &str,
|
||||
@@ -348,6 +362,7 @@ impl AuthImpl for KomodoAuthImpl {
|
||||
additional_audiences: config
|
||||
.oidc_additional_audiences
|
||||
.clone(),
|
||||
auto_redirect: config.oidc_auto_redirect,
|
||||
}
|
||||
});
|
||||
Some(&OIDC_CONFIG)
|
||||
|
||||
@@ -235,6 +235,9 @@ pub fn core_config() -> &'static CoreConfig {
|
||||
env.komodo_oidc_additional_audiences,
|
||||
)
|
||||
.unwrap_or(config.oidc_additional_audiences),
|
||||
oidc_auto_redirect: env
|
||||
.komodo_oidc_auto_redirect
|
||||
.unwrap_or(config.oidc_auto_redirect),
|
||||
google_oauth: NamedOauthConfig {
|
||||
enabled: env
|
||||
.komodo_google_oauth_enabled
|
||||
@@ -312,6 +315,21 @@ pub fn core_config() -> &'static CoreConfig {
|
||||
session_allow_cross_site: env
|
||||
.komodo_session_allow_cross_site
|
||||
.unwrap_or(config.session_allow_cross_site),
|
||||
x_content_type_options: env
|
||||
.komodo_x_content_type_options
|
||||
.unwrap_or(config.x_content_type_options),
|
||||
x_frame_options: env
|
||||
.komodo_x_frame_options
|
||||
.unwrap_or(config.x_frame_options),
|
||||
x_xss_protection: env
|
||||
.komodo_x_xss_protection
|
||||
.unwrap_or(config.x_xss_protection),
|
||||
referrer_policy: env
|
||||
.komodo_referrer_policy
|
||||
.unwrap_or(config.referrer_policy),
|
||||
content_security_policy: env
|
||||
.komodo_content_security_policy
|
||||
.unwrap_or(config.content_security_policy),
|
||||
resource_poll_interval: env
|
||||
.komodo_resource_poll_interval
|
||||
.unwrap_or(config.resource_poll_interval),
|
||||
@@ -345,6 +363,12 @@ pub fn core_config() -> &'static CoreConfig {
|
||||
disable_user_registration: env
|
||||
.komodo_disable_user_registration
|
||||
.unwrap_or(config.disable_user_registration),
|
||||
disable_local_user_registration: env
|
||||
.komodo_disable_local_user_registration
|
||||
.or(config.disable_local_user_registration),
|
||||
disable_oidc_user_registration: env
|
||||
.komodo_disable_oidc_user_registration
|
||||
.or(config.disable_oidc_user_registration),
|
||||
disable_non_admin_create: env
|
||||
.komodo_disable_non_admin_create
|
||||
.unwrap_or(config.disable_non_admin_create),
|
||||
@@ -375,6 +399,9 @@ pub fn core_config() -> &'static CoreConfig {
|
||||
.komodo_logging_location
|
||||
.unwrap_or(config.logging.location),
|
||||
ansi: env.komodo_logging_ansi.unwrap_or(config.logging.ansi),
|
||||
timestamps: env
|
||||
.komodo_logging_timestamps
|
||||
.unwrap_or(config.logging.timestamps),
|
||||
otlp_endpoint: env
|
||||
.komodo_logging_otlp_endpoint
|
||||
.unwrap_or(config.logging.otlp_endpoint),
|
||||
|
||||
@@ -307,6 +307,13 @@ async fn fix_server(
|
||||
} else {
|
||||
None
|
||||
},
|
||||
// Move address to external_address if not set.
|
||||
// This helps preserve container port link behavior.
|
||||
external_address: if !server.config.external_address.is_empty() {
|
||||
Some(server.config.address)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
if !config.is_none() {
|
||||
|
||||
+356
-1417
File diff suppressed because it is too large
Load Diff
+144
-457
@@ -123,464 +123,151 @@ pub async fn init_execution_update(
|
||||
request: &ExecuteRequest,
|
||||
user: &User,
|
||||
) -> anyhow::Result<Update> {
|
||||
let (operation, target) = match &request {
|
||||
// Swarm
|
||||
ExecuteRequest::RemoveSwarmNodes(data) => (
|
||||
Operation::RemoveSwarmNodes,
|
||||
ResourceTarget::Swarm(
|
||||
resource::get::<Swarm>(&data.swarm).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::RemoveSwarmStacks(data) => (
|
||||
Operation::RemoveSwarmStacks,
|
||||
ResourceTarget::Swarm(
|
||||
resource::get::<Swarm>(&data.swarm).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::RemoveSwarmServices(data) => (
|
||||
Operation::RemoveSwarmServices,
|
||||
ResourceTarget::Swarm(
|
||||
resource::get::<Swarm>(&data.swarm).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::CreateSwarmConfig(data) => (
|
||||
Operation::CreateSwarmConfig,
|
||||
ResourceTarget::Swarm(
|
||||
resource::get::<Swarm>(&data.swarm).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::RotateSwarmConfig(data) => (
|
||||
Operation::RotateSwarmConfig,
|
||||
ResourceTarget::Swarm(
|
||||
resource::get::<Swarm>(&data.swarm).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::RemoveSwarmConfigs(data) => (
|
||||
Operation::RemoveSwarmConfigs,
|
||||
ResourceTarget::Swarm(
|
||||
resource::get::<Swarm>(&data.swarm).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::CreateSwarmSecret(data) => (
|
||||
Operation::CreateSwarmSecret,
|
||||
ResourceTarget::Swarm(
|
||||
resource::get::<Swarm>(&data.swarm).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::RotateSwarmSecret(data) => (
|
||||
Operation::RotateSwarmSecret,
|
||||
ResourceTarget::Swarm(
|
||||
resource::get::<Swarm>(&data.swarm).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::RemoveSwarmSecrets(data) => (
|
||||
Operation::RemoveSwarmSecrets,
|
||||
ResourceTarget::Swarm(
|
||||
resource::get::<Swarm>(&data.swarm).await?.id,
|
||||
),
|
||||
),
|
||||
macro_rules! init_execution_match {
|
||||
(
|
||||
resource: [$(($Variant:ident, $ResType:ident, $field:ident)),* $(,)?],
|
||||
batch: [$($BatchVariant:ident),* $(,)?],
|
||||
stack_service: [$(($StackVariant:ident, $ServiceOp:ident)),* $(,)?],
|
||||
system: [$($SysVariant:ident),* $(,)?],
|
||||
) => {
|
||||
match &request {
|
||||
$(
|
||||
ExecuteRequest::$Variant(data) => (
|
||||
Operation::$Variant,
|
||||
ResourceTarget::$ResType(
|
||||
resource::get::<$ResType>(&data.$field).await?.id,
|
||||
),
|
||||
),
|
||||
)*
|
||||
$(
|
||||
ExecuteRequest::$BatchVariant(_data) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
)*
|
||||
$(
|
||||
ExecuteRequest::$StackVariant(data) => (
|
||||
if !data.services.is_empty() {
|
||||
Operation::$ServiceOp
|
||||
} else {
|
||||
Operation::$StackVariant
|
||||
},
|
||||
ResourceTarget::Stack(
|
||||
resource::get::<Stack>(&data.stack).await?.id,
|
||||
),
|
||||
),
|
||||
)*
|
||||
// DeployStackIfChanged doesn't have a service variant
|
||||
ExecuteRequest::DeployStackIfChanged(data) => (
|
||||
Operation::DeployStack,
|
||||
ResourceTarget::Stack(
|
||||
resource::get::<Stack>(&data.stack).await?.id,
|
||||
),
|
||||
),
|
||||
$(
|
||||
ExecuteRequest::$SysVariant(_data) => {
|
||||
(Operation::$SysVariant, ResourceTarget::system())
|
||||
}
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Server
|
||||
ExecuteRequest::StartContainer(data) => (
|
||||
Operation::StartContainer,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::RestartContainer(data) => (
|
||||
Operation::RestartContainer,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::PauseContainer(data) => (
|
||||
Operation::PauseContainer,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::UnpauseContainer(data) => (
|
||||
Operation::UnpauseContainer,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::StopContainer(data) => (
|
||||
Operation::StopContainer,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::DestroyContainer(data) => (
|
||||
Operation::DestroyContainer,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::StartAllContainers(data) => (
|
||||
Operation::StartAllContainers,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::RestartAllContainers(data) => (
|
||||
Operation::RestartAllContainers,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::PauseAllContainers(data) => (
|
||||
Operation::PauseAllContainers,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::UnpauseAllContainers(data) => (
|
||||
Operation::UnpauseAllContainers,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::StopAllContainers(data) => (
|
||||
Operation::StopAllContainers,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::PruneContainers(data) => (
|
||||
Operation::PruneContainers,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::DeleteNetwork(data) => (
|
||||
Operation::DeleteNetwork,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::PruneNetworks(data) => (
|
||||
Operation::PruneNetworks,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::DeleteImage(data) => (
|
||||
Operation::DeleteImage,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::PruneImages(data) => (
|
||||
Operation::PruneImages,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::DeleteVolume(data) => (
|
||||
Operation::DeleteVolume,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::PruneVolumes(data) => (
|
||||
Operation::PruneVolumes,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::PruneDockerBuilders(data) => (
|
||||
Operation::PruneDockerBuilders,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::PruneBuildx(data) => (
|
||||
Operation::PruneBuildx,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::PruneSystem(data) => (
|
||||
Operation::PruneSystem,
|
||||
ResourceTarget::Server(
|
||||
resource::get::<Server>(&data.server).await?.id,
|
||||
),
|
||||
),
|
||||
|
||||
// Deployment
|
||||
ExecuteRequest::Deploy(data) => (
|
||||
Operation::Deploy,
|
||||
ResourceTarget::Deployment(
|
||||
resource::get::<Deployment>(&data.deployment).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::BatchDeploy(_data) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
ExecuteRequest::PullDeployment(data) => (
|
||||
Operation::PullDeployment,
|
||||
ResourceTarget::Deployment(
|
||||
resource::get::<Deployment>(&data.deployment).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::StartDeployment(data) => (
|
||||
Operation::StartDeployment,
|
||||
ResourceTarget::Deployment(
|
||||
resource::get::<Deployment>(&data.deployment).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::RestartDeployment(data) => (
|
||||
Operation::RestartDeployment,
|
||||
ResourceTarget::Deployment(
|
||||
resource::get::<Deployment>(&data.deployment).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::PauseDeployment(data) => (
|
||||
Operation::PauseDeployment,
|
||||
ResourceTarget::Deployment(
|
||||
resource::get::<Deployment>(&data.deployment).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::UnpauseDeployment(data) => (
|
||||
Operation::UnpauseDeployment,
|
||||
ResourceTarget::Deployment(
|
||||
resource::get::<Deployment>(&data.deployment).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::StopDeployment(data) => (
|
||||
Operation::StopDeployment,
|
||||
ResourceTarget::Deployment(
|
||||
resource::get::<Deployment>(&data.deployment).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::DestroyDeployment(data) => (
|
||||
Operation::DestroyDeployment,
|
||||
ResourceTarget::Deployment(
|
||||
resource::get::<Deployment>(&data.deployment).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::BatchDestroyDeployment(_data) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
|
||||
// Build
|
||||
ExecuteRequest::RunBuild(data) => (
|
||||
Operation::RunBuild,
|
||||
ResourceTarget::Build(
|
||||
resource::get::<Build>(&data.build).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::BatchRunBuild(_data) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
ExecuteRequest::CancelBuild(data) => (
|
||||
Operation::CancelBuild,
|
||||
ResourceTarget::Build(
|
||||
resource::get::<Build>(&data.build).await?.id,
|
||||
),
|
||||
),
|
||||
|
||||
// Repo
|
||||
ExecuteRequest::CloneRepo(data) => (
|
||||
Operation::CloneRepo,
|
||||
ResourceTarget::Repo(
|
||||
resource::get::<Repo>(&data.repo).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::BatchCloneRepo(_data) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
ExecuteRequest::PullRepo(data) => (
|
||||
Operation::PullRepo,
|
||||
ResourceTarget::Repo(
|
||||
resource::get::<Repo>(&data.repo).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::BatchPullRepo(_data) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
ExecuteRequest::BuildRepo(data) => (
|
||||
Operation::BuildRepo,
|
||||
ResourceTarget::Repo(
|
||||
resource::get::<Repo>(&data.repo).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::BatchBuildRepo(_data) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
ExecuteRequest::CancelRepoBuild(data) => (
|
||||
Operation::CancelRepoBuild,
|
||||
ResourceTarget::Repo(
|
||||
resource::get::<Repo>(&data.repo).await?.id,
|
||||
),
|
||||
),
|
||||
|
||||
// Procedure
|
||||
ExecuteRequest::RunProcedure(data) => (
|
||||
Operation::RunProcedure,
|
||||
ResourceTarget::Procedure(
|
||||
resource::get::<Procedure>(&data.procedure).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::BatchRunProcedure(_) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
|
||||
// Action
|
||||
ExecuteRequest::RunAction(data) => (
|
||||
Operation::RunAction,
|
||||
ResourceTarget::Action(
|
||||
resource::get::<Action>(&data.action).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::BatchRunAction(_) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
|
||||
// Resource Sync
|
||||
ExecuteRequest::RunSync(data) => (
|
||||
Operation::RunSync,
|
||||
ResourceTarget::ResourceSync(
|
||||
resource::get::<ResourceSync>(&data.sync).await?.id,
|
||||
),
|
||||
),
|
||||
|
||||
// Stack
|
||||
ExecuteRequest::DeployStack(data) => (
|
||||
if !data.services.is_empty() {
|
||||
Operation::DeployStackService
|
||||
} else {
|
||||
Operation::DeployStack
|
||||
},
|
||||
ResourceTarget::Stack(
|
||||
resource::get::<Stack>(&data.stack).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::BatchDeployStack(_data) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
ExecuteRequest::DeployStackIfChanged(data) => (
|
||||
Operation::DeployStack,
|
||||
ResourceTarget::Stack(
|
||||
resource::get::<Stack>(&data.stack).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::BatchDeployStackIfChanged(_data) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
ExecuteRequest::StartStack(data) => (
|
||||
if !data.services.is_empty() {
|
||||
Operation::StartStackService
|
||||
} else {
|
||||
Operation::StartStack
|
||||
},
|
||||
ResourceTarget::Stack(
|
||||
resource::get::<Stack>(&data.stack).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::PullStack(data) => (
|
||||
if !data.services.is_empty() {
|
||||
Operation::PullStackService
|
||||
} else {
|
||||
Operation::PullStack
|
||||
},
|
||||
ResourceTarget::Stack(
|
||||
resource::get::<Stack>(&data.stack).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::BatchPullStack(_data) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
ExecuteRequest::RestartStack(data) => (
|
||||
if !data.services.is_empty() {
|
||||
Operation::RestartStackService
|
||||
} else {
|
||||
Operation::RestartStack
|
||||
},
|
||||
ResourceTarget::Stack(
|
||||
resource::get::<Stack>(&data.stack).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::PauseStack(data) => (
|
||||
if !data.services.is_empty() {
|
||||
Operation::PauseStackService
|
||||
} else {
|
||||
Operation::PauseStack
|
||||
},
|
||||
ResourceTarget::Stack(
|
||||
resource::get::<Stack>(&data.stack).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::UnpauseStack(data) => (
|
||||
if !data.services.is_empty() {
|
||||
Operation::UnpauseStackService
|
||||
} else {
|
||||
Operation::UnpauseStack
|
||||
},
|
||||
ResourceTarget::Stack(
|
||||
resource::get::<Stack>(&data.stack).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::StopStack(data) => (
|
||||
if !data.services.is_empty() {
|
||||
Operation::StopStackService
|
||||
} else {
|
||||
Operation::StopStack
|
||||
},
|
||||
ResourceTarget::Stack(
|
||||
resource::get::<Stack>(&data.stack).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::DestroyStack(data) => (
|
||||
if !data.services.is_empty() {
|
||||
Operation::DestroyStackService
|
||||
} else {
|
||||
Operation::DestroyStack
|
||||
},
|
||||
ResourceTarget::Stack(
|
||||
resource::get::<Stack>(&data.stack).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::BatchDestroyStack(_data) => {
|
||||
return Ok(Default::default());
|
||||
}
|
||||
|
||||
ExecuteRequest::RunStackService(data) => (
|
||||
Operation::RunStackService,
|
||||
ResourceTarget::Stack(
|
||||
resource::get::<Stack>(&data.stack).await?.id,
|
||||
),
|
||||
),
|
||||
|
||||
// Alerter
|
||||
ExecuteRequest::TestAlerter(data) => (
|
||||
Operation::TestAlerter,
|
||||
ResourceTarget::Alerter(
|
||||
resource::get::<Alerter>(&data.alerter).await?.id,
|
||||
),
|
||||
),
|
||||
ExecuteRequest::SendAlert(_) => {
|
||||
(Operation::SendAlert, ResourceTarget::system())
|
||||
}
|
||||
|
||||
// Maintenance
|
||||
ExecuteRequest::ClearRepoCache(_data) => {
|
||||
(Operation::ClearRepoCache, ResourceTarget::system())
|
||||
}
|
||||
ExecuteRequest::BackupCoreDatabase(_data) => {
|
||||
(Operation::BackupCoreDatabase, ResourceTarget::system())
|
||||
}
|
||||
ExecuteRequest::GlobalAutoUpdate(_data) => {
|
||||
(Operation::GlobalAutoUpdate, ResourceTarget::system())
|
||||
}
|
||||
ExecuteRequest::RotateAllServerKeys(_data) => {
|
||||
(Operation::RotateAllServerKeys, ResourceTarget::system())
|
||||
}
|
||||
ExecuteRequest::RotateCoreKeys(_data) => {
|
||||
(Operation::RotateCoreKeys, ResourceTarget::system())
|
||||
}
|
||||
};
|
||||
let (operation, target) = init_execution_match!(
|
||||
resource: [
|
||||
// Swarm
|
||||
(RemoveSwarmNodes, Swarm, swarm),
|
||||
(UpdateSwarmNode, Swarm, swarm),
|
||||
(RemoveSwarmStacks, Swarm, swarm),
|
||||
(RemoveSwarmServices, Swarm, swarm),
|
||||
(CreateSwarmConfig, Swarm, swarm),
|
||||
(RotateSwarmConfig, Swarm, swarm),
|
||||
(RemoveSwarmConfigs, Swarm, swarm),
|
||||
(CreateSwarmSecret, Swarm, swarm),
|
||||
(RotateSwarmSecret, Swarm, swarm),
|
||||
(RemoveSwarmSecrets, Swarm, swarm),
|
||||
// Server
|
||||
(StartContainer, Server, server),
|
||||
(RestartContainer, Server, server),
|
||||
(PauseContainer, Server, server),
|
||||
(UnpauseContainer, Server, server),
|
||||
(StopContainer, Server, server),
|
||||
(DestroyContainer, Server, server),
|
||||
(StartAllContainers, Server, server),
|
||||
(RestartAllContainers, Server, server),
|
||||
(PauseAllContainers, Server, server),
|
||||
(UnpauseAllContainers, Server, server),
|
||||
(StopAllContainers, Server, server),
|
||||
(PruneContainers, Server, server),
|
||||
(DeleteNetwork, Server, server),
|
||||
(PruneNetworks, Server, server),
|
||||
(DeleteImage, Server, server),
|
||||
(PruneImages, Server, server),
|
||||
(DeleteVolume, Server, server),
|
||||
(PruneVolumes, Server, server),
|
||||
(PruneDockerBuilders, Server, server),
|
||||
(PruneBuildx, Server, server),
|
||||
(PruneSystem, Server, server),
|
||||
// Deployment
|
||||
(Deploy, Deployment, deployment),
|
||||
(PullDeployment, Deployment, deployment),
|
||||
(StartDeployment, Deployment, deployment),
|
||||
(RestartDeployment, Deployment, deployment),
|
||||
(PauseDeployment, Deployment, deployment),
|
||||
(UnpauseDeployment, Deployment, deployment),
|
||||
(StopDeployment, Deployment, deployment),
|
||||
(DestroyDeployment, Deployment, deployment),
|
||||
// Build
|
||||
(RunBuild, Build, build),
|
||||
(CancelBuild, Build, build),
|
||||
// Repo
|
||||
(CloneRepo, Repo, repo),
|
||||
(PullRepo, Repo, repo),
|
||||
(BuildRepo, Repo, repo),
|
||||
(CancelRepoBuild, Repo, repo),
|
||||
// Procedure
|
||||
(RunProcedure, Procedure, procedure),
|
||||
// Action
|
||||
(RunAction, Action, action),
|
||||
// Resource Sync
|
||||
(RunSync, ResourceSync, sync),
|
||||
// Stack (simple)
|
||||
(RunStackService, Stack, stack),
|
||||
// Alerter
|
||||
(TestAlerter, Alerter, alerter),
|
||||
],
|
||||
batch: [
|
||||
BatchDeploy,
|
||||
BatchDestroyDeployment,
|
||||
BatchRunBuild,
|
||||
BatchCloneRepo,
|
||||
BatchPullRepo,
|
||||
BatchBuildRepo,
|
||||
BatchRunProcedure,
|
||||
BatchRunAction,
|
||||
BatchDeployStack,
|
||||
BatchDeployStackIfChanged,
|
||||
BatchPullStack,
|
||||
BatchDestroyStack,
|
||||
],
|
||||
stack_service: [
|
||||
(DeployStack, DeployStackService),
|
||||
(PullStack, PullStackService),
|
||||
(StartStack, StartStackService),
|
||||
(RestartStack, RestartStackService),
|
||||
(PauseStack, PauseStackService),
|
||||
(UnpauseStack, UnpauseStackService),
|
||||
(StopStack, StopStackService),
|
||||
(DestroyStack, DestroyStackService),
|
||||
],
|
||||
system: [
|
||||
SendAlert,
|
||||
ClearRepoCache,
|
||||
BackupCoreDatabase,
|
||||
GlobalAutoUpdate,
|
||||
RotateAllServerKeys,
|
||||
RotateCoreKeys,
|
||||
],
|
||||
);
|
||||
|
||||
let mut update = make_update(target, operation, user);
|
||||
update.in_progress();
|
||||
|
||||
@@ -46,8 +46,10 @@ pub async fn update_swarm_stack_cache(
|
||||
Some(SwarmState::Unknown) | None => StackState::Unknown,
|
||||
})
|
||||
.unwrap_or(StackState::Down);
|
||||
|
||||
let services = extract_services_from_stack(&stack);
|
||||
let service_prefix = format!("{project_name}_");
|
||||
|
||||
let mut services_with_swarm_services = services
|
||||
.iter()
|
||||
.map(
|
||||
@@ -74,27 +76,50 @@ pub async fn update_swarm_stack_cache(
|
||||
.unwrap_or_default()
|
||||
})
|
||||
.cloned();
|
||||
|
||||
let (image, image_digests) = swarm_service
|
||||
.as_ref()
|
||||
.and_then(|swarm_service| swarm_service.image.as_ref())
|
||||
.map(|image| {
|
||||
(
|
||||
image.clone(),
|
||||
ImageDigest::parse(image).map(|d| vec![d]),
|
||||
)
|
||||
})
|
||||
.unwrap_or((
|
||||
if image.contains(':') {
|
||||
image.to_string()
|
||||
} else {
|
||||
format!("{image}:latest")
|
||||
},
|
||||
None,
|
||||
));
|
||||
|
||||
StackService {
|
||||
service: service_name.clone(),
|
||||
image: image.clone(),
|
||||
container: None,
|
||||
swarm_service,
|
||||
image_digests: Default::default(),
|
||||
image,
|
||||
image_digests,
|
||||
}
|
||||
},
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
services_with_swarm_services
|
||||
.sort_by(|a, b| a.service.cmp(&b.service));
|
||||
|
||||
let prev_state = stack_status_cache
|
||||
.get(&stack.id)
|
||||
.await
|
||||
.map(|s| s.curr.state);
|
||||
|
||||
let status = CachedStackStatus {
|
||||
id: stack.id.clone(),
|
||||
state: current_state,
|
||||
services: services_with_swarm_services,
|
||||
};
|
||||
|
||||
stack_status_cache
|
||||
.insert(
|
||||
stack.id,
|
||||
@@ -207,10 +232,17 @@ pub async fn update_swarm_deployment_cache(
|
||||
.unwrap_or_default()
|
||||
})
|
||||
.cloned();
|
||||
|
||||
let image_digests = service
|
||||
.as_ref()
|
||||
.and_then(|service| service.image.as_ref())
|
||||
.and_then(|image| ImageDigest::parse(image).map(|d| vec![d]));
|
||||
|
||||
let prev_state = deployment_status_cache
|
||||
.get(&deployment.id)
|
||||
.await
|
||||
.map(|s| s.curr.state);
|
||||
|
||||
let current_state = service
|
||||
.as_ref()
|
||||
.map(|service| match service.state {
|
||||
@@ -220,6 +252,7 @@ pub async fn update_swarm_deployment_cache(
|
||||
SwarmState::Unknown => DeploymentState::Unknown,
|
||||
})
|
||||
.unwrap_or(DeploymentState::NotDeployed);
|
||||
|
||||
deployment_status_cache
|
||||
.insert(
|
||||
deployment.id.clone(),
|
||||
@@ -227,9 +260,9 @@ pub async fn update_swarm_deployment_cache(
|
||||
curr: CachedDeploymentStatus {
|
||||
id: deployment.id,
|
||||
state: current_state,
|
||||
service,
|
||||
container: None,
|
||||
image_digests: None,
|
||||
service,
|
||||
image_digests,
|
||||
},
|
||||
prev: prev_state,
|
||||
}
|
||||
@@ -251,6 +284,7 @@ pub async fn update_server_deployment_cache(
|
||||
.iter()
|
||||
.find(|container| container.name == deployment.name)
|
||||
.cloned();
|
||||
|
||||
let image_digests = container
|
||||
.as_ref()
|
||||
.and_then(|container| container.image_id.as_ref())
|
||||
@@ -263,10 +297,12 @@ pub async fn update_server_deployment_cache(
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
let prev_state = deployment_status_cache
|
||||
.get(&deployment.id)
|
||||
.await
|
||||
.map(|s| s.curr.state);
|
||||
|
||||
let current_state = container
|
||||
.as_ref()
|
||||
.map(|c| c.state.into())
|
||||
|
||||
@@ -6,7 +6,6 @@ use std::{
|
||||
use anyhow::anyhow;
|
||||
use async_timing_util::wait_until_timelength;
|
||||
use database::mungos::find::find_collect;
|
||||
use formatting::format_serror;
|
||||
use futures_util::future::join_all;
|
||||
use komodo_client::entities::{
|
||||
docker::node::NodeState,
|
||||
@@ -108,9 +107,9 @@ pub async fn refresh_swarm_cache(swarm: &Swarm, force: bool) {
|
||||
state: SwarmState::Unknown,
|
||||
inspect: None,
|
||||
lists: None,
|
||||
err: Some(format_serror(
|
||||
&anyhow!("No Servers configured as manager nodes").into(),
|
||||
)),
|
||||
err: Some(
|
||||
anyhow!("No servers configured as manager nodes").into(),
|
||||
),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
@@ -137,7 +136,7 @@ pub async fn refresh_swarm_cache(swarm: &Swarm, force: bool) {
|
||||
state: SwarmState::Unknown,
|
||||
inspect: None,
|
||||
lists: None,
|
||||
err: Some(format_serror(&e.into())),
|
||||
err: Some(e.into()),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
|
||||
+172
-684
@@ -183,695 +183,183 @@ async fn validate_config(
|
||||
};
|
||||
for stage in stages {
|
||||
for exec in &mut stage.executions {
|
||||
match &mut exec.execution {
|
||||
Execution::None(_) => {}
|
||||
Execution::RunProcedure(params) => {
|
||||
let procedure = super::get_check_permissions::<Procedure>(
|
||||
¶ms.procedure,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
match id {
|
||||
Some(id) if procedure.id == id => {
|
||||
return Err(anyhow!(
|
||||
"Cannot have self-referential procedure"
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
params.procedure = procedure.id;
|
||||
}
|
||||
Execution::BatchRunProcedure(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::RunAction(params) => {
|
||||
let action = super::get_check_permissions::<Action>(
|
||||
¶ms.action,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.action = action.id;
|
||||
}
|
||||
Execution::BatchRunAction(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::RunBuild(params) => {
|
||||
let build = super::get_check_permissions::<Build>(
|
||||
¶ms.build,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.build = build.id;
|
||||
}
|
||||
Execution::BatchRunBuild(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::CancelBuild(params) => {
|
||||
let build = super::get_check_permissions::<Build>(
|
||||
¶ms.build,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.build = build.id;
|
||||
}
|
||||
Execution::Deploy(params) => {
|
||||
let deployment =
|
||||
super::get_check_permissions::<Deployment>(
|
||||
¶ms.deployment,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.deployment = deployment.id;
|
||||
}
|
||||
Execution::BatchDeploy(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::PullDeployment(params) => {
|
||||
let deployment =
|
||||
super::get_check_permissions::<Deployment>(
|
||||
¶ms.deployment,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.deployment = deployment.id;
|
||||
}
|
||||
Execution::StartDeployment(params) => {
|
||||
let deployment =
|
||||
super::get_check_permissions::<Deployment>(
|
||||
¶ms.deployment,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.deployment = deployment.id;
|
||||
}
|
||||
Execution::RestartDeployment(params) => {
|
||||
let deployment =
|
||||
super::get_check_permissions::<Deployment>(
|
||||
¶ms.deployment,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.deployment = deployment.id;
|
||||
}
|
||||
Execution::PauseDeployment(params) => {
|
||||
let deployment =
|
||||
super::get_check_permissions::<Deployment>(
|
||||
¶ms.deployment,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.deployment = deployment.id;
|
||||
}
|
||||
Execution::UnpauseDeployment(params) => {
|
||||
let deployment =
|
||||
super::get_check_permissions::<Deployment>(
|
||||
¶ms.deployment,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.deployment = deployment.id;
|
||||
}
|
||||
Execution::StopDeployment(params) => {
|
||||
let deployment =
|
||||
super::get_check_permissions::<Deployment>(
|
||||
¶ms.deployment,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.deployment = deployment.id;
|
||||
}
|
||||
Execution::DestroyDeployment(params) => {
|
||||
let deployment =
|
||||
super::get_check_permissions::<Deployment>(
|
||||
¶ms.deployment,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.deployment = deployment.id;
|
||||
}
|
||||
Execution::BatchDestroyDeployment(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::CloneRepo(params) => {
|
||||
let repo = super::get_check_permissions::<Repo>(
|
||||
¶ms.repo,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.repo = repo.id;
|
||||
}
|
||||
Execution::BatchCloneRepo(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::PullRepo(params) => {
|
||||
let repo = super::get_check_permissions::<Repo>(
|
||||
¶ms.repo,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.repo = repo.id;
|
||||
}
|
||||
Execution::BatchPullRepo(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::BuildRepo(params) => {
|
||||
let repo = super::get_check_permissions::<Repo>(
|
||||
¶ms.repo,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.repo = repo.id;
|
||||
}
|
||||
Execution::BatchBuildRepo(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::CancelRepoBuild(params) => {
|
||||
let repo = super::get_check_permissions::<Repo>(
|
||||
¶ms.repo,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.repo = repo.id;
|
||||
}
|
||||
Execution::StartContainer(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::RestartContainer(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::PauseContainer(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::UnpauseContainer(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::StopContainer(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::DestroyContainer(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::StartAllContainers(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::RestartAllContainers(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::PauseAllContainers(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::UnpauseAllContainers(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::StopAllContainers(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::PruneContainers(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::DeleteNetwork(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::PruneNetworks(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::DeleteImage(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::PruneImages(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::DeleteVolume(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::PruneVolumes(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::PruneDockerBuilders(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::PruneBuildx(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::PruneSystem(params) => {
|
||||
let server = super::get_check_permissions::<Server>(
|
||||
¶ms.server,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.server = server.id;
|
||||
}
|
||||
Execution::RunSync(params) => {
|
||||
let sync = super::get_check_permissions::<ResourceSync>(
|
||||
¶ms.sync,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.sync = sync.id;
|
||||
}
|
||||
Execution::CommitSync(params) => {
|
||||
// This one is actually a write operation.
|
||||
let sync = super::get_check_permissions::<ResourceSync>(
|
||||
¶ms.sync,
|
||||
user,
|
||||
PermissionLevel::Write.into(),
|
||||
)
|
||||
.await?;
|
||||
params.sync = sync.id;
|
||||
}
|
||||
Execution::DeployStack(params) => {
|
||||
let stack = super::get_check_permissions::<Stack>(
|
||||
¶ms.stack,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.stack = stack.id;
|
||||
}
|
||||
Execution::BatchDeployStack(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::DeployStackIfChanged(params) => {
|
||||
let stack = super::get_check_permissions::<Stack>(
|
||||
¶ms.stack,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.stack = stack.id;
|
||||
}
|
||||
Execution::BatchDeployStackIfChanged(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::PullStack(params) => {
|
||||
let stack = super::get_check_permissions::<Stack>(
|
||||
¶ms.stack,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.stack = stack.id;
|
||||
}
|
||||
Execution::BatchPullStack(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::StartStack(params) => {
|
||||
let stack = super::get_check_permissions::<Stack>(
|
||||
¶ms.stack,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.stack = stack.id;
|
||||
}
|
||||
Execution::RestartStack(params) => {
|
||||
let stack = super::get_check_permissions::<Stack>(
|
||||
¶ms.stack,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.stack = stack.id;
|
||||
}
|
||||
Execution::PauseStack(params) => {
|
||||
let stack = super::get_check_permissions::<Stack>(
|
||||
¶ms.stack,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.stack = stack.id;
|
||||
}
|
||||
Execution::UnpauseStack(params) => {
|
||||
let stack = super::get_check_permissions::<Stack>(
|
||||
¶ms.stack,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.stack = stack.id;
|
||||
}
|
||||
Execution::StopStack(params) => {
|
||||
let stack = super::get_check_permissions::<Stack>(
|
||||
¶ms.stack,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.stack = stack.id;
|
||||
}
|
||||
Execution::DestroyStack(params) => {
|
||||
let stack = super::get_check_permissions::<Stack>(
|
||||
¶ms.stack,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.stack = stack.id;
|
||||
}
|
||||
Execution::RunStackService(params) => {
|
||||
let stack = super::get_check_permissions::<Stack>(
|
||||
¶ms.stack,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.stack = stack.id;
|
||||
}
|
||||
Execution::BatchDestroyStack(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::TestAlerter(params) => {
|
||||
let alerter = super::get_check_permissions::<Alerter>(
|
||||
¶ms.alerter,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.alerter = alerter.id;
|
||||
}
|
||||
Execution::SendAlert(params) => {
|
||||
params.alerters = params
|
||||
.alerters
|
||||
.iter()
|
||||
.map(async |alerter| {
|
||||
let id = super::get_check_permissions::<Alerter>(
|
||||
alerter,
|
||||
macro_rules! check_execution_perms {
|
||||
(
|
||||
execute: [$(($Variant:ident, $Type:ident, $field:ident)),* $(,)?],
|
||||
batch_admin: [$($BatchVariant:ident),* $(,)?],
|
||||
admin_only: [$(($AdminVariant:ident, $msg:literal)),* $(,)?],
|
||||
) => {
|
||||
match &mut exec.execution {
|
||||
$(
|
||||
Execution::$Variant(params) => {
|
||||
let resource = super::get_check_permissions::<$Type>(
|
||||
¶ms.$field,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.$field = resource.id;
|
||||
}
|
||||
)*
|
||||
$(
|
||||
Execution::$BatchVariant(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot configure Batch executions"
|
||||
));
|
||||
}
|
||||
}
|
||||
)*
|
||||
$(
|
||||
Execution::$AdminVariant(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!($msg));
|
||||
}
|
||||
}
|
||||
)*
|
||||
// Special: self-referential procedure check
|
||||
Execution::RunProcedure(params) => {
|
||||
let procedure = super::get_check_permissions::<Procedure>(
|
||||
¶ms.procedure,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?
|
||||
.id;
|
||||
anyhow::Ok(id)
|
||||
})
|
||||
.collect::<FuturesUnordered<_>>()
|
||||
.try_collect::<Vec<_>>()
|
||||
.await?;
|
||||
}
|
||||
Execution::RemoveSwarmNodes(params) => {
|
||||
let swarm = super::get_check_permissions::<Swarm>(
|
||||
¶ms.swarm,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.swarm = swarm.id;
|
||||
}
|
||||
Execution::RemoveSwarmStacks(params) => {
|
||||
let swarm = super::get_check_permissions::<Swarm>(
|
||||
¶ms.swarm,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.swarm = swarm.id;
|
||||
}
|
||||
Execution::RemoveSwarmServices(params) => {
|
||||
let swarm = super::get_check_permissions::<Swarm>(
|
||||
¶ms.swarm,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.swarm = swarm.id;
|
||||
}
|
||||
Execution::CreateSwarmConfig(params) => {
|
||||
let swarm = super::get_check_permissions::<Swarm>(
|
||||
¶ms.swarm,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.swarm = swarm.id;
|
||||
}
|
||||
Execution::RotateSwarmConfig(params) => {
|
||||
let swarm = super::get_check_permissions::<Swarm>(
|
||||
¶ms.swarm,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.swarm = swarm.id;
|
||||
}
|
||||
Execution::RemoveSwarmConfigs(params) => {
|
||||
let swarm = super::get_check_permissions::<Swarm>(
|
||||
¶ms.swarm,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.swarm = swarm.id;
|
||||
}
|
||||
Execution::CreateSwarmSecret(params) => {
|
||||
let swarm = super::get_check_permissions::<Swarm>(
|
||||
¶ms.swarm,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.swarm = swarm.id;
|
||||
}
|
||||
Execution::RotateSwarmSecret(params) => {
|
||||
let swarm = super::get_check_permissions::<Swarm>(
|
||||
¶ms.swarm,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.swarm = swarm.id;
|
||||
}
|
||||
Execution::RemoveSwarmSecrets(params) => {
|
||||
let swarm = super::get_check_permissions::<Swarm>(
|
||||
¶ms.swarm,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?;
|
||||
params.swarm = swarm.id;
|
||||
}
|
||||
Execution::ClearRepoCache(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot clear repo cache"
|
||||
));
|
||||
.await?;
|
||||
match id {
|
||||
Some(id) if procedure.id == id => {
|
||||
return Err(anyhow!(
|
||||
"Cannot have self-referential procedure"
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
params.procedure = procedure.id;
|
||||
}
|
||||
// Special: CommitSync uses Write permission
|
||||
Execution::CommitSync(params) => {
|
||||
let sync = super::get_check_permissions::<ResourceSync>(
|
||||
¶ms.sync,
|
||||
user,
|
||||
PermissionLevel::Write.into(),
|
||||
)
|
||||
.await?;
|
||||
params.sync = sync.id;
|
||||
}
|
||||
// Special: SendAlert checks a Vec of alerters
|
||||
Execution::SendAlert(params) => {
|
||||
params.alerters = params
|
||||
.alerters
|
||||
.iter()
|
||||
.map(async |alerter| {
|
||||
let id = super::get_check_permissions::<Alerter>(
|
||||
alerter,
|
||||
user,
|
||||
PermissionLevel::Execute.into(),
|
||||
)
|
||||
.await?
|
||||
.id;
|
||||
anyhow::Ok(id)
|
||||
})
|
||||
.collect::<FuturesUnordered<_>>()
|
||||
.try_collect::<Vec<_>>()
|
||||
.await?;
|
||||
}
|
||||
Execution::None(_) | Execution::Sleep(_) => {}
|
||||
}
|
||||
}
|
||||
Execution::BackupCoreDatabase(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot trigger core database backup"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::GlobalAutoUpdate(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot trigger global auto update"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::RotateAllServerKeys(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot trigger rotate all server keys"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::RotateCoreKeys(_params) => {
|
||||
if !user.admin {
|
||||
return Err(anyhow!(
|
||||
"Non admin user cannot trigger rotate core keys"
|
||||
));
|
||||
}
|
||||
}
|
||||
Execution::Sleep(_) => {}
|
||||
};
|
||||
}
|
||||
check_execution_perms!(
|
||||
execute: [
|
||||
// Action
|
||||
(RunAction, Action, action),
|
||||
// Build
|
||||
(RunBuild, Build, build),
|
||||
(CancelBuild, Build, build),
|
||||
// Deployment
|
||||
(Deploy, Deployment, deployment),
|
||||
(PullDeployment, Deployment, deployment),
|
||||
(StartDeployment, Deployment, deployment),
|
||||
(RestartDeployment, Deployment, deployment),
|
||||
(PauseDeployment, Deployment, deployment),
|
||||
(UnpauseDeployment, Deployment, deployment),
|
||||
(StopDeployment, Deployment, deployment),
|
||||
(DestroyDeployment, Deployment, deployment),
|
||||
// Repo
|
||||
(CloneRepo, Repo, repo),
|
||||
(PullRepo, Repo, repo),
|
||||
(BuildRepo, Repo, repo),
|
||||
(CancelRepoBuild, Repo, repo),
|
||||
// Server
|
||||
(StartContainer, Server, server),
|
||||
(RestartContainer, Server, server),
|
||||
(PauseContainer, Server, server),
|
||||
(UnpauseContainer, Server, server),
|
||||
(StopContainer, Server, server),
|
||||
(DestroyContainer, Server, server),
|
||||
(StartAllContainers, Server, server),
|
||||
(RestartAllContainers, Server, server),
|
||||
(PauseAllContainers, Server, server),
|
||||
(UnpauseAllContainers, Server, server),
|
||||
(StopAllContainers, Server, server),
|
||||
(PruneContainers, Server, server),
|
||||
(DeleteNetwork, Server, server),
|
||||
(PruneNetworks, Server, server),
|
||||
(DeleteImage, Server, server),
|
||||
(PruneImages, Server, server),
|
||||
(DeleteVolume, Server, server),
|
||||
(PruneVolumes, Server, server),
|
||||
(PruneDockerBuilders, Server, server),
|
||||
(PruneBuildx, Server, server),
|
||||
(PruneSystem, Server, server),
|
||||
// Resource Sync
|
||||
(RunSync, ResourceSync, sync),
|
||||
// Stack
|
||||
(DeployStack, Stack, stack),
|
||||
(DeployStackIfChanged, Stack, stack),
|
||||
(PullStack, Stack, stack),
|
||||
(StartStack, Stack, stack),
|
||||
(RestartStack, Stack, stack),
|
||||
(PauseStack, Stack, stack),
|
||||
(UnpauseStack, Stack, stack),
|
||||
(StopStack, Stack, stack),
|
||||
(DestroyStack, Stack, stack),
|
||||
(RunStackService, Stack, stack),
|
||||
// Alerter
|
||||
(TestAlerter, Alerter, alerter),
|
||||
// Swarm
|
||||
(RemoveSwarmNodes, Swarm, swarm),
|
||||
(UpdateSwarmNode, Swarm, swarm),
|
||||
(RemoveSwarmStacks, Swarm, swarm),
|
||||
(RemoveSwarmServices, Swarm, swarm),
|
||||
(CreateSwarmConfig, Swarm, swarm),
|
||||
(RotateSwarmConfig, Swarm, swarm),
|
||||
(RemoveSwarmConfigs, Swarm, swarm),
|
||||
(CreateSwarmSecret, Swarm, swarm),
|
||||
(RotateSwarmSecret, Swarm, swarm),
|
||||
(RemoveSwarmSecrets, Swarm, swarm),
|
||||
],
|
||||
batch_admin: [
|
||||
BatchRunProcedure,
|
||||
BatchRunAction,
|
||||
BatchRunBuild,
|
||||
BatchDeploy,
|
||||
BatchDestroyDeployment,
|
||||
BatchCloneRepo,
|
||||
BatchPullRepo,
|
||||
BatchBuildRepo,
|
||||
BatchDeployStack,
|
||||
BatchDeployStackIfChanged,
|
||||
BatchPullStack,
|
||||
BatchDestroyStack,
|
||||
],
|
||||
admin_only: [
|
||||
(ClearRepoCache, "Non admin user cannot clear repo cache"),
|
||||
(BackupCoreDatabase, "Non admin user cannot trigger core database backup"),
|
||||
(GlobalAutoUpdate, "Non admin user cannot trigger global auto update"),
|
||||
(RotateAllServerKeys, "Non admin user cannot trigger rotate all server keys"),
|
||||
(RotateCoreKeys, "Non admin user cannot trigger rotate core keys"),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ impl super::KomodoResource for Server {
|
||||
resource_type: ResourceTargetVariant::Server,
|
||||
info: ServerListItemInfo {
|
||||
state: status.as_ref().map(|s| s.state).unwrap_or_default(),
|
||||
err: status.as_ref().and_then(|s| s.err.clone()),
|
||||
region: server.config.region,
|
||||
address: optional_string(server.config.address),
|
||||
external_address: optional_string(
|
||||
|
||||
@@ -38,8 +38,6 @@ pub fn extract_services_into_res(
|
||||
"failed to parse service names from compose contents",
|
||||
)?;
|
||||
|
||||
let mut services = Vec::with_capacity(compose.services.capacity());
|
||||
|
||||
for (
|
||||
service_name,
|
||||
ComposeService {
|
||||
@@ -49,17 +47,29 @@ pub fn extract_services_into_res(
|
||||
},
|
||||
) in compose.services
|
||||
{
|
||||
let image = image.unwrap_or_default();
|
||||
services.push(StackServiceNames {
|
||||
container_name: container_name
|
||||
.unwrap_or_else(|| format!("{project_name}-{service_name}")),
|
||||
image_digest: service_image_digests.get(&service_name).cloned(),
|
||||
service_name,
|
||||
image,
|
||||
});
|
||||
if let Some(existing) =
|
||||
res.iter_mut().find(|s| s.service_name == service_name)
|
||||
{
|
||||
// Override any defined fields
|
||||
if let Some(container_name) = container_name {
|
||||
existing.container_name = container_name;
|
||||
}
|
||||
if let Some(image) = image {
|
||||
existing.image = image;
|
||||
}
|
||||
} else {
|
||||
res.push(StackServiceNames {
|
||||
container_name: container_name.unwrap_or_else(|| {
|
||||
format!("{project_name}-{service_name}")
|
||||
}),
|
||||
image_digest: service_image_digests
|
||||
.get(&service_name)
|
||||
.cloned(),
|
||||
image: image.unwrap_or_default(),
|
||||
service_name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
res.extend(services);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ pub struct CachedSwarmStatus {
|
||||
pub inspect: Option<SwarmInspectInfo>,
|
||||
pub lists: Option<SwarmLists>,
|
||||
/// Store the error in communicating with Swarm
|
||||
pub err: Option<String>,
|
||||
pub err: Option<mogh_error::Serror>,
|
||||
}
|
||||
|
||||
pub type SwarmStatusCache =
|
||||
|
||||
+21
-30
@@ -243,36 +243,27 @@ pub fn extend_resources(
|
||||
more: ResourcesToml,
|
||||
match_tags: &[String],
|
||||
) {
|
||||
resources
|
||||
.servers
|
||||
.extend(filter_by_tag(more.servers, match_tags));
|
||||
resources
|
||||
.stacks
|
||||
.extend(filter_by_tag(more.stacks, match_tags));
|
||||
resources
|
||||
.deployments
|
||||
.extend(filter_by_tag(more.deployments, match_tags));
|
||||
resources
|
||||
.builds
|
||||
.extend(filter_by_tag(more.builds, match_tags));
|
||||
resources
|
||||
.repos
|
||||
.extend(filter_by_tag(more.repos, match_tags));
|
||||
resources
|
||||
.procedures
|
||||
.extend(filter_by_tag(more.procedures, match_tags));
|
||||
resources
|
||||
.actions
|
||||
.extend(filter_by_tag(more.actions, match_tags));
|
||||
resources
|
||||
.alerters
|
||||
.extend(filter_by_tag(more.alerters, match_tags));
|
||||
resources
|
||||
.builders
|
||||
.extend(filter_by_tag(more.builders, match_tags));
|
||||
resources
|
||||
.resource_syncs
|
||||
.extend(filter_by_tag(more.resource_syncs, match_tags));
|
||||
macro_rules! extend_filtered {
|
||||
($($field:ident),* $(,)?) => {
|
||||
$(
|
||||
resources.$field.extend(filter_by_tag(more.$field, match_tags));
|
||||
)*
|
||||
};
|
||||
}
|
||||
// New resource types need to be added here manually.
|
||||
extend_filtered!(
|
||||
servers,
|
||||
swarms,
|
||||
stacks,
|
||||
deployments,
|
||||
builds,
|
||||
repos,
|
||||
procedures,
|
||||
actions,
|
||||
alerters,
|
||||
builders,
|
||||
resource_syncs,
|
||||
);
|
||||
resources.user_groups.extend(more.user_groups);
|
||||
resources.variables.extend(more.variables);
|
||||
}
|
||||
|
||||
+18
-136
@@ -1,29 +1,27 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use formatting::{Color, bold, colored, muted};
|
||||
use komodo_client::{
|
||||
api::execute::Execution,
|
||||
entities::{
|
||||
ResourceTargetVariant,
|
||||
action::Action,
|
||||
alerter::Alerter,
|
||||
build::Build,
|
||||
builder::{Builder, BuilderConfig},
|
||||
deployment::{Deployment, DeploymentImage},
|
||||
procedure::Procedure,
|
||||
repo::Repo,
|
||||
server::Server,
|
||||
stack::Stack,
|
||||
swarm::Swarm,
|
||||
sync::ResourceSync,
|
||||
tag::Tag,
|
||||
update::Log,
|
||||
user::sync_user,
|
||||
},
|
||||
use komodo_client::entities::{
|
||||
ResourceTargetVariant,
|
||||
action::Action,
|
||||
alerter::Alerter,
|
||||
build::Build,
|
||||
builder::{Builder, BuilderConfig},
|
||||
deployment::{Deployment, DeploymentImage},
|
||||
procedure::Procedure,
|
||||
repo::Repo,
|
||||
server::Server,
|
||||
stack::Stack,
|
||||
swarm::Swarm,
|
||||
sync::ResourceSync,
|
||||
tag::Tag,
|
||||
update::Log,
|
||||
user::sync_user,
|
||||
};
|
||||
use partial_derive2::{MaybeNone, PartialDiff};
|
||||
|
||||
use crate::{
|
||||
helpers::procedure::replace_procedure_stage_ids_with_names,
|
||||
resource::{KomodoResource, ResourceMetaUpdate},
|
||||
state::all_resources_cache,
|
||||
sync::{ToUpdateItem, execute::run_update_meta},
|
||||
@@ -341,123 +339,7 @@ impl ResourceSyncTrait for Procedure {
|
||||
mut original: Self::Config,
|
||||
update: Self::PartialConfig,
|
||||
) -> anyhow::Result<Self::ConfigDiff> {
|
||||
let all = all_resources_cache().load();
|
||||
for stage in &mut original.stages {
|
||||
for execution in &mut stage.executions {
|
||||
// Replaces an id field on config with the resource name from `all`.
|
||||
macro_rules! replace_id_with_name {
|
||||
($($Variant:ident => $field:ident, $collection:ident);* $(;)?) => {
|
||||
match &mut execution.execution {
|
||||
$(
|
||||
Execution::$Variant(config) => {
|
||||
config.$field = all
|
||||
.$collection
|
||||
.get(&config.$field)
|
||||
.map(|r| r.name.clone())
|
||||
.unwrap_or_default();
|
||||
}
|
||||
)*
|
||||
// SendAlert maps a Vec of alerter ids
|
||||
Execution::SendAlert(config) => {
|
||||
config.alerters = config
|
||||
.alerters
|
||||
.iter()
|
||||
.map(|alerter| {
|
||||
all
|
||||
.alerters
|
||||
.get(alerter)
|
||||
.map(|a| a.name.clone())
|
||||
.unwrap_or_default()
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
// No-op variants
|
||||
Execution::None(_)
|
||||
| Execution::BatchRunProcedure(_)
|
||||
| Execution::BatchRunAction(_)
|
||||
| Execution::BatchRunBuild(_)
|
||||
| Execution::BatchDeploy(_)
|
||||
| Execution::BatchDestroyDeployment(_)
|
||||
| Execution::BatchCloneRepo(_)
|
||||
| Execution::BatchPullRepo(_)
|
||||
| Execution::BatchBuildRepo(_)
|
||||
| Execution::BatchDeployStack(_)
|
||||
| Execution::BatchDeployStackIfChanged(_)
|
||||
| Execution::BatchPullStack(_)
|
||||
| Execution::BatchDestroyStack(_)
|
||||
| Execution::ClearRepoCache(_)
|
||||
| Execution::BackupCoreDatabase(_)
|
||||
| Execution::GlobalAutoUpdate(_)
|
||||
| Execution::RotateAllServerKeys(_)
|
||||
| Execution::RotateCoreKeys(_)
|
||||
| Execution::Sleep(_) => {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
replace_id_with_name!(
|
||||
RunProcedure => procedure, procedures;
|
||||
RunAction => action, actions;
|
||||
RunBuild => build, builds;
|
||||
CancelBuild => build, builds;
|
||||
Deploy => deployment, deployments;
|
||||
PullDeployment => deployment, deployments;
|
||||
StartDeployment => deployment, deployments;
|
||||
RestartDeployment => deployment, deployments;
|
||||
PauseDeployment => deployment, deployments;
|
||||
UnpauseDeployment => deployment, deployments;
|
||||
StopDeployment => deployment, deployments;
|
||||
DestroyDeployment => deployment, deployments;
|
||||
CloneRepo => repo, repos;
|
||||
PullRepo => repo, repos;
|
||||
BuildRepo => repo, repos;
|
||||
CancelRepoBuild => repo, repos;
|
||||
StartContainer => server, servers;
|
||||
RestartContainer => server, servers;
|
||||
PauseContainer => server, servers;
|
||||
UnpauseContainer => server, servers;
|
||||
StopContainer => server, servers;
|
||||
DestroyContainer => server, servers;
|
||||
StartAllContainers => server, servers;
|
||||
RestartAllContainers => server, servers;
|
||||
PauseAllContainers => server, servers;
|
||||
UnpauseAllContainers => server, servers;
|
||||
StopAllContainers => server, servers;
|
||||
PruneContainers => server, servers;
|
||||
DeleteNetwork => server, servers;
|
||||
PruneNetworks => server, servers;
|
||||
DeleteImage => server, servers;
|
||||
PruneImages => server, servers;
|
||||
DeleteVolume => server, servers;
|
||||
PruneVolumes => server, servers;
|
||||
PruneDockerBuilders => server, servers;
|
||||
PruneBuildx => server, servers;
|
||||
PruneSystem => server, servers;
|
||||
RunSync => sync, syncs;
|
||||
CommitSync => sync, syncs;
|
||||
DeployStack => stack, stacks;
|
||||
DeployStackIfChanged => stack, stacks;
|
||||
PullStack => stack, stacks;
|
||||
StartStack => stack, stacks;
|
||||
RestartStack => stack, stacks;
|
||||
PauseStack => stack, stacks;
|
||||
UnpauseStack => stack, stacks;
|
||||
StopStack => stack, stacks;
|
||||
DestroyStack => stack, stacks;
|
||||
RunStackService => stack, stacks;
|
||||
TestAlerter => alerter, alerters;
|
||||
RemoveSwarmNodes => swarm, swarms;
|
||||
RemoveSwarmStacks => swarm, swarms;
|
||||
RemoveSwarmServices => swarm, swarms;
|
||||
CreateSwarmConfig => swarm, swarms;
|
||||
RotateSwarmConfig => swarm, swarms;
|
||||
RemoveSwarmConfigs => swarm, swarms;
|
||||
CreateSwarmSecret => swarm, swarms;
|
||||
RotateSwarmSecret => swarm, swarms;
|
||||
RemoveSwarmSecrets => swarm, swarms;
|
||||
);
|
||||
}
|
||||
}
|
||||
replace_procedure_stage_ids_with_names(&mut original.stages);
|
||||
Ok(original.partial_diff(update))
|
||||
}
|
||||
}
|
||||
|
||||
+57
-519
@@ -2,28 +2,28 @@ use std::collections::HashMap;
|
||||
|
||||
use anyhow::Context;
|
||||
use indexmap::IndexMap;
|
||||
use komodo_client::{
|
||||
api::execute::Execution,
|
||||
entities::{
|
||||
action::Action,
|
||||
alerter::Alerter,
|
||||
build::Build,
|
||||
builder::{Builder, BuilderConfig, PartialBuilderConfig},
|
||||
deployment::{Deployment, DeploymentImage},
|
||||
procedure::Procedure,
|
||||
repo::Repo,
|
||||
resource::Resource,
|
||||
server::Server,
|
||||
stack::Stack,
|
||||
swarm::Swarm,
|
||||
sync::ResourceSync,
|
||||
tag::Tag,
|
||||
toml::ResourceToml,
|
||||
},
|
||||
use komodo_client::entities::{
|
||||
action::Action,
|
||||
alerter::Alerter,
|
||||
build::Build,
|
||||
builder::{Builder, BuilderConfig, PartialBuilderConfig},
|
||||
deployment::{Deployment, DeploymentImage},
|
||||
procedure::Procedure,
|
||||
repo::Repo,
|
||||
resource::Resource,
|
||||
server::Server,
|
||||
stack::Stack,
|
||||
swarm::Swarm,
|
||||
sync::ResourceSync,
|
||||
tag::Tag,
|
||||
toml::ResourceToml,
|
||||
};
|
||||
use partial_derive2::{MaybeNone, PartialDiff};
|
||||
|
||||
use crate::{resource::KomodoResource, state::all_resources_cache};
|
||||
use crate::{
|
||||
helpers::procedure::replace_procedure_stage_ids_with_names,
|
||||
resource::KomodoResource, state::all_resources_cache,
|
||||
};
|
||||
|
||||
pub const TOML_PRETTY_OPTIONS: toml_pretty::Options =
|
||||
toml_pretty::Options {
|
||||
@@ -458,510 +458,48 @@ impl ToToml for Builder {
|
||||
toml.push_str("\nparams = {}");
|
||||
}
|
||||
}
|
||||
|
||||
fn edit_config_object(
|
||||
_resource: &ResourceToml<Self::PartialConfig>,
|
||||
config: IndexMap<String, serde_json::Value>,
|
||||
) -> anyhow::Result<IndexMap<String, serde_json::Value>> {
|
||||
config
|
||||
.into_iter()
|
||||
.map(|(key, value)| {
|
||||
#[allow(clippy::single_match)]
|
||||
match key.as_str() {
|
||||
"params" => match value {
|
||||
serde_json::Value::Object(obj) => Ok((
|
||||
key,
|
||||
serde_json::Value::Object(
|
||||
obj
|
||||
.into_iter()
|
||||
.map(|(key, value)| {
|
||||
match key.as_str() {
|
||||
"server_id" => {
|
||||
return (String::from("server"), value);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
(key, value)
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
)),
|
||||
value => Ok((key, value)),
|
||||
},
|
||||
_ => Ok((key, value)),
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToToml for Procedure {
|
||||
fn replace_ids(resource: &mut Resource<Self::Config, Self::Info>) {
|
||||
let all = all_resources_cache().load();
|
||||
for stage in &mut resource.config.stages {
|
||||
for execution in &mut stage.executions {
|
||||
match &mut execution.execution {
|
||||
Execution::RunProcedure(exec) => exec.procedure.clone_from(
|
||||
all
|
||||
.procedures
|
||||
.get(&exec.procedure)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::BatchRunProcedure(_exec) => {}
|
||||
Execution::RunAction(exec) => exec.action.clone_from(
|
||||
all
|
||||
.actions
|
||||
.get(&exec.action)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::BatchRunAction(_exec) => {}
|
||||
Execution::RunBuild(exec) => exec.build.clone_from(
|
||||
all
|
||||
.builds
|
||||
.get(&exec.build)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::BatchRunBuild(_exec) => {}
|
||||
Execution::CancelBuild(exec) => exec.build.clone_from(
|
||||
all
|
||||
.builds
|
||||
.get(&exec.build)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::Deploy(exec) => exec.deployment.clone_from(
|
||||
all
|
||||
.deployments
|
||||
.get(&exec.deployment)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::BatchDeploy(_exec) => {}
|
||||
Execution::PullDeployment(exec) => {
|
||||
exec.deployment.clone_from(
|
||||
all
|
||||
.deployments
|
||||
.get(&exec.deployment)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::StartDeployment(exec) => {
|
||||
exec.deployment.clone_from(
|
||||
all
|
||||
.deployments
|
||||
.get(&exec.deployment)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::RestartDeployment(exec) => {
|
||||
exec.deployment.clone_from(
|
||||
all
|
||||
.deployments
|
||||
.get(&exec.deployment)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::PauseDeployment(exec) => {
|
||||
exec.deployment.clone_from(
|
||||
all
|
||||
.deployments
|
||||
.get(&exec.deployment)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::UnpauseDeployment(exec) => {
|
||||
exec.deployment.clone_from(
|
||||
all
|
||||
.deployments
|
||||
.get(&exec.deployment)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::StopDeployment(exec) => {
|
||||
exec.deployment.clone_from(
|
||||
all
|
||||
.deployments
|
||||
.get(&exec.deployment)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::DestroyDeployment(exec) => {
|
||||
exec.deployment.clone_from(
|
||||
all
|
||||
.deployments
|
||||
.get(&exec.deployment)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::BatchDestroyDeployment(_exec) => {}
|
||||
Execution::CloneRepo(exec) => exec.repo.clone_from(
|
||||
all
|
||||
.repos
|
||||
.get(&exec.repo)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::BatchCloneRepo(_exec) => {}
|
||||
Execution::PullRepo(exec) => exec.repo.clone_from(
|
||||
all
|
||||
.repos
|
||||
.get(&exec.repo)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::BatchPullRepo(_exec) => {}
|
||||
Execution::BuildRepo(exec) => exec.repo.clone_from(
|
||||
all
|
||||
.repos
|
||||
.get(&exec.repo)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::BatchBuildRepo(_exec) => {}
|
||||
Execution::CancelRepoBuild(exec) => exec.repo.clone_from(
|
||||
all
|
||||
.repos
|
||||
.get(&exec.repo)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::StartContainer(exec) => exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::RestartContainer(exec) => {
|
||||
exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::PauseContainer(exec) => exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::UnpauseContainer(exec) => {
|
||||
exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::StopContainer(exec) => exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::DestroyContainer(exec) => {
|
||||
exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::StartAllContainers(exec) => {
|
||||
exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::RestartAllContainers(exec) => {
|
||||
exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::PauseAllContainers(exec) => {
|
||||
exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::UnpauseAllContainers(exec) => {
|
||||
exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::StopAllContainers(exec) => {
|
||||
exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::PruneContainers(exec) => exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::DeleteNetwork(exec) => exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::PruneNetworks(exec) => exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::DeleteImage(exec) => exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::PruneImages(exec) => exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::DeleteVolume(exec) => exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::PruneVolumes(exec) => exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::PruneDockerBuilders(exec) => {
|
||||
exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::PruneBuildx(exec) => exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::PruneSystem(exec) => exec.server.clone_from(
|
||||
all
|
||||
.servers
|
||||
.get(&exec.server)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::RunSync(exec) => exec.sync.clone_from(
|
||||
all
|
||||
.syncs
|
||||
.get(&exec.sync)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::CommitSync(exec) => exec.sync.clone_from(
|
||||
all
|
||||
.syncs
|
||||
.get(&exec.sync)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::DeployStack(exec) => exec.stack.clone_from(
|
||||
all
|
||||
.stacks
|
||||
.get(&exec.stack)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::BatchDeployStack(_exec) => {}
|
||||
Execution::DeployStackIfChanged(exec) => {
|
||||
exec.stack.clone_from(
|
||||
all
|
||||
.stacks
|
||||
.get(&exec.stack)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::BatchDeployStackIfChanged(_exec) => {}
|
||||
Execution::PullStack(exec) => exec.stack.clone_from(
|
||||
all
|
||||
.stacks
|
||||
.get(&exec.stack)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::BatchPullStack(_exec) => {}
|
||||
Execution::StartStack(exec) => exec.stack.clone_from(
|
||||
all
|
||||
.stacks
|
||||
.get(&exec.stack)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::RestartStack(exec) => exec.stack.clone_from(
|
||||
all
|
||||
.stacks
|
||||
.get(&exec.stack)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::RunStackService(exec) => exec.stack.clone_from(
|
||||
all
|
||||
.stacks
|
||||
.get(&exec.stack)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::PauseStack(exec) => exec.stack.clone_from(
|
||||
all
|
||||
.stacks
|
||||
.get(&exec.stack)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::UnpauseStack(exec) => exec.stack.clone_from(
|
||||
all
|
||||
.stacks
|
||||
.get(&exec.stack)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::StopStack(exec) => exec.stack.clone_from(
|
||||
all
|
||||
.stacks
|
||||
.get(&exec.stack)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::DestroyStack(exec) => exec.stack.clone_from(
|
||||
all
|
||||
.stacks
|
||||
.get(&exec.stack)
|
||||
.map(|r| &r.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::BatchDestroyStack(_exec) => {}
|
||||
Execution::TestAlerter(exec) => exec.alerter.clone_from(
|
||||
all
|
||||
.alerters
|
||||
.get(&exec.alerter)
|
||||
.map(|a| &a.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::SendAlert(exec) => {
|
||||
exec.alerters.iter_mut().for_each(|a| {
|
||||
a.clone_from(
|
||||
all
|
||||
.alerters
|
||||
.get(a)
|
||||
.map(|a| &a.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
})
|
||||
}
|
||||
Execution::RemoveSwarmNodes(exec) => exec.swarm.clone_from(
|
||||
all
|
||||
.swarms
|
||||
.get(&exec.swarm)
|
||||
.map(|a| &a.name)
|
||||
.unwrap_or(&String::new()),
|
||||
),
|
||||
Execution::RemoveSwarmStacks(exec) => {
|
||||
exec.swarm.clone_from(
|
||||
all
|
||||
.swarms
|
||||
.get(&exec.swarm)
|
||||
.map(|a| &a.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::RemoveSwarmServices(exec) => {
|
||||
exec.swarm.clone_from(
|
||||
all
|
||||
.swarms
|
||||
.get(&exec.swarm)
|
||||
.map(|a| &a.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::CreateSwarmConfig(exec) => {
|
||||
exec.swarm.clone_from(
|
||||
all
|
||||
.swarms
|
||||
.get(&exec.swarm)
|
||||
.map(|a| &a.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::RotateSwarmConfig(exec) => {
|
||||
exec.swarm.clone_from(
|
||||
all
|
||||
.swarms
|
||||
.get(&exec.swarm)
|
||||
.map(|a| &a.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::RemoveSwarmConfigs(exec) => {
|
||||
exec.swarm.clone_from(
|
||||
all
|
||||
.swarms
|
||||
.get(&exec.swarm)
|
||||
.map(|a| &a.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::CreateSwarmSecret(exec) => {
|
||||
exec.swarm.clone_from(
|
||||
all
|
||||
.swarms
|
||||
.get(&exec.swarm)
|
||||
.map(|a| &a.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::RotateSwarmSecret(exec) => {
|
||||
exec.swarm.clone_from(
|
||||
all
|
||||
.swarms
|
||||
.get(&exec.swarm)
|
||||
.map(|a| &a.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::RemoveSwarmSecrets(exec) => {
|
||||
exec.swarm.clone_from(
|
||||
all
|
||||
.swarms
|
||||
.get(&exec.swarm)
|
||||
.map(|a| &a.name)
|
||||
.unwrap_or(&String::new()),
|
||||
)
|
||||
}
|
||||
Execution::None(_)
|
||||
| Execution::Sleep(_)
|
||||
| Execution::ClearRepoCache(_)
|
||||
| Execution::BackupCoreDatabase(_)
|
||||
| Execution::GlobalAutoUpdate(_)
|
||||
| Execution::RotateAllServerKeys(_)
|
||||
| Execution::RotateCoreKeys(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
replace_procedure_stage_ids_with_names(
|
||||
&mut resource.config.stages,
|
||||
);
|
||||
}
|
||||
|
||||
fn push_to_toml_string(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## All in one, multi stage compile + runtime Docker build for your architecture.
|
||||
|
||||
FROM rust:1.94.0-trixie AS builder
|
||||
FROM rust:1.95.0-trixie AS builder
|
||||
RUN cargo install cargo-strip
|
||||
|
||||
WORKDIR /builder
|
||||
@@ -9,6 +9,7 @@ COPY ./lib ./lib
|
||||
COPY ./client/core/rs ./client/core/rs
|
||||
COPY ./client/periphery ./client/periphery
|
||||
COPY ./bin/periphery ./bin/periphery
|
||||
COPY ./xtask ./xtask
|
||||
|
||||
# Compile app
|
||||
RUN cargo build -p komodo_periphery --release && cargo strip
|
||||
|
||||
@@ -271,7 +271,11 @@ impl Resolve<crate::api::Args> for build::Build {
|
||||
"Pre Build",
|
||||
pre_build_path.as_path(),
|
||||
&pre_build.command,
|
||||
KomodoCommandMode::Multiline,
|
||||
if pre_build.shell_mode {
|
||||
KomodoCommandMode::Shell
|
||||
} else {
|
||||
KomodoCommandMode::Multiline
|
||||
},
|
||||
&replacers,
|
||||
)
|
||||
.instrument(span)
|
||||
|
||||
@@ -490,7 +490,11 @@ impl Resolve<crate::api::Args> for ComposeUp {
|
||||
"Pre Deploy",
|
||||
pre_deploy_path.as_path(),
|
||||
&stack.config.pre_deploy.command,
|
||||
KomodoCommandMode::Multiline,
|
||||
if stack.config.pre_deploy.shell_mode {
|
||||
KomodoCommandMode::Shell
|
||||
} else {
|
||||
KomodoCommandMode::Multiline
|
||||
},
|
||||
&replacers,
|
||||
)
|
||||
.instrument(span)
|
||||
@@ -760,7 +764,11 @@ impl Resolve<crate::api::Args> for ComposeUp {
|
||||
"Post Deploy",
|
||||
post_deploy_path.as_path(),
|
||||
&stack.config.post_deploy.command,
|
||||
KomodoCommandMode::Multiline,
|
||||
if stack.config.post_deploy.shell_mode {
|
||||
KomodoCommandMode::Shell
|
||||
} else {
|
||||
KomodoCommandMode::Multiline
|
||||
},
|
||||
&replacers,
|
||||
)
|
||||
.instrument(span)
|
||||
|
||||
@@ -99,13 +99,9 @@ impl Resolve<crate::api::Args> for UpdateSwarmNode {
|
||||
}
|
||||
|
||||
if let Some(label_add) = self.label_add {
|
||||
for (key, value) in label_add {
|
||||
for key_value in label_add {
|
||||
command += " --label-add ";
|
||||
command += &key;
|
||||
if let Some(value) = value {
|
||||
command += "=";
|
||||
command += &value;
|
||||
}
|
||||
command += &key_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,10 @@ use komodo_client::{
|
||||
entities::{
|
||||
all_logs_success,
|
||||
docker::stack::SwarmStack,
|
||||
stack::{ComposeFile, ComposeService, StackServiceNames},
|
||||
stack::{
|
||||
AdditionalEnvFile, ComposeFile, ComposeService,
|
||||
StackServiceNames,
|
||||
},
|
||||
update::Log,
|
||||
},
|
||||
parsers::parse_multiline_command,
|
||||
@@ -139,7 +142,7 @@ impl Resolve<crate::api::Args> for DeploySwarmStack {
|
||||
replacers.extend(interpolator.secret_replacers);
|
||||
|
||||
// Env files are not supported by docker stack deploy so are ignored.
|
||||
let (run_directory, _) = match write_stack(
|
||||
let (run_directory, env_file_path) = match write_stack(
|
||||
&stack,
|
||||
repo.as_ref(),
|
||||
git_token,
|
||||
@@ -218,10 +221,16 @@ impl Resolve<crate::api::Args> for DeploySwarmStack {
|
||||
&stack.config.compose_cmd_wrapper_include
|
||||
};
|
||||
|
||||
let env_file_args = env_file_args(
|
||||
env_file_path,
|
||||
&stack.config.additional_env_files,
|
||||
)?;
|
||||
|
||||
// Uses 'docker stack config' command to extract services (including image)
|
||||
// after performing interpolation
|
||||
{
|
||||
let command = format!("docker stack config -c {file_args}",);
|
||||
let command =
|
||||
format!("{env_file_args}docker stack config -c {file_args}",);
|
||||
let (command, wrapped) = match maybe_wrap_command(
|
||||
command,
|
||||
&compose_cmd_wrapper,
|
||||
@@ -234,7 +243,7 @@ impl Resolve<crate::api::Args> for DeploySwarmStack {
|
||||
return Ok(res);
|
||||
}
|
||||
};
|
||||
let mode = if wrapped {
|
||||
let mode = if wrapped || !env_file_args.is_empty() {
|
||||
KomodoCommandMode::Shell
|
||||
} else {
|
||||
KomodoCommandMode::Standard
|
||||
@@ -288,8 +297,9 @@ impl Resolve<crate::api::Args> for DeploySwarmStack {
|
||||
}
|
||||
|
||||
// Run stack deploy
|
||||
let mut command =
|
||||
format!("docker stack deploy --detach=false -c {file_args}");
|
||||
let mut command = format!(
|
||||
"{env_file_args}docker stack deploy --detach=true -c {file_args}"
|
||||
);
|
||||
if use_with_registry_auth {
|
||||
command += " --with-registry-auth";
|
||||
}
|
||||
@@ -349,6 +359,43 @@ impl Resolve<crate::api::Args> for DeploySwarmStack {
|
||||
}
|
||||
}
|
||||
|
||||
/// Prefix docker stack deploy command.
|
||||
///
|
||||
/// Produces either
|
||||
/// - Empty string (no env files defined)
|
||||
/// - 'set -a && . .env1 && . .env2 && '
|
||||
fn env_file_args(
|
||||
env_file_path: Option<&str>,
|
||||
additional_env_files: &[AdditionalEnvFile],
|
||||
) -> anyhow::Result<String> {
|
||||
let mut res = String::new();
|
||||
|
||||
// Add additional env files (except komodo's own, which comes last)
|
||||
for file in additional_env_files
|
||||
.iter()
|
||||
.filter(|f| env_file_path != Some(f.path.as_str()))
|
||||
{
|
||||
let path = &file.path;
|
||||
write!(res, ". {path} && ").with_context(|| {
|
||||
format!("Failed to write env source arg for {path}")
|
||||
})?;
|
||||
}
|
||||
|
||||
// Add komodo's env file last for highest priority
|
||||
if let Some(file) = env_file_path {
|
||||
write!(res, ". {file} && ").with_context(|| {
|
||||
format!("Failed to write env source arg for {file}")
|
||||
})?;
|
||||
}
|
||||
|
||||
if !res.is_empty() {
|
||||
// Add 'set -a' so vars are auto exported to child 'docker stack' process.
|
||||
Ok(format!("set -a && {res}"))
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument("RemoveStack", skip(res))]
|
||||
async fn remove_stack(
|
||||
stack: &str,
|
||||
|
||||
@@ -144,6 +144,9 @@ pub fn periphery_config() -> &'static PeripheryConfig {
|
||||
ansi: env
|
||||
.periphery_logging_ansi
|
||||
.unwrap_or(config.logging.ansi),
|
||||
timestamps: env
|
||||
.periphery_logging_timestamps
|
||||
.unwrap_or(config.logging.timestamps),
|
||||
otlp_endpoint: env
|
||||
.periphery_logging_otlp_endpoint
|
||||
.unwrap_or(config.logging.otlp_endpoint),
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::state::container_stats;
|
||||
|
||||
use super::{
|
||||
DockerClient, convert_health_config, convert_mount,
|
||||
convert_mount_point_type, convert_resources_ulimits,
|
||||
convert_resources_ulimits,
|
||||
};
|
||||
|
||||
impl DockerClient {
|
||||
@@ -360,10 +360,7 @@ impl DockerClient {
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|mount| MountPoint {
|
||||
typ: mount
|
||||
.typ
|
||||
.map(convert_mount_point_type)
|
||||
.unwrap_or_default(),
|
||||
typ: mount.typ,
|
||||
name: mount.name,
|
||||
source: mount.source,
|
||||
destination: mount.destination,
|
||||
@@ -482,6 +479,9 @@ fn convert_summary_container_state(
|
||||
bollard::config::ContainerSummaryStateEnum::EXITED => {
|
||||
ContainerStateStatusEnum::Exited
|
||||
}
|
||||
bollard::config::ContainerSummaryStateEnum::STOPPING => {
|
||||
ContainerStateStatusEnum::Stopping
|
||||
}
|
||||
bollard::config::ContainerSummaryStateEnum::REMOVING => {
|
||||
ContainerStateStatusEnum::Removing
|
||||
}
|
||||
@@ -516,6 +516,9 @@ fn convert_container_state_status(
|
||||
bollard::config::ContainerStateStatusEnum::REMOVING => {
|
||||
ContainerStateStatusEnum::Removing
|
||||
}
|
||||
bollard::config::ContainerStateStatusEnum::STOPPING => {
|
||||
ContainerStateStatusEnum::Stopping
|
||||
}
|
||||
bollard::config::ContainerStateStatusEnum::DEAD => {
|
||||
ContainerStateStatusEnum::Dead
|
||||
}
|
||||
|
||||
@@ -150,17 +150,14 @@ fn convert_mount(mount: bollard::models::Mount) -> Mount {
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_mount_type(
|
||||
typ: bollard::config::MountTypeEnum,
|
||||
) -> MountTypeEnum {
|
||||
fn convert_mount_type(typ: bollard::config::MountType) -> MountType {
|
||||
match typ {
|
||||
bollard::config::MountTypeEnum::EMPTY => MountTypeEnum::Empty,
|
||||
bollard::config::MountTypeEnum::BIND => MountTypeEnum::Bind,
|
||||
bollard::config::MountTypeEnum::VOLUME => MountTypeEnum::Volume,
|
||||
bollard::config::MountTypeEnum::IMAGE => MountTypeEnum::Image,
|
||||
bollard::config::MountTypeEnum::TMPFS => MountTypeEnum::Tmpfs,
|
||||
bollard::config::MountTypeEnum::NPIPE => MountTypeEnum::Npipe,
|
||||
bollard::config::MountTypeEnum::CLUSTER => MountTypeEnum::Cluster,
|
||||
bollard::config::MountType::BIND => MountType::Bind,
|
||||
bollard::config::MountType::VOLUME => MountType::Volume,
|
||||
bollard::config::MountType::IMAGE => MountType::Image,
|
||||
bollard::config::MountType::TMPFS => MountType::Tmpfs,
|
||||
bollard::config::MountType::NPIPE => MountType::Npipe,
|
||||
bollard::config::MountType::CLUSTER => MountType::Cluster,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,32 +189,6 @@ fn convert_mount_propogation(
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_mount_point_type(
|
||||
typ: bollard::config::MountPointTypeEnum,
|
||||
) -> MountTypeEnum {
|
||||
match typ {
|
||||
bollard::config::MountPointTypeEnum::EMPTY => {
|
||||
MountTypeEnum::Empty
|
||||
}
|
||||
bollard::config::MountPointTypeEnum::BIND => MountTypeEnum::Bind,
|
||||
bollard::config::MountPointTypeEnum::VOLUME => {
|
||||
MountTypeEnum::Volume
|
||||
}
|
||||
bollard::config::MountPointTypeEnum::IMAGE => {
|
||||
MountTypeEnum::Image
|
||||
}
|
||||
bollard::config::MountPointTypeEnum::TMPFS => {
|
||||
MountTypeEnum::Tmpfs
|
||||
}
|
||||
bollard::config::MountPointTypeEnum::NPIPE => {
|
||||
MountTypeEnum::Npipe
|
||||
}
|
||||
bollard::config::MountPointTypeEnum::CLUSTER => {
|
||||
MountTypeEnum::Cluster
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_health_config(
|
||||
config: bollard::models::HealthConfig,
|
||||
) -> HealthConfig {
|
||||
|
||||
@@ -51,24 +51,24 @@ impl DockerClient {
|
||||
fn convert_node_list_item(
|
||||
node: bollard::models::Node,
|
||||
) -> SwarmNodeListItem {
|
||||
let (name, role, availability) = node
|
||||
let (name, role, availability, labels) = node
|
||||
.spec
|
||||
.map(|spec| {
|
||||
(
|
||||
spec.name,
|
||||
spec.role.map(convert_role),
|
||||
spec.availability.map(convert_availability),
|
||||
spec.labels,
|
||||
)
|
||||
})
|
||||
.unwrap_or_default();
|
||||
SwarmNodeListItem {
|
||||
id: node.id,
|
||||
name,
|
||||
hostname: node.description.and_then(|d| d.hostname),
|
||||
role,
|
||||
availability,
|
||||
hostname: node
|
||||
.description
|
||||
.and_then(|description| description.hostname),
|
||||
labels,
|
||||
state: node
|
||||
.status
|
||||
.and_then(|status| status.state.map(convert_state)),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use bollard::query_parameters::ListVolumesOptions;
|
||||
use komodo_client::entities::docker::{
|
||||
PortBinding, container::ContainerListItem, volume::*,
|
||||
Topology, container::ContainerListItem, volume::*,
|
||||
};
|
||||
|
||||
use crate::docker::DockerClient;
|
||||
@@ -108,8 +108,8 @@ impl DockerClient {
|
||||
}).collect(),
|
||||
accessibility_requirements: mode
|
||||
.accessibility_requirements.map(|req| ClusterVolumeSpecAccessModeAccessibilityRequirements {
|
||||
requisite: req.requisite.unwrap_or_default().into_iter().map(|map| map.into_iter().map(|(k, v)| (k, v.unwrap_or_default().into_iter().map(|p| PortBinding { host_ip: p.host_ip, host_port: p.host_port }).collect())).collect()).collect(),
|
||||
preferred: req.preferred.unwrap_or_default().into_iter().map(|map| map.into_iter().map(|(k, v)| (k, v.unwrap_or_default().into_iter().map(|p| PortBinding { host_ip: p.host_ip, host_port: p.host_port }).collect())).collect()).collect(),
|
||||
requisite: req.requisite.map(|v| v.into_iter().map(|t| Topology { segments: t.segments }).collect()),
|
||||
preferred: req.preferred.map(|v| v.into_iter().map(|t| Topology { segments: t.segments }).collect()),
|
||||
}),
|
||||
capacity_range: mode.capacity_range.map(|range| ClusterVolumeSpecAccessModeCapacityRange {
|
||||
required_bytes: range.required_bytes,
|
||||
@@ -128,7 +128,7 @@ impl DockerClient {
|
||||
capacity_bytes: info.capacity_bytes,
|
||||
volume_context: info.volume_context.unwrap_or_default(),
|
||||
volume_id: info.volume_id,
|
||||
accessible_topology: info.accessible_topology.unwrap_or_default().into_iter().map(|map| map.into_iter().map(|(k, v)| (k, v.unwrap_or_default().into_iter().map(|p| PortBinding { host_ip: p.host_ip, host_port: p.host_port }).collect())).collect()).collect(),
|
||||
accessible_topology: info.accessible_topology.map(|v| v.into_iter().map(|t| Topology { segments: t.segments }).collect()),
|
||||
}),
|
||||
publish_status: volume
|
||||
.publish_status
|
||||
|
||||
@@ -189,7 +189,11 @@ pub async fn handle_post_repo_execution(
|
||||
"On Clone",
|
||||
path.as_path(),
|
||||
on_clone.command,
|
||||
KomodoCommandMode::Multiline,
|
||||
if on_clone.shell_mode {
|
||||
KomodoCommandMode::Shell
|
||||
} else {
|
||||
KomodoCommandMode::Multiline
|
||||
},
|
||||
&replacers,
|
||||
)
|
||||
.await
|
||||
@@ -214,7 +218,11 @@ pub async fn handle_post_repo_execution(
|
||||
"On Pull",
|
||||
path.as_path(),
|
||||
on_pull.command,
|
||||
KomodoCommandMode::Multiline,
|
||||
if on_pull.shell_mode {
|
||||
KomodoCommandMode::Shell
|
||||
} else {
|
||||
KomodoCommandMode::Multiline
|
||||
},
|
||||
&replacers,
|
||||
)
|
||||
.await
|
||||
@@ -276,37 +284,31 @@ pub fn registry_token(
|
||||
// Public IP over DNS
|
||||
// ====================
|
||||
|
||||
type OpenDNSResolver = hickory_resolver::Resolver<
|
||||
hickory_resolver::name_server::TokioConnectionProvider,
|
||||
>;
|
||||
type OpenDNSResolver = hickory_resolver::TokioResolver;
|
||||
|
||||
fn opendns_resolver() -> &'static OpenDNSResolver {
|
||||
static OPENDNS_RESOLVER: OnceLock<OpenDNSResolver> =
|
||||
OnceLock::new();
|
||||
OPENDNS_RESOLVER.get_or_init(|| {
|
||||
// OpenDNS resolver ipv4s
|
||||
let ips = [
|
||||
// OpenDNS resolver ipv4s.
|
||||
let name_servers = [
|
||||
IpAddr::from_str("208.67.220.220").unwrap(),
|
||||
IpAddr::from_str("208.67.222.222").unwrap(),
|
||||
];
|
||||
|
||||
// trust_negative_responses=true means NXDOMAIN/empty NOERROR from an
|
||||
// authoritative upstream won’t be retried on other servers.
|
||||
let ns =
|
||||
hickory_resolver::config::NameServerConfigGroup::from_ips_clear(
|
||||
&ips, 53, true,
|
||||
);
|
||||
]
|
||||
.into_iter()
|
||||
.map(hickory_resolver::config::NameServerConfig::udp_and_tcp)
|
||||
.collect();
|
||||
|
||||
hickory_resolver::Resolver::builder_with_config(
|
||||
hickory_resolver::config::ResolverConfig::from_parts(
|
||||
None,
|
||||
vec![],
|
||||
ns,
|
||||
),
|
||||
hickory_resolver::name_server::TokioConnectionProvider::default(
|
||||
name_servers,
|
||||
),
|
||||
hickory_resolver::net::runtime::TokioRuntimeProvider::default(),
|
||||
)
|
||||
.build()
|
||||
.expect("Failed to build OpenDNS resolver")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -319,7 +321,7 @@ pub async fn resolve_host_public_ip() -> anyhow::Result<String> {
|
||||
.context(
|
||||
"Failed to query OpenDNS resolvers for host public IP",
|
||||
)?
|
||||
.into_iter()
|
||||
.iter()
|
||||
.map(|ip| ip.to_string())
|
||||
.next()
|
||||
.context("OpenDNS call for public IP didn't return anything")
|
||||
|
||||
@@ -14,6 +14,7 @@ repository.workspace = true
|
||||
blocking = ["reqwest/blocking"]
|
||||
mongo = ["dep:mongo_indexed"]
|
||||
utoipa = ["dep:utoipa", "mogh_auth_client/utoipa", "mogh_error/utoipa"]
|
||||
schemars = ["dep:schemars"]
|
||||
logger = ["dep:mogh_logger"]
|
||||
cli = ["logger", "dep:mogh_pki",]
|
||||
core = ["mongo", "utoipa", "logger", "dep:mogh_server"]
|
||||
@@ -33,6 +34,7 @@ partial_derive2.workspace = true
|
||||
mogh_resolver.workspace = true
|
||||
# external
|
||||
ipnetwork = { workspace = true, optional = true }
|
||||
schemars = { workspace = true, optional = true }
|
||||
utoipa = { workspace = true, optional = true }
|
||||
tokio-tungstenite.workspace = true
|
||||
derive_builder.workspace = true
|
||||
|
||||
@@ -28,6 +28,7 @@ pub fn run_action() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -68,6 +69,7 @@ pub fn batch_run_action() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(BatchExecutionResponse)]
|
||||
#[error(mogh_error::Error)]
|
||||
|
||||
@@ -27,6 +27,7 @@ pub fn test_alerter() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -56,6 +57,7 @@ pub fn send_alert() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
|
||||
@@ -39,6 +39,7 @@ pub fn run_build() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -67,6 +68,7 @@ pub fn batch_run_build() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(BatchExecutionResponse)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -106,6 +108,7 @@ pub fn cancel_build() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
|
||||
@@ -34,6 +34,7 @@ pub fn deploy() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -68,6 +69,7 @@ pub fn batch_deploy() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(BatchExecutionResponse)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -105,6 +107,7 @@ pub fn pull_deployment() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -135,6 +138,7 @@ pub fn start_deployment() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -165,6 +169,7 @@ pub fn restart_deployment() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -195,6 +200,7 @@ pub fn pause_deployment() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -228,6 +234,7 @@ pub fn unpause_deployment() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -258,6 +265,7 @@ pub fn stop_deployment() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -295,6 +303,7 @@ pub fn destroy_deployment() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -327,6 +336,7 @@ pub fn batch_destroy_deployment() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(BatchExecutionResponse)]
|
||||
#[error(mogh_error::Error)]
|
||||
|
||||
@@ -28,6 +28,7 @@ pub fn clear_repo_cache() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -60,6 +61,7 @@ pub fn backup_core_database() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -92,6 +94,7 @@ pub fn global_auto_update() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -125,6 +128,7 @@ pub fn rotate_all_server_keys() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -155,6 +159,7 @@ pub fn rotate_core_keys() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
|
||||
@@ -78,6 +78,7 @@ pub trait KomodoExecuteRequest: HasResponse {}
|
||||
utoipa::ToSchema
|
||||
))
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(tag = "type", content = "params")]
|
||||
pub enum Execution {
|
||||
/// The "null" execution. Does nothing.
|
||||
@@ -183,6 +184,7 @@ pub enum Execution {
|
||||
|
||||
// SWARM
|
||||
RemoveSwarmNodes(RemoveSwarmNodes),
|
||||
UpdateSwarmNode(UpdateSwarmNode),
|
||||
RemoveSwarmStacks(RemoveSwarmStacks),
|
||||
RemoveSwarmServices(RemoveSwarmServices),
|
||||
CreateSwarmConfig(CreateSwarmConfig),
|
||||
@@ -214,6 +216,7 @@ pub enum Execution {
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Parser)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct Sleep {
|
||||
#[serde(default)]
|
||||
pub duration_ms: I64,
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::api::execute;
|
||||
paths(
|
||||
// swarm
|
||||
execute::remove_swarm_nodes,
|
||||
execute::update_swarm_node,
|
||||
execute::remove_swarm_stacks,
|
||||
execute::remove_swarm_services,
|
||||
execute::create_swarm_config,
|
||||
|
||||
@@ -27,6 +27,7 @@ pub fn run_procedure() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -55,6 +56,7 @@ pub fn batch_run_procedure() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(BatchExecutionResponse)]
|
||||
#[error(mogh_error::Error)]
|
||||
|
||||
@@ -35,6 +35,7 @@ pub fn clone_repo() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -63,6 +64,7 @@ pub fn batch_clone_repo() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(BatchExecutionResponse)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -105,6 +107,7 @@ pub fn pull_repo() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -133,6 +136,7 @@ pub fn batch_pull_repo() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(BatchExecutionResponse)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -179,6 +183,7 @@ pub fn build_repo() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -207,6 +212,7 @@ pub fn batch_build_repo() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(BatchExecutionResponse)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -246,6 +252,7 @@ pub fn cancel_repo_build() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
|
||||
@@ -31,6 +31,7 @@ pub fn start_container() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -63,6 +64,7 @@ pub fn restart_container() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -95,6 +97,7 @@ pub fn pause_container() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -129,6 +132,7 @@ pub fn unpause_container() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -161,6 +165,7 @@ pub fn stop_container() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -198,6 +203,7 @@ pub fn destroy_container() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -232,6 +238,7 @@ pub fn start_all_containers() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -260,6 +267,7 @@ pub fn restart_all_containers() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -288,6 +296,7 @@ pub fn pause_all_containers() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -316,6 +325,7 @@ pub fn unpause_all_containers() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -344,6 +354,7 @@ pub fn stop_all_containers() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -374,6 +385,7 @@ pub fn prune_containers() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -405,6 +417,7 @@ pub fn delete_network() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -437,6 +450,7 @@ pub fn prune_networks() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -466,6 +480,7 @@ pub fn delete_image() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -498,6 +513,7 @@ pub fn prune_images() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -527,6 +543,7 @@ pub fn delete_volume() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -559,6 +576,7 @@ pub fn prune_volumes() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -589,6 +607,7 @@ pub fn prune_docker_builders() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -619,6 +638,7 @@ pub fn prune_buildx() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -649,6 +669,7 @@ pub fn prune_system() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
|
||||
@@ -27,6 +27,7 @@ pub fn deploy_stack() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -64,6 +65,7 @@ pub fn batch_deploy_stack() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(BatchExecutionResponse)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -103,6 +105,7 @@ pub fn deploy_stack_if_changed() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -134,6 +137,7 @@ pub fn batch_deploy_stack_if_changed() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(BatchExecutionResponse)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -171,6 +175,7 @@ pub fn pull_stack() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -203,6 +208,7 @@ pub fn batch_pull_stack() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(BatchExecutionResponse)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -240,6 +246,7 @@ pub fn start_stack() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -272,6 +279,7 @@ pub fn restart_stack() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -304,6 +312,7 @@ pub fn pause_stack() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -338,6 +347,7 @@ pub fn unpause_stack() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -370,6 +380,7 @@ pub fn stop_stack() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -404,6 +415,7 @@ pub fn destroy_stack() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -441,6 +453,7 @@ pub fn run_stack_service() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -505,6 +518,7 @@ pub fn batch_destroy_stack() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(BatchExecutionResponse)]
|
||||
#[error(mogh_error::Error)]
|
||||
|
||||
@@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::{
|
||||
api::execute::KomodoExecuteRequest, entities::update::Update,
|
||||
api::execute::KomodoExecuteRequest,
|
||||
entities::{
|
||||
docker::node::{NodeSpecAvailabilityEnum, NodeSpecRoleEnum},
|
||||
update::Update,
|
||||
},
|
||||
};
|
||||
|
||||
// ========
|
||||
@@ -31,6 +35,7 @@ pub fn remove_swarm_nodes() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -45,6 +50,49 @@ pub struct RemoveSwarmNodes {
|
||||
pub force: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "utoipa")]
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/UpdateSwarmNode",
|
||||
description = "Update a swarm node's availability, labels, and role.",
|
||||
request_body(content = UpdateSwarmNode),
|
||||
responses(
|
||||
(status = 200, description = "The update", body = Update),
|
||||
),
|
||||
)]
|
||||
pub fn update_swarm_node() {}
|
||||
|
||||
/// `docker node update [OPTIONS] NODE`
|
||||
///
|
||||
/// https://docs.docker.com/reference/cli/docker/node/update/
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
pub struct UpdateSwarmNode {
|
||||
/// Name or id
|
||||
pub swarm: String,
|
||||
/// Node hostname or id
|
||||
pub node: String,
|
||||
/// Update the node's availability: 'active', 'pause', or 'drain'
|
||||
#[arg(long, short = 'a')]
|
||||
pub availability: Option<NodeSpecAvailabilityEnum>,
|
||||
/// Add labels to node (`key=value`).
|
||||
#[arg(long, short = 'l')]
|
||||
pub label_add: Option<Vec<String>>,
|
||||
/// Add labels to node (`key=value`). (alias: `lr`)
|
||||
#[arg(long, alias = "lr")]
|
||||
pub label_rm: Option<Vec<String>>,
|
||||
/// Update the node's role: 'worker' or 'manager'
|
||||
#[arg(long, short = 'r')]
|
||||
pub role: Option<NodeSpecRoleEnum>,
|
||||
}
|
||||
|
||||
// =========
|
||||
// = Stack =
|
||||
// =========
|
||||
@@ -69,6 +117,7 @@ pub fn remove_swarm_stacks() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -111,6 +160,7 @@ pub fn remove_swarm_services() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -145,6 +195,7 @@ pub fn create_swarm_config() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -194,6 +245,7 @@ pub fn rotate_swarm_config() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -228,6 +280,7 @@ pub fn remove_swarm_configs() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -262,6 +315,7 @@ pub fn create_swarm_secret() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -313,6 +367,7 @@ pub fn rotate_swarm_secret() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
@@ -347,6 +402,7 @@ pub fn remove_swarm_secrets() {}
|
||||
Serialize, Deserialize, Debug, Clone, PartialEq, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
|
||||
@@ -27,6 +27,7 @@ pub fn run_sync() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoExecuteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
|
||||
@@ -144,7 +144,7 @@ pub struct GetCoreInfoResponse {
|
||||
pub enable_fancy_toml: bool,
|
||||
/// TZ identifier Core is using, if manually set.
|
||||
pub timezone: String,
|
||||
/// Default public key allowing this Core to authenticate to Periphery agents.
|
||||
/// Public key for Core / Periphery authentication.
|
||||
pub public_key: String,
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ pub struct CreateOnboardingKey {
|
||||
#[serde(default)]
|
||||
pub expires: I64,
|
||||
/// Optionally specify an existing private key, otherwise
|
||||
/// generate fresh key.
|
||||
/// generate fresh key. This key is not stored directly,
|
||||
/// only the public key.
|
||||
pub private_key: Option<String>,
|
||||
/// Default tags to apply to Servers created using this key.
|
||||
#[serde(default)]
|
||||
|
||||
@@ -242,6 +242,7 @@ pub fn commit_sync() {}
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Resolve, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[empty_traits(KomodoWriteRequest)]
|
||||
#[response(Update)]
|
||||
#[error(mogh_error::Error)]
|
||||
|
||||
@@ -81,6 +81,10 @@ pub type _PartialActionConfig = PartialActionConfig;
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
pub struct ActionConfig {
|
||||
|
||||
@@ -74,6 +74,10 @@ pub struct Alert {
|
||||
utoipa::ToSchema
|
||||
))
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
strum_discriminants(derive(schemars::JsonSchema))
|
||||
)]
|
||||
#[serde(tag = "type", content = "data")]
|
||||
pub enum AlertData {
|
||||
/// A null alert
|
||||
@@ -95,7 +99,7 @@ pub enum AlertData {
|
||||
/// The name of the swarm
|
||||
name: String,
|
||||
/// The error data
|
||||
err: Option<String>,
|
||||
err: Option<_Serror>,
|
||||
},
|
||||
|
||||
/// A server could not be reached.
|
||||
@@ -382,6 +386,7 @@ impl Default for AlertDataVariant {
|
||||
EnumString,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(rename_all = "UPPERCASE")]
|
||||
#[strum(serialize_all = "UPPERCASE")]
|
||||
pub enum SeverityLevel {
|
||||
|
||||
@@ -45,6 +45,10 @@ pub type _PartialAlerterConfig = PartialAlerterConfig;
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
pub struct AlerterConfig {
|
||||
@@ -149,6 +153,7 @@ impl utoipa::ToSchema for PartialAlerterConfig {}
|
||||
utoipa::ToSchema
|
||||
))
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(tag = "type", content = "params")]
|
||||
pub enum AlerterEndpoint {
|
||||
/// Send alert serialized to JSON to an http endpoint.
|
||||
@@ -179,6 +184,7 @@ impl Default for AlerterEndpoint {
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Builder,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct CustomAlerterEndpoint {
|
||||
/// The http/s endpoint to send the POST to
|
||||
#[serde(default = "default_custom_url")]
|
||||
@@ -204,6 +210,7 @@ fn default_custom_url() -> String {
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Builder,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct SlackAlerterEndpoint {
|
||||
/// The Slack app webhook url
|
||||
#[serde(default = "default_slack_url")]
|
||||
@@ -231,6 +238,7 @@ fn default_slack_url() -> String {
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Builder,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct DiscordAlerterEndpoint {
|
||||
/// The Discord webhook url
|
||||
#[serde(default = "default_discord_url")]
|
||||
@@ -258,6 +266,7 @@ fn default_discord_url() -> String {
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Builder,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct NtfyAlerterEndpoint {
|
||||
/// The ntfy topic URL
|
||||
#[serde(default = "default_ntfy_url")]
|
||||
@@ -288,6 +297,7 @@ fn default_ntfy_url() -> String {
|
||||
Debug, Clone, PartialEq, Serialize, Deserialize, Builder,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct PushoverAlerterEndpoint {
|
||||
/// The pushover URL including application and user tokens in parameters.
|
||||
#[serde(default = "default_pushover_url")]
|
||||
|
||||
@@ -260,18 +260,30 @@ pub type _PartialBuildConfig = PartialBuildConfig;
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Builder, Partial)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
pub struct BuildConfig {
|
||||
/// Which builder is used to build the image.
|
||||
#[serde(default, alias = "builder")]
|
||||
#[partial_attr(serde(alias = "builder"))]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_attr(schemars(rename = "builder"))
|
||||
)]
|
||||
#[builder(default)]
|
||||
pub builder_id: String,
|
||||
|
||||
/// The current version of the build.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_attr(schemars(default, schema_with = "version_schema"))
|
||||
)]
|
||||
pub version: Version,
|
||||
|
||||
/// Whether to automatically increment the patch on every build.
|
||||
@@ -523,6 +535,26 @@ fn default_webhook_enabled() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(feature = "schemars")]
|
||||
fn version_schema(
|
||||
_: &mut schemars::SchemaGenerator,
|
||||
) -> schemars::Schema {
|
||||
schemars::json_schema!({
|
||||
"description": "The current version of the build.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/$defs/Version"
|
||||
},
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
impl Default for BuildConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
@@ -577,6 +609,7 @@ impl utoipa::ToSchema for PartialBuildConfig {}
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct ImageRegistryConfig {
|
||||
/// Specify the registry provider domain, eg `docker.io`.
|
||||
/// If not provided, will not push to any registry.
|
||||
|
||||
@@ -125,6 +125,7 @@ impl Default for BuilderConfig {
|
||||
utoipa::ToSchema
|
||||
))
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(tag = "type", content = "params")]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum PartialBuilderConfig {
|
||||
@@ -370,13 +371,10 @@ pub type _PartialUrlBuilderConfig = PartialUrlBuilderConfig;
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(
|
||||
not(feature = "utoipa"),
|
||||
partial_derive(Serialize, Deserialize, Debug, Clone, Default)
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "utoipa",
|
||||
partial_derive(Serialize, Deserialize, Debug, Clone, Default,)
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
@@ -451,12 +449,20 @@ pub type _PartialServerBuilderConfig = PartialServerBuilderConfig;
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
pub struct ServerBuilderConfig {
|
||||
/// The server id of the builder
|
||||
#[serde(default, alias = "server")]
|
||||
#[partial_attr(serde(alias = "server"))]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_attr(schemars(rename = "server"))
|
||||
)]
|
||||
pub server_id: String,
|
||||
}
|
||||
|
||||
@@ -485,6 +491,10 @@ pub type _PartialAwsBuilderConfig = PartialAwsBuilderConfig;
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Builder, Partial)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
pub struct AwsBuilderConfig {
|
||||
|
||||
@@ -96,6 +96,8 @@ pub struct Env {
|
||||
pub komodo_cli_logging_pretty: Option<bool>,
|
||||
/// Override `logging.ansi`
|
||||
pub komodo_cli_logging_ansi: Option<bool>,
|
||||
/// Override `logging.timestamps`
|
||||
pub komodo_cli_logging_timestamps: Option<bool>,
|
||||
/// Override `logging.otlp_endpoint`
|
||||
pub komodo_cli_logging_otlp_endpoint: Option<String>,
|
||||
/// Override `logging.opentelemetry_service_name`
|
||||
|
||||
@@ -116,27 +116,6 @@ pub struct Env {
|
||||
/// Override `webhook_base_url`
|
||||
pub komodo_webhook_base_url: Option<String>,
|
||||
|
||||
/// Override `logging.level`
|
||||
pub komodo_logging_level: Option<LogLevel>,
|
||||
/// Override `logging.stdio`
|
||||
pub komodo_logging_stdio: Option<StdioLogMode>,
|
||||
/// Override `logging.pretty`
|
||||
pub komodo_logging_pretty: Option<bool>,
|
||||
/// Override `logging.location`
|
||||
pub komodo_logging_location: Option<bool>,
|
||||
/// Override `logging.ansi`
|
||||
pub komodo_logging_ansi: Option<bool>,
|
||||
/// Override `logging.otlp_endpoint`
|
||||
pub komodo_logging_otlp_endpoint: Option<String>,
|
||||
/// Override `logging.opentelemetry_service_name`
|
||||
pub komodo_logging_opentelemetry_service_name: Option<String>,
|
||||
/// Override `logging.opentelemetry_scope_name`
|
||||
pub komodo_logging_opentelemetry_scope_name: Option<String>,
|
||||
/// Override `pretty_startup_config`
|
||||
pub komodo_pretty_startup_config: Option<bool>,
|
||||
/// Override `unsafe_unsanitized_startup_config`
|
||||
pub komodo_unsafe_unsanitized_startup_config: Option<bool>,
|
||||
|
||||
/// Override `transparent_mode`
|
||||
pub komodo_transparent_mode: Option<bool>,
|
||||
/// Override `ui_write_disabled`
|
||||
@@ -145,6 +124,10 @@ pub struct Env {
|
||||
pub komodo_enable_new_users: Option<bool>,
|
||||
/// Override `disable_user_registration`
|
||||
pub komodo_disable_user_registration: Option<bool>,
|
||||
/// Override `disable_local_user_registration`
|
||||
pub komodo_disable_local_user_registration: Option<bool>,
|
||||
/// Override `disable_oidc_user_registration`
|
||||
pub komodo_disable_oidc_user_registration: Option<bool>,
|
||||
/// Override `lock_login_credentials_for`
|
||||
pub komodo_lock_login_credentials_for: Option<Vec<String>>,
|
||||
/// Override `disable_confirm_dialog`
|
||||
@@ -191,6 +174,8 @@ pub struct Env {
|
||||
pub komodo_oidc_additional_audiences: Option<Vec<String>>,
|
||||
/// Override `oidc_additional_audiences` from file
|
||||
pub komodo_oidc_additional_audiences_file: Option<PathBuf>,
|
||||
/// Override `oidc_auto_redirect`
|
||||
pub komodo_oidc_auto_redirect: Option<bool>,
|
||||
|
||||
/// Override `google_oauth.enabled`
|
||||
pub komodo_google_oauth_enabled: Option<bool>,
|
||||
@@ -228,6 +213,17 @@ pub struct Env {
|
||||
/// Override `session_allow_cross_site`
|
||||
pub komodo_session_allow_cross_site: Option<bool>,
|
||||
|
||||
/// Override `x_content_type_options`
|
||||
pub komodo_x_content_type_options: Option<String>,
|
||||
/// Override `x_frame_options`
|
||||
pub komodo_x_frame_options: Option<String>,
|
||||
/// Override `x_xss_protection`
|
||||
pub komodo_x_xss_protection: Option<String>,
|
||||
/// Override `x_referrer_policy`
|
||||
pub komodo_referrer_policy: Option<String>,
|
||||
/// Override `content_security_policy`
|
||||
pub komodo_content_security_policy: Option<String>,
|
||||
|
||||
/// Override `database.uri`
|
||||
#[serde(alias = "komodo_mongo_uri")]
|
||||
pub komodo_database_uri: Option<String>,
|
||||
@@ -265,6 +261,29 @@ pub struct Env {
|
||||
/// Override `aws.secret_access_key` with file
|
||||
pub komodo_aws_secret_access_key_file: Option<PathBuf>,
|
||||
|
||||
/// Override `logging.level`
|
||||
pub komodo_logging_level: Option<LogLevel>,
|
||||
/// Override `logging.stdio`
|
||||
pub komodo_logging_stdio: Option<StdioLogMode>,
|
||||
/// Override `logging.pretty`
|
||||
pub komodo_logging_pretty: Option<bool>,
|
||||
/// Override `logging.location`
|
||||
pub komodo_logging_location: Option<bool>,
|
||||
/// Override `logging.ansi`
|
||||
pub komodo_logging_ansi: Option<bool>,
|
||||
/// Override `logging.timestamps`
|
||||
pub komodo_logging_timestamps: Option<bool>,
|
||||
/// Override `logging.otlp_endpoint`
|
||||
pub komodo_logging_otlp_endpoint: Option<String>,
|
||||
/// Override `logging.opentelemetry_service_name`
|
||||
pub komodo_logging_opentelemetry_service_name: Option<String>,
|
||||
/// Override `logging.opentelemetry_scope_name`
|
||||
pub komodo_logging_opentelemetry_scope_name: Option<String>,
|
||||
/// Override `pretty_startup_config`
|
||||
pub komodo_pretty_startup_config: Option<bool>,
|
||||
/// Override `unsafe_unsanitized_startup_config`
|
||||
pub komodo_unsafe_unsanitized_startup_config: Option<bool>,
|
||||
|
||||
/// Override `internet_interface`
|
||||
pub komodo_internet_interface: Option<String>,
|
||||
|
||||
@@ -455,6 +474,20 @@ pub struct CoreConfig {
|
||||
#[serde(default)]
|
||||
pub disable_user_registration: bool,
|
||||
|
||||
/// Disable local (username/password) user registration only.
|
||||
/// When set, the "Sign Up" button is hidden and local signups are blocked,
|
||||
/// but OIDC and other external provider signups are still allowed.
|
||||
/// If not set, falls back to `disable_user_registration`.
|
||||
#[serde(default)]
|
||||
pub disable_local_user_registration: Option<bool>,
|
||||
|
||||
/// Disable OIDC user registration only.
|
||||
/// When set, new users cannot register via OIDC,
|
||||
/// but local and other provider signups are still allowed.
|
||||
/// If not set, falls back to `disable_user_registration`.
|
||||
#[serde(default)]
|
||||
pub disable_oidc_user_registration: Option<bool>,
|
||||
|
||||
/// List of usernames for which the update username / password
|
||||
/// APIs are disabled. Used by demo to lock the 'demo' : 'demo' login.
|
||||
///
|
||||
@@ -523,6 +556,12 @@ pub struct CoreConfig {
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub oidc_additional_audiences: Vec<String>,
|
||||
|
||||
/// Automatically redirect unauthenticated users to the OIDC provider
|
||||
/// instead of showing the login page.
|
||||
/// Users can bypass the redirect by appending `?disableAutoLogin` to the login URL.
|
||||
#[serde(default)]
|
||||
pub oidc_auto_redirect: bool,
|
||||
|
||||
// =========
|
||||
// = Oauth =
|
||||
// =========
|
||||
@@ -569,6 +608,37 @@ pub struct CoreConfig {
|
||||
#[serde(default)]
|
||||
pub session_allow_cross_site: bool,
|
||||
|
||||
// ====================
|
||||
// = Security Headers =
|
||||
// ====================
|
||||
/// `X-Content-Type-Options` header value.
|
||||
/// Default is `nosniff`. Set as empty string
|
||||
/// to omit the header.
|
||||
#[serde(default = "default_x_content_type_options")]
|
||||
pub x_content_type_options: String,
|
||||
/// `X-Frame-Options` header value. Return an empty string to
|
||||
/// omit the header entirely and allow iframe on any origin. Use `"SAMEORIGIN"` to allow
|
||||
/// same-origin embedding only. Defaults to `"DENY"`.
|
||||
#[serde(default = "default_x_frame_options")]
|
||||
pub x_frame_options: String,
|
||||
/// `X-XSS-PROTECTION` header value. Return an empty string to
|
||||
/// omit the header entirely. Default: `1; mode=block`
|
||||
#[serde(default = "default_x_xss_protection")]
|
||||
pub x_xss_protection: String,
|
||||
/// Apply Referrer Policy directives.
|
||||
/// If empty string, no header is applied.
|
||||
/// Default: `strict-origin-when-cross-origin`
|
||||
#[serde(default = "default_referrer_policy")]
|
||||
pub referrer_policy: String,
|
||||
/// Apply Content Security Policy directives.
|
||||
/// If empty string, no header is applied.
|
||||
/// Default: None
|
||||
///
|
||||
/// Example:
|
||||
/// `default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; form-action 'self'`
|
||||
#[serde(default)]
|
||||
pub content_security_policy: String,
|
||||
|
||||
// ============
|
||||
// = Webhooks =
|
||||
// ============
|
||||
@@ -765,6 +835,22 @@ fn default_auth_rate_limit_window_seconds() -> u64 {
|
||||
15
|
||||
}
|
||||
|
||||
fn default_x_content_type_options() -> String {
|
||||
String::from("nosniff")
|
||||
}
|
||||
|
||||
fn default_x_frame_options() -> String {
|
||||
String::from("DENY")
|
||||
}
|
||||
|
||||
fn default_x_xss_protection() -> String {
|
||||
String::from("1; mode=block")
|
||||
}
|
||||
|
||||
fn default_referrer_policy() -> String {
|
||||
String::from("strict-origin-when-cross-origin")
|
||||
}
|
||||
|
||||
fn default_sync_directory() -> PathBuf {
|
||||
PathBuf::from("/syncs")
|
||||
}
|
||||
@@ -824,6 +910,8 @@ impl Default for CoreConfig {
|
||||
transparent_mode: Default::default(),
|
||||
enable_new_users: Default::default(),
|
||||
disable_user_registration: Default::default(),
|
||||
disable_local_user_registration: Default::default(),
|
||||
disable_oidc_user_registration: Default::default(),
|
||||
lock_login_credentials_for: Default::default(),
|
||||
disable_non_admin_create: Default::default(),
|
||||
jwt_secret: Default::default(),
|
||||
@@ -835,6 +923,7 @@ impl Default for CoreConfig {
|
||||
oidc_client_secret: Default::default(),
|
||||
oidc_use_full_email: Default::default(),
|
||||
oidc_additional_audiences: Default::default(),
|
||||
oidc_auto_redirect: Default::default(),
|
||||
google_oauth: Default::default(),
|
||||
github_oauth: Default::default(),
|
||||
auth_rate_limit_disabled: Default::default(),
|
||||
@@ -845,6 +934,11 @@ impl Default for CoreConfig {
|
||||
cors_allowed_origins: Default::default(),
|
||||
cors_allow_credentials: Default::default(),
|
||||
session_allow_cross_site: Default::default(),
|
||||
x_content_type_options: default_x_content_type_options(),
|
||||
x_frame_options: default_x_frame_options(),
|
||||
x_xss_protection: default_x_xss_protection(),
|
||||
referrer_policy: default_referrer_policy(),
|
||||
content_security_policy: Default::default(),
|
||||
webhook_secret: Default::default(),
|
||||
webhook_base_url: Default::default(),
|
||||
logging: Default::default(),
|
||||
@@ -907,6 +1001,10 @@ impl CoreConfig {
|
||||
enable_fancy_toml: config.enable_fancy_toml,
|
||||
enable_new_users: config.enable_new_users,
|
||||
disable_user_registration: config.disable_user_registration,
|
||||
disable_local_user_registration: config
|
||||
.disable_local_user_registration,
|
||||
disable_oidc_user_registration: config
|
||||
.disable_oidc_user_registration,
|
||||
disable_non_admin_create: config.disable_non_admin_create,
|
||||
lock_login_credentials_for: config.lock_login_credentials_for,
|
||||
local_auth: config.local_auth,
|
||||
@@ -930,6 +1028,7 @@ impl CoreConfig {
|
||||
.iter()
|
||||
.map(|aud| empty_or_redacted(aud))
|
||||
.collect(),
|
||||
oidc_auto_redirect: config.oidc_auto_redirect,
|
||||
google_oauth: NamedOauthConfig {
|
||||
enabled: config.google_oauth.enabled,
|
||||
client_id: empty_or_redacted(&config.google_oauth.client_id),
|
||||
@@ -952,6 +1051,11 @@ impl CoreConfig {
|
||||
cors_allowed_origins: config.cors_allowed_origins,
|
||||
cors_allow_credentials: config.cors_allow_credentials,
|
||||
session_allow_cross_site: config.session_allow_cross_site,
|
||||
x_content_type_options: config.x_content_type_options,
|
||||
x_frame_options: config.x_frame_options,
|
||||
x_xss_protection: config.x_xss_protection,
|
||||
referrer_policy: config.referrer_policy,
|
||||
content_security_policy: config.content_security_policy,
|
||||
webhook_secret: empty_or_redacted(&config.webhook_secret),
|
||||
webhook_base_url: config.webhook_base_url,
|
||||
database: config.database.sanitized(),
|
||||
@@ -1030,6 +1134,21 @@ impl mogh_server::ServerConfig for &CoreConfig {
|
||||
fn ssl_cert_file(&self) -> &str {
|
||||
&self.ssl_cert_file
|
||||
}
|
||||
fn x_content_type_options(&self) -> &str {
|
||||
&self.x_content_type_options
|
||||
}
|
||||
fn x_frame_options(&self) -> &str {
|
||||
&self.x_frame_options
|
||||
}
|
||||
fn x_xss_protection(&self) -> &str {
|
||||
&self.x_xss_protection
|
||||
}
|
||||
fn referrer_policy(&self) -> &str {
|
||||
&self.referrer_policy
|
||||
}
|
||||
fn content_security_policy(&self) -> &str {
|
||||
&self.content_security_policy
|
||||
}
|
||||
}
|
||||
|
||||
impl mogh_server::cors::CorsConfig for &CoreConfig {
|
||||
|
||||
@@ -119,6 +119,7 @@ impl DatabaseConfig {
|
||||
Deserialize,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct GitProvider {
|
||||
/// The git provider domain. Default: `github.com`.
|
||||
#[serde(default = "default_git_provider")]
|
||||
@@ -152,6 +153,7 @@ fn default_git_https() -> bool {
|
||||
Deserialize,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct DockerRegistry {
|
||||
/// The docker provider domain. Default: `docker.io`.
|
||||
#[serde(default = "default_docker_provider")]
|
||||
@@ -182,6 +184,7 @@ fn default_docker_provider() -> String {
|
||||
Deserialize,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct ProviderAccount {
|
||||
/// The account username. Required.
|
||||
#[serde(alias = "account")]
|
||||
|
||||
@@ -199,6 +199,8 @@ pub struct Env {
|
||||
pub periphery_logging_location: Option<bool>,
|
||||
/// Override `logging.ansi`
|
||||
pub periphery_logging_ansi: Option<bool>,
|
||||
/// Override `logging.timestamps`
|
||||
pub periphery_logging_timestamps: Option<bool>,
|
||||
/// Override `logging.otlp_endpoint`
|
||||
pub periphery_logging_otlp_endpoint: Option<String>,
|
||||
/// Override `logging.opentelemetry_service_name`
|
||||
|
||||
@@ -80,6 +80,10 @@ pub type _PartialDeploymentConfig = PartialDeploymentConfig;
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
pub struct DeploymentConfig {
|
||||
@@ -89,6 +93,10 @@ pub struct DeploymentConfig {
|
||||
/// swarm_id overrides server_id and the Deployment will be in Swarm mode.
|
||||
#[serde(default, alias = "swarm")]
|
||||
#[partial_attr(serde(alias = "swarm"))]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_attr(schemars(rename = "swarm"))
|
||||
)]
|
||||
#[builder(default)]
|
||||
pub swarm_id: String,
|
||||
|
||||
@@ -98,6 +106,10 @@ pub struct DeploymentConfig {
|
||||
/// swarm_id overrides server_id and the Deployment will be in Swarm mode.
|
||||
#[serde(default, alias = "server")]
|
||||
#[partial_attr(serde(alias = "server"))]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_attr(schemars(rename = "server"))
|
||||
)]
|
||||
#[builder(default)]
|
||||
pub server_id: String,
|
||||
|
||||
@@ -355,6 +367,7 @@ impl utoipa::ToSchema for PartialDeploymentConfig {}
|
||||
utoipa::ToSchema
|
||||
))
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(tag = "type", content = "params")]
|
||||
pub enum DeploymentImage {
|
||||
/// Deploy any external image.
|
||||
@@ -368,6 +381,7 @@ pub enum DeploymentImage {
|
||||
Build {
|
||||
/// The id of the Build
|
||||
#[serde(default, alias = "build")]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "build"))]
|
||||
build_id: String,
|
||||
/// Use a custom / older version of the image produced by the build.
|
||||
/// if version is 0.0.0, this means `latest` image.
|
||||
@@ -450,6 +464,8 @@ pub enum DeploymentState {
|
||||
Created,
|
||||
/// Server mode only. Container is in restart loop
|
||||
Restarting,
|
||||
/// Server mode only. Container is in the process of stopping
|
||||
Stopping,
|
||||
/// Server mode only. Container is being removed
|
||||
Removing,
|
||||
/// Server mode only. Container is paused
|
||||
@@ -477,6 +493,7 @@ impl From<ContainerStateStatusEnum> for DeploymentState {
|
||||
ContainerStateStatusEnum::Restarting => {
|
||||
DeploymentState::Restarting
|
||||
}
|
||||
ContainerStateStatusEnum::Stopping => DeploymentState::Stopping,
|
||||
ContainerStateStatusEnum::Removing => DeploymentState::Removing,
|
||||
ContainerStateStatusEnum::Exited => DeploymentState::Exited,
|
||||
ContainerStateStatusEnum::Dead => DeploymentState::Dead,
|
||||
@@ -500,6 +517,7 @@ impl From<ContainerStateStatusEnum> for DeploymentState {
|
||||
AsRefStr,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub enum RestartMode {
|
||||
#[default]
|
||||
#[serde(rename = "no")]
|
||||
|
||||
@@ -8,8 +8,8 @@ use typeshare::typeshare;
|
||||
use crate::entities::{I64, Usize};
|
||||
|
||||
use super::{
|
||||
ContainerConfig, GraphDriverData, Mount, MountTypeEnum,
|
||||
PortBinding, ResourcesUlimits,
|
||||
ContainerConfig, GraphDriverData, Mount, PortBinding,
|
||||
ResourcesUlimits,
|
||||
};
|
||||
|
||||
/// Container summary returned by container list apis.
|
||||
@@ -294,6 +294,7 @@ pub enum ContainerStateStatusEnum {
|
||||
Paused,
|
||||
Restarting,
|
||||
Exited,
|
||||
Stopping,
|
||||
Removing,
|
||||
Dead,
|
||||
#[default]
|
||||
@@ -858,8 +859,8 @@ pub enum HostConfigCgroupnsModeEnum {
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
pub struct MountPoint {
|
||||
/// The mount type: - `bind` a mount of a file or directory from the host into the container. - `volume` a docker volume with the given `Name`. - `tmpfs` a `tmpfs`. - `npipe` a named pipe from the host into the container. - `cluster` a Swarm cluster volume
|
||||
#[serde(default, rename = "Type")]
|
||||
pub typ: MountTypeEnum,
|
||||
#[serde(rename = "Type")]
|
||||
pub typ: Option<String>,
|
||||
|
||||
/// Name is the name reference to the underlying data defined by `Source` e.g., the volume name.
|
||||
#[serde(rename = "Name")]
|
||||
|
||||
@@ -267,7 +267,7 @@ pub struct Mount {
|
||||
/// - `tmpfs` Create a tmpfs with the given options. The mount source cannot be specified for tmpfs. - `npipe` Mounts a named pipe from the host into the container. Must exist prior to creating the container.
|
||||
/// - `cluster` a Swarm cluster volume
|
||||
#[serde(default, rename = "Type")]
|
||||
pub typ: MountTypeEnum,
|
||||
pub typ: MountType,
|
||||
|
||||
/// Whether the mount should be read-only.
|
||||
#[serde(rename = "ReadOnly")]
|
||||
@@ -301,10 +301,8 @@ pub struct Mount {
|
||||
Default,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
pub enum MountTypeEnum {
|
||||
pub enum MountType {
|
||||
#[default]
|
||||
#[serde(rename = "")]
|
||||
Empty,
|
||||
#[serde(rename = "bind")]
|
||||
Bind,
|
||||
#[serde(rename = "volume")]
|
||||
@@ -643,3 +641,15 @@ pub struct TlsInfo {
|
||||
#[serde(rename = "CertIssuerPublicKey")]
|
||||
pub cert_issuer_public_key: Option<String>,
|
||||
}
|
||||
|
||||
/// A map of topological domains to topological segments. For in depth details, see documentation for the Topology object in the CSI specification.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
pub struct Topology {
|
||||
#[serde(rename = "Segments")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub segments: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use clap::ValueEnum;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::AsRefStr;
|
||||
use typeshare::typeshare;
|
||||
@@ -22,6 +23,7 @@ pub struct SwarmNodeListItem {
|
||||
#[serde(rename = "Name")]
|
||||
pub name: Option<String>,
|
||||
|
||||
/// Node hostname, more commonly used than Name
|
||||
#[serde(rename = "Hostname")]
|
||||
pub hostname: Option<String>,
|
||||
|
||||
@@ -33,6 +35,10 @@ pub struct SwarmNodeListItem {
|
||||
#[serde(rename = "Availability")]
|
||||
pub availability: Option<NodeSpecAvailabilityEnum>,
|
||||
|
||||
/// Labels of the node
|
||||
#[serde(rename = "Labels")]
|
||||
pub labels: Option<HashMap<String, String>>,
|
||||
|
||||
/// State of the node
|
||||
#[serde(rename = "State")]
|
||||
pub state: Option<NodeState>,
|
||||
@@ -120,8 +126,10 @@ pub struct NodeSpec {
|
||||
Serialize,
|
||||
Deserialize,
|
||||
AsRefStr,
|
||||
ValueEnum,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub enum NodeSpecRoleEnum {
|
||||
#[default]
|
||||
#[serde(rename = "")]
|
||||
@@ -145,8 +153,10 @@ pub enum NodeSpecRoleEnum {
|
||||
Serialize,
|
||||
Deserialize,
|
||||
AsRefStr,
|
||||
ValueEnum,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub enum NodeSpecAvailabilityEnum {
|
||||
#[default]
|
||||
#[serde(rename = "")]
|
||||
|
||||
@@ -3,9 +3,9 @@ use std::collections::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use typeshare::typeshare;
|
||||
|
||||
use crate::entities::I64;
|
||||
use crate::entities::{I64, docker::Topology};
|
||||
|
||||
use super::{ObjectVersion, PortBinding};
|
||||
use super::ObjectVersion;
|
||||
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
@@ -145,8 +145,8 @@ pub struct ClusterVolumeInfo {
|
||||
pub volume_id: Option<String>,
|
||||
|
||||
/// The topology this volume is actually accessible from.
|
||||
#[serde(default, rename = "AccessibleTopology")]
|
||||
pub accessible_topology: Vec<Topology>,
|
||||
#[serde(rename = "AccessibleTopology")]
|
||||
pub accessible_topology: Option<Vec<Topology>>,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
@@ -319,17 +319,14 @@ pub struct ClusterVolumeSpecAccessModeSecrets {
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
pub struct ClusterVolumeSpecAccessModeAccessibilityRequirements {
|
||||
/// A list of required topologies, at least one of which the volume must be accessible from.
|
||||
#[serde(default, rename = "Requisite")]
|
||||
pub requisite: Vec<Topology>,
|
||||
#[serde(rename = "Requisite")]
|
||||
pub requisite: Option<Vec<Topology>>,
|
||||
|
||||
/// A list of topologies that the volume should attempt to be provisioned in.
|
||||
#[serde(default, rename = "Preferred")]
|
||||
pub preferred: Vec<Topology>,
|
||||
#[serde(rename = "Preferred")]
|
||||
pub preferred: Option<Vec<Topology>>,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
pub type Topology = HashMap<String, Vec<PortBinding>>;
|
||||
|
||||
/// The desired capacity that the volume should be created with. If empty, the plugin will decide the capacity.
|
||||
#[typeshare]
|
||||
#[derive(
|
||||
|
||||
@@ -17,14 +17,18 @@ pub struct LogConfig {
|
||||
pub pretty: bool,
|
||||
|
||||
/// Including information about the log location (ie the function which produced the log).
|
||||
/// Tracing refers to this as the 'target'.
|
||||
/// Tracing refers to this as the 'target'. (default: false)
|
||||
#[serde(default = "default_location")]
|
||||
pub location: bool,
|
||||
|
||||
/// Logs use ansi colors for readability.
|
||||
/// Logs use ansi colors for readability. (default: true)
|
||||
#[serde(default = "default_ansi")]
|
||||
pub ansi: bool,
|
||||
|
||||
/// Logs include timestamps. (default: true)
|
||||
#[serde(default = "default_timestamps")]
|
||||
pub timestamps: bool,
|
||||
|
||||
/// Enable opentelemetry exporting
|
||||
#[serde(default)]
|
||||
pub otlp_endpoint: String,
|
||||
@@ -52,6 +56,10 @@ fn default_ansi() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn default_timestamps() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
impl Default for LogConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
@@ -60,6 +68,7 @@ impl Default for LogConfig {
|
||||
pretty: Default::default(),
|
||||
location: default_location(),
|
||||
ansi: default_ansi(),
|
||||
timestamps: default_timestamps(),
|
||||
otlp_endpoint: Default::default(),
|
||||
opentelemetry_service_name: default_opentelemetry_service_name(
|
||||
),
|
||||
@@ -166,15 +175,18 @@ impl mogh_logger::LogConfig for &LogConfig {
|
||||
&TARGETS
|
||||
}
|
||||
|
||||
fn ansi(&self) -> bool {
|
||||
self.ansi
|
||||
}
|
||||
fn level(&self) -> tracing::Level {
|
||||
self.level.into()
|
||||
}
|
||||
fn location(&self) -> bool {
|
||||
self.location
|
||||
}
|
||||
fn ansi(&self) -> bool {
|
||||
self.ansi
|
||||
}
|
||||
fn timestamps(&self) -> bool {
|
||||
self.timestamps
|
||||
}
|
||||
fn opentelemetry_scope_name(&self) -> String {
|
||||
self.opentelemetry_scope_name.clone()
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ pub type _Serror = Serror;
|
||||
Debug, Clone, Default, PartialEq, Serialize, Deserialize, Parser,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct NoData {}
|
||||
|
||||
pub trait MergePartial: Sized {
|
||||
@@ -210,11 +211,14 @@ pub struct __Serror {
|
||||
Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct SystemCommand {
|
||||
#[serde(default)]
|
||||
pub path: String,
|
||||
#[serde(default, deserialize_with = "file_contents_deserializer")]
|
||||
pub command: String,
|
||||
#[serde(default)]
|
||||
pub shell_mode: bool,
|
||||
}
|
||||
|
||||
impl SystemCommand {
|
||||
@@ -238,6 +242,7 @@ impl SystemCommand {
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Debug, Clone, Copy, Default, PartialEq)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct Version {
|
||||
pub major: i32,
|
||||
pub minor: i32,
|
||||
@@ -488,6 +493,7 @@ impl ImageDigest {
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct MaintenanceWindow {
|
||||
/// Name for the maintenance window (required)
|
||||
pub name: String,
|
||||
@@ -920,6 +926,7 @@ pub enum DayOfWeek {
|
||||
Deserialize,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub enum MaintenanceScheduleType {
|
||||
/// Daily at the specified time
|
||||
#[default]
|
||||
@@ -1167,6 +1174,7 @@ pub enum Operation {
|
||||
RenameSwarm,
|
||||
DeleteSwarm,
|
||||
RemoveSwarmNodes,
|
||||
UpdateSwarmNode,
|
||||
RemoveSwarmStacks,
|
||||
RemoveSwarmServices,
|
||||
CreateSwarmConfig,
|
||||
@@ -1363,6 +1371,7 @@ pub enum SearchCombinator {
|
||||
EnumString,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(rename_all = "UPPERCASE")]
|
||||
#[strum(serialize_all = "UPPERCASE")]
|
||||
pub enum TerminationSignal {
|
||||
@@ -1420,6 +1429,11 @@ pub enum TerminationSignal {
|
||||
utoipa::ToSchema,
|
||||
))
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
strum_discriminants(derive(schemars::JsonSchema))
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(tag = "type", content = "id")]
|
||||
pub enum ResourceTarget {
|
||||
System(String),
|
||||
@@ -1576,6 +1590,7 @@ impl ResourceTargetVariant {
|
||||
Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub enum ScheduleFormat {
|
||||
#[default]
|
||||
English,
|
||||
@@ -1587,6 +1602,7 @@ pub enum ScheduleFormat {
|
||||
Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum FileFormat {
|
||||
#[default]
|
||||
|
||||
@@ -118,6 +118,7 @@ impl UserTarget {
|
||||
Default,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub enum PermissionLevel {
|
||||
/// No permissions.
|
||||
#[default]
|
||||
@@ -156,6 +157,7 @@ impl Default for &PermissionLevel {
|
||||
Ord,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub enum SpecificPermission {
|
||||
/// On **Server**
|
||||
/// - Access the terminal apis
|
||||
@@ -193,6 +195,7 @@ impl SpecificPermission {
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct PermissionLevelAndSpecifics {
|
||||
pub level: PermissionLevel,
|
||||
#[cfg_attr(feature = "utoipa", schema(value_type = Vec<SpecificPermission>))]
|
||||
|
||||
@@ -82,12 +82,20 @@ pub type _PartialProcedureConfig = PartialProcedureConfig;
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Partial, Builder)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
pub struct ProcedureConfig {
|
||||
/// The stages to be run by the procedure.
|
||||
#[serde(default, alias = "stage")]
|
||||
#[partial_attr(serde(alias = "stage"))]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_attr(schemars(rename = "stage"))
|
||||
)]
|
||||
#[builder(default)]
|
||||
pub stages: Vec<ProcedureStage>,
|
||||
|
||||
@@ -207,6 +215,7 @@ impl utoipa::ToSchema for PartialProcedureConfig {}
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct ProcedureStage {
|
||||
/// A name for the procedure
|
||||
pub name: String,
|
||||
@@ -222,6 +231,7 @@ pub struct ProcedureStage {
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct EnabledExecution {
|
||||
/// The execution request to run.
|
||||
pub execution: Execution,
|
||||
|
||||
@@ -113,18 +113,30 @@ pub type _PartialRepoConfig = PartialRepoConfig;
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
pub struct RepoConfig {
|
||||
/// The server to clone the repo on.
|
||||
#[serde(default, alias = "server")]
|
||||
#[partial_attr(serde(alias = "server"))]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_attr(schemars(rename = "server"))
|
||||
)]
|
||||
#[builder(default)]
|
||||
pub server_id: String,
|
||||
|
||||
/// Attach a builder to 'build' the repo.
|
||||
#[serde(default, alias = "builder")]
|
||||
#[partial_attr(serde(alias = "builder"))]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_attr(schemars(rename = "builder"))
|
||||
)]
|
||||
#[builder(default)]
|
||||
pub builder_id: String,
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
deserializers::{
|
||||
option_string_list_deserializer, string_list_deserializer,
|
||||
},
|
||||
entities::{MaintenanceWindow, Timelength},
|
||||
entities::{_Serror, MaintenanceWindow, Timelength},
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -37,6 +37,9 @@ pub type ServerListItem = ResourceListItem<ServerListItemInfo>;
|
||||
pub struct ServerListItemInfo {
|
||||
/// The server's state.
|
||||
pub state: ServerState,
|
||||
/// If there is an error reaching
|
||||
/// the server, message will be given here.
|
||||
pub err: Option<_Serror>,
|
||||
/// Region of the server.
|
||||
pub region: String,
|
||||
/// Address of the server, or null if empty.
|
||||
@@ -93,6 +96,10 @@ pub type _PartialServerConfig = PartialServerConfig;
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Builder, Partial)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
pub struct ServerConfig {
|
||||
|
||||
@@ -293,6 +293,10 @@ pub type _PartialStackConfig = PartialStackConfig;
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Builder, Partial)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
pub struct StackConfig {
|
||||
@@ -302,6 +306,10 @@ pub struct StackConfig {
|
||||
/// swarm_id overrides server_id and the Stack will be in Swarm mode.
|
||||
#[serde(default, alias = "swarm")]
|
||||
#[partial_attr(serde(alias = "swarm"))]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_attr(schemars(rename = "swarm"))
|
||||
)]
|
||||
#[builder(default)]
|
||||
pub swarm_id: String,
|
||||
|
||||
@@ -311,6 +319,10 @@ pub struct StackConfig {
|
||||
/// swarm_id overrides server_id and the Stack will be in Swarm mode.
|
||||
#[serde(default, alias = "server")]
|
||||
#[partial_attr(serde(alias = "server"))]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_attr(schemars(rename = "server"))
|
||||
)]
|
||||
#[builder(default)]
|
||||
pub server_id: String,
|
||||
|
||||
@@ -371,6 +383,17 @@ pub struct StackConfig {
|
||||
#[builder(default)]
|
||||
pub auto_update_all_services: bool,
|
||||
|
||||
/// Ignore certain services during Global Auto Update polling.
|
||||
/// Services listed here are skipped only in the global auto-update flow.
|
||||
/// Manual checks still include all services.
|
||||
#[serde(default, deserialize_with = "string_list_deserializer")]
|
||||
#[partial_attr(serde(
|
||||
default,
|
||||
deserialize_with = "option_string_list_deserializer"
|
||||
))]
|
||||
#[builder(default)]
|
||||
pub auto_update_skip_services: Vec<String>,
|
||||
|
||||
/// Whether to run `docker compose down` before `compose up`.
|
||||
#[serde(default)]
|
||||
#[builder(default)]
|
||||
@@ -688,6 +711,7 @@ impl Default for StackConfig {
|
||||
poll_for_updates: Default::default(),
|
||||
auto_update: Default::default(),
|
||||
auto_update_all_services: Default::default(),
|
||||
auto_update_skip_services: Default::default(),
|
||||
ignore_services: Default::default(),
|
||||
pre_deploy: Default::default(),
|
||||
post_deploy: Default::default(),
|
||||
@@ -915,6 +939,7 @@ pub struct StackRemoteFileContents {
|
||||
Deserialize,
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub enum StackFileRequires {
|
||||
/// Diff requires service redeploy.
|
||||
#[serde(alias = "redeploy")]
|
||||
@@ -933,6 +958,7 @@ pub enum StackFileRequires {
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct AdditionalEnvFile {
|
||||
/// File path relative to run directory
|
||||
pub path: String,
|
||||
@@ -1012,6 +1038,7 @@ impl<'de> Deserialize<'de> for AdditionalEnvFile {
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct StackFileDependency {
|
||||
/// Specify the file
|
||||
pub path: String,
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
deserializers::{
|
||||
option_string_list_deserializer, string_list_deserializer,
|
||||
},
|
||||
entities::MaintenanceWindow,
|
||||
entities::{_Serror, MaintenanceWindow},
|
||||
};
|
||||
|
||||
use super::resource::{Resource, ResourceListItem, ResourceQuery};
|
||||
@@ -28,7 +28,7 @@ pub struct SwarmListItemInfo {
|
||||
pub state: SwarmState,
|
||||
/// If there is an error reaching
|
||||
/// Swarm, message will be given here.
|
||||
pub err: Option<String>,
|
||||
pub err: Option<_Serror>,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
@@ -82,6 +82,10 @@ pub type _PartialSwarmConfig = PartialSwarmConfig;
|
||||
)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
pub struct SwarmConfig {
|
||||
@@ -90,6 +94,10 @@ pub struct SwarmConfig {
|
||||
/// tries the next Server.
|
||||
#[serde(default, alias = "servers")]
|
||||
#[partial_attr(serde(alias = "servers"))]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_attr(schemars(rename = "servers"))
|
||||
)]
|
||||
#[builder(default)]
|
||||
pub server_ids: Vec<String>,
|
||||
|
||||
|
||||
@@ -186,6 +186,10 @@ pub type _PartialResourceSyncConfig = PartialResourceSyncConfig;
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Builder, Partial)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[partial_derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
partial_derive(schemars::JsonSchema)
|
||||
)]
|
||||
#[diff_derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[partial(skip_serializing_none, from, diff)]
|
||||
pub struct ResourceSyncConfig {
|
||||
|
||||
@@ -26,102 +26,134 @@ use super::{
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "Resources"))]
|
||||
pub struct ResourcesToml {
|
||||
/// Declare a swarm
|
||||
#[serde(
|
||||
default,
|
||||
alias = "swarm",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "swarm"))]
|
||||
pub swarms: Vec<ResourceToml<_PartialSwarmConfig>>,
|
||||
|
||||
/// Declare a server
|
||||
#[serde(
|
||||
default,
|
||||
alias = "server",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "server"))]
|
||||
pub servers: Vec<ResourceToml<_PartialServerConfig>>,
|
||||
|
||||
#[serde(
|
||||
default,
|
||||
alias = "deployment",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
pub deployments: Vec<ResourceToml<_PartialDeploymentConfig>>,
|
||||
|
||||
/// Declare a stack
|
||||
#[serde(
|
||||
default,
|
||||
alias = "stack",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "stack"))]
|
||||
pub stacks: Vec<ResourceToml<_PartialStackConfig>>,
|
||||
|
||||
/// Declare a deployment
|
||||
#[serde(
|
||||
default,
|
||||
alias = "deployment",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "deployment"))]
|
||||
pub deployments: Vec<ResourceToml<_PartialDeploymentConfig>>,
|
||||
|
||||
/// Declare a build
|
||||
#[serde(
|
||||
default,
|
||||
alias = "build",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "build"))]
|
||||
pub builds: Vec<ResourceToml<_PartialBuildConfig>>,
|
||||
|
||||
/// Declare a repo
|
||||
#[serde(
|
||||
default,
|
||||
alias = "repo",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "repo"))]
|
||||
pub repos: Vec<ResourceToml<_PartialRepoConfig>>,
|
||||
|
||||
/// Declare a procedure
|
||||
#[serde(
|
||||
default,
|
||||
alias = "procedure",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "procedure"))]
|
||||
pub procedures: Vec<ResourceToml<_PartialProcedureConfig>>,
|
||||
|
||||
/// Declare an action
|
||||
#[serde(
|
||||
default,
|
||||
alias = "action",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "action"))]
|
||||
pub actions: Vec<ResourceToml<_PartialActionConfig>>,
|
||||
|
||||
/// Declare an alerter
|
||||
#[serde(
|
||||
default,
|
||||
alias = "alerter",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "alerter"))]
|
||||
pub alerters: Vec<ResourceToml<_PartialAlerterConfig>>,
|
||||
|
||||
/// Declare a builder
|
||||
#[serde(
|
||||
default,
|
||||
alias = "builder",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "builder"))]
|
||||
pub builders: Vec<ResourceToml<_PartialBuilderConfig>>,
|
||||
|
||||
/// Declare a resource sync
|
||||
#[serde(
|
||||
default,
|
||||
alias = "resource_sync",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "schemars",
|
||||
schemars(rename = "resource_sync")
|
||||
)]
|
||||
pub resource_syncs: Vec<ResourceToml<_PartialResourceSyncConfig>>,
|
||||
|
||||
/// Declare a user group
|
||||
#[serde(
|
||||
default,
|
||||
alias = "user_group",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "user_group"))]
|
||||
pub user_groups: Vec<UserGroupToml>,
|
||||
|
||||
/// Declare a variable
|
||||
#[serde(
|
||||
default,
|
||||
alias = "variable",
|
||||
skip_serializing_if = "Vec::is_empty"
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", schemars(rename = "variable"))]
|
||||
pub variables: Vec<Variable>,
|
||||
}
|
||||
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct ResourceToml<PartialConfig: Default> {
|
||||
/// The resource name. Required
|
||||
pub name: String,
|
||||
@@ -165,6 +197,7 @@ fn is_false(b: &bool) -> bool {
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct UserGroupToml {
|
||||
/// User group name
|
||||
pub name: String,
|
||||
@@ -191,6 +224,7 @@ pub struct UserGroupToml {
|
||||
#[typeshare]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct PermissionToml {
|
||||
/// Id can be:
|
||||
/// - resource name. `id = "abcd-build"`
|
||||
|
||||
@@ -6,6 +6,7 @@ use typeshare::typeshare;
|
||||
#[typeshare]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[cfg_attr(
|
||||
feature = "mongo",
|
||||
derive(mongo_indexed::derive::MongoIndexed)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "komodo_client",
|
||||
"version": "2.0.0",
|
||||
"version": "2.2.0",
|
||||
"description": "Komodo client package",
|
||||
"homepage": "https://komo.do",
|
||||
"main": "dist/lib.js",
|
||||
@@ -13,10 +13,10 @@
|
||||
"build": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"mogh_auth_client": "^1.2.1"
|
||||
"mogh_auth_client": "^1.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.6.3"
|
||||
"typescript": "^6.0.2"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||
}
|
||||
|
||||
@@ -433,6 +433,7 @@ export type ExecuteResponses = {
|
||||
|
||||
// ==== SWARM ====
|
||||
RemoveSwarmNodes: Types.Update;
|
||||
UpdateSwarmNode: Types.Update;
|
||||
RemoveSwarmStacks: Types.Update;
|
||||
RemoveSwarmServices: Types.Update;
|
||||
CreateSwarmConfig: Types.Update;
|
||||
|
||||
+74
-17
@@ -378,6 +378,7 @@ export enum Operation {
|
||||
RenameSwarm = "RenameSwarm",
|
||||
DeleteSwarm = "DeleteSwarm",
|
||||
RemoveSwarmNodes = "RemoveSwarmNodes",
|
||||
UpdateSwarmNode = "UpdateSwarmNode",
|
||||
RemoveSwarmStacks = "RemoveSwarmStacks",
|
||||
RemoveSwarmServices = "RemoveSwarmServices",
|
||||
CreateSwarmConfig = "CreateSwarmConfig",
|
||||
@@ -611,6 +612,7 @@ export interface ImageRegistryConfig {
|
||||
export interface SystemCommand {
|
||||
path?: string;
|
||||
command?: string;
|
||||
shell_mode?: boolean;
|
||||
}
|
||||
|
||||
/** The build configuration. */
|
||||
@@ -927,6 +929,7 @@ export type Execution =
|
||||
| { type: "PruneBuildx", params: PruneBuildx }
|
||||
| { type: "PruneSystem", params: PruneSystem }
|
||||
| { type: "RemoveSwarmNodes", params: RemoveSwarmNodes }
|
||||
| { type: "UpdateSwarmNode", params: UpdateSwarmNode }
|
||||
| { type: "RemoveSwarmStacks", params: RemoveSwarmStacks }
|
||||
| { type: "RemoveSwarmServices", params: RemoveSwarmServices }
|
||||
| { type: "CreateSwarmConfig", params: CreateSwarmConfig }
|
||||
@@ -1425,6 +1428,8 @@ export enum DeploymentState {
|
||||
Created = "created",
|
||||
/** Server mode only. Container is in restart loop */
|
||||
Restarting = "restarting",
|
||||
/** Server mode only. Container is in the process of stopping */
|
||||
Stopping = "stopping",
|
||||
/** Server mode only. Container is being removed */
|
||||
Removing = "removing",
|
||||
/** Server mode only. Container is paused */
|
||||
@@ -1561,7 +1566,7 @@ export type AlertData =
|
||||
/** The name of the swarm */
|
||||
name: string;
|
||||
/** The error data */
|
||||
err?: string;
|
||||
err?: _Serror;
|
||||
}}
|
||||
/** A server could not be reached. */
|
||||
| { type: "ServerUnreachable", data: {
|
||||
@@ -2468,6 +2473,12 @@ export interface StackConfig {
|
||||
* Komodo will redeploy the whole Stack (all services).
|
||||
*/
|
||||
auto_update_all_services?: boolean;
|
||||
/**
|
||||
* Ignore certain services during Global Auto Update polling.
|
||||
* Services listed here are skipped only in the global auto-update flow.
|
||||
* Manual checks still include all services.
|
||||
*/
|
||||
auto_update_skip_services?: string[];
|
||||
/** Whether to run `docker compose down` before `compose up`. */
|
||||
destroy_before_deploy?: boolean;
|
||||
/** Whether to skip secret interpolation into the stack environment variables. */
|
||||
@@ -2954,6 +2965,7 @@ export enum ContainerStateStatusEnum {
|
||||
Paused = "paused",
|
||||
Restarting = "restarting",
|
||||
Exited = "exited",
|
||||
Stopping = "stopping",
|
||||
Removing = "removing",
|
||||
Dead = "dead",
|
||||
Empty = "",
|
||||
@@ -3085,8 +3097,7 @@ export interface RestartPolicy {
|
||||
MaximumRetryCount?: I64;
|
||||
}
|
||||
|
||||
export enum MountTypeEnum {
|
||||
Empty = "",
|
||||
export enum MountType {
|
||||
Bind = "bind",
|
||||
Volume = "volume",
|
||||
Image = "image",
|
||||
@@ -3158,7 +3169,7 @@ export interface Mount {
|
||||
* - `tmpfs` Create a tmpfs with the given options. The mount source cannot be specified for tmpfs. - `npipe` Mounts a named pipe from the host into the container. Must exist prior to creating the container.
|
||||
* - `cluster` a Swarm cluster volume
|
||||
*/
|
||||
Type?: MountTypeEnum;
|
||||
Type?: MountType;
|
||||
/** Whether the mount should be read-only. */
|
||||
ReadOnly?: boolean;
|
||||
/** The consistency requirement for the mount: `default`, `consistent`, `cached`, or `delegated`. */
|
||||
@@ -3331,7 +3342,7 @@ export interface GraphDriverData {
|
||||
/** MountPoint represents a mount point configuration inside the container. This is used for reporting the mountpoints in use by a container. */
|
||||
export interface MountPoint {
|
||||
/** The mount type: - `bind` a mount of a file or directory from the host into the container. - `volume` a docker volume with the given `Name`. - `tmpfs` a `tmpfs`. - `npipe` a named pipe from the host into the container. - `cluster` a Swarm cluster volume */
|
||||
Type?: MountTypeEnum;
|
||||
Type?: string;
|
||||
/** Name is the name reference to the underlying data defined by `Source` e.g., the volume name. */
|
||||
Name?: string;
|
||||
/** Source location of the mount. For volumes, this contains the storage location of the volume (within `/var/lib/docker/volumes/`). For bind-mounts, and `npipe`, this contains the source (host) part of the bind-mount. For `tmpfs` mount points, this field is empty. */
|
||||
@@ -4291,7 +4302,10 @@ export interface ClusterVolumeSpecAccessModeSecrets {
|
||||
Secret?: string;
|
||||
}
|
||||
|
||||
export type Topology = Record<string, PortBinding[]>;
|
||||
/** A map of topological domains to topological segments. For in depth details, see documentation for the Topology object in the CSI specification. */
|
||||
export interface Topology {
|
||||
Segments?: Record<string, string>;
|
||||
}
|
||||
|
||||
/** Requirements for the accessible topology of the volume. These fields are optional. For an in-depth description of what these fields mean, see the CSI specification. */
|
||||
export interface ClusterVolumeSpecAccessModeAccessibilityRequirements {
|
||||
@@ -5328,9 +5342,21 @@ export enum ServerState {
|
||||
Disabled = "Disabled",
|
||||
}
|
||||
|
||||
export interface __Serror {
|
||||
error: string;
|
||||
trace: string[];
|
||||
}
|
||||
|
||||
export type _Serror = __Serror;
|
||||
|
||||
export interface ServerListItemInfo {
|
||||
/** The server's state. */
|
||||
state: ServerState;
|
||||
/**
|
||||
* If there is an error reaching
|
||||
* the server, message will be given here.
|
||||
*/
|
||||
err?: _Serror;
|
||||
/** Region of the server. */
|
||||
region: string;
|
||||
/** Address of the server, or null if empty. */
|
||||
@@ -5492,11 +5518,14 @@ export interface SwarmNodeListItem {
|
||||
ID?: string;
|
||||
/** Name for the node. */
|
||||
Name?: string;
|
||||
/** Node hostname, more commonly used than Name */
|
||||
Hostname?: string;
|
||||
/** Role of the node. */
|
||||
Role?: NodeSpecRoleEnum;
|
||||
/** Availability of the node. */
|
||||
Availability?: NodeSpecAvailabilityEnum;
|
||||
/** Labels of the node */
|
||||
Labels?: Record<string, string>;
|
||||
/** State of the node */
|
||||
State?: NodeState;
|
||||
/** For manager nodes, include the manager addr. */
|
||||
@@ -5569,7 +5598,7 @@ export interface SwarmListItemInfo {
|
||||
* If there is an error reaching
|
||||
* Swarm, message will be given here.
|
||||
*/
|
||||
err?: string;
|
||||
err?: _Serror;
|
||||
}
|
||||
|
||||
export type SwarmListItem = ResourceListItem<SwarmListItemInfo>;
|
||||
@@ -5778,13 +5807,6 @@ export type _PartialTag = Partial<Tag>;
|
||||
|
||||
export type _PartialUrlBuilderConfig = Partial<UrlBuilderConfig>;
|
||||
|
||||
export interface __Serror {
|
||||
error: string;
|
||||
trace: string[];
|
||||
}
|
||||
|
||||
export type _Serror = __Serror;
|
||||
|
||||
/** **Admin only.** Add a user to a user group. Response: [UserGroup] */
|
||||
export interface AddUserToUserGroup {
|
||||
/** The name or id of UserGroup that user should be added to. */
|
||||
@@ -6806,7 +6828,8 @@ export interface CreateOnboardingKey {
|
||||
expires?: I64;
|
||||
/**
|
||||
* Optionally specify an existing private key, otherwise
|
||||
* generate fresh key.
|
||||
* generate fresh key. This key is not stored directly,
|
||||
* only the public key.
|
||||
*/
|
||||
private_key?: string;
|
||||
/** Default tags to apply to Servers created using this key. */
|
||||
@@ -7428,18 +7451,31 @@ export interface UserGroupToml {
|
||||
|
||||
/** Specifies resources to sync on Komodo */
|
||||
export interface ResourcesToml {
|
||||
/** Declare a swarm */
|
||||
swarms?: ResourceToml<_PartialSwarmConfig>[];
|
||||
/** Declare a server */
|
||||
servers?: ResourceToml<_PartialServerConfig>[];
|
||||
deployments?: ResourceToml<_PartialDeploymentConfig>[];
|
||||
/** Declare a stack */
|
||||
stacks?: ResourceToml<_PartialStackConfig>[];
|
||||
/** Declare a deployment */
|
||||
deployments?: ResourceToml<_PartialDeploymentConfig>[];
|
||||
/** Declare a build */
|
||||
builds?: ResourceToml<_PartialBuildConfig>[];
|
||||
/** Declare a repo */
|
||||
repos?: ResourceToml<_PartialRepoConfig>[];
|
||||
/** Declare a procedure */
|
||||
procedures?: ResourceToml<_PartialProcedureConfig>[];
|
||||
/** Declare an action */
|
||||
actions?: ResourceToml<_PartialActionConfig>[];
|
||||
/** Declare an alerter */
|
||||
alerters?: ResourceToml<_PartialAlerterConfig>[];
|
||||
/** Declare a builder */
|
||||
builders?: ResourceToml<_PartialBuilderConfig>[];
|
||||
/** Declare a resource sync */
|
||||
resource_syncs?: ResourceToml<_PartialResourceSyncConfig>[];
|
||||
/** Declare a user group */
|
||||
user_groups?: UserGroupToml[];
|
||||
/** Declare a variable */
|
||||
variables?: Variable[];
|
||||
}
|
||||
|
||||
@@ -7728,7 +7764,7 @@ export interface GetCoreInfoResponse {
|
||||
enable_fancy_toml: boolean;
|
||||
/** TZ identifier Core is using, if manually set. */
|
||||
timezone: string;
|
||||
/** Default public key allowing this Core to authenticate to Periphery agents. */
|
||||
/** Public key for Core / Periphery authentication. */
|
||||
public_key: string;
|
||||
}
|
||||
|
||||
@@ -10477,6 +10513,26 @@ export interface UpdateSwarm {
|
||||
config: _PartialSwarmConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* `docker node update [OPTIONS] NODE`
|
||||
*
|
||||
* https://docs.docker.com/reference/cli/docker/node/update/
|
||||
*/
|
||||
export interface UpdateSwarmNode {
|
||||
/** Name or id */
|
||||
swarm: string;
|
||||
/** Node hostname or id */
|
||||
node: string;
|
||||
/** Update the node's availability: 'active', 'pause', or 'drain' */
|
||||
availability?: NodeSpecAvailabilityEnum;
|
||||
/** Add labels to node (`key=value`). */
|
||||
label_add?: string[];
|
||||
/** Add labels to node (`key=value`). (alias: `lr`) */
|
||||
label_rm?: string[];
|
||||
/** Update the node's role: 'worker' or 'manager' */
|
||||
role?: NodeSpecRoleEnum;
|
||||
}
|
||||
|
||||
/** Update color for tag. Response: [Tag]. */
|
||||
export interface UpdateTagColor {
|
||||
/** The name or id of the tag to update. */
|
||||
@@ -10666,6 +10722,7 @@ export type ExecuteRequest =
|
||||
| { type: "PruneBuildx", params: PruneBuildx }
|
||||
| { type: "PruneSystem", params: PruneSystem }
|
||||
| { type: "RemoveSwarmNodes", params: RemoveSwarmNodes }
|
||||
| { type: "UpdateSwarmNode", params: UpdateSwarmNode }
|
||||
| { type: "RemoveSwarmStacks", params: RemoveSwarmStacks }
|
||||
| { type: "RemoveSwarmServices", params: RemoveSwarmServices }
|
||||
| { type: "CreateSwarmConfig", params: CreateSwarmConfig }
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
"strict": true,
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "node",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"isolatedModules": true,
|
||||
"rootDir": "src/",
|
||||
"outDir": "dist",
|
||||
"declaration": true
|
||||
}
|
||||
|
||||
@@ -7,14 +7,14 @@ jwt-decode@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-4.0.0.tgz#2270352425fd413785b2faf11f6e755c5151bd4b"
|
||||
integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==
|
||||
|
||||
mogh_auth_client@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/mogh_auth_client/-/mogh_auth_client-1.2.1.tgz#c8b5e9da101dc8da7b30586e5c5463f5f7a95edb"
|
||||
integrity sha512-8uUjgqagwbMW8BKtTRzfQ4txpw+54hqLszbIvcYf99murVIQu5+NsRZ8/vjP/fOMawgXJXCVsR6O2lamm1BCnQ==
|
||||
mogh_auth_client@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/mogh_auth_client/-/mogh_auth_client-1.5.0.tgz#f54b8ae35648d5bf1e60d7b67fcdcef45b0ccd7a"
|
||||
integrity sha512-eUQmx682AzJRaY4QJSALtIGxXzg2r2Tr8exnDeFMrNe0Ibn4Oqm3h9SkOzYiqqZjKQ13wvHm0RoxT2QKo+908g==
|
||||
dependencies:
|
||||
jwt-decode "^4.0.0"
|
||||
|
||||
typescript@^5.6.3:
|
||||
version "5.6.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b"
|
||||
integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==
|
||||
typescript@^6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.2.tgz#0b1bfb15f68c64b97032f3d78abbf98bdbba501f"
|
||||
integrity sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use komodo_client::entities::{
|
||||
SearchCombinator,
|
||||
deployment::Deployment,
|
||||
@@ -63,11 +61,12 @@ pub struct RemoveSwarmNodes {
|
||||
#[response(Log)]
|
||||
#[error(anyhow::Error)]
|
||||
pub struct UpdateSwarmNode {
|
||||
/// Node hostname or id
|
||||
pub node: String,
|
||||
/// Update the node's availability: 'active', 'pause', or 'drain'
|
||||
pub availability: Option<NodeSpecAvailabilityEnum>,
|
||||
/// Add metadata to a swarm node using node labels (`key=value`).
|
||||
/// You can specify a node label as a key with an empty value.
|
||||
pub label_add: Option<HashMap<String, Option<String>>>,
|
||||
pub label_add: Option<Vec<String>>,
|
||||
/// Remove labels by the label key.
|
||||
pub label_rm: Option<Vec<String>>,
|
||||
/// Update the node role (`worker`, `manager`)
|
||||
|
||||
+2
-1
@@ -145,6 +145,7 @@ PERIPHERY_CORE_PUBLIC_KEYS=file:/config/keys/core.pub
|
||||
## ------ ./my_stack_2
|
||||
## --- ./repos
|
||||
## ------ ./my_repo_1
|
||||
## --- ./builds
|
||||
PERIPHERY_ROOT_DIRECTORY=/etc/komodo
|
||||
|
||||
## Specify whether to disable the terminals feature
|
||||
@@ -164,4 +165,4 @@ PERIPHERY_INCLUDE_DISK_MOUNTS=/etc/hostname
|
||||
## Prettier logging with empty lines between logs
|
||||
PERIPHERY_LOGGING_PRETTY=false
|
||||
## More human readable logging of startup config (multi-line)
|
||||
PERIPHERY_PRETTY_STARTUP_CONFIG=false
|
||||
PERIPHERY_PRETTY_STARTUP_CONFIG=false
|
||||
|
||||
+60
-3
@@ -167,6 +167,20 @@ init_admin_password = "changeme"
|
||||
## Default: false
|
||||
disable_user_registration = false
|
||||
|
||||
## Disable local (username/password) user registration only.
|
||||
## When set to true, the "Sign Up" button is hidden and local signups are blocked,
|
||||
## but OIDC and other external provider signups may still be allowed.
|
||||
## If not set, falls back to `disable_user_registration`.
|
||||
## Env: KOMODO_DISABLE_LOCAL_USER_REGISTRATION
|
||||
# disable_local_user_registration = true
|
||||
|
||||
## Disable OIDC user registration only.
|
||||
## When set to true, new users cannot register via OIDC,
|
||||
## but local and other provider signups may still be allowed.
|
||||
## If not set, falls back to `disable_user_registration`.
|
||||
## Env: KOMODO_DISABLE_OIDC_USER_REGISTRATION
|
||||
# disable_oidc_user_registration = true
|
||||
|
||||
## New users will be automatically enabled when they sign up.
|
||||
## Otherwise, new users will be disabled on first login.
|
||||
## The first user to login will always be enabled on creation.
|
||||
@@ -267,6 +281,13 @@ oidc_use_full_email = false
|
||||
## Default: empty
|
||||
oidc_additional_audiences = []
|
||||
|
||||
## Automatically redirect unauthenticated users to the OIDC provider
|
||||
## instead of showing the login page.
|
||||
## Users can bypass the redirect by appending `?disableAutoLogin` to the login URL.
|
||||
## Env: KOMODO_OIDC_AUTO_REDIRECT
|
||||
## Default: false
|
||||
oidc_auto_redirect = false
|
||||
|
||||
#########
|
||||
# OAUTH #
|
||||
#########
|
||||
@@ -324,9 +345,9 @@ auth_rate_limit_max_attempts = 5
|
||||
## Default: 15
|
||||
auth_rate_limit_window_seconds = 15
|
||||
|
||||
##################
|
||||
# CORS / SESSION #
|
||||
##################
|
||||
############################
|
||||
# CORS / SESSION / HEADERS #
|
||||
############################
|
||||
|
||||
## Specifically set list of CORS allowed origins.
|
||||
## If empty, allows all origins (`*`).
|
||||
@@ -343,8 +364,44 @@ cors_allow_credentials = false
|
||||
|
||||
## Enabling this sets 'SameSite=None', which allows externally
|
||||
## hosted UIs to use the login flows.
|
||||
## Env: KOMODO_SESSION_ALLOW_CROSS_SITE
|
||||
## Default: false
|
||||
session_allow_cross_site = false
|
||||
|
||||
## `X-Content-Type-Options` header value.
|
||||
## Set as empty string to omit the header.
|
||||
## Env: KOMODO_X_CONTENT_TYPE_OPTIONS
|
||||
## Default: "nosniff"
|
||||
x_content_type_options = "nosniff"
|
||||
|
||||
## `X-Frame-Options` header value.
|
||||
## Set as empty string to omit the header.
|
||||
## Use "SAMEORIGIN" to allow same-origin embedding only.
|
||||
## Env: KOMODO_X_FRAME_OPTIONS
|
||||
## Default: "DENY"
|
||||
x_frame_options = "DENY"
|
||||
|
||||
## `X-Xss-Protection` header value.
|
||||
## Set as empty string to omit the header.
|
||||
## Env: KOMODO_X_XSS_PROTECTION
|
||||
## Default: "1; mode=block"
|
||||
x_xss_protection = "1; mode=block"
|
||||
|
||||
## Apply Referrer Policy directives.
|
||||
## If empty string, no header is applied.
|
||||
## Env: KOMODO_REFERRER_POLICY
|
||||
## Default: "strict-origin-when-cross-origin"
|
||||
referrer_policy = "strict-origin-when-cross-origin"
|
||||
|
||||
## Apply Content Security Policy directives.
|
||||
## If empty string, no header is applied.
|
||||
## Env: KOMODO_CONTENT_SECURITY_POLICY
|
||||
## Default: ""
|
||||
##
|
||||
## Example:
|
||||
## `default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; form-action 'self'`
|
||||
content_security_policy = ""
|
||||
|
||||
##################
|
||||
# POLL INTERVALS #
|
||||
##################
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
## ------ ./my_stack_2
|
||||
## --- ./repos
|
||||
## ------ ./my_repo_1
|
||||
## --- ./builds
|
||||
## Each specific sub-directory (like ./stacks) can be overridden below.
|
||||
## Env: PERIPHERY_ROOT_DIRECTORY
|
||||
## Default: /etc/komodo
|
||||
@@ -291,4 +292,4 @@ pretty_startup_config = false
|
||||
## Provide periphery-based secrets
|
||||
# [secrets]
|
||||
# SECRET_1 = "value_1"
|
||||
# SECRET_2 = "value_2"
|
||||
# SECRET_2 = "value_2"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user