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 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 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}