use k8s_openapi::api::apps::v1::{Deployment, DeploymentSpec}; use k8s_openapi::api::core::v1::{ Container, ContainerPort, EnvVar, PodSpec, PodTemplateSpec, Service, ServicePort, ServiceSpec, }; use k8s_openapi::apimachinery::pkg::apis::meta::v1::LabelSelector; use kube::api::{ListParams, ObjectMeta, Patch, PatchParams}; use kube::{Api, Client, Error}; use std::collections::BTreeMap; use tracing::{info, instrument}; const NAME: &str = "minio"; pub async fn create_deployment(client: Client, namespace: &str) -> Result<(), Error> { let minio_container = Container { name: NAME.to_string(), env: Some(vec![ EnvVar { name: "MINIO_ROOT_USER".to_string(), value: Some("minio".to_string()), ..Default::default() }, EnvVar { name: "MINIO_ROOT_PASSWORD".to_string(), value: Some("password".to_string()), ..Default::default() }, ]), image: Some("quay.io/minio/minio:RELEASE.2022-10-20T00-55-09Z".to_string()), ports: Some(vec![ ContainerPort { container_port: 9000, ..Default::default() }, ContainerPort { container_port: 9001, ..Default::default() }, ]), args: Some( vec![ "server", "/data", "--address", ":9000", "--console-address", ":9001", ] .iter() .map(|s| s.to_string()) .collect::>(), ), liveness_probe: Some(k8s_openapi::api::core::v1::Probe { http_get: Some(k8s_openapi::api::core::v1::HTTPGetAction { path: Some("/minio/health/live".to_string()), port: k8s_openapi::apimachinery::pkg::util::intstr::IntOrString::Int(9000), ..Default::default() }), initial_delay_seconds: Some(10), period_seconds: Some(30), ..Default::default() }), readiness_probe: Some(k8s_openapi::api::core::v1::Probe { http_get: Some(k8s_openapi::api::core::v1::HTTPGetAction { path: Some("/minio/health/ready".to_string()), port: k8s_openapi::apimachinery::pkg::util::intstr::IntOrString::Int(9000), ..Default::default() }), initial_delay_seconds: Some(10), period_seconds: Some(30), ..Default::default() }), ..Default::default() }; let mc_container = Container { name: "mc".to_string(), env: Some(vec![ EnvVar { name: "MINIO_ROOT_USER".to_string(), value: Some("minio".to_string()), ..Default::default() }, EnvVar { name: "MINIO_ROOT_PASSWORD".to_string(), value: Some("password".to_string()), ..Default::default() }, ]), image: Some("minio/mc".to_string()), command: Some(vec!["bash".to_string(), "-c".to_string()]), args: Some(vec!["until (/usr/bin/mc alias set minio http://minio:9000 $$MINIO_ROOT_USER $$MINIO_ROOT_PASSWORD) do echo 'Waiting to start minio...' && sleep 1; done; /usr/bin/mc mb --ignore-existing minio/neon --region=eu-north-1; sleep inf;".to_string()]), ..Default::default() }; let deployment = Deployment { metadata: ObjectMeta { name: Some(NAME.to_string()), namespace: Some(namespace.to_string()), labels: Some(BTreeMap::from([("app".to_string(), NAME.to_string())])), ..Default::default() }, spec: Some(DeploymentSpec { replicas: Some(1), selector: LabelSelector { match_labels: Some(BTreeMap::from([("app".to_string(), NAME.to_string())])), ..Default::default() }, template: PodTemplateSpec { metadata: Some(ObjectMeta { labels: Some(BTreeMap::from([("app".to_string(), NAME.to_string())])), ..Default::default() }), spec: Some(PodSpec { containers: vec![minio_container, mc_container], ..Default::default() }), ..Default::default() }, ..Default::default() }), ..Default::default() }; let deployment_api = Api::::namespaced(client, namespace); deployment_api .patch( NAME, &PatchParams::apply("neon-operator"), &Patch::Apply(deployment), ) .await?; Ok(()) } pub async fn create_service(client: Client, namespace: &str) -> Result<(), Error> { let service = Service { metadata: ObjectMeta { name: Some(NAME.to_string()), namespace: Some(namespace.to_string()), labels: Some(BTreeMap::from([("app".to_string(), NAME.to_string())])), ..Default::default() }, spec: Some(ServiceSpec { selector: Some(BTreeMap::from([("app".to_string(), NAME.to_string())])), ports: Some(vec![ServicePort { port: 9000, ..Default::default() }]), ..Default::default() }), ..Default::default() }; info!("Reconciling service"); Api::::namespaced(client, namespace) .patch( NAME, &PatchParams::apply("neon-operator"), &Patch::Apply(service), ) .await?; Ok(()) } #[instrument(err, skip(client))] pub async fn deployment_exists(client: Client, namespace: &str) -> Result { let deployment_api: Api = Api::namespaced(client, namespace); let lp = ListParams { label_selector: Some(format!("app={}", NAME)), ..Default::default() }; let list_result = deployment_api.list(&lp).await?; Ok(list_result.items.len() > 0) }