mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-09-02 10:18:11 +00:00
admin api: expose routing rules, cors rules and lifecycle rules
This commit is contained in:
@@ -44,6 +44,7 @@ url.workspace = true
|
||||
quick-xml.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
utoipa.workspace = true
|
||||
|
||||
opentelemetry.workspace = true
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use hyper::{header::HeaderName, Method};
|
||||
|
||||
@@ -16,7 +17,8 @@ pub struct CorsConfiguration {
|
||||
pub cors_rules: Vec<CorsRule>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
#[schema(as = cors::Rule)]
|
||||
pub struct CorsRule {
|
||||
#[serde(rename = "ID", skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<Value>,
|
||||
@@ -32,19 +34,22 @@ pub struct CorsRule {
|
||||
pub expose_headers: Vec<Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
#[schema(as = cors::AllowedMethod)]
|
||||
pub struct AllowedMethod {
|
||||
#[serde(rename = "AllowedMethod")]
|
||||
pub allowed_method: Value,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
#[schema(as = cors::AllowedHeader)]
|
||||
pub struct AllowedHeader {
|
||||
#[serde(rename = "AllowedHeader")]
|
||||
pub allowed_header: Value,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
#[schema(as = cors::ExposedHeader)]
|
||||
pub struct ExposeHeader {
|
||||
#[serde(rename = "ExposeHeader")]
|
||||
pub expose_header: Value,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use garage_model::bucket_table::{
|
||||
parse_lifecycle_date, LifecycleExpiration as GarageLifecycleExpiration,
|
||||
@@ -15,7 +16,8 @@ pub struct LifecycleConfiguration {
|
||||
pub lifecycle_rules: Vec<LifecycleRule>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[schema(as = lifecycle::Rule)]
|
||||
pub struct LifecycleRule {
|
||||
#[serde(rename = "ID", skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<Value>,
|
||||
@@ -37,9 +39,13 @@ pub struct LifecycleRule {
|
||||
pub abort_incomplete_mpu: Option<AbortIncompleteMpu>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Default)]
|
||||
#[derive(
|
||||
Debug, ToSchema, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Default,
|
||||
)]
|
||||
#[schema(as = lifecycle::Filter)]
|
||||
pub struct Filter {
|
||||
#[serde(rename = "And", skip_serializing_if = "Option::is_none")]
|
||||
#[schema(no_recursion)]
|
||||
pub and: Option<Box<Filter>>,
|
||||
#[serde(rename = "Prefix", skip_serializing_if = "Option::is_none")]
|
||||
pub prefix: Option<Value>,
|
||||
@@ -52,7 +58,8 @@ pub struct Filter {
|
||||
pub size_lt: Option<IntValue>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[schema(as = lifecycle::Expiration)]
|
||||
pub struct Expiration {
|
||||
#[serde(rename = "Days", skip_serializing_if = "Option::is_none")]
|
||||
pub days: Option<IntValue>,
|
||||
@@ -60,7 +67,8 @@ pub struct Expiration {
|
||||
pub at_date: Option<Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[schema(as = lifecycle::AbortIncompleteMpu)]
|
||||
pub struct AbortIncompleteMpu {
|
||||
#[serde(rename = "DaysAfterInitiation")]
|
||||
pub days: IntValue,
|
||||
|
||||
@@ -3,6 +3,7 @@ pub mod lifecycle;
|
||||
pub mod website;
|
||||
|
||||
use serde::{Deserialize, Serialize, Serializer};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub fn to_xml_with_header<T: Serialize>(x: &T) -> Result<String, quick_xml::se::SeError> {
|
||||
use quick_xml::se::{self, EmptyElementHandling, QuoteLevel};
|
||||
@@ -32,7 +33,8 @@ pub fn xmlns_xsi_tag<S: Serializer>(_v: &(), s: S) -> Result<S::Ok, S::Error> {
|
||||
s.serialize_str("http://www.w3.org/2001/XMLSchema-instance")
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
#[schema(as = xml::Value)]
|
||||
pub struct Value(#[serde(rename = "$value")] pub String);
|
||||
|
||||
impl From<&str> for Value {
|
||||
@@ -41,5 +43,6 @@ impl From<&str> for Value {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
#[schema(as = xml::IntValue)]
|
||||
pub struct IntValue(#[serde(rename = "$value")] pub i64);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use garage_model::bucket_table::{self, WebsiteConfig};
|
||||
use garage_model::bucket_table::{self, RoutingRule as GarageRoutingRule, WebsiteConfig};
|
||||
|
||||
use crate::common_error::CommonError as Error;
|
||||
use crate::xml::{xmlns_tag, IntValue, Value};
|
||||
@@ -35,7 +36,8 @@ impl RoutingRules {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
#[schema(as = website::RoutingRule)]
|
||||
pub struct RoutingRule {
|
||||
#[serde(rename = "Condition")]
|
||||
pub condition: Option<Condition>,
|
||||
@@ -43,19 +45,22 @@ pub struct RoutingRule {
|
||||
pub redirect: Redirect,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
#[schema(as = website::Key)]
|
||||
pub struct Key {
|
||||
#[serde(rename = "Key")]
|
||||
pub key: Value,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
#[schema(as = website::Suffix)]
|
||||
pub struct Suffix {
|
||||
#[serde(rename = "Suffix")]
|
||||
pub suffix: Value,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
#[schema(as = website::Target)]
|
||||
pub struct Target {
|
||||
#[serde(rename = "HostName")]
|
||||
pub hostname: Value,
|
||||
@@ -63,7 +68,8 @@ pub struct Target {
|
||||
pub protocol: Option<Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
#[schema(as = website::Condition)]
|
||||
pub struct Condition {
|
||||
#[serde(
|
||||
rename = "HttpErrorCodeReturnedEquals",
|
||||
@@ -74,7 +80,8 @@ pub struct Condition {
|
||||
pub prefix: Option<Value>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, ToSchema, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
#[schema(as = website::Redirect)]
|
||||
pub struct Redirect {
|
||||
#[serde(rename = "HostName", skip_serializing_if = "Option::is_none")]
|
||||
pub hostname: Option<Value>,
|
||||
@@ -214,6 +221,22 @@ impl RoutingRule {
|
||||
}
|
||||
self.redirect.validate()
|
||||
}
|
||||
|
||||
pub fn from_garage_routing_rule(rule: GarageRoutingRule) -> Self {
|
||||
RoutingRule {
|
||||
condition: rule.condition.map(|cond| Condition {
|
||||
http_error_code: cond.http_error_code.map(|c| IntValue(c as i64)),
|
||||
prefix: cond.prefix.map(Value),
|
||||
}),
|
||||
redirect: Redirect {
|
||||
hostname: rule.redirect.hostname.map(Value),
|
||||
http_redirect_code: Some(IntValue(rule.redirect.http_redirect_code as i64)),
|
||||
protocol: rule.redirect.protocol.map(Value),
|
||||
replace_full: rule.redirect.replace_key.map(Value),
|
||||
replace_prefix: rule.redirect.replace_key_prefix.map(Value),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Condition {
|
||||
|
||||
Reference in New Issue
Block a user