Implement base operator #1
90
src/minio.rs
90
src/minio.rs
@ -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)]
|
||||||
@ -91,6 +93,23 @@ struct MinioRetentionResult {
|
|||||||
pub validity: 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"
|
||||||
@ -412,6 +431,49 @@ impl MinioService {
|
|||||||
}
|
}
|
||||||
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)]
|
||||||
@ -420,6 +482,7 @@ mod test {
|
|||||||
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() {
|
||||||
@ -863,4 +926,31 @@ mod test {
|
|||||||
None
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
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"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user