From 0b83e0558e5e3fee5237edac0ae6d9ba304bb073 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Tue, 29 Aug 2023 16:44:27 +0200 Subject: bucket_table: data model for lifecycle configuration --- src/model/bucket_table.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'src/model/bucket_table.rs') diff --git a/src/model/bucket_table.rs b/src/model/bucket_table.rs index ac163736..dc4e4509 100644 --- a/src/model/bucket_table.rs +++ b/src/model/bucket_table.rs @@ -48,6 +48,9 @@ mod v08 { pub website_config: crdt::Lww>, /// CORS rules pub cors_config: crdt::Lww>>, + /// Lifecycle configuration + #[serde(default)] + pub lifecycle_config: crdt::Lww>>, /// Bucket quotas #[serde(default)] pub quotas: crdt::Lww, @@ -69,6 +72,42 @@ mod v08 { pub expose_headers: Vec, } + /// Lifecycle configuration rule + #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] + pub struct LifecycleRule { + /// The ID of the rule + pub id: Option, + /// Whether the rule is active + pub enabled: bool, + /// The filter to check whether rule applies to a given object + pub filter: LifecycleFilter, + /// Number of days after which incomplete multipart uploads are aborted + pub abort_incomplete_mpu_days: Option, + /// Expiration policy for stored objects + pub expiration: Option, + } + + /// A lifecycle filter is a set of conditions that must all be true. + /// For each condition, if it is None, it is not verified (always true), + /// and if it is Some(x), then it is verified for value x + #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] + pub struct LifecycleFilter { + /// If Some(x), object key has to start with prefix x + pub prefix: Option, + /// If Some(x), object size has to be more than x + pub size_gt: Option, + /// If Some(x), object size has to be less than x + pub size_lt: Option, + } + + #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] + pub enum LifecycleExpiration { + /// Objects expire x days after they were created + AfterDays(usize), + /// Objects expire at date x (must be in yyyy-mm-dd format) + AtDate(String), + } + #[derive(Default, PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Serialize, Deserialize)] pub struct BucketQuotas { /// Maximum size in bytes (bucket size = sum of sizes of objects in the bucket) @@ -96,6 +135,7 @@ impl BucketParams { local_aliases: crdt::LwwMap::new(), website_config: crdt::Lww::new(None), cors_config: crdt::Lww::new(None), + lifecycle_config: crdt::Lww::new(None), quotas: crdt::Lww::new(BucketQuotas::default()), } } -- cgit v1.2.3 From abf011c2906d04200bb39d7bc82f7ed973215500 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Tue, 29 Aug 2023 18:22:03 +0200 Subject: lifecycle: implement validation into garage's internal data structure --- src/model/bucket_table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/model/bucket_table.rs') diff --git a/src/model/bucket_table.rs b/src/model/bucket_table.rs index dc4e4509..fed20e05 100644 --- a/src/model/bucket_table.rs +++ b/src/model/bucket_table.rs @@ -90,7 +90,7 @@ mod v08 { /// A lifecycle filter is a set of conditions that must all be true. /// For each condition, if it is None, it is not verified (always true), /// and if it is Some(x), then it is verified for value x - #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] + #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize, Default)] pub struct LifecycleFilter { /// If Some(x), object key has to start with prefix x pub prefix: Option, -- cgit v1.2.3 From f7b409f1140addd508c626b1e80f0f8de52a5639 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Wed, 30 Aug 2023 11:24:01 +0200 Subject: use a NaiveDate in data model, it serializes to string (iso 8601 format) --- src/model/bucket_table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/model/bucket_table.rs') diff --git a/src/model/bucket_table.rs b/src/model/bucket_table.rs index fed20e05..306a58ab 100644 --- a/src/model/bucket_table.rs +++ b/src/model/bucket_table.rs @@ -105,7 +105,7 @@ mod v08 { /// Objects expire x days after they were created AfterDays(usize), /// Objects expire at date x (must be in yyyy-mm-dd format) - AtDate(String), + AtDate(chrono::naive::NaiveDate), } #[derive(Default, PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Serialize, Deserialize)] -- cgit v1.2.3 From 2996dc875fc378ec3597bfa3bdb8ba8951e1865c Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Wed, 30 Aug 2023 14:28:48 +0200 Subject: lifecycle worker: implement main functionality --- src/model/bucket_table.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/model/bucket_table.rs') diff --git a/src/model/bucket_table.rs b/src/model/bucket_table.rs index 306a58ab..e9d574c5 100644 --- a/src/model/bucket_table.rs +++ b/src/model/bucket_table.rs @@ -95,9 +95,9 @@ mod v08 { /// If Some(x), object key has to start with prefix x pub prefix: Option, /// If Some(x), object size has to be more than x - pub size_gt: Option, + pub size_gt: Option, /// If Some(x), object size has to be less than x - pub size_lt: Option, + pub size_lt: Option, } #[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] -- cgit v1.2.3 From 75ccc5a95c76f31235fcaab8a2c1795693733a4b Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Wed, 30 Aug 2023 20:02:07 +0200 Subject: lifecycle config: store date as given, try to debug --- src/model/bucket_table.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src/model/bucket_table.rs') diff --git a/src/model/bucket_table.rs b/src/model/bucket_table.rs index e9d574c5..df2e9b4a 100644 --- a/src/model/bucket_table.rs +++ b/src/model/bucket_table.rs @@ -105,7 +105,7 @@ mod v08 { /// Objects expire x days after they were created AfterDays(usize), /// Objects expire at date x (must be in yyyy-mm-dd format) - AtDate(chrono::naive::NaiveDate), + AtDate(String), } #[derive(Default, PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Serialize, Deserialize)] @@ -155,6 +155,20 @@ impl Crdt for BucketParams { } } +pub fn parse_lifecycle_date(date: &str) -> Result { + use chrono::prelude::*; + + if let Ok(datetime) = NaiveDateTime::parse_from_str(date, "%Y-%m-%dT%H:%M:%SZ") { + if datetime.time() == NaiveTime::MIN { + Ok(datetime.date()) + } else { + Err("date must be at midnight") + } + } else { + NaiveDate::parse_from_str(date, "%Y-%m-%d").map_err(|_| "date has invalid format") + } +} + impl Default for Bucket { fn default() -> Self { Self::new() -- cgit v1.2.3 From d2e94e36d64d4062ebe1fabac65ac1a6f265de17 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Wed, 30 Aug 2023 20:05:53 +0200 Subject: lifecycle config: add missing line in merge() and remove tracing --- src/model/bucket_table.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/model/bucket_table.rs') diff --git a/src/model/bucket_table.rs b/src/model/bucket_table.rs index df2e9b4a..0eefa0e5 100644 --- a/src/model/bucket_table.rs +++ b/src/model/bucket_table.rs @@ -151,6 +151,7 @@ impl Crdt for BucketParams { self.website_config.merge(&o.website_config); self.cors_config.merge(&o.cors_config); + self.lifecycle_config.merge(&o.lifecycle_config); self.quotas.merge(&o.quotas); } } -- cgit v1.2.3 From a1d57283c0b37baabfb624d3696cc6efbaa4a500 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Wed, 30 Aug 2023 20:07:14 +0200 Subject: bucket_table: bucketparams::new doesn't need to be pub --- src/model/bucket_table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/model/bucket_table.rs') diff --git a/src/model/bucket_table.rs b/src/model/bucket_table.rs index 0eefa0e5..4c48a76f 100644 --- a/src/model/bucket_table.rs +++ b/src/model/bucket_table.rs @@ -127,7 +127,7 @@ impl AutoCrdt for BucketQuotas { impl BucketParams { /// Create an empty BucketParams with no authorized keys and no website accesss - pub fn new() -> Self { + fn new() -> Self { BucketParams { creation_date: now_msec(), authorized_keys: crdt::Map::new(), -- cgit v1.2.3