mz_cloud_resources/crd/
balancer.rs1use std::collections::BTreeMap;
11
12use anyhow::bail;
13use k8s_openapi::{
14 api::core::v1::ResourceRequirements, apimachinery::pkg::apis::meta::v1::Condition,
15};
16use kube::CustomResource;
17use schemars::JsonSchema;
18use serde::{Deserialize, Serialize};
19
20use crate::crd::{ManagedResource, MaterializeCertSpec, new_resource_id};
21
22pub mod v1alpha1 {
23 use super::*;
24
25 #[derive(Clone, Debug)]
26 pub enum Routing<'a> {
27 Static(&'a StaticRoutingConfig),
28 Frontegg(&'a FronteggRoutingConfig),
29 }
30
31 #[derive(Clone, Debug, PartialEq, Deserialize, Serialize, JsonSchema)]
32 #[serde(rename_all = "camelCase")]
33 pub struct StaticRoutingConfig {
34 pub environmentd_namespace: String,
35 pub environmentd_service_name: String,
36 }
37
38 #[derive(Clone, Debug, PartialEq, Deserialize, Serialize, JsonSchema)]
39 #[serde(rename_all = "camelCase")]
40 pub struct FronteggRoutingConfig {
41 }
43
44 #[derive(
45 CustomResource, Clone, Debug, Default, PartialEq, Deserialize, Serialize, JsonSchema,
46 )]
47 #[serde(rename_all = "camelCase")]
48 #[kube(
49 namespaced,
50 group = "materialize.cloud",
51 version = "v1alpha1",
52 kind = "Balancer",
53 singular = "balancer",
54 plural = "balancers",
55 status = "BalancerStatus",
56 printcolumn = r#"{"name": "ImageRef", "type": "string", "description": "Reference to the Docker image.", "jsonPath": ".spec.balancerdImageRef", "priority": 1}"#,
57 printcolumn = r#"{"name": "Ready", "type": "string", "description": "Whether the deployment is ready", "jsonPath": ".status.conditions[?(@.type==\"Ready\")].status", "priority": 1}"#
58 )]
59 pub struct BalancerSpec {
60 pub balancerd_image_ref: String,
62 pub resource_requirements: Option<ResourceRequirements>,
64 pub replicas: Option<i32>,
66 pub external_certificate_spec: Option<MaterializeCertSpec>,
70 pub internal_certificate_spec: Option<MaterializeCertSpec>,
74 pub pod_annotations: Option<BTreeMap<String, String>>,
76 pub pod_labels: Option<BTreeMap<String, String>>,
78
79 pub static_routing: Option<StaticRoutingConfig>,
81 pub frontegg_routing: Option<FronteggRoutingConfig>,
83
84 pub resource_id: Option<String>,
86 }
87
88 impl Balancer {
89 pub fn name_prefixed(&self, suffix: &str) -> String {
90 format!("mz{}-{}", self.resource_id(), suffix)
91 }
92
93 pub fn resource_id(&self) -> &str {
94 &self.status.as_ref().unwrap().resource_id
95 }
96
97 pub fn deployment_name(&self) -> String {
98 self.name_prefixed("balancerd")
99 }
100
101 pub fn replicas(&self) -> i32 {
102 self.spec.replicas.unwrap_or(2)
103 }
104
105 pub fn app_name(&self) -> String {
106 "balancerd".to_owned()
107 }
108
109 pub fn service_name(&self) -> String {
110 self.name_prefixed("balancerd")
111 }
112
113 pub fn external_certificate_name(&self) -> String {
114 self.name_prefixed("balancerd-external")
115 }
116
117 pub fn external_certificate_secret_name(&self) -> String {
118 self.name_prefixed("balancerd-external-tls")
119 }
120
121 pub fn routing(&self) -> anyhow::Result<Routing<'_>> {
122 match (&self.spec.static_routing, &self.spec.frontegg_routing) {
123 (Some(config), None) => Ok(Routing::Static(config)),
124 (None, Some(config)) => Ok(Routing::Frontegg(config)),
125 (None, None) => bail!("no routing configuration present"),
126 _ => bail!("multiple routing configurations present"),
127 }
128 }
129
130 pub fn status(&self) -> BalancerStatus {
131 self.status.clone().unwrap_or_else(|| BalancerStatus {
132 resource_id: self
133 .spec
134 .resource_id
135 .clone()
136 .unwrap_or_else(new_resource_id),
137 conditions: vec![],
138 })
139 }
140 }
141
142 #[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq)]
143 #[serde(rename_all = "camelCase")]
144 pub struct BalancerStatus {
145 pub resource_id: String,
147
148 pub conditions: Vec<Condition>,
149 }
150
151 impl ManagedResource for Balancer {
152 fn default_labels(&self) -> BTreeMap<String, String> {
153 BTreeMap::from_iter([
154 (
155 "materialize.cloud/mz-resource-id".to_owned(),
156 self.resource_id().to_owned(),
157 ),
158 ("materialize.cloud/app".to_owned(), "balancerd".to_owned()),
159 ])
160 }
161 }
162}