Implement base operator (#1)
	
		
			
	
		
	
	
		
	
		
			Some checks reported errors
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build was killed
				
			
		
		
	
	
				
					
				
			
		
			Some checks reported errors
		
		
	
	continuous-integration/drone/push Build was killed
				
			Add base operator logic Reviewed-on: #1
This commit is contained in:
		
							
								
								
									
										16
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					kind: pipeline
 | 
				
			||||||
 | 
					type: docker
 | 
				
			||||||
 | 
					name: default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					steps:
 | 
				
			||||||
 | 
					- name: cargo_check
 | 
				
			||||||
 | 
					  image: rust
 | 
				
			||||||
 | 
					  commands:
 | 
				
			||||||
 | 
					  - wget -O /usr/bin/minio https://dl.min.io/server/minio/release/linux-amd64/minio
 | 
				
			||||||
 | 
					  - wget -O /usr/bin/mc https://dl.min.io/client/mc/release/linux-amd64/mc
 | 
				
			||||||
 | 
					  - chmod +x /usr/bin/minio /usr/bin/mc
 | 
				
			||||||
 | 
					  - rustup component add clippy
 | 
				
			||||||
 | 
					  - cargo clippy -- -D warnings
 | 
				
			||||||
 | 
					  - cargo test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					/target
 | 
				
			||||||
 | 
					.idea
 | 
				
			||||||
							
								
								
									
										2121
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										2121
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										22
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "minio-operator"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					log = "0.4.17"
 | 
				
			||||||
 | 
					env_logger = "0.10.0"
 | 
				
			||||||
 | 
					anyhow = "1.0.71"
 | 
				
			||||||
 | 
					serde = { version = "1.0.162", features = ["derive"] }
 | 
				
			||||||
 | 
					serde_json = "1.0.96"
 | 
				
			||||||
 | 
					schemars = "0.8.12"
 | 
				
			||||||
 | 
					tokio = { version = "1.28.0", features = ["full"] }
 | 
				
			||||||
 | 
					kube = { version = "0.82.2", features = ["runtime", "derive"] }
 | 
				
			||||||
 | 
					k8s-openapi = { version = "0.18.0", features = ["v1_26"] } # TODO : switch to v1_27
 | 
				
			||||||
 | 
					futures = "0.3.28"
 | 
				
			||||||
 | 
					thiserror = "1.0.40"
 | 
				
			||||||
 | 
					rand = "0.8.5"
 | 
				
			||||||
 | 
					mktemp = "0.5.0"
 | 
				
			||||||
 | 
					reqwest = "0.11.17"
 | 
				
			||||||
							
								
								
									
										6
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					FROM debian:bullseye-slim
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY minio-operator /usr/local/bin/minio-operator
 | 
				
			||||||
 | 
					COPY mc /usr/local/bin/mc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENTRYPOINT /usr/local/bin/minio-operator
 | 
				
			||||||
@@ -3,3 +3,11 @@
 | 
				
			|||||||
Automatically create Minio buckets based on K8S CRD.
 | 
					Automatically create Minio buckets based on K8S CRD.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WIP, early project
 | 
					WIP, early project
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Apply all K8s config files manually:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					cat yaml/*.yaml | kubectl apply -f -
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note : [mc tool](https://min.io/download) is required
 | 
				
			||||||
							
								
								
									
										14
									
								
								build_docker_image.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										14
									
								
								build_docker_image.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					cargo build --release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEMP_DIR=$(mktemp -d)
 | 
				
			||||||
 | 
					cp target/release/minio-operator "$TEMP_DIR"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Download mc
 | 
				
			||||||
 | 
					wget -O "$TEMP_DIR/mc" https://dl.min.io/client/mc/release/linux-amd64/mc
 | 
				
			||||||
 | 
					chmod +x "$TEMP_DIR/mc" 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					docker build -f Dockerfile "$TEMP_DIR" -t pierre42100/minio_operator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rm -r $TEMP_DIR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										11
									
								
								src/constants.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/constants.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					//! # Application constants
 | 
				
			||||||
 | 
					pub const SECRET_MINIO_INSTANCE_ACCESS_KEY: &str = "accessKey";
 | 
				
			||||||
 | 
					pub const SECRET_MINIO_INSTANCE_SECRET_KEY: &str = "secretKey";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const SECRET_MINIO_BUCKET_ACCESS_KEY: &str = "accessKey";
 | 
				
			||||||
 | 
					pub const SECRET_MINIO_BUCKET_SECRET_KEY: &str = "secretKey";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const SECRET_MINIO_BUCKET_ACCESS_LEN: usize = 20;
 | 
				
			||||||
 | 
					pub const SECRET_MINIO_BUCKET_SECRET_LEN: usize = 35;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const MC_EXE: &str = "mc";
 | 
				
			||||||
							
								
								
									
										51
									
								
								src/crd.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/crd.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					use kube::CustomResource;
 | 
				
			||||||
 | 
					use schemars::JsonSchema;
 | 
				
			||||||
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(CustomResource, Debug, Serialize, Deserialize, Default, Clone, JsonSchema)]
 | 
				
			||||||
 | 
					#[kube(
 | 
				
			||||||
 | 
					    group = "communiquons.org",
 | 
				
			||||||
 | 
					    version = "v1",
 | 
				
			||||||
 | 
					    kind = "MinioInstance",
 | 
				
			||||||
 | 
					    namespaced
 | 
				
			||||||
 | 
					)]
 | 
				
			||||||
 | 
					pub struct MinioInstanceSpec {
 | 
				
			||||||
 | 
					    pub endpoint: String,
 | 
				
			||||||
 | 
					    pub credentials: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Serialize, Deserialize, Default, Copy, Clone, JsonSchema, PartialEq, Eq)]
 | 
				
			||||||
 | 
					pub enum RetentionType {
 | 
				
			||||||
 | 
					    #[default]
 | 
				
			||||||
 | 
					    #[serde(rename_all = "lowercase")]
 | 
				
			||||||
 | 
					    Compliance,
 | 
				
			||||||
 | 
					    #[serde(rename_all = "lowercase")]
 | 
				
			||||||
 | 
					    Governance,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Serialize, Deserialize, Default, Clone, Copy, JsonSchema, PartialEq, Eq)]
 | 
				
			||||||
 | 
					pub struct BucketRetention {
 | 
				
			||||||
 | 
					    pub validity: usize,
 | 
				
			||||||
 | 
					    pub r#type: RetentionType,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(CustomResource, Debug, Serialize, Deserialize, Default, Clone, JsonSchema)]
 | 
				
			||||||
 | 
					#[kube(
 | 
				
			||||||
 | 
					    group = "communiquons.org",
 | 
				
			||||||
 | 
					    version = "v1",
 | 
				
			||||||
 | 
					    kind = "MinioBucket",
 | 
				
			||||||
 | 
					    namespaced
 | 
				
			||||||
 | 
					)]
 | 
				
			||||||
 | 
					pub struct MinioBucketSpec {
 | 
				
			||||||
 | 
					    pub instance: String,
 | 
				
			||||||
 | 
					    pub name: String,
 | 
				
			||||||
 | 
					    pub secret: String,
 | 
				
			||||||
 | 
					    #[serde(default)]
 | 
				
			||||||
 | 
					    pub anonymous_read_access: bool,
 | 
				
			||||||
 | 
					    #[serde(default)]
 | 
				
			||||||
 | 
					    pub versioning: bool,
 | 
				
			||||||
 | 
					    pub quota: Option<usize>,
 | 
				
			||||||
 | 
					    #[serde(default)]
 | 
				
			||||||
 | 
					    pub lock: bool,
 | 
				
			||||||
 | 
					    pub retention: Option<BucketRetention>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					pub mod constants;
 | 
				
			||||||
 | 
					pub mod crd;
 | 
				
			||||||
 | 
					pub mod minio;
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					pub mod minio_test_server;
 | 
				
			||||||
 | 
					pub mod secrets;
 | 
				
			||||||
 | 
					pub mod utils;
 | 
				
			||||||
							
								
								
									
										109
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
				
			|||||||
 | 
					use futures::TryStreamExt;
 | 
				
			||||||
 | 
					use k8s_openapi::api::core::v1::Secret;
 | 
				
			||||||
 | 
					use kube::runtime::{watcher, WatchStreamExt};
 | 
				
			||||||
 | 
					use kube::{Api, Client};
 | 
				
			||||||
 | 
					use minio_operator::constants::{
 | 
				
			||||||
 | 
					    SECRET_MINIO_BUCKET_ACCESS_KEY, SECRET_MINIO_BUCKET_SECRET_KEY,
 | 
				
			||||||
 | 
					    SECRET_MINIO_INSTANCE_ACCESS_KEY, SECRET_MINIO_INSTANCE_SECRET_KEY,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					use minio_operator::crd::{MinioBucket, MinioInstance};
 | 
				
			||||||
 | 
					use minio_operator::minio::{MinioService, MinioUser};
 | 
				
			||||||
 | 
					use minio_operator::secrets::{create_secret, read_secret_str};
 | 
				
			||||||
 | 
					use std::collections::BTreeMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[tokio::main]
 | 
				
			||||||
 | 
					async fn main() -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let client = Client::try_default().await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let buckets: Api<MinioBucket> = Api::default_namespaced(client.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Listen for events / buckets creation or update (deletion is not supported)
 | 
				
			||||||
 | 
					    let wc = watcher::Config::default();
 | 
				
			||||||
 | 
					    let bw = watcher(buckets, wc).applied_objects();
 | 
				
			||||||
 | 
					    futures::pin_mut!(bw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while let Some(b) = bw.try_next().await? {
 | 
				
			||||||
 | 
					        if let Err(e) = apply_bucket(&b, &client).await {
 | 
				
			||||||
 | 
					            log::error!(
 | 
				
			||||||
 | 
					                "Failed to apply desired configuration for applied bucket {} : {}",
 | 
				
			||||||
 | 
					                b.spec.name,
 | 
				
			||||||
 | 
					                e
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Make sure a bucket is compliant with a desired configuration
 | 
				
			||||||
 | 
					async fn apply_bucket(b: &MinioBucket, client: &Client) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    log::info!("Apply configuration for bucket {}", b.spec.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Get instance information
 | 
				
			||||||
 | 
					    let instances: Api<MinioInstance> = Api::default_namespaced(client.clone());
 | 
				
			||||||
 | 
					    let instance = instances.get(&b.spec.instance).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Get instance configuration
 | 
				
			||||||
 | 
					    let secrets: Api<Secret> = Api::default_namespaced(client.clone());
 | 
				
			||||||
 | 
					    let instance_secret = secrets.get(&instance.spec.credentials).await?;
 | 
				
			||||||
 | 
					    let service = MinioService {
 | 
				
			||||||
 | 
					        hostname: instance.spec.endpoint,
 | 
				
			||||||
 | 
					        access_key: read_secret_str(&instance_secret, SECRET_MINIO_INSTANCE_ACCESS_KEY)?,
 | 
				
			||||||
 | 
					        secret_key: read_secret_str(&instance_secret, SECRET_MINIO_INSTANCE_SECRET_KEY)?,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Get user key & password
 | 
				
			||||||
 | 
					    let user_secret = match secrets.get_opt(&b.spec.secret).await? {
 | 
				
			||||||
 | 
					        Some(s) => s,
 | 
				
			||||||
 | 
					        None => {
 | 
				
			||||||
 | 
					            log::info!(
 | 
				
			||||||
 | 
					                "Needs to create the secret {} for the bucket {}",
 | 
				
			||||||
 | 
					                b.spec.secret,
 | 
				
			||||||
 | 
					                b.spec.name
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The secret needs to be created
 | 
				
			||||||
 | 
					            let new_user = MinioUser::gen_random();
 | 
				
			||||||
 | 
					            create_secret(
 | 
				
			||||||
 | 
					                &secrets,
 | 
				
			||||||
 | 
					                &b.spec.secret,
 | 
				
			||||||
 | 
					                BTreeMap::from([
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        SECRET_MINIO_BUCKET_ACCESS_KEY.to_string(),
 | 
				
			||||||
 | 
					                        new_user.username,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        SECRET_MINIO_BUCKET_SECRET_KEY.to_string(),
 | 
				
			||||||
 | 
					                        new_user.password,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                ]),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    let user = MinioUser {
 | 
				
			||||||
 | 
					        username: read_secret_str(&user_secret, SECRET_MINIO_BUCKET_ACCESS_KEY)?,
 | 
				
			||||||
 | 
					        password: read_secret_str(&user_secret, SECRET_MINIO_BUCKET_SECRET_KEY)?,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    log::debug!("Create or update bucket...");
 | 
				
			||||||
 | 
					    service.bucket_apply(&b.spec).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let policy_name = format!("bucket-{}", b.spec.name);
 | 
				
			||||||
 | 
					    log::debug!("Create or update policy '{policy_name}'...");
 | 
				
			||||||
 | 
					    let policy_content =
 | 
				
			||||||
 | 
					        include_str!("policy_template.json").replace("{{ bucket }}", b.spec.name.as_str());
 | 
				
			||||||
 | 
					    service.policy_apply(&policy_name, &policy_content).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    log::debug!("Create or update user '{}'...", user.username);
 | 
				
			||||||
 | 
					    service.user_apply(&user).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    log::debug!("Attach policy '{policy_name}' to user...");
 | 
				
			||||||
 | 
					    service.policy_attach_user(&user, &policy_name).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    log::debug!("Successfully applied desired configuration!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1138
									
								
								src/minio.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1138
									
								
								src/minio.rs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										117
									
								
								src/minio_test_server.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								src/minio_test_server.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					//! # Minio server controller
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! Used for testing only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::minio::MinioService;
 | 
				
			||||||
 | 
					use crate::utils::rand_str;
 | 
				
			||||||
 | 
					use rand::RngCore;
 | 
				
			||||||
 | 
					use std::io::ErrorKind;
 | 
				
			||||||
 | 
					use std::process::{Child, Command};
 | 
				
			||||||
 | 
					use std::time::Duration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct MinioTestServer {
 | 
				
			||||||
 | 
					    #[allow(dead_code)]
 | 
				
			||||||
 | 
					    storage_base_dir: mktemp::Temp,
 | 
				
			||||||
 | 
					    child: Child,
 | 
				
			||||||
 | 
					    pub api_port: u16,
 | 
				
			||||||
 | 
					    pub root_user: String,
 | 
				
			||||||
 | 
					    pub root_password: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl MinioTestServer {
 | 
				
			||||||
 | 
					    pub async fn start() -> anyhow::Result<Self> {
 | 
				
			||||||
 | 
					        let storage_dir = mktemp::Temp::new_dir()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let root_user = rand_str(30);
 | 
				
			||||||
 | 
					        let root_password = rand_str(30);
 | 
				
			||||||
 | 
					        let api_port = (2000 + rand::thread_rng().next_u64() % 5000) as u16;
 | 
				
			||||||
 | 
					        log::info!(
 | 
				
			||||||
 | 
					            "Spwan a new Minio server on port {} with root credentials {}:{}",
 | 
				
			||||||
 | 
					            api_port,
 | 
				
			||||||
 | 
					            root_user,
 | 
				
			||||||
 | 
					            root_password
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let child = Command::new("minio")
 | 
				
			||||||
 | 
					            .current_dir(storage_dir.clone())
 | 
				
			||||||
 | 
					            .arg("server")
 | 
				
			||||||
 | 
					            .arg("--address")
 | 
				
			||||||
 | 
					            .arg(format!(":{api_port}"))
 | 
				
			||||||
 | 
					            .arg(storage_dir.to_str().unwrap())
 | 
				
			||||||
 | 
					            .env("MINIO_ROOT_USER", &root_user)
 | 
				
			||||||
 | 
					            .env("MINIO_ROOT_PASSWORD", &root_password)
 | 
				
			||||||
 | 
					            .spawn()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let instance = Self {
 | 
				
			||||||
 | 
					            storage_base_dir: storage_dir,
 | 
				
			||||||
 | 
					            child,
 | 
				
			||||||
 | 
					            api_port,
 | 
				
			||||||
 | 
					            root_user,
 | 
				
			||||||
 | 
					            root_password,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Wait for Minio to become ready
 | 
				
			||||||
 | 
					        std::thread::sleep(Duration::from_millis(500));
 | 
				
			||||||
 | 
					        let mut check_count = 0;
 | 
				
			||||||
 | 
					        loop {
 | 
				
			||||||
 | 
					            if check_count >= 100 {
 | 
				
			||||||
 | 
					                log::error!("Minio failed to respond properly in time!");
 | 
				
			||||||
 | 
					                return Err(std::io::Error::new(
 | 
				
			||||||
 | 
					                    ErrorKind::Other,
 | 
				
			||||||
 | 
					                    "Minio failed to respond in time!",
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					                .into());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            check_count += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::thread::sleep(Duration::from_millis(100));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if instance.as_service().is_ready().await {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(instance)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn base_url(&self) -> String {
 | 
				
			||||||
 | 
					        format!("http://127.0.0.1:{}", self.api_port)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Get a MinioService instance of this temporary server
 | 
				
			||||||
 | 
					    pub fn as_service(&self) -> MinioService {
 | 
				
			||||||
 | 
					        MinioService {
 | 
				
			||||||
 | 
					            hostname: self.base_url(),
 | 
				
			||||||
 | 
					            access_key: self.root_user.clone(),
 | 
				
			||||||
 | 
					            secret_key: self.root_password.clone(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Drop for MinioTestServer {
 | 
				
			||||||
 | 
					    fn drop(&mut self) {
 | 
				
			||||||
 | 
					        if let Err(e) = self.child.kill() {
 | 
				
			||||||
 | 
					            log::error!("Failed to kill child server! {}", e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
					mod test {
 | 
				
			||||||
 | 
					    use crate::minio_test_server::MinioTestServer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[tokio::test]
 | 
				
			||||||
 | 
					    async fn start_minio() {
 | 
				
			||||||
 | 
					        let _ = env_logger::builder().is_test(true).try_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let server = MinioTestServer::start().await.unwrap();
 | 
				
			||||||
 | 
					        let service = server.as_service();
 | 
				
			||||||
 | 
					        println!("{:?}", service);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert!(service.is_ready().await);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Check if minio properly exit
 | 
				
			||||||
 | 
					        drop(server);
 | 
				
			||||||
 | 
					        assert!(!service.is_ready().await);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										17
									
								
								src/policy_template.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/policy_template.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "Version": "2012-10-17",
 | 
				
			||||||
 | 
					  "Statement": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "Sid": "ListObjectsInBucket",
 | 
				
			||||||
 | 
					      "Effect": "Allow",
 | 
				
			||||||
 | 
					      "Action": ["s3:ListBucket"],
 | 
				
			||||||
 | 
					      "Resource": ["arn:aws:s3:::{{ bucket }}"]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "Sid": "AllObjectActions",
 | 
				
			||||||
 | 
					      "Effect": "Allow",
 | 
				
			||||||
 | 
					      "Action": ["s3:DeleteObject", "s3:Get*", "s3:PutObject", "s3:*Object"],
 | 
				
			||||||
 | 
					      "Resource": ["arn:aws:s3:::{{ bucket }}/*"]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										64
									
								
								src/secrets.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/secrets.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					use k8s_openapi::api::core::v1::Secret;
 | 
				
			||||||
 | 
					use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta;
 | 
				
			||||||
 | 
					use kube::api::PostParams;
 | 
				
			||||||
 | 
					use kube::Api;
 | 
				
			||||||
 | 
					use std::collections::BTreeMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(thiserror::Error, Debug)]
 | 
				
			||||||
 | 
					enum SecretError {
 | 
				
			||||||
 | 
					    #[error("Secret has no data!")]
 | 
				
			||||||
 | 
					    MissingData,
 | 
				
			||||||
 | 
					    #[error("The key '{0}' is not present in the secret!")]
 | 
				
			||||||
 | 
					    MissingKey(String),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Attempt to read a value contained in a secret. Returns an error in case
 | 
				
			||||||
 | 
					/// of failure
 | 
				
			||||||
 | 
					pub fn read_secret_str(s: &Secret, key: &str) -> anyhow::Result<String> {
 | 
				
			||||||
 | 
					    let data = s.data.as_ref().ok_or(SecretError::MissingData)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let value = data
 | 
				
			||||||
 | 
					        .get(key)
 | 
				
			||||||
 | 
					        .ok_or(SecretError::MissingKey(key.to_string()))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(String::from_utf8(value.0.clone())?)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Create a secret consisting only of string key / value pairs
 | 
				
			||||||
 | 
					pub async fn create_secret(
 | 
				
			||||||
 | 
					    secrets: &Api<Secret>,
 | 
				
			||||||
 | 
					    name: &str,
 | 
				
			||||||
 | 
					    values: BTreeMap<String, String>,
 | 
				
			||||||
 | 
					) -> anyhow::Result<Secret> {
 | 
				
			||||||
 | 
					    Ok(secrets
 | 
				
			||||||
 | 
					        .create(
 | 
				
			||||||
 | 
					            &PostParams::default(),
 | 
				
			||||||
 | 
					            &Secret {
 | 
				
			||||||
 | 
					                data: None,
 | 
				
			||||||
 | 
					                immutable: None,
 | 
				
			||||||
 | 
					                metadata: ObjectMeta {
 | 
				
			||||||
 | 
					                    annotations: None,
 | 
				
			||||||
 | 
					                    creation_timestamp: None,
 | 
				
			||||||
 | 
					                    deletion_grace_period_seconds: None,
 | 
				
			||||||
 | 
					                    deletion_timestamp: None,
 | 
				
			||||||
 | 
					                    finalizers: None,
 | 
				
			||||||
 | 
					                    generate_name: None,
 | 
				
			||||||
 | 
					                    generation: None,
 | 
				
			||||||
 | 
					                    labels: Some(BTreeMap::from([(
 | 
				
			||||||
 | 
					                        "created-by".to_string(),
 | 
				
			||||||
 | 
					                        "miniok8sbuckets".to_string(),
 | 
				
			||||||
 | 
					                    )])),
 | 
				
			||||||
 | 
					                    managed_fields: None,
 | 
				
			||||||
 | 
					                    name: Some(name.to_string()),
 | 
				
			||||||
 | 
					                    namespace: None,
 | 
				
			||||||
 | 
					                    owner_references: None,
 | 
				
			||||||
 | 
					                    resource_version: None,
 | 
				
			||||||
 | 
					                    self_link: None,
 | 
				
			||||||
 | 
					                    uid: None,
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                string_data: Some(values),
 | 
				
			||||||
 | 
					                type_: None,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .await?)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								src/utils.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/utils.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					use rand::distributions::Alphanumeric;
 | 
				
			||||||
 | 
					use rand::Rng;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Generate a random string of a given size
 | 
				
			||||||
 | 
					pub fn rand_str(len: usize) -> String {
 | 
				
			||||||
 | 
					    rand::thread_rng()
 | 
				
			||||||
 | 
					        .sample_iter(&Alphanumeric)
 | 
				
			||||||
 | 
					        .take(len)
 | 
				
			||||||
 | 
					        .map(char::from)
 | 
				
			||||||
 | 
					        .collect()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										25
									
								
								test/first-test.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								test/first-test.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					kind: Secret
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: minio-root
 | 
				
			||||||
 | 
					type: Opaque
 | 
				
			||||||
 | 
					data:
 | 
				
			||||||
 | 
					  accessKey: bWluaW9hZG1pbg==
 | 
				
			||||||
 | 
					  secretKey: bWluaW9hZG1pbg==
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: "communiquons.org/v1"
 | 
				
			||||||
 | 
					kind: MinioInstance
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: my-minio-instance
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  endpoint: http://minio:9000/
 | 
				
			||||||
 | 
					  credentials: minio-root
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: "communiquons.org/v1"
 | 
				
			||||||
 | 
					kind: MinioBucket
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: first-bucket
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  instance: my-minio-instance
 | 
				
			||||||
 | 
					  name: first-bucket
 | 
				
			||||||
 | 
					  secret: first-bucket-secret
 | 
				
			||||||
							
								
								
									
										10
									
								
								test/second-bucket.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								test/second-bucket.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: "communiquons.org/v1"
 | 
				
			||||||
 | 
					kind: MinioBucket
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: second-bucket
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  instance: my-minio-instance
 | 
				
			||||||
 | 
					  name: second-bucket
 | 
				
			||||||
 | 
					  secret: second-bucket-secret
 | 
				
			||||||
 | 
					  versioning: false
 | 
				
			||||||
							
								
								
									
										25
									
								
								test/test-inside-cluster.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								test/test-inside-cluster.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					kind: Secret
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: minio-root
 | 
				
			||||||
 | 
					type: Opaque
 | 
				
			||||||
 | 
					data:
 | 
				
			||||||
 | 
					  accessKey: bWluaW9hZG1pbg==
 | 
				
			||||||
 | 
					  secretKey: bWluaW9hZG1pbg==
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: "communiquons.org/v1"
 | 
				
			||||||
 | 
					kind: MinioInstance
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: my-minio-instance
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  endpoint: http://192.168.2.103:9000/
 | 
				
			||||||
 | 
					  credentials: minio-root
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: "communiquons.org/v1"
 | 
				
			||||||
 | 
					kind: MinioBucket
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: first-bucket
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  instance: my-minio-instance
 | 
				
			||||||
 | 
					  name: first-bucket
 | 
				
			||||||
 | 
					  secret: first-bucket-secret
 | 
				
			||||||
							
								
								
									
										25
									
								
								test/test-outside-cluster.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								test/test-outside-cluster.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					kind: Secret
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: minio-root
 | 
				
			||||||
 | 
					type: Opaque
 | 
				
			||||||
 | 
					data:
 | 
				
			||||||
 | 
					  accessKey: bWluaW9hZG1pbg==
 | 
				
			||||||
 | 
					  secretKey: bWluaW9hZG1pbg==
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: "communiquons.org/v1"
 | 
				
			||||||
 | 
					kind: MinioInstance
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: my-minio-instance
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  endpoint: http://localhost:9000/
 | 
				
			||||||
 | 
					  credentials: minio-root
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: "communiquons.org/v1"
 | 
				
			||||||
 | 
					kind: MinioBucket
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: first-bucket
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  instance: my-minio-instance
 | 
				
			||||||
 | 
					  name: first-bucket
 | 
				
			||||||
 | 
					  secret: first-bucket-secret
 | 
				
			||||||
							
								
								
									
										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"]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,5 +1,54 @@
 | 
				
			|||||||
apiVersion: apiextensions.k8s.io/v1
 | 
					apiVersion: apiextensions.k8s.io/v1
 | 
				
			||||||
kind: CustomResourceDefinition
 | 
					kind: CustomResourceDefinition
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  # name must match the spec fields below, and be in the form: <plural>.<group>
 | 
				
			||||||
 | 
					  name: minioinstances.communiquons.org
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  # group name to use for REST API: /apis/<group>/<version>
 | 
				
			||||||
 | 
					  group: communiquons.org
 | 
				
			||||||
 | 
					  # list of versions supported by this CustomResourceDefinition
 | 
				
			||||||
 | 
					  versions:
 | 
				
			||||||
 | 
					    - name: v1
 | 
				
			||||||
 | 
					      # Each version can be enabled/disabled by Served flag.
 | 
				
			||||||
 | 
					      served: true
 | 
				
			||||||
 | 
					      # One and only one version must be marked as the storage version.
 | 
				
			||||||
 | 
					      storage: true
 | 
				
			||||||
 | 
					      schema:
 | 
				
			||||||
 | 
					        openAPIV3Schema:
 | 
				
			||||||
 | 
					          type: object
 | 
				
			||||||
 | 
					          properties:
 | 
				
			||||||
 | 
					            spec:
 | 
				
			||||||
 | 
					              type: object
 | 
				
			||||||
 | 
					              description: Information about how to reach the Minio bucket
 | 
				
			||||||
 | 
					              properties:
 | 
				
			||||||
 | 
					                endpoint:
 | 
				
			||||||
 | 
					                  description: The URL where the Minio API can be reached
 | 
				
			||||||
 | 
					                  example: https://minio.communiquons.org
 | 
				
			||||||
 | 
					                  type: string
 | 
				
			||||||
 | 
					                credentials:
 | 
				
			||||||
 | 
					                  description: |
 | 
				
			||||||
 | 
					                    The name of the secret containings privilegied / root credentials of Minio instance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    The secret must contains two fields :
 | 
				
			||||||
 | 
					                    * An access key named `accessKey`
 | 
				
			||||||
 | 
					                    * A secret key named `secretKey`
 | 
				
			||||||
 | 
					                  type: string
 | 
				
			||||||
 | 
					                  example: minio-root
 | 
				
			||||||
 | 
					  # either Namespaced or Cluster
 | 
				
			||||||
 | 
					  scope: Namespaced
 | 
				
			||||||
 | 
					  names:
 | 
				
			||||||
 | 
					    # plural name to be used in the URL: /apis/<group>/<version>/<plural>
 | 
				
			||||||
 | 
					    plural: minioinstances
 | 
				
			||||||
 | 
					    # singular name to be used as an alias on the CLI and for display
 | 
				
			||||||
 | 
					    singular: minioinstance
 | 
				
			||||||
 | 
					    # kind is normally the CamelCased singular type. Your resource manifests use this.
 | 
				
			||||||
 | 
					    kind: MinioInstance
 | 
				
			||||||
 | 
					    # shortNames allow shorter string to match your resource on the CLI
 | 
				
			||||||
 | 
					    shortNames:
 | 
				
			||||||
 | 
					    - mis
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: apiextensions.k8s.io/v1
 | 
				
			||||||
 | 
					kind: CustomResourceDefinition
 | 
				
			||||||
metadata:
 | 
					metadata:
 | 
				
			||||||
  # name must match the spec fields below, and be in the form: <plural>.<group>
 | 
					  # name must match the spec fields below, and be in the form: <plural>.<group>
 | 
				
			||||||
  name: miniobuckets.communiquons.org
 | 
					  name: miniobuckets.communiquons.org
 | 
				
			||||||
@@ -34,7 +83,7 @@ spec:
 | 
				
			|||||||
                  type: string
 | 
					                  type: string
 | 
				
			||||||
                  example: mybucket
 | 
					                  example: mybucket
 | 
				
			||||||
                secret:
 | 
					                secret:
 | 
				
			||||||
                  description: The name of the secret that will receive an access key & token with write access on the bucket
 | 
					                  description: The name of the secret that will receive an access key & a secret key with write access on the bucket
 | 
				
			||||||
                  type: string
 | 
					                  type: string
 | 
				
			||||||
                  example: secret-name
 | 
					                  example: secret-name
 | 
				
			||||||
                anonymous_read_access:
 | 
					                anonymous_read_access:
 | 
				
			||||||
@@ -47,8 +96,12 @@ spec:
 | 
				
			|||||||
                  default: false
 | 
					                  default: false
 | 
				
			||||||
                quota:
 | 
					                quota:
 | 
				
			||||||
                  type: integer
 | 
					                  type: integer
 | 
				
			||||||
                  description: Limits the amount of data in the bucket, in Megabytes. By default it is unlimited
 | 
					                  description: Limits the amount of data in the bucket, in bytes. By default it is unlimited
 | 
				
			||||||
                  example: 100
 | 
					                  example: 1000000000
 | 
				
			||||||
 | 
					                lock:
 | 
				
			||||||
 | 
					                  description: Object locking prevent objects from being deleted. MUST be set to true when retention is defined. Cannot be changed.
 | 
				
			||||||
 | 
					                  type: boolean
 | 
				
			||||||
 | 
					                  default: false
 | 
				
			||||||
                retention:
 | 
					                retention:
 | 
				
			||||||
                  type: object
 | 
					                  type: object
 | 
				
			||||||
                  description: Impose rules to prevent object deletion for a period of time. It requires versioning to be enabled/disabled
 | 
					                  description: Impose rules to prevent object deletion for a period of time. It requires versioning to be enabled/disabled
 | 
				
			||||||
@@ -60,15 +113,12 @@ spec:
 | 
				
			|||||||
                      type: integer
 | 
					                      type: integer
 | 
				
			||||||
                      description: The number of days the data shall be kept
 | 
					                      description: The number of days the data shall be kept
 | 
				
			||||||
                      example: 180
 | 
					                      example: 180
 | 
				
			||||||
                    mode:
 | 
					                    type:
 | 
				
			||||||
                      type: string
 | 
					                      type: string
 | 
				
			||||||
                      description: Retention type. In governance mode, some privileged user can bypass retention policy, while in governance policy, no one, including root user, can delete the data
 | 
					                      description: Retention type. In governance mode, some privileged user can bypass retention policy, while in governance policy, no one, including root user, can delete the data
 | 
				
			||||||
                      enum:
 | 
					                      enum:
 | 
				
			||||||
                      - compliance
 | 
					                      - compliance
 | 
				
			||||||
                      - governance
 | 
					                      - governance
 | 
				
			||||||
                
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  # either Namespaced or Cluster
 | 
					  # either Namespaced or Cluster
 | 
				
			||||||
  scope: Namespaced
 | 
					  scope: Namespaced
 | 
				
			||||||
  names:
 | 
					  names:
 | 
				
			||||||
@@ -82,3 +132,4 @@ spec:
 | 
				
			|||||||
    shortNames:
 | 
					    shortNames:
 | 
				
			||||||
    - mbs
 | 
					    - mbs
 | 
				
			||||||
    - buckets
 | 
					    - buckets
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
							
								
								
									
										70
									
								
								yaml/deployment.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								yaml/deployment.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					kind: ServiceAccount
 | 
				
			||||||
 | 
					automountServiceAccountToken: true
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: minio-operator
 | 
				
			||||||
 | 
					  namespace: default
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    app: minio-operator
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: rbac.authorization.k8s.io/v1
 | 
				
			||||||
 | 
					kind: Role
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: minio-operator
 | 
				
			||||||
 | 
					  namespace: default
 | 
				
			||||||
 | 
					rules:
 | 
				
			||||||
 | 
					- apiGroups: ["communiquons.org"]
 | 
				
			||||||
 | 
					  resources: ["minioinstances", "miniobuckets"]
 | 
				
			||||||
 | 
					  verbs: ["get", "list", "watch"]
 | 
				
			||||||
 | 
					- apiGroups: [""]
 | 
				
			||||||
 | 
					  resources: ["secrets"]
 | 
				
			||||||
 | 
					  verbs: ["get", "create"]
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					kind: RoleBinding
 | 
				
			||||||
 | 
					apiVersion: rbac.authorization.k8s.io/v1
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: minio-operator
 | 
				
			||||||
 | 
					  namespace: default
 | 
				
			||||||
 | 
					subjects:
 | 
				
			||||||
 | 
					- kind: ServiceAccount
 | 
				
			||||||
 | 
					  name: minio-operator
 | 
				
			||||||
 | 
					  namespace: default
 | 
				
			||||||
 | 
					roleRef:
 | 
				
			||||||
 | 
					  apiGroup: rbac.authorization.k8s.io
 | 
				
			||||||
 | 
					  kind: Role
 | 
				
			||||||
 | 
					  name: minio-operator
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: apps/v1
 | 
				
			||||||
 | 
					kind: Deployment
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: minio-operator
 | 
				
			||||||
 | 
					  labels:
 | 
				
			||||||
 | 
					    app: minio-operator
 | 
				
			||||||
 | 
					spec:
 | 
				
			||||||
 | 
					  replicas: 1
 | 
				
			||||||
 | 
					  strategy:
 | 
				
			||||||
 | 
					    type: Recreate
 | 
				
			||||||
 | 
					  selector:
 | 
				
			||||||
 | 
					    matchLabels:
 | 
				
			||||||
 | 
					      app: minio-operator
 | 
				
			||||||
 | 
					  template:
 | 
				
			||||||
 | 
					    metadata:
 | 
				
			||||||
 | 
					      labels:
 | 
				
			||||||
 | 
					        app: minio-operator
 | 
				
			||||||
 | 
					    spec:
 | 
				
			||||||
 | 
					      serviceAccountName: minio-operator
 | 
				
			||||||
 | 
					      containers:
 | 
				
			||||||
 | 
					        - name: minio-operator
 | 
				
			||||||
 | 
					          image: pierre42100/minio_operator
 | 
				
			||||||
 | 
					          resources:
 | 
				
			||||||
 | 
					            limits:
 | 
				
			||||||
 | 
					              memory: 300Mi
 | 
				
			||||||
 | 
					              cpu: "0.1"
 | 
				
			||||||
 | 
					            requests:
 | 
				
			||||||
 | 
					              memory: 150Mi
 | 
				
			||||||
 | 
					              cpu: "0.01"
 | 
				
			||||||
 | 
					          securityContext:
 | 
				
			||||||
 | 
					            allowPrivilegeEscalation: false
 | 
				
			||||||
 | 
					            capabilities:
 | 
				
			||||||
 | 
					              drop:
 | 
				
			||||||
 | 
					              - ALL
 | 
				
			||||||
@@ -1,48 +0,0 @@
 | 
				
			|||||||
apiVersion: apiextensions.k8s.io/v1
 | 
					 | 
				
			||||||
kind: CustomResourceDefinition
 | 
					 | 
				
			||||||
metadata:
 | 
					 | 
				
			||||||
  # name must match the spec fields below, and be in the form: <plural>.<group>
 | 
					 | 
				
			||||||
  name: minioinstances.communiquons.org
 | 
					 | 
				
			||||||
spec:
 | 
					 | 
				
			||||||
  # group name to use for REST API: /apis/<group>/<version>
 | 
					 | 
				
			||||||
  group: communiquons.org
 | 
					 | 
				
			||||||
  # list of versions supported by this CustomResourceDefinition
 | 
					 | 
				
			||||||
  versions:
 | 
					 | 
				
			||||||
    - name: v1
 | 
					 | 
				
			||||||
      # Each version can be enabled/disabled by Served flag.
 | 
					 | 
				
			||||||
      served: true
 | 
					 | 
				
			||||||
      # One and only one version must be marked as the storage version.
 | 
					 | 
				
			||||||
      storage: true
 | 
					 | 
				
			||||||
      schema:
 | 
					 | 
				
			||||||
        openAPIV3Schema:
 | 
					 | 
				
			||||||
          type: object
 | 
					 | 
				
			||||||
          properties:
 | 
					 | 
				
			||||||
            spec:
 | 
					 | 
				
			||||||
              type: object
 | 
					 | 
				
			||||||
              description: Information about how to reach the Minio bucket
 | 
					 | 
				
			||||||
              properties:
 | 
					 | 
				
			||||||
                endpoint:
 | 
					 | 
				
			||||||
                  description: The URL where the Minio API can be reached
 | 
					 | 
				
			||||||
                  example: https://minio.communiquons.org
 | 
					 | 
				
			||||||
                  type: string
 | 
					 | 
				
			||||||
                credentials:
 | 
					 | 
				
			||||||
                  description: |
 | 
					 | 
				
			||||||
                    The name of the secret containings privilegied / root credentials of Minio instance
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    The secret must contains two fields :
 | 
					 | 
				
			||||||
                    * An access key named `accessKey`
 | 
					 | 
				
			||||||
                    * A secret key named `secretKey`
 | 
					 | 
				
			||||||
                  type: string
 | 
					 | 
				
			||||||
                  example: minio-root
 | 
					 | 
				
			||||||
  # either Namespaced or Cluster
 | 
					 | 
				
			||||||
  scope: Namespaced
 | 
					 | 
				
			||||||
  names:
 | 
					 | 
				
			||||||
    # plural name to be used in the URL: /apis/<group>/<version>/<plural>
 | 
					 | 
				
			||||||
    plural: minioinstances
 | 
					 | 
				
			||||||
    # singular name to be used as an alias on the CLI and for display
 | 
					 | 
				
			||||||
    singular: minioinstance
 | 
					 | 
				
			||||||
    # kind is normally the CamelCased singular type. Your resource manifests use this.
 | 
					 | 
				
			||||||
    kind: MinioInstance
 | 
					 | 
				
			||||||
    # shortNames allow shorter string to match your resource on the CLI
 | 
					 | 
				
			||||||
    shortNames:
 | 
					 | 
				
			||||||
    - mis
 | 
					 | 
				
			||||||
@@ -1,32 +0,0 @@
 | 
				
			|||||||
apiVersion: v1
 | 
					 | 
				
			||||||
kind: ServiceAccount
 | 
					 | 
				
			||||||
automountServiceAccountToken: true
 | 
					 | 
				
			||||||
metadata:
 | 
					 | 
				
			||||||
  name: minio-buckets
 | 
					 | 
				
			||||||
  namespace: default
 | 
					 | 
				
			||||||
  labels:
 | 
					 | 
				
			||||||
    app: minio
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
apiVersion: rbac.authorization.k8s.io/v1
 | 
					 | 
				
			||||||
kind: Role
 | 
					 | 
				
			||||||
metadata:
 | 
					 | 
				
			||||||
  name: minio-buckets
 | 
					 | 
				
			||||||
  namespace: default
 | 
					 | 
				
			||||||
rules:
 | 
					 | 
				
			||||||
- apiGroups: ["communiquons.org"]
 | 
					 | 
				
			||||||
  resources: ["minioinstances", "miniobuckets"]
 | 
					 | 
				
			||||||
  verbs: ["get", "watch"]
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
kind: RoleBinding
 | 
					 | 
				
			||||||
apiVersion: rbac.authorization.k8s.io/v1
 | 
					 | 
				
			||||||
metadata:
 | 
					 | 
				
			||||||
  name: minio-buckets
 | 
					 | 
				
			||||||
  namespace: default
 | 
					 | 
				
			||||||
subjects:
 | 
					 | 
				
			||||||
- kind: ServiceAccount
 | 
					 | 
				
			||||||
  name: minio-buckets
 | 
					 | 
				
			||||||
  namespace: default
 | 
					 | 
				
			||||||
roleRef:
 | 
					 | 
				
			||||||
  apiGroup: rbac.authorization.k8s.io
 | 
					 | 
				
			||||||
  kind: Role
 | 
					 | 
				
			||||||
  name: minio-buckets
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user