Compare commits
3 Commits
e3860d9f93
...
1ae2cf7282
| Author | SHA1 | Date | |
|---|---|---|---|
| 1ae2cf7282 | |||
| 42e2ea5539 | |||
| 239b58d8db |
@@ -14,7 +14,7 @@ pub struct MinioInstanceSpec {
|
|||||||
pub credentials: String,
|
pub credentials: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Default, Clone, JsonSchema)]
|
#[derive(Debug, Serialize, Deserialize, Default, Copy, Clone, JsonSchema, PartialEq, Eq)]
|
||||||
pub enum RetentionType {
|
pub enum RetentionType {
|
||||||
#[default]
|
#[default]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
@@ -23,7 +23,7 @@ pub enum RetentionType {
|
|||||||
Governance,
|
Governance,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Default, Clone, JsonSchema)]
|
#[derive(Debug, Serialize, Deserialize, Default, Clone, Copy, JsonSchema, PartialEq, Eq)]
|
||||||
pub struct BucketRetention {
|
pub struct BucketRetention {
|
||||||
pub validity: usize,
|
pub validity: usize,
|
||||||
pub r#type: RetentionType,
|
pub r#type: RetentionType,
|
||||||
|
|||||||
354
src/minio.rs
354
src/minio.rs
@@ -4,7 +4,7 @@ use serde::de::DeserializeOwned;
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::constants::{MC_EXE, SECRET_MINIO_BUCKET_ACCESS_LEN, SECRET_MINIO_BUCKET_SECRET_LEN};
|
use crate::constants::{MC_EXE, SECRET_MINIO_BUCKET_ACCESS_LEN, SECRET_MINIO_BUCKET_SECRET_LEN};
|
||||||
use crate::crd::{MinioBucketSpec, RetentionType};
|
use crate::crd::{BucketRetention, MinioBucketSpec, RetentionType};
|
||||||
use crate::utils::rand_str;
|
use crate::utils::rand_str;
|
||||||
|
|
||||||
const MC_ALIAS_NAME: &str = "managedminioinst";
|
const MC_ALIAS_NAME: &str = "managedminioinst";
|
||||||
@@ -23,6 +23,8 @@ enum MinioError {
|
|||||||
SetQuotaFailed,
|
SetQuotaFailed,
|
||||||
#[error("Failed to set bucket retention!")]
|
#[error("Failed to set bucket retention!")]
|
||||||
SetRetentionFailed,
|
SetRetentionFailed,
|
||||||
|
#[error("Failed to set policy!")]
|
||||||
|
ApplyPolicyFailed,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -84,6 +86,30 @@ struct MinioQuota {
|
|||||||
pub quota: Option<usize>,
|
pub quota: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
struct MinioRetentionResult {
|
||||||
|
pub enabled: Option<String>,
|
||||||
|
pub mode: Option<String>,
|
||||||
|
pub validity: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
struct MinioPolicy {
|
||||||
|
pub policy: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
struct MinioPolicyInfo {
|
||||||
|
pub policyInfo: PolicyInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
struct PolicyInfo {
|
||||||
|
Policy: serde_json::Value,
|
||||||
|
}
|
||||||
|
|
||||||
impl BasicMinioResult {
|
impl BasicMinioResult {
|
||||||
pub fn success(&self) -> bool {
|
pub fn success(&self) -> bool {
|
||||||
self.status == "success"
|
self.status == "success"
|
||||||
@@ -200,13 +226,13 @@ impl MinioService {
|
|||||||
.any(|b| b.bucket_name().eq(name)))
|
.any(|b| b.bucket_name().eq(name)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a bucket
|
/// Apply bucket desired configuration. If bucket already exists, it is not dropped
|
||||||
pub async fn create_bucket(&self, b: &MinioBucketSpec) -> anyhow::Result<()> {
|
pub async fn apply_bucket(&self, b: &MinioBucketSpec) -> anyhow::Result<()> {
|
||||||
// Set base parameters
|
// Set base parameters
|
||||||
let bucket_name = format!("{}/{}", MC_ALIAS_NAME, b.name);
|
let bucket_name = format!("{}/{}", MC_ALIAS_NAME, b.name);
|
||||||
let mut args = ["mb", bucket_name.as_str()].to_vec();
|
let mut args = ["mb", bucket_name.as_str(), "-p"].to_vec();
|
||||||
|
|
||||||
if b.lock || b.retention.is_some() {
|
if b.lock {
|
||||||
args.push("--with-lock");
|
args.push("--with-lock");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,36 +241,15 @@ impl MinioService {
|
|||||||
return Err(MinioError::MakeBucketFailed.into());
|
return Err(MinioError::MakeBucketFailed.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.bucket_set_versioning(&b.name, b.versioning).await?;
|
self.bucket_set_versioning(&b.name, b.versioning || b.lock)
|
||||||
|
.await?;
|
||||||
self.bucket_set_anonymous_access(&b.name, b.anonymous_read_access)
|
self.bucket_set_anonymous_access(&b.name, b.anonymous_read_access)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Set quota, if requested
|
|
||||||
self.bucket_set_quota(&b.name, b.quota).await?;
|
self.bucket_set_quota(&b.name, b.quota).await?;
|
||||||
|
if b.lock {
|
||||||
// Set retention, if requested
|
self.bucket_set_default_retention(&b.name, b.retention)
|
||||||
if let Some(retention) = &b.retention {
|
|
||||||
let days = format!("{}d", retention.validity);
|
|
||||||
|
|
||||||
let res = self
|
|
||||||
.exec_mc_cmd::<BasicMinioResult>(&[
|
|
||||||
"retention",
|
|
||||||
"set",
|
|
||||||
"--default",
|
|
||||||
match retention.r#type {
|
|
||||||
RetentionType::Compliance => "compliance",
|
|
||||||
RetentionType::Governance => "governance",
|
|
||||||
},
|
|
||||||
days.as_str(),
|
|
||||||
bucket_name.as_str(),
|
|
||||||
])
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if res.get(0).map(|r| r.success()) != Some(true) {
|
|
||||||
return Err(MinioError::SetRetentionFailed.into());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,14 +358,131 @@ impl MinioService {
|
|||||||
.remove(0)
|
.remove(0)
|
||||||
.quota)
|
.quota)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set bucket default retention policy
|
||||||
|
pub async fn bucket_set_default_retention(
|
||||||
|
&self,
|
||||||
|
bucket_name: &str,
|
||||||
|
retention: Option<BucketRetention>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let bucket_name = self.absolute_bucket_name(bucket_name);
|
||||||
|
let res = if let Some(retention) = &retention {
|
||||||
|
let days = format!("{}d", retention.validity);
|
||||||
|
|
||||||
|
self.exec_mc_cmd::<BasicMinioResult>(&[
|
||||||
|
"retention",
|
||||||
|
"set",
|
||||||
|
"--default",
|
||||||
|
match retention.r#type {
|
||||||
|
RetentionType::Compliance => "compliance",
|
||||||
|
RetentionType::Governance => "governance",
|
||||||
|
},
|
||||||
|
days.as_str(),
|
||||||
|
bucket_name.as_str(),
|
||||||
|
])
|
||||||
|
.await?
|
||||||
|
} else {
|
||||||
|
self.exec_mc_cmd::<BasicMinioResult>(&[
|
||||||
|
"retention",
|
||||||
|
"clear",
|
||||||
|
"--default",
|
||||||
|
bucket_name.as_str(),
|
||||||
|
])
|
||||||
|
.await?
|
||||||
|
};
|
||||||
|
|
||||||
|
if res.get(0).map(|r| r.success()) != Some(true) {
|
||||||
|
return Err(MinioError::SetRetentionFailed.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get bucket default retention policy
|
||||||
|
pub async fn bucket_get_default_retention(
|
||||||
|
&self,
|
||||||
|
bucket: &str,
|
||||||
|
) -> anyhow::Result<Option<BucketRetention>> {
|
||||||
|
let bucket_name = self.absolute_bucket_name(bucket);
|
||||||
|
let res = self
|
||||||
|
.exec_mc_cmd::<MinioRetentionResult>(&[
|
||||||
|
"retention",
|
||||||
|
"info",
|
||||||
|
bucket_name.as_str(),
|
||||||
|
"--default",
|
||||||
|
])
|
||||||
|
.await?
|
||||||
|
.remove(0);
|
||||||
|
|
||||||
|
if let (Some(mode), Some(validity), Some(enabled)) = (res.mode, res.validity, res.enabled) {
|
||||||
|
if enabled.to_lowercase().eq("enabled") {
|
||||||
|
return Ok(Some(BucketRetention {
|
||||||
|
validity: validity.to_lowercase().replace("days", "").parse()?,
|
||||||
|
r#type: match mode.to_lowercase().as_str() {
|
||||||
|
"governance" => RetentionType::Governance,
|
||||||
|
"compliance" => RetentionType::Compliance,
|
||||||
|
o => {
|
||||||
|
log::error!("Unknown retention type: {}", o);
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Apply a bucket policy
|
||||||
|
pub async fn policy_apply(&self, name: &str, content: &str) -> anyhow::Result<()> {
|
||||||
|
let tmp_file = mktemp::Temp::new_file()?;
|
||||||
|
std::fs::write(&tmp_file, content)?;
|
||||||
|
|
||||||
|
let res = self
|
||||||
|
.exec_mc_cmd::<BasicMinioResult>(&[
|
||||||
|
"admin",
|
||||||
|
"policy",
|
||||||
|
"create",
|
||||||
|
MC_ALIAS_NAME,
|
||||||
|
name,
|
||||||
|
tmp_file.to_str().unwrap(),
|
||||||
|
])
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if res.get(0).map(|r| r.success()) != Some(true) {
|
||||||
|
return Err(MinioError::ApplyPolicyFailed.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the list of existing policies
|
||||||
|
pub async fn policy_list(&self) -> anyhow::Result<Vec<String>> {
|
||||||
|
Ok(self
|
||||||
|
.exec_mc_cmd::<MinioPolicy>(&["admin", "policy", "list", MC_ALIAS_NAME])
|
||||||
|
.await?
|
||||||
|
.iter()
|
||||||
|
.map(|p| p.policy.to_string())
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the content of a given policy
|
||||||
|
pub async fn policy_content(&self, name: &str) -> anyhow::Result<String> {
|
||||||
|
let policy = self
|
||||||
|
.exec_mc_cmd::<MinioPolicyInfo>(&["admin", "policy", "info", MC_ALIAS_NAME, name])
|
||||||
|
.await?
|
||||||
|
.remove(0);
|
||||||
|
|
||||||
|
Ok(serde_json::to_string(&policy.policyInfo.Policy)?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::crd::MinioBucketSpec;
|
use crate::crd::{BucketRetention, MinioBucketSpec, RetentionType};
|
||||||
use crate::minio_test_server::MinioTestServer;
|
use crate::minio_test_server::MinioTestServer;
|
||||||
|
|
||||||
const TEST_BUCKET_NAME: &str = "mybucket";
|
const TEST_BUCKET_NAME: &str = "mybucket";
|
||||||
|
const TEST_POLICY_NAME: &str = "mypolicy";
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn list_buckets_empty_instance() {
|
async fn list_buckets_empty_instance() {
|
||||||
@@ -382,7 +504,7 @@ mod test {
|
|||||||
let srv = MinioTestServer::start().await.unwrap();
|
let srv = MinioTestServer::start().await.unwrap();
|
||||||
let service = srv.as_service();
|
let service = srv.as_service();
|
||||||
service
|
service
|
||||||
.create_bucket(&MinioBucketSpec {
|
.apply_bucket(&MinioBucketSpec {
|
||||||
instance: "".to_string(),
|
instance: "".to_string(),
|
||||||
name: TEST_BUCKET_NAME.to_string(),
|
name: TEST_BUCKET_NAME.to_string(),
|
||||||
secret: "".to_string(),
|
secret: "".to_string(),
|
||||||
@@ -404,7 +526,7 @@ mod test {
|
|||||||
let srv = MinioTestServer::start().await.unwrap();
|
let srv = MinioTestServer::start().await.unwrap();
|
||||||
let service = srv.as_service();
|
let service = srv.as_service();
|
||||||
service
|
service
|
||||||
.create_bucket(&MinioBucketSpec {
|
.apply_bucket(&MinioBucketSpec {
|
||||||
instance: "".to_string(),
|
instance: "".to_string(),
|
||||||
name: TEST_BUCKET_NAME.to_string(),
|
name: TEST_BUCKET_NAME.to_string(),
|
||||||
secret: "".to_string(),
|
secret: "".to_string(),
|
||||||
@@ -439,7 +561,7 @@ mod test {
|
|||||||
let srv = MinioTestServer::start().await.unwrap();
|
let srv = MinioTestServer::start().await.unwrap();
|
||||||
let service = srv.as_service();
|
let service = srv.as_service();
|
||||||
service
|
service
|
||||||
.create_bucket(&MinioBucketSpec {
|
.apply_bucket(&MinioBucketSpec {
|
||||||
instance: "".to_string(),
|
instance: "".to_string(),
|
||||||
name: TEST_BUCKET_NAME.to_string(),
|
name: TEST_BUCKET_NAME.to_string(),
|
||||||
secret: "".to_string(),
|
secret: "".to_string(),
|
||||||
@@ -470,7 +592,7 @@ mod test {
|
|||||||
let srv = MinioTestServer::start().await.unwrap();
|
let srv = MinioTestServer::start().await.unwrap();
|
||||||
let service = srv.as_service();
|
let service = srv.as_service();
|
||||||
service
|
service
|
||||||
.create_bucket(&MinioBucketSpec {
|
.apply_bucket(&MinioBucketSpec {
|
||||||
instance: "".to_string(),
|
instance: "".to_string(),
|
||||||
name: TEST_BUCKET_NAME.to_string(),
|
name: TEST_BUCKET_NAME.to_string(),
|
||||||
secret: "".to_string(),
|
secret: "".to_string(),
|
||||||
@@ -523,7 +645,7 @@ mod test {
|
|||||||
let srv = MinioTestServer::start().await.unwrap();
|
let srv = MinioTestServer::start().await.unwrap();
|
||||||
let service = srv.as_service();
|
let service = srv.as_service();
|
||||||
service
|
service
|
||||||
.create_bucket(&MinioBucketSpec {
|
.apply_bucket(&MinioBucketSpec {
|
||||||
instance: "".to_string(),
|
instance: "".to_string(),
|
||||||
name: TEST_BUCKET_NAME.to_string(),
|
name: TEST_BUCKET_NAME.to_string(),
|
||||||
secret: "".to_string(),
|
secret: "".to_string(),
|
||||||
@@ -550,7 +672,7 @@ mod test {
|
|||||||
let srv = MinioTestServer::start().await.unwrap();
|
let srv = MinioTestServer::start().await.unwrap();
|
||||||
let service = srv.as_service();
|
let service = srv.as_service();
|
||||||
service
|
service
|
||||||
.create_bucket(&MinioBucketSpec {
|
.apply_bucket(&MinioBucketSpec {
|
||||||
instance: "".to_string(),
|
instance: "".to_string(),
|
||||||
name: TEST_BUCKET_NAME.to_string(),
|
name: TEST_BUCKET_NAME.to_string(),
|
||||||
secret: "".to_string(),
|
secret: "".to_string(),
|
||||||
@@ -577,7 +699,7 @@ mod test {
|
|||||||
let srv = MinioTestServer::start().await.unwrap();
|
let srv = MinioTestServer::start().await.unwrap();
|
||||||
let service = srv.as_service();
|
let service = srv.as_service();
|
||||||
service
|
service
|
||||||
.create_bucket(&MinioBucketSpec {
|
.apply_bucket(&MinioBucketSpec {
|
||||||
instance: "".to_string(),
|
instance: "".to_string(),
|
||||||
name: TEST_BUCKET_NAME.to_string(),
|
name: TEST_BUCKET_NAME.to_string(),
|
||||||
secret: "".to_string(),
|
secret: "".to_string(),
|
||||||
@@ -614,13 +736,13 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn bucket_without_qutoa() {
|
async fn bucket_without_quota() {
|
||||||
let _ = env_logger::builder().is_test(true).try_init();
|
let _ = env_logger::builder().is_test(true).try_init();
|
||||||
|
|
||||||
let srv = MinioTestServer::start().await.unwrap();
|
let srv = MinioTestServer::start().await.unwrap();
|
||||||
let service = srv.as_service();
|
let service = srv.as_service();
|
||||||
service
|
service
|
||||||
.create_bucket(&MinioBucketSpec {
|
.apply_bucket(&MinioBucketSpec {
|
||||||
instance: "".to_string(),
|
instance: "".to_string(),
|
||||||
name: TEST_BUCKET_NAME.to_string(),
|
name: TEST_BUCKET_NAME.to_string(),
|
||||||
secret: "".to_string(),
|
secret: "".to_string(),
|
||||||
@@ -659,13 +781,13 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn bucket_with_qutoa() {
|
async fn bucket_with_quota() {
|
||||||
let _ = env_logger::builder().is_test(true).try_init();
|
let _ = env_logger::builder().is_test(true).try_init();
|
||||||
|
|
||||||
let srv = MinioTestServer::start().await.unwrap();
|
let srv = MinioTestServer::start().await.unwrap();
|
||||||
let service = srv.as_service();
|
let service = srv.as_service();
|
||||||
service
|
service
|
||||||
.create_bucket(&MinioBucketSpec {
|
.apply_bucket(&MinioBucketSpec {
|
||||||
instance: "".to_string(),
|
instance: "".to_string(),
|
||||||
name: TEST_BUCKET_NAME.to_string(),
|
name: TEST_BUCKET_NAME.to_string(),
|
||||||
secret: "".to_string(),
|
secret: "".to_string(),
|
||||||
@@ -685,6 +807,150 @@ mod test {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : with retention
|
#[tokio::test]
|
||||||
// TODO : without retention
|
async fn bucket_with_retention() {
|
||||||
|
let _ = env_logger::builder().is_test(true).try_init();
|
||||||
|
|
||||||
|
let srv = MinioTestServer::start().await.unwrap();
|
||||||
|
let service = srv.as_service();
|
||||||
|
service
|
||||||
|
.apply_bucket(&MinioBucketSpec {
|
||||||
|
instance: "".to_string(),
|
||||||
|
name: TEST_BUCKET_NAME.to_string(),
|
||||||
|
secret: "".to_string(),
|
||||||
|
anonymous_read_access: false,
|
||||||
|
versioning: false,
|
||||||
|
quota: Some(42300),
|
||||||
|
lock: true,
|
||||||
|
retention: Some(BucketRetention {
|
||||||
|
validity: 10,
|
||||||
|
r#type: RetentionType::Governance,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert!(service.bucket_exists(TEST_BUCKET_NAME).await.unwrap());
|
||||||
|
assert_eq!(
|
||||||
|
service
|
||||||
|
.bucket_get_default_retention(TEST_BUCKET_NAME)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
Some(BucketRetention {
|
||||||
|
validity: 10,
|
||||||
|
r#type: RetentionType::Governance
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
service
|
||||||
|
.bucket_set_default_retention(TEST_BUCKET_NAME, None)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
service
|
||||||
|
.bucket_get_default_retention(TEST_BUCKET_NAME)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
|
||||||
|
service
|
||||||
|
.bucket_set_default_retention(
|
||||||
|
TEST_BUCKET_NAME,
|
||||||
|
Some(BucketRetention {
|
||||||
|
validity: 42,
|
||||||
|
r#type: RetentionType::Compliance,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
service
|
||||||
|
.bucket_get_default_retention(TEST_BUCKET_NAME)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
Some(BucketRetention {
|
||||||
|
validity: 42,
|
||||||
|
r#type: RetentionType::Compliance
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
service
|
||||||
|
.bucket_set_default_retention(
|
||||||
|
TEST_BUCKET_NAME,
|
||||||
|
Some(BucketRetention {
|
||||||
|
validity: 21,
|
||||||
|
r#type: RetentionType::Governance,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
service
|
||||||
|
.bucket_get_default_retention(TEST_BUCKET_NAME)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
Some(BucketRetention {
|
||||||
|
validity: 21,
|
||||||
|
r#type: RetentionType::Governance
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn bucket_without_retention() {
|
||||||
|
let _ = env_logger::builder().is_test(true).try_init();
|
||||||
|
|
||||||
|
let srv = MinioTestServer::start().await.unwrap();
|
||||||
|
let service = srv.as_service();
|
||||||
|
service
|
||||||
|
.apply_bucket(&MinioBucketSpec {
|
||||||
|
instance: "".to_string(),
|
||||||
|
name: TEST_BUCKET_NAME.to_string(),
|
||||||
|
secret: "".to_string(),
|
||||||
|
anonymous_read_access: false,
|
||||||
|
versioning: false,
|
||||||
|
quota: Some(42300),
|
||||||
|
lock: true,
|
||||||
|
retention: None,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert!(service.bucket_exists(TEST_BUCKET_NAME).await.unwrap());
|
||||||
|
assert_eq!(
|
||||||
|
service
|
||||||
|
.bucket_get_default_retention(TEST_BUCKET_NAME)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
None
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unify_policy(p: &str) -> String {
|
||||||
|
serde_json::to_string(&serde_json::from_str::<serde_json::Value>(p).unwrap()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn policy_apply() {
|
||||||
|
let _ = env_logger::builder().is_test(true).try_init();
|
||||||
|
|
||||||
|
let srv = MinioTestServer::start().await.unwrap();
|
||||||
|
let service = srv.as_service();
|
||||||
|
|
||||||
|
let policy_1 = unify_policy(include_str!("../test/test-policy1.json"));
|
||||||
|
let policy_2 = unify_policy(include_str!("../test/test-policy2.json"));
|
||||||
|
|
||||||
|
assert_ne!(policy_1, policy_2);
|
||||||
|
|
||||||
|
assert!(!service.policy_list().await.unwrap().contains(&TEST_POLICY_NAME.to_string()));
|
||||||
|
|
||||||
|
service.policy_apply(TEST_POLICY_NAME, &policy_1).await.unwrap();
|
||||||
|
assert!(service.policy_list().await.unwrap().contains(&TEST_POLICY_NAME.to_string()));
|
||||||
|
assert_eq!(unify_policy(&service.policy_content(TEST_POLICY_NAME).await.unwrap()), policy_1);
|
||||||
|
|
||||||
|
service.policy_apply(TEST_POLICY_NAME, &policy_2).await.unwrap();
|
||||||
|
assert!(service.policy_list().await.unwrap().contains(&TEST_POLICY_NAME.to_string()));
|
||||||
|
assert_eq!(unify_policy(&service.policy_content(TEST_POLICY_NAME).await.unwrap()), policy_2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use crate::utils::rand_str;
|
|||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::process::{Child, Command};
|
use std::process::{Child, Command};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
pub struct MinioTestServer {
|
pub struct MinioTestServer {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -62,6 +63,8 @@ impl MinioTestServer {
|
|||||||
}
|
}
|
||||||
check_count += 1;
|
check_count += 1;
|
||||||
|
|
||||||
|
std::thread::sleep(Duration::from_millis(100));
|
||||||
|
|
||||||
if instance.as_service().is_ready().await {
|
if instance.as_service().is_ready().await {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
15
test/test-policy1.json
Normal file
15
test/test-policy1.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Sid": "ListObjectsInBucket",
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": [
|
||||||
|
"s3:ListBucket"
|
||||||
|
],
|
||||||
|
"Resource": [
|
||||||
|
"arn:aws:s3:::bucket"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
11
test/test-policy2.json
Normal file
11
test/test-policy2.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Sid": "ListObjectsInBucket",
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": ["s3:ListBucket"],
|
||||||
|
"Resource": ["arn:aws:s3:::bucketdos"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -50,7 +50,7 @@ spec:
|
|||||||
description: Limits the amount of data in the bucket, in bytes. By default it is unlimited
|
description: Limits the amount of data in the bucket, in bytes. By default it is unlimited
|
||||||
example: 1000000000
|
example: 1000000000
|
||||||
lock:
|
lock:
|
||||||
description: Object locking prevent objects from being deleted. Will be considered as set to true when retention is defined.
|
description: Object locking prevent objects from being deleted. MUST be set to true when retention is defined. Cannot be changed.
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
retention:
|
retention:
|
||||||
|
|||||||
Reference in New Issue
Block a user