use super::{ReductClient, Result};
use crate::http_client::HttpClient;
use reduct_base::msg::lifecycle_api::{
FullLifecycleInfo, LifecycleInfo, LifecycleList, LifecycleMode, LifecycleModePayload,
LifecycleSettings, LifecycleType,
};
use reqwest::Method;
use serde_json::Value;
use std::sync::Arc;
pub struct LifecycleBuilder {
name: String,
settings: LifecycleSettings,
http_client: Arc<HttpClient>,
}
impl LifecycleBuilder {
pub(super) fn new(name: String, http_client: Arc<HttpClient>) -> Self {
Self {
name,
settings: LifecycleSettings::default(),
http_client,
}
}
pub fn lifecycle_type(mut self, lifecycle_type: LifecycleType) -> Self {
self.settings.lifecycle_type = lifecycle_type;
self
}
pub fn bucket(mut self, bucket: &str) -> Self {
self.settings.bucket = bucket.to_string();
self
}
pub fn entries(mut self, entries: Vec<String>) -> Self {
self.settings.entries = entries;
self
}
pub fn older_than(mut self, older_than: &str) -> Self {
self.settings.older_than = older_than.to_string();
self
}
pub fn interval(mut self, interval: &str) -> Self {
self.settings.interval = interval.to_string();
self
}
pub fn when(mut self, when: Value) -> Self {
self.settings.when = Some(when);
self
}
pub fn mode(mut self, mode: LifecycleMode) -> Self {
self.settings.mode = mode;
self
}
pub fn set_settings(mut self, settings: LifecycleSettings) -> Self {
self.settings = settings;
self
}
pub async fn send(self) -> Result<()> {
self.http_client
.send_json(
Method::POST,
&format!("/lifecycles/{}", self.name),
self.settings,
)
.await
}
}
impl ReductClient {
pub async fn list_lifecycles(&self) -> Result<Vec<LifecycleInfo>> {
let list = self
.http_client
.send_and_receive_json::<(), LifecycleList>(Method::GET, "/lifecycles", None)
.await?;
Ok(list.lifecycles)
}
pub async fn get_lifecycle(&self, name: &str) -> Result<FullLifecycleInfo> {
let info = self
.http_client
.send_and_receive_json::<(), FullLifecycleInfo>(
Method::GET,
&format!("/lifecycles/{}", name),
None,
)
.await?;
Ok(info)
}
pub fn create_lifecycle(&self, name: &str) -> LifecycleBuilder {
LifecycleBuilder::new(name.to_string(), Arc::clone(&self.http_client))
}
pub async fn update_lifecycle(&self, name: &str, settings: LifecycleSettings) -> Result<()> {
self.http_client
.send_json(Method::PUT, &format!("/lifecycles/{}", name), settings)
.await
}
pub async fn set_lifecycle_mode(&self, name: &str, mode: LifecycleMode) -> Result<()> {
self.http_client
.send_json(
Method::PATCH,
&format!("/lifecycles/{}/mode", name),
LifecycleModePayload { mode },
)
.await
}
pub async fn delete_lifecycle(&self, name: &str) -> Result<()> {
let request = self
.http_client
.request(Method::DELETE, &format!("/lifecycles/{}", name));
self.http_client.send_request(request).await?;
Ok(())
}
}
#[cfg(all(test, feature = "test-api-120"))]
mod tests {
use super::*;
use crate::client::tests::client;
use crate::condition;
use rstest::{fixture, rstest};
fn test_lifecycles(lifecycles: Vec<LifecycleInfo>) -> Vec<LifecycleInfo> {
lifecycles
.into_iter()
.filter(|lifecycle| lifecycle.name.starts_with("test-lifecycle"))
.collect()
}
#[rstest]
#[tokio::test]
async fn test_list_lifecycles(#[future] client: ReductClient) {
let lifecycles = test_lifecycles(client.await.list_lifecycles().await.unwrap());
assert!(lifecycles.is_empty());
}
#[rstest]
#[tokio::test]
async fn test_create_lifecycle(#[future] client: ReductClient, settings: LifecycleSettings) {
let client = client.await;
client
.create_lifecycle("test-lifecycle")
.lifecycle_type(LifecycleType::Compress)
.bucket(settings.bucket.as_str())
.entries(settings.entries.clone())
.older_than(settings.older_than.as_str())
.interval(settings.interval.as_str())
.mode(settings.mode)
.send()
.await
.unwrap();
let lifecycles = test_lifecycles(client.list_lifecycles().await.unwrap());
assert_eq!(lifecycles.len(), 1);
assert_eq!(lifecycles[0].lifecycle_type, LifecycleType::Compress);
assert_eq!(lifecycles[0].mode, settings.mode);
assert!(lifecycles[0].last_run.is_none());
}
#[rstest]
#[tokio::test]
async fn test_get_lifecycle(#[future] client: ReductClient, settings: LifecycleSettings) {
let client = client.await;
client
.create_lifecycle("test-lifecycle")
.set_settings(settings.clone())
.send()
.await
.unwrap();
let lifecycle = client.get_lifecycle("test-lifecycle").await.unwrap();
assert_eq!(lifecycle.info.name, "test-lifecycle");
assert_eq!(lifecycle.info.lifecycle_type, settings.lifecycle_type);
assert_eq!(lifecycle.info.mode, settings.mode);
assert!(lifecycle.info.last_run.is_none());
assert_eq!(lifecycle.settings, settings);
}
#[rstest]
#[tokio::test]
async fn test_update_lifecycle(
#[future] client: ReductClient,
mut settings: LifecycleSettings,
) {
let client = client.await;
client
.create_lifecycle("test-lifecycle")
.set_settings(settings.clone())
.send()
.await
.unwrap();
settings.older_than = "2h".to_string();
settings.mode = LifecycleMode::Disabled;
client
.update_lifecycle("test-lifecycle", settings.clone())
.await
.unwrap();
let lifecycle = client.get_lifecycle("test-lifecycle").await.unwrap();
assert_eq!(lifecycle.settings, settings);
}
#[rstest]
#[tokio::test]
async fn test_set_lifecycle_mode(#[future] client: ReductClient, settings: LifecycleSettings) {
let client = client.await;
client
.create_lifecycle("test-lifecycle")
.set_settings(settings)
.send()
.await
.unwrap();
client
.set_lifecycle_mode("test-lifecycle", LifecycleMode::Disabled)
.await
.unwrap();
let lifecycle = client.get_lifecycle("test-lifecycle").await.unwrap();
assert_eq!(lifecycle.info.mode, LifecycleMode::Disabled);
assert_eq!(lifecycle.settings.mode, LifecycleMode::Disabled);
}
#[rstest]
#[tokio::test]
async fn test_set_lifecycle_mode_dry_run(
#[future] client: ReductClient,
settings: LifecycleSettings,
) {
let client = client.await;
client
.create_lifecycle("test-lifecycle")
.set_settings(settings)
.send()
.await
.unwrap();
client
.set_lifecycle_mode("test-lifecycle", LifecycleMode::DryRun)
.await
.unwrap();
let lifecycle = client.get_lifecycle("test-lifecycle").await.unwrap();
assert_eq!(lifecycle.info.mode, LifecycleMode::DryRun);
assert_eq!(lifecycle.settings.mode, LifecycleMode::DryRun);
}
#[rstest]
#[tokio::test]
async fn test_delete_lifecycle(#[future] client: ReductClient, settings: LifecycleSettings) {
let client = client.await;
client
.create_lifecycle("test-lifecycle")
.set_settings(settings)
.send()
.await
.unwrap();
client.delete_lifecycle("test-lifecycle").await.unwrap();
let lifecycles = test_lifecycles(client.list_lifecycles().await.unwrap());
assert!(lifecycles.is_empty());
}
#[fixture]
fn settings() -> LifecycleSettings {
LifecycleSettings {
lifecycle_type: LifecycleType::Delete,
bucket: "test-bucket-1".to_string(),
entries: vec![],
older_than: "1h".to_string(),
interval: "10m".to_string(),
when: Some(condition!({"$eq": ["&label", 1]})),
mode: LifecycleMode::Enabled,
}
}
}