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:
@ -166,3 +166,64 @@ async fn backups_are_admin_only_for_writes() {
|
||||
StatusCode::UNAUTHORIZED
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn applications_are_listed_and_can_be_backed_up_in_one_step() {
|
||||
let app = test_app_with_admin().await;
|
||||
let token = common::login(&app, ADMIN, PW).await.access;
|
||||
let target = post(&app, "/api/backups/targets", smb(), Some(&token)).await;
|
||||
let tid = target.json["id"].as_str().unwrap().to_string();
|
||||
|
||||
let res = get(&app, "/api/backups/applications", Some(&token)).await;
|
||||
assert_eq!(res.status, StatusCode::OK, "{}", res.json);
|
||||
let apps = res.json.as_array().unwrap();
|
||||
let gitea = apps
|
||||
.iter()
|
||||
.find(|a| a["name"] == "Gitea")
|
||||
.expect("the gitea release");
|
||||
assert_eq!(gitea["kind"], "kubernetes");
|
||||
assert_eq!(gitea["namespace"], "gitea");
|
||||
let components = gitea["components"].as_array().unwrap();
|
||||
let data = components
|
||||
.iter()
|
||||
.find(|c| c["id"] == "data:gitea-shared-storage")
|
||||
.unwrap();
|
||||
assert_eq!(data["kind"], "data");
|
||||
assert_eq!(data["recommended"], true);
|
||||
assert!(components
|
||||
.iter()
|
||||
.any(|c| c["id"] == "db:gitea-postgresql-0" && c["kind"] == "database"));
|
||||
assert!(apps.iter().any(|a| a["kind"] == "host"));
|
||||
|
||||
// "Gitea → data + database → 3am → target → save"
|
||||
let body = json!({
|
||||
"application_id": gitea["id"],
|
||||
"component_ids": ["data:gitea-shared-storage", "db:gitea-postgresql-0"],
|
||||
"schedule": "0 0 3 * * *",
|
||||
"target_id": tid,
|
||||
"retention": 7
|
||||
});
|
||||
let res = post(&app, "/api/backups/applications", body, Some(&token)).await;
|
||||
assert_eq!(res.status, StatusCode::CREATED, "{}", res.json);
|
||||
let created = res.json.as_array().unwrap();
|
||||
assert_eq!(created.len(), 2);
|
||||
assert!(created[0]["name"].as_str().unwrap().starts_with("Gitea – "));
|
||||
assert_eq!(created[0]["schedule"], "0 0 3 * * *");
|
||||
|
||||
let strategies = get(&app, "/api/backups/strategies", Some(&token)).await;
|
||||
assert_eq!(strategies.json.as_array().unwrap().len(), 2);
|
||||
|
||||
// a viewer may look but not create
|
||||
post(&app, "/api/users", json!({"email": "u@x.de", "display_name": "U", "password": "user-password-123", "role": "user"}), Some(&token)).await;
|
||||
let user = common::login(&app, "u@x.de", "user-password-123")
|
||||
.await
|
||||
.access;
|
||||
assert_eq!(
|
||||
get(&app, "/api/backups/applications", Some(&user))
|
||||
.await
|
||||
.status,
|
||||
StatusCode::OK
|
||||
);
|
||||
let res = post(&app, "/api/backups/applications", json!({"application_id": "x", "component_ids": [], "schedule": "0 0 3 * * *", "target_id": tid, "retention": 7}), Some(&user)).await;
|
||||
assert_eq!(res.status, StatusCode::FORBIDDEN);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user