client: add basic namespace commands
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
parent
473063e9ec
commit
226a4e68da
@ -71,6 +71,7 @@ pub use catalog::*;
|
|||||||
mod snapshot;
|
mod snapshot;
|
||||||
pub use snapshot::*;
|
pub use snapshot::*;
|
||||||
pub mod key;
|
pub mod key;
|
||||||
|
pub mod namespace;
|
||||||
|
|
||||||
fn record_repository(repo: &BackupRepository) {
|
fn record_repository(repo: &BackupRepository) {
|
||||||
let base = match BaseDirectories::with_prefix("proxmox-backup") {
|
let base = match BaseDirectories::with_prefix("proxmox-backup") {
|
||||||
@ -1685,6 +1686,7 @@ fn main() {
|
|||||||
.insert("version", version_cmd_def)
|
.insert("version", version_cmd_def)
|
||||||
.insert("benchmark", benchmark_cmd_def)
|
.insert("benchmark", benchmark_cmd_def)
|
||||||
.insert("change-owner", change_owner_cmd_def)
|
.insert("change-owner", change_owner_cmd_def)
|
||||||
|
.insert("namespace", namespace::cli_map())
|
||||||
.alias(&["files"], &["snapshot", "files"])
|
.alias(&["files"], &["snapshot", "files"])
|
||||||
.alias(&["forget"], &["snapshot", "forget"])
|
.alias(&["forget"], &["snapshot", "forget"])
|
||||||
.alias(&["upload-log"], &["snapshot", "upload-log"])
|
.alias(&["upload-log"], &["snapshot", "upload-log"])
|
||||||
|
170
proxmox-backup-client/src/namespace.rs
Normal file
170
proxmox-backup-client/src/namespace.rs
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
use anyhow::{bail, Error};
|
||||||
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
|
use pbs_api_types::BackupNamespace;
|
||||||
|
use pbs_client::tools::REPO_URL_SCHEMA;
|
||||||
|
|
||||||
|
use proxmox_router::cli::{
|
||||||
|
format_and_print_result, get_output_format, CliCommand, CliCommandMap, OUTPUT_FORMAT,
|
||||||
|
};
|
||||||
|
use proxmox_schema::api;
|
||||||
|
|
||||||
|
use crate::{connect, extract_repository_from_value, optional_ns_param, record_repository};
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
input: {
|
||||||
|
properties: {
|
||||||
|
repository: {
|
||||||
|
schema: REPO_URL_SCHEMA,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
ns: {
|
||||||
|
type: BackupNamespace,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
"max-depth": {
|
||||||
|
description: "maximum recursion depth",
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
"output-format": {
|
||||||
|
schema: OUTPUT_FORMAT,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// List namespaces in a repository.
|
||||||
|
async fn list_namespaces(param: Value, max_depth: Option<usize>) -> Result<(), Error> {
|
||||||
|
let output_format = get_output_format(¶m);
|
||||||
|
let repo = extract_repository_from_value(¶m)?;
|
||||||
|
let backup_ns = optional_ns_param(¶m)?;
|
||||||
|
|
||||||
|
let path = format!("api2/json/admin/datastore/{}/namespace", repo.store());
|
||||||
|
|
||||||
|
let mut param = json!({});
|
||||||
|
|
||||||
|
if let Some(max_depth) = max_depth {
|
||||||
|
param["max-depth"] = max_depth.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
if !backup_ns.is_root() {
|
||||||
|
param["parent"] = serde_json::to_value(backup_ns)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let client = connect(&repo)?;
|
||||||
|
|
||||||
|
let mut result = client.get(&path, Some(param)).await?;
|
||||||
|
|
||||||
|
record_repository(&repo);
|
||||||
|
|
||||||
|
if output_format == "text" {
|
||||||
|
let data: Vec<pbs_api_types::NamespaceListItem> =
|
||||||
|
serde_json::from_value(result["data"].take())?;
|
||||||
|
for entry in data {
|
||||||
|
if entry.ns.is_root() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(comment) = entry.comment {
|
||||||
|
println!("{} ({comment})", entry.ns);
|
||||||
|
} else {
|
||||||
|
println!("{}", entry.ns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
format_and_print_result(&result, &output_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
input: {
|
||||||
|
properties: {
|
||||||
|
repository: {
|
||||||
|
schema: REPO_URL_SCHEMA,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
ns: {
|
||||||
|
type: BackupNamespace,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// Create a new namespace.
|
||||||
|
async fn create_namespace(param: Value) -> Result<(), Error> {
|
||||||
|
let repo = extract_repository_from_value(¶m)?;
|
||||||
|
let mut backup_ns = optional_ns_param(¶m)?;
|
||||||
|
|
||||||
|
let path = format!("api2/json/admin/datastore/{}/namespace", repo.store());
|
||||||
|
|
||||||
|
let name = match backup_ns.pop() {
|
||||||
|
Some(name) => name,
|
||||||
|
None => bail!("root namespace is always present"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let param = json!({
|
||||||
|
"parent": backup_ns,
|
||||||
|
"name": name,
|
||||||
|
});
|
||||||
|
|
||||||
|
let client = connect(&repo)?;
|
||||||
|
|
||||||
|
let _result = client.post(&path, Some(param)).await?;
|
||||||
|
|
||||||
|
record_repository(&repo);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
input: {
|
||||||
|
properties: {
|
||||||
|
repository: {
|
||||||
|
schema: REPO_URL_SCHEMA,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
ns: {
|
||||||
|
type: BackupNamespace,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// Delete an existing namespace.
|
||||||
|
async fn delete_namespace(param: Value) -> Result<(), Error> {
|
||||||
|
let repo = extract_repository_from_value(¶m)?;
|
||||||
|
let backup_ns = optional_ns_param(¶m)?;
|
||||||
|
|
||||||
|
if backup_ns.is_root() {
|
||||||
|
bail!("root namespace cannot be deleted");
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = format!("api2/json/admin/datastore/{}/namespace", repo.store());
|
||||||
|
let param = json!({ "ns": backup_ns });
|
||||||
|
|
||||||
|
let client = connect(&repo)?;
|
||||||
|
|
||||||
|
let _result = client.delete(&path, Some(param)).await?;
|
||||||
|
|
||||||
|
record_repository(&repo);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cli_map() -> CliCommandMap {
|
||||||
|
CliCommandMap::new()
|
||||||
|
.insert(
|
||||||
|
"list",
|
||||||
|
CliCommand::new(&API_METHOD_LIST_NAMESPACES).arg_param(&["ns"]),
|
||||||
|
)
|
||||||
|
.insert(
|
||||||
|
"create",
|
||||||
|
CliCommand::new(&API_METHOD_CREATE_NAMESPACE).arg_param(&["ns"]),
|
||||||
|
)
|
||||||
|
.insert(
|
||||||
|
"delete",
|
||||||
|
CliCommand::new(&API_METHOD_DELETE_NAMESPACE).arg_param(&["ns"]),
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user