k8_obj_core/
service.rs

1use serde::Deserialize;
2use serde::Serialize;
3use std::collections::HashMap;
4
5use k8_obj_metadata::default_store_spec;
6use k8_obj_metadata::Crd;
7use k8_obj_metadata::CrdNames;
8use k8_obj_metadata::DefaultHeader;
9use k8_obj_metadata::Spec;
10use k8_obj_metadata::Status;
11
12const SERVICE_API: Crd = Crd {
13    group: "core",
14    version: "v1",
15    names: CrdNames {
16        kind: "Service",
17        plural: "services",
18        singular: "service",
19    },
20};
21
22#[derive(Deserialize, Serialize, Debug, PartialEq, Default, Clone)]
23#[serde(rename_all = "camelCase", default)]
24pub struct ServiceSpec {
25    #[serde(rename = "clusterIP")]
26    pub cluster_ip: String,
27    #[serde(rename = "externalIPs")]
28    pub external_ips: Vec<String>,
29    #[serde(rename = "loadBalancerIP")]
30    pub load_balancer_ip: Option<String>,
31    pub r#type: Option<LoadBalancerType>,
32    pub external_name: Option<String>,
33    pub external_traffic_policy: Option<ExternalTrafficPolicy>,
34    pub ports: Vec<ServicePort>,
35    pub selector: Option<HashMap<String, String>>,
36}
37
38impl Spec for ServiceSpec {
39    type Status = ServiceStatus;
40    type Header = DefaultHeader;
41
42    fn metadata() -> &'static Crd {
43        &SERVICE_API
44    }
45
46    fn make_same(&mut self, other: &Self) {
47        if other.cluster_ip.is_empty() {
48            self.cluster_ip = "".to_owned();
49        }
50    }
51}
52
53default_store_spec!(ServiceSpec, ServiceStatus, "Service");
54
55#[derive(Deserialize, Serialize, Debug, PartialEq, Default, Clone)]
56#[serde(rename_all = "camelCase")]
57pub struct ServicePort {
58    pub name: Option<String>,
59    pub node_port: Option<u16>,
60    pub port: u16,
61    pub target_port: Option<u16>,
62}
63
64#[derive(Deserialize, Serialize, Debug, PartialEq, Default, Clone)]
65#[serde(rename_all = "camelCase", default)]
66pub struct ServiceStatus {
67    pub load_balancer: LoadBalancerStatus,
68}
69
70impl Status for ServiceStatus {}
71
72#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
73pub enum ExternalTrafficPolicy {
74    Local,
75    Cluster,
76}
77
78#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
79pub enum LoadBalancerType {
80    ExternalName,
81    ClusterIP,
82    NodePort,
83    LoadBalancer,
84}
85
86#[derive(Deserialize, Serialize, Debug, PartialEq, Default, Clone)]
87#[serde(rename_all = "camelCase", default)]
88pub struct LoadBalancerStatus {
89    pub ingress: Vec<LoadBalancerIngress>,
90}
91
92impl LoadBalancerStatus {
93    /// find any ip or host
94    pub fn find_any_ip_or_host(&self) -> Option<&str> {
95        self.ingress.iter().find_map(|ingress| ingress.host_or_ip())
96    }
97}
98
99#[derive(Deserialize, Serialize, Debug, PartialEq, Default, Clone)]
100#[serde(rename_all = "camelCase")]
101pub struct LoadBalancerIngress {
102    pub hostname: Option<String>,
103    pub ip: Option<String>,
104}
105
106impl LoadBalancerIngress {
107    /// return either host or ip
108    pub fn host_or_ip(&self) -> Option<&str> {
109        if let Some(host) = &self.hostname {
110            Some(host)
111        } else if let Some(ip) = &self.ip {
112            Some(ip)
113        } else {
114            None
115        }
116    }
117}