Discover applications on the cluster and the host for backups
Kubernetes workloads are grouped by their Helm instance label into applications, each offering what is worth backing up: data volumes, a PostgreSQL dump instead of the database's own volume, and optionally the namespace manifests. Caches are listed but not preselected. Host applications come from running systemd services that declare a state or working directory. Selecting components creates one strategy each. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@ -1,9 +1,10 @@
|
||||
//! /api/backups: targets, strategies, records, manual runs.
|
||||
use application::backup_service::StrategyStatus;
|
||||
use application::backup_service::{ApplicationBackupPlan, StrategyStatus};
|
||||
use axum::extract::{Path, State};
|
||||
use axum::http::StatusCode;
|
||||
use axum::routing::{get, post};
|
||||
use axum::{Json, Router};
|
||||
use domain::application::Application;
|
||||
use domain::backup::{BackupRecord, BackupSource, BackupStrategy, BackupTarget, StorageKind};
|
||||
use domain::jobs::JobKind;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -31,6 +32,55 @@ pub fn router() -> Router<AppState> {
|
||||
)
|
||||
.route("/strategies/{id}/run", post(run_strategy))
|
||||
.route("/strategies/{id}/records", get(records))
|
||||
.route(
|
||||
"/applications",
|
||||
get(list_applications).post(create_from_application),
|
||||
)
|
||||
}
|
||||
|
||||
// ---- applications ----
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct ApplicationBackupRequest {
|
||||
pub application_id: String,
|
||||
pub component_ids: Vec<String>,
|
||||
pub schedule: String,
|
||||
pub target_id: Uuid,
|
||||
pub retention: u32,
|
||||
#[serde(default)]
|
||||
pub passphrase: Option<String>,
|
||||
}
|
||||
|
||||
#[utoipa::path(get, path = "/api/backups/applications", tag = "backups", security(("bearer" = [])),
|
||||
responses((status = 200, body = Vec<Object>)))]
|
||||
async fn list_applications(
|
||||
State(s): State<AppState>,
|
||||
_: AuthUser,
|
||||
) -> Result<Json<Vec<Application>>, ApiError> {
|
||||
Ok(Json(s.backups.applications().await?))
|
||||
}
|
||||
|
||||
#[utoipa::path(post, path = "/api/backups/applications", tag = "backups", security(("bearer" = [])),
|
||||
request_body = ApplicationBackupRequest, responses((status = 201, body = Vec<StrategyView>), (status = 404), (status = 422)))]
|
||||
async fn create_from_application(
|
||||
State(s): State<AppState>,
|
||||
_: AdminUser,
|
||||
Json(req): Json<ApplicationBackupRequest>,
|
||||
) -> Result<(StatusCode, Json<Vec<StrategyView>>), ApiError> {
|
||||
let plan = ApplicationBackupPlan {
|
||||
schedule: req.schedule,
|
||||
target_id: req.target_id,
|
||||
retention: req.retention,
|
||||
passphrase: req.passphrase.filter(|p| !p.is_empty()),
|
||||
};
|
||||
let created = s
|
||||
.backups
|
||||
.create_from_application(&req.application_id, &req.component_ids, plan)
|
||||
.await?;
|
||||
Ok((
|
||||
StatusCode::CREATED,
|
||||
Json(created.into_iter().map(Into::into).collect()),
|
||||
))
|
||||
}
|
||||
|
||||
// ---- targets ----
|
||||
|
||||
@ -130,6 +130,7 @@ impl AppState {
|
||||
} = adapters;
|
||||
let pool_for_findings = pool.clone();
|
||||
let cluster_gateway = cluster.clone();
|
||||
let cluster_gateway_for_backups = cluster.clone();
|
||||
let users = Arc::new(SqliteUsers(pool.clone()));
|
||||
let hasher = Arc::new(Argon2Hasher);
|
||||
let auth = AuthService::new(
|
||||
@ -141,6 +142,8 @@ impl AppState {
|
||||
);
|
||||
let cipher = Arc::new(AesGcmCipher::from_hex(&cfg.master_key)?);
|
||||
let backups = Arc::new(BackupService::new(BackupDeps {
|
||||
cluster: cluster_gateway_for_backups,
|
||||
host: inspector.clone(),
|
||||
targets: Arc::new(SqliteBackupTargets(pool.clone())),
|
||||
strategies: Arc::new(SqliteBackupStrategies(pool.clone())),
|
||||
records: Arc::new(SqliteBackupRecords(pool.clone())),
|
||||
|
||||
@ -34,6 +34,7 @@ impl Modify for BearerAuth {
|
||||
crate::backups::delete_target, crate::backups::test_target, crate::backups::list_strategies, crate::backups::get_strategy,
|
||||
crate::backups::create_strategy, crate::backups::update_strategy, crate::backups::delete_strategy,
|
||||
crate::backups::run_strategy, crate::backups::records,
|
||||
crate::backups::list_applications, crate::backups::create_from_application,
|
||||
crate::dashboard::dashboard,
|
||||
),
|
||||
modifiers(&BearerAuth)
|
||||
|
||||
Reference in New Issue
Block a user