WP-30/31/32: backup targets, strategies and execution
SMB (smbclient) and FTP/FTPS (curl with netrc) targets with encrypted credentials and connection test; strategies with cron schedule, retention, optional openssl AES-256 encryption; sources: PVC hostpath tar, pg_dumpall in the Postgres pod, namespace manifests, host directory. Backup job collects, encrypts, uploads, verifies size, records sha256 and applies retention on the target; scheduler starts due strategies. Backups page with target/strategy forms, run now and history. Restore guide in docs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@ -58,17 +58,25 @@ async fn unknown_kind_is_404_and_run_is_admin_only() {
|
||||
.status,
|
||||
StatusCode::UNPROCESSABLE_ENTITY
|
||||
);
|
||||
assert_eq!(
|
||||
post(
|
||||
&app,
|
||||
"/api/jobs/run",
|
||||
json!({"kind": "backup"}),
|
||||
Some(&admin)
|
||||
)
|
||||
.await
|
||||
.status,
|
||||
StatusCode::NOT_FOUND
|
||||
);
|
||||
// every kind has a handler now; a backup without a strategy id starts and then fails
|
||||
let run = post(
|
||||
&app,
|
||||
"/api/jobs/run",
|
||||
json!({"kind": "backup"}),
|
||||
Some(&admin),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(run.status, StatusCode::ACCEPTED);
|
||||
let id = run.json["id"].as_str().unwrap().to_string();
|
||||
for _ in 0..50 {
|
||||
let r = get(&app, &format!("/api/jobs/{id}"), Some(&admin)).await;
|
||||
if r.json["status"] != "running" {
|
||||
assert_eq!(r.json["status"], "failed");
|
||||
assert!(r.json["log"].as_str().unwrap().contains("strategy id"));
|
||||
break;
|
||||
}
|
||||
tokio::time::sleep(std::time::Duration::from_millis(20)).await;
|
||||
}
|
||||
post(&app, "/api/users", json!({"email": "u@x.de", "display_name": "U", "password": "user-password-123", "role": "user"}), Some(&admin)).await;
|
||||
let user = common::login(&app, "u@x.de", "user-password-123")
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user