Skip to main content

mz_cloud_resources/crd/
console.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use std::collections::BTreeMap;
11
12use k8s_openapi::{
13    api::core::v1::ResourceRequirements, apimachinery::pkg::apis::meta::v1::Condition,
14};
15use kube::{CustomResource, Resource, ResourceExt};
16use schemars::JsonSchema;
17use serde::{Deserialize, Serialize};
18
19use crate::crd::{ManagedResource, MaterializeCertSpec, new_resource_id};
20use mz_server_core::listeners::AuthenticatorKind;
21
22pub mod v1alpha1 {
23    use super::*;
24
25    #[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize, JsonSchema)]
26    #[serde(rename_all = "camelCase")]
27    pub enum HttpConnectionScheme {
28        #[default]
29        Http,
30        Https,
31    }
32
33    #[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize, JsonSchema)]
34    #[serde(rename_all = "camelCase")]
35    pub struct BalancerdRef {
36        /// The service name for the balancerd service to connect to
37        pub service_name: String,
38        /// The namespace the balancerd service runs in
39        pub namespace: String,
40        /// Whether to use HTTP or HTTPS to communicate with Materialize.
41        pub scheme: HttpConnectionScheme,
42    }
43
44    #[derive(
45        CustomResource,
46        Clone,
47        Debug,
48        Default,
49        PartialEq,
50        Deserialize,
51        Serialize,
52        JsonSchema
53    )]
54    #[serde(rename_all = "camelCase")]
55    #[kube(
56        namespaced,
57        group = "materialize.cloud",
58        version = "v1alpha1",
59        kind = "Console",
60        singular = "console",
61        plural = "consoles",
62        status = "ConsoleStatus",
63        printcolumn = r#"{"name": "ImageRef", "type": "string", "description": "Reference to the Docker image.", "jsonPath": ".spec.consoleImageRef", "priority": 1}"#,
64        printcolumn = r#"{"name": "Ready", "type": "string", "description": "Whether the deployment is ready", "jsonPath": ".status.conditions[?(@.type==\"Ready\")].status", "priority": 1}"#
65    )]
66    pub struct ConsoleSpec {
67        /// The console image to run.
68        pub console_image_ref: String,
69        // Resource requirements for the console pod
70        pub resource_requirements: Option<ResourceRequirements>,
71        // Number of console pods to create
72        pub replicas: Option<i32>,
73        // The configuration for generating an x509 certificate using cert-manager for console
74        // to present to incoming connections.
75        // The dns_names and issuer_ref fields are required.
76        pub external_certificate_spec: Option<MaterializeCertSpec>,
77        // Annotations to apply to the pods
78        pub pod_annotations: Option<BTreeMap<String, String>>,
79        // Labels to apply to the pods
80        pub pod_labels: Option<BTreeMap<String, String>>,
81
82        // Connection information for the balancerd service to use
83        pub balancerd: BalancerdRef,
84        /// How to authenticate with Materialize.
85        #[serde(default)]
86        pub authenticator_kind: AuthenticatorKind,
87
88        // This can be set to override the randomly chosen resource id
89        pub resource_id: Option<String>,
90    }
91
92    impl Console {
93        pub fn name_prefixed(&self, suffix: &str) -> String {
94            format!("mz{}-{}", self.resource_id(), suffix)
95        }
96
97        pub fn resource_id(&self) -> &str {
98            &self.status.as_ref().unwrap().resource_id
99        }
100
101        pub fn namespace(&self) -> String {
102            self.meta().namespace.clone().unwrap()
103        }
104
105        pub fn deployment_name(&self) -> String {
106            self.name_prefixed("console")
107        }
108
109        pub fn replicas(&self) -> i32 {
110            self.spec.replicas.unwrap_or(2)
111        }
112
113        pub fn app_name(&self) -> String {
114            "console".to_owned()
115        }
116
117        pub fn service_name(&self) -> String {
118            self.name_prefixed("console")
119        }
120
121        pub fn configmap_name(&self) -> String {
122            self.name_prefixed("console")
123        }
124
125        pub fn external_certificate_name(&self) -> String {
126            self.name_prefixed("console-external")
127        }
128
129        pub fn external_certificate_secret_name(&self) -> String {
130            self.name_prefixed("console-external-tls")
131        }
132
133        pub fn status(&self) -> ConsoleStatus {
134            self.status.clone().unwrap_or_else(|| ConsoleStatus {
135                resource_id: self
136                    .spec
137                    .resource_id
138                    .clone()
139                    .unwrap_or_else(new_resource_id),
140                conditions: vec![],
141            })
142        }
143    }
144
145    #[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq)]
146    #[serde(rename_all = "camelCase")]
147    pub struct ConsoleStatus {
148        /// Resource identifier used as a name prefix to avoid pod name collisions.
149        pub resource_id: String,
150
151        pub conditions: Vec<Condition>,
152    }
153
154    impl ManagedResource for Console {
155        fn default_labels(&self) -> BTreeMap<String, String> {
156            BTreeMap::from_iter([
157                (
158                    "materialize.cloud/organization-name".to_owned(),
159                    self.name_unchecked(),
160                ),
161                (
162                    "materialize.cloud/organization-namespace".to_owned(),
163                    self.namespace(),
164                ),
165                (
166                    "materialize.cloud/mz-resource-id".to_owned(),
167                    self.resource_id().to_owned(),
168                ),
169                ("materialize.cloud/app".to_owned(), "console".to_owned()),
170            ])
171        }
172    }
173}