api-types: add PruneJobConfig
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
8721b42e2f
commit
5557af0efb
|
@ -157,52 +157,6 @@ pub const PRUNE_SCHEMA_KEEP_YEARLY: Schema =
|
||||||
.minimum(1)
|
.minimum(1)
|
||||||
.schema();
|
.schema();
|
||||||
|
|
||||||
#[api(
|
|
||||||
properties: {
|
|
||||||
"keep-last": {
|
|
||||||
schema: PRUNE_SCHEMA_KEEP_LAST,
|
|
||||||
optional: true,
|
|
||||||
},
|
|
||||||
"keep-hourly": {
|
|
||||||
schema: PRUNE_SCHEMA_KEEP_HOURLY,
|
|
||||||
optional: true,
|
|
||||||
},
|
|
||||||
"keep-daily": {
|
|
||||||
schema: PRUNE_SCHEMA_KEEP_DAILY,
|
|
||||||
optional: true,
|
|
||||||
},
|
|
||||||
"keep-weekly": {
|
|
||||||
schema: PRUNE_SCHEMA_KEEP_WEEKLY,
|
|
||||||
optional: true,
|
|
||||||
},
|
|
||||||
"keep-monthly": {
|
|
||||||
schema: PRUNE_SCHEMA_KEEP_MONTHLY,
|
|
||||||
optional: true,
|
|
||||||
},
|
|
||||||
"keep-yearly": {
|
|
||||||
schema: PRUNE_SCHEMA_KEEP_YEARLY,
|
|
||||||
optional: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)]
|
|
||||||
#[derive(Serialize, Deserialize, Default)]
|
|
||||||
#[serde(rename_all = "kebab-case")]
|
|
||||||
/// Common pruning options
|
|
||||||
pub struct PruneOptions {
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub keep_last: Option<u64>,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub keep_hourly: Option<u64>,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub keep_daily: Option<u64>,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub keep_weekly: Option<u64>,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub keep_monthly: Option<u64>,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub keep_yearly: Option<u64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[api]
|
#[api]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
|
@ -705,6 +659,28 @@ impl BackupNamespace {
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check whether this namespace contains another namespace.
|
||||||
|
///
|
||||||
|
/// If so, the depth is returned.
|
||||||
|
///
|
||||||
|
/// Example:
|
||||||
|
/// ```
|
||||||
|
/// # use pbs_api_types::BackupNamespace;
|
||||||
|
/// let main: BackupNamespace = "a/b".parse().unwrap();
|
||||||
|
/// let sub: BackupNamespace = "a/b/c/d".parse().unwrap();
|
||||||
|
/// let other: BackupNamespace = "x/y".parse().unwrap();
|
||||||
|
/// assert_eq!(main.contains(&main), Some(0));
|
||||||
|
/// assert_eq!(main.contains(&sub), Some(2));
|
||||||
|
/// assert_eq!(sub.contains(&main), None);
|
||||||
|
/// assert_eq!(main.contains(&other), None);
|
||||||
|
/// ```
|
||||||
|
pub fn contains(&self, other: &BackupNamespace) -> Option<usize> {
|
||||||
|
other
|
||||||
|
.inner
|
||||||
|
.strip_prefix(&self.inner[..])
|
||||||
|
.map(|suffix| suffix.len())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for BackupNamespace {
|
impl fmt::Display for BackupNamespace {
|
||||||
|
|
|
@ -535,3 +535,185 @@ pub struct SyncJobStatus {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub status: JobScheduleStatus,
|
pub status: JobScheduleStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// These are used separately without `ns`/`max-depth` sometimes in the API, specifically in the API
|
||||||
|
/// call to prune a specific group, where `max-depth` makes no sense.
|
||||||
|
#[api(
|
||||||
|
properties: {
|
||||||
|
"keep-last": {
|
||||||
|
schema: crate::PRUNE_SCHEMA_KEEP_LAST,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
"keep-hourly": {
|
||||||
|
schema: crate::PRUNE_SCHEMA_KEEP_HOURLY,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
"keep-daily": {
|
||||||
|
schema: crate::PRUNE_SCHEMA_KEEP_DAILY,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
"keep-weekly": {
|
||||||
|
schema: crate::PRUNE_SCHEMA_KEEP_WEEKLY,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
"keep-monthly": {
|
||||||
|
schema: crate::PRUNE_SCHEMA_KEEP_MONTHLY,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
"keep-yearly": {
|
||||||
|
schema: crate::PRUNE_SCHEMA_KEEP_YEARLY,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)]
|
||||||
|
#[derive(Serialize, Deserialize, Default, Updater)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
/// Common pruning options
|
||||||
|
pub struct KeepOptions {
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub keep_last: Option<u64>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub keep_hourly: Option<u64>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub keep_daily: Option<u64>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub keep_weekly: Option<u64>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub keep_monthly: Option<u64>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub keep_yearly: Option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeepOptions {
|
||||||
|
pub fn keeps_something(&self) -> bool {
|
||||||
|
self.keep_last.unwrap_or(0)
|
||||||
|
+ self.keep_hourly.unwrap_or(0)
|
||||||
|
+ self.keep_daily.unwrap_or(0)
|
||||||
|
+ self.keep_monthly.unwrap_or(0)
|
||||||
|
+ self.keep_yearly.unwrap_or(0)
|
||||||
|
> 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
properties: {
|
||||||
|
keep: {
|
||||||
|
type: KeepOptions,
|
||||||
|
},
|
||||||
|
ns: {
|
||||||
|
type: BackupNamespace,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
"max-depth": {
|
||||||
|
schema: NS_MAX_DEPTH_REDUCED_SCHEMA,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)]
|
||||||
|
#[derive(Serialize, Deserialize, Default, Updater)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
/// Common pruning options
|
||||||
|
pub struct PruneJobOptions {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub keep: KeepOptions,
|
||||||
|
|
||||||
|
/// The (optional) recursion depth
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub max_depth: Option<usize>,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub ns: Option<BackupNamespace>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PruneJobOptions {
|
||||||
|
pub fn keeps_something(&self) -> bool {
|
||||||
|
self.keep.keeps_something()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn acl_path<'a>(&'a self, store: &'a str) -> Vec<&'a str> {
|
||||||
|
match &self.ns {
|
||||||
|
Some(ns) => ns.acl_path(store),
|
||||||
|
None => vec!["datastore", store],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
properties: {
|
||||||
|
disable: {
|
||||||
|
type: Boolean,
|
||||||
|
optional: true,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
schema: JOB_ID_SCHEMA,
|
||||||
|
},
|
||||||
|
store: {
|
||||||
|
schema: DATASTORE_SCHEMA,
|
||||||
|
},
|
||||||
|
schedule: {
|
||||||
|
schema: PRUNE_SCHEDULE_SCHEMA,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
comment: {
|
||||||
|
optional: true,
|
||||||
|
schema: SINGLE_LINE_COMMENT_SCHEMA,
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: PruneJobOptions,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
#[derive(Deserialize, Serialize, Updater)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
/// Prune configuration.
|
||||||
|
pub struct PruneJobConfig {
|
||||||
|
/// unique ID to address this job
|
||||||
|
#[updater(skip)]
|
||||||
|
pub id: String,
|
||||||
|
|
||||||
|
pub store: String,
|
||||||
|
|
||||||
|
/// Disable this job.
|
||||||
|
#[serde(default, skip_serializing_if = "is_false")]
|
||||||
|
#[updater(serde(skip_serializing_if = "Option::is_none"))]
|
||||||
|
pub disable: bool,
|
||||||
|
|
||||||
|
pub schedule: String,
|
||||||
|
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub comment: Option<String>,
|
||||||
|
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub options: PruneJobOptions,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PruneJobConfig {
|
||||||
|
pub fn acl_path(&self) -> Vec<&str> {
|
||||||
|
self.options.acl_path(&self.store)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_false(b: &bool) -> bool {
|
||||||
|
!b
|
||||||
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
properties: {
|
||||||
|
config: {
|
||||||
|
type: PruneJobConfig,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: JobScheduleStatus,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
/// Status of prune job
|
||||||
|
pub struct PruneJobStatus {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub config: PruneJobConfig,
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub status: JobScheduleStatus,
|
||||||
|
}
|
||||||
|
|
|
@ -103,41 +103,6 @@ fn remove_incomplete_snapshots(mark: &mut HashMap<PathBuf, PruneMark>, list: &[B
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn keeps_something(options: &PruneOptions) -> bool {
|
|
||||||
let mut keep_something = false;
|
|
||||||
if let Some(count) = options.keep_last {
|
|
||||||
if count > 0 {
|
|
||||||
keep_something = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(count) = options.keep_hourly {
|
|
||||||
if count > 0 {
|
|
||||||
keep_something = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(count) = options.keep_daily {
|
|
||||||
if count > 0 {
|
|
||||||
keep_something = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(count) = options.keep_weekly {
|
|
||||||
if count > 0 {
|
|
||||||
keep_something = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(count) = options.keep_monthly {
|
|
||||||
if count > 0 {
|
|
||||||
keep_something = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(count) = options.keep_yearly {
|
|
||||||
if count > 0 {
|
|
||||||
keep_something = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
keep_something
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cli_options_string(options: &PruneOptions) -> String {
|
pub fn cli_options_string(options: &PruneOptions) -> String {
|
||||||
let mut opts = Vec::new();
|
let mut opts = Vec::new();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue