1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use crate::{BackendPodSpec, ImagePullPolicy, SessionLivedBackend, SessionLivedBackendSpec};
use k8s_openapi::api::core::v1::{Container, EnvVar, LocalObjectReference};
use kube::core::ObjectMeta;
use std::collections::HashMap;

pub const DEFAULT_GRACE_SECONDS: u32 = 300;
pub const APPLICATION: &str = "application";
pub const DEFAULT_PREFIX: &str = "spawner-";

pub struct SessionLivedBackendBuilder {
    image: String,
    image_pull_secret: Option<String>,
    env: HashMap<String, String>,
    image_pull_policy: Option<ImagePullPolicy>,
    namespace: Option<String>,
    grace_period_seconds: Option<u32>,
    http_port: Option<u16>,
}

impl SessionLivedBackendBuilder {
    pub fn new(image: &str) -> Self {
        SessionLivedBackendBuilder {
            image: image.to_string(),
            env: HashMap::default(),
            image_pull_policy: None,
            image_pull_secret: None,
            namespace: None,
            grace_period_seconds: Some(DEFAULT_GRACE_SECONDS),
            http_port: None,
        }
    }

    pub fn with_env(self, env: HashMap<String, String>) -> Self {
        SessionLivedBackendBuilder { env, ..self }
    }

    pub fn with_port(self, http_port: Option<u16>) -> Self {
        SessionLivedBackendBuilder { http_port, ..self }
    }

    pub fn with_image_pull_policy(self, image_pull_policy: Option<ImagePullPolicy>) -> Self {
        SessionLivedBackendBuilder {
            image_pull_policy,
            ..self
        }
    }

    pub fn with_namespace(self, namespace: Option<String>) -> Self {
        SessionLivedBackendBuilder { namespace, ..self }
    }

    pub fn with_grace_period(self, grace_period_seconds: Option<u32>) -> Self {
        SessionLivedBackendBuilder {
            grace_period_seconds,
            ..self
        }
    }

    pub fn with_image_pull_secret(self, image_pull_secret: Option<String>) -> Self {
        SessionLivedBackendBuilder {
            image_pull_secret,
            ..self
        }
    }

    pub fn build_spec(&self) -> SessionLivedBackendSpec {
        let env: Vec<EnvVar> = self
            .env
            .iter()
            .map(|(name, value)| EnvVar {
                name: name.to_string(),
                value: Some(value.to_string()),
                ..EnvVar::default()
            })
            .collect();

        SessionLivedBackendSpec {
            http_port: self.http_port,
            grace_period_seconds: self.grace_period_seconds,
            template: BackendPodSpec {
                containers: vec![Container {
                    image: Some(self.image.to_string()),
                    image_pull_policy: self.image_pull_policy.as_ref().map(|d| d.to_string()),
                    env: Some(env),
                    name: APPLICATION.to_string(),
                    ..Default::default()
                }],
                image_pull_secrets: self.image_pull_secret.as_ref().map(|d| {
                    vec![LocalObjectReference {
                        name: Some(d.to_string()),
                    }]
                }),
                ..Default::default()
            },
        }
    }

    pub fn build_prefixed(&self, prefix: &str) -> SessionLivedBackend {
        SessionLivedBackend {
            metadata: ObjectMeta {
                generate_name: Some(prefix.to_string()),
                ..Default::default()
            },
            spec: self.build_spec(),
            status: None,
        }
    }

    pub fn build_named(&self, name: &str) -> SessionLivedBackend {
        SessionLivedBackend {
            metadata: ObjectMeta {
                name: Some(name.to_string()),
                namespace: self.namespace.clone(),
                ..Default::default()
            },
            spec: self.build_spec(),
            status: None,
        }
    }

    pub fn build(&self) -> SessionLivedBackend {
        self.build_prefixed(DEFAULT_PREFIX)
    }
}