Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 28 additions & 17 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -967,10 +967,17 @@ pub enum EventCommands {

#[derive(Subcommand)]
pub enum BackupCommands {
/// List backups for a site
/// List backups
List {
/// Site ID
site_id: String,
/// Filter by site ID
#[arg(long)]
site_id: Option<String>,
/// Filter by environment ID
#[arg(long)]
environment_id: Option<String>,
/// Filter by type (site, environment)
#[arg(long = "type")]
backup_type: Option<String>,
/// Page number
#[arg(long, default_value = "1")]
page: u32,
Expand All @@ -980,15 +987,17 @@ pub enum BackupCommands {
},
/// Show backup details
Show {
/// Site ID
site_id: String,
/// Backup ID
backup_id: String,
},
/// Create a manual backup
Create {
/// Site ID
site_id: String,
#[arg(long)]
site_id: Option<String>,
/// Environment ID
#[arg(long)]
environment_id: Option<String>,
/// Backup scope (full, database, files)
#[arg(long, default_value = "full")]
scope: String,
Expand All @@ -1007,15 +1016,11 @@ pub enum BackupCommands {
pub enum BackupDownloadCommands {
/// Create a backup download request
Create {
/// Site ID
site_id: String,
/// Backup ID
backup_id: String,
},
/// Check backup download status
Status {
/// Site ID
site_id: String,
/// Backup ID
backup_id: String,
/// Download ID
Expand All @@ -1025,10 +1030,20 @@ pub enum BackupDownloadCommands {

#[derive(Subcommand)]
pub enum RestoreCommands {
/// List restores for a site
/// List restores
List {
/// Site ID
site_id: String,
/// Filter by site ID
#[arg(long)]
site_id: Option<String>,
/// Filter by environment ID
#[arg(long)]
environment_id: Option<String>,
/// Filter by type (site, environment)
#[arg(long = "type")]
restore_type: Option<String>,
/// Filter by backup ID
#[arg(long)]
backup_id: Option<String>,
/// Page number
#[arg(long, default_value = "1")]
page: u32,
Expand All @@ -1038,15 +1053,11 @@ pub enum RestoreCommands {
},
/// Show restore details
Show {
/// Site ID
site_id: String,
/// Restore ID
restore_id: String,
},
/// Create a restore from a backup
Create {
/// Site ID
site_id: String,
/// Backup ID to restore from
backup_id: String,
/// Restore scope (full, database, files)
Expand Down
99 changes: 66 additions & 33 deletions src/commands/backup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,50 @@ use serde_json::Value;

use crate::api::{ApiClient, ApiError};
use crate::output::{
OutputFormat, extract_pagination, format_option, print_json, print_key_value, print_message,
print_pagination, print_table,
OutputFormat, extract_pagination, format_archivable_type, format_option, print_json,
print_key_value, print_message, print_pagination, print_table,
};

#[derive(Debug, Serialize)]
struct PaginationQuery {
struct ListBackupsQuery {
#[serde(skip_serializing_if = "Option::is_none")]
r#type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
site_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
environment_id: Option<String>,
page: u32,
per_page: u32,
}

#[derive(Debug, Serialize)]
struct CreateBackupRequest {
r#type: String,
#[serde(skip_serializing_if = "Option::is_none")]
site_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
environment_id: Option<String>,
scope: String,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
}

pub fn list(
client: &ApiClient,
site_id: &str,
site_id: Option<String>,
environment_id: Option<String>,
backup_type: Option<String>,
page: u32,
per_page: u32,
format: OutputFormat,
) -> Result<(), ApiError> {
let query = PaginationQuery { page, per_page };
let response: Value =
client.get_with_query(&format!("/api/v1/vector/sites/{}/backups", site_id), &query)?;
let query = ListBackupsQuery {
r#type: backup_type,
site_id,
environment_id,
page,
per_page,
};
let response: Value = client.get_with_query("/api/v1/vector/backups", &query)?;

if format == OutputFormat::Json {
print_json(&response);
Expand All @@ -51,6 +67,10 @@ pub fn list(
.map(|b| {
vec![
b["id"].as_str().unwrap_or("-").to_string(),
b["archivable_type"]
.as_str()
.map(format_archivable_type)
.unwrap_or_else(|| "-".to_string()),
b["type"].as_str().unwrap_or("-").to_string(),
b["scope"].as_str().unwrap_or("-").to_string(),
b["status"].as_str().unwrap_or("-").to_string(),
Expand All @@ -61,7 +81,15 @@ pub fn list(
.collect();

print_table(
vec!["ID", "Type", "Scope", "Status", "Description", "Created"],
vec![
"ID",
"Model",
"Type",
"Scope",
"Status",
"Description",
"Created",
],
rows,
);

Expand All @@ -72,16 +100,8 @@ pub fn list(
Ok(())
}

pub fn show(
client: &ApiClient,
site_id: &str,
backup_id: &str,
format: OutputFormat,
) -> Result<(), ApiError> {
let response: Value = client.get(&format!(
"/api/v1/vector/sites/{}/backups/{}",
site_id, backup_id
))?;
pub fn show(client: &ApiClient, backup_id: &str, format: OutputFormat) -> Result<(), ApiError> {
let response: Value = client.get(&format!("/api/v1/vector/backups/{}", backup_id))?;

if format == OutputFormat::Json {
print_json(&response);
Expand All @@ -92,6 +112,17 @@ pub fn show(

print_key_value(vec![
("ID", backup["id"].as_str().unwrap_or("-").to_string()),
(
"Model",
backup["archivable_type"]
.as_str()
.map(format_archivable_type)
.unwrap_or_else(|| "-".to_string()),
),
(
"Model ID",
backup["archivable_id"].as_str().unwrap_or("-").to_string(),
),
("Type", backup["type"].as_str().unwrap_or("-").to_string()),
("Scope", backup["scope"].as_str().unwrap_or("-").to_string()),
(
Expand Down Expand Up @@ -133,19 +164,26 @@ pub fn show(

pub fn create(
client: &ApiClient,
site_id: &str,
site_id: Option<String>,
environment_id: Option<String>,
scope: &str,
description: Option<String>,
format: OutputFormat,
) -> Result<(), ApiError> {
if site_id.is_none() && environment_id.is_none() {
return Err(ApiError::Other(
"Either --site-id or --environment-id is required".to_string(),
));
}

let body = CreateBackupRequest {
r#type: "manual".to_string(),
site_id,
environment_id,
scope: scope.to_string(),
description,
};

let response: Value =
client.post(&format!("/api/v1/vector/sites/{}/backups", site_id), &body)?;
let response: Value = client.post("/api/v1/vector/backups", &body)?;

if format == OutputFormat::Json {
print_json(&response);
Expand Down Expand Up @@ -181,14 +219,11 @@ pub fn create(

pub fn download_create(
client: &ApiClient,
site_id: &str,
backup_id: &str,
format: OutputFormat,
) -> Result<(), ApiError> {
let response: Value = client.post_empty(&format!(
"/api/v1/vector/sites/{}/backups/{}/downloads",
site_id, backup_id
))?;
let response: Value =
client.post_empty(&format!("/api/v1/vector/backups/{}/downloads", backup_id))?;

if format == OutputFormat::Json {
print_json(&response);
Expand All @@ -203,8 +238,7 @@ pub fn download_create(
));
print_message("\nCheck status with:");
print_message(&format!(
" vector backup download status {} {} {}",
site_id,
" vector backup download status {} {}",
backup_id,
data["id"].as_str().unwrap_or("DOWNLOAD_ID")
));
Expand All @@ -214,14 +248,13 @@ pub fn download_create(

pub fn download_status(
client: &ApiClient,
site_id: &str,
backup_id: &str,
download_id: &str,
format: OutputFormat,
) -> Result<(), ApiError> {
let response: Value = client.get(&format!(
"/api/v1/vector/sites/{}/backups/{}/downloads/{}",
site_id, backup_id, download_id
"/api/v1/vector/backups/{}/downloads/{}",
backup_id, download_id
))?;

if format == OutputFormat::Json {
Expand Down
Loading
Loading