+3
Cargo.lock
+3
Cargo.lock
+4
-1
admin_cli/Cargo.toml
+4
-1
admin_cli/Cargo.toml
+56
admin_cli/src/main.rs
+56
admin_cli/src/main.rs
···
11
11
use log;
12
12
use reqwest::header;
13
13
use reqwest::header::{HeaderMap, HeaderValue};
14
+
use s3::creds::Credentials;
15
+
use s3::{Bucket, Region};
16
+
use sqlx::PgPool;
14
17
use std::env;
15
18
16
19
fn init_logging() {
···
52
55
},
53
56
/// Trigger an instance-wide backup job (no parameters)
54
57
RequestInstanceBackup,
58
+
/// Verify all backups in S3 against the database
59
+
VerifyBackups,
55
60
}
56
61
57
62
#[derive(Debug, Subcommand)]
···
219
224
}
220
225
Err(err) => {
221
226
log::error!("Instance backup request failed: {}", err);
227
+
}
228
+
}
229
+
}
230
+
Commands::VerifyBackups => {
231
+
log::info!("Verifying backups in S3...");
232
+
233
+
// Get database URL from environment
234
+
let database_url =
235
+
env::var("DATABASE_URL").context("DATABASE_URL environment variable not set")?;
236
+
237
+
// Connect to database
238
+
let pool = PgPool::connect(&database_url)
239
+
.await
240
+
.context("Failed to connect to database")?;
241
+
242
+
// Setup S3 client
243
+
let region_name = env::var("S3_REGION")?;
244
+
let endpoint = env::var("S3_ENDPOINT")?;
245
+
let region = Region::Custom {
246
+
region: region_name,
247
+
endpoint,
248
+
};
249
+
let bucket = Bucket::new(
250
+
env::var("S3_BUCKET_NAME")?.as_str(),
251
+
region,
252
+
Credentials::new(
253
+
Some(env::var("S3_ACCESS_KEY")?.as_str()),
254
+
Some(env::var("S3_SECRET_KEY")?.as_str()),
255
+
None,
256
+
None,
257
+
None,
258
+
)?,
259
+
)?;
260
+
261
+
// Call the verify_backups function
262
+
match shared::jobs::verify_backups::verify_backups(&pool, &bucket).await {
263
+
Ok(missing_blobs) => {
264
+
if missing_blobs.is_empty() {
265
+
log::info!("✓ All backups verified successfully! No missing blobs found.");
266
+
} else {
267
+
log::error!("✗ Found {} missing blobs:", missing_blobs.len());
268
+
for missing in &missing_blobs {
269
+
println!(
270
+
"Missing: DID={}, CID/REV={}, TYPE={:?}, PATH={}",
271
+
missing.did, missing.cid_or_rev, missing.blob_type, missing.s3_path
272
+
);
273
+
}
274
+
}
275
+
}
276
+
Err(err) => {
277
+
log::error!("Failed to verify backups: {}", err);
222
278
}
223
279
}
224
280
}