Skip to content

Commit 0434276

Browse files
add console crd and operator
1 parent f35188b commit 0434276

File tree

7 files changed

+767
-8
lines changed

7 files changed

+767
-8
lines changed

misc/helm-charts/operator/templates/clusterrole.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ rules:
9090
- materializes/status
9191
- balancers
9292
- balancers/status
93+
- consoles
94+
- consoles/status
9395
- vpcendpoints
9496
verbs:
9597
- create

src/cloud-resources/src/crd.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use crate::crd::generated::cert_manager::certificates::{
3232
use mz_ore::retry::Retry;
3333

3434
pub mod balancer;
35+
pub mod console;
3536
pub mod generated;
3637
pub mod materialize;
3738
#[cfg(feature = "vpc-endpoints")]
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
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+
10+
use std::collections::BTreeMap;
11+
12+
use k8s_openapi::{
13+
api::core::v1::ResourceRequirements, apimachinery::pkg::apis::meta::v1::Condition,
14+
};
15+
use kube::CustomResource;
16+
use schemars::JsonSchema;
17+
use serde::{Deserialize, Serialize};
18+
19+
use crate::crd::{ManagedResource, MaterializeCertSpec, new_resource_id};
20+
use mz_server_core::listeners::AuthenticatorKind;
21+
22+
pub mod v1alpha1 {
23+
use super::*;
24+
25+
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize, JsonSchema)]
26+
#[serde(rename_all = "camelCase")]
27+
pub struct BalancerdRef {
28+
// The service name for the balancerd service to connect to
29+
pub service_name: String,
30+
// The namespace the balancerd service runs in
31+
pub namespace: String,
32+
// The configuration for generating an x509 certificate using cert-manager for balancerd
33+
// to present to incoming connections.
34+
// The dns_names and issuer_ref fields are required.
35+
pub external_certificate_spec: Option<MaterializeCertSpec>,
36+
/// How to authenticate with Materialize.
37+
#[serde(default)]
38+
pub authenticator_kind: AuthenticatorKind,
39+
}
40+
41+
#[derive(
42+
CustomResource, Clone, Debug, Default, PartialEq, Deserialize, Serialize, JsonSchema,
43+
)]
44+
#[serde(rename_all = "camelCase")]
45+
#[kube(
46+
namespaced,
47+
group = "materialize.cloud",
48+
version = "v1alpha1",
49+
kind = "Console",
50+
singular = "console",
51+
plural = "consoles",
52+
status = "ConsoleStatus",
53+
printcolumn = r#"{"name": "ImageRef", "type": "string", "description": "Reference to the Docker image.", "jsonPath": ".spec.consoleImageRef", "priority": 1}"#,
54+
printcolumn = r#"{"name": "Ready", "type": "string", "description": "Whether the deployment is ready", "jsonPath": ".status.conditions[?(@.type==\"Ready\")].status", "priority": 1}"#
55+
)]
56+
pub struct ConsoleSpec {
57+
/// The console image to run.
58+
pub console_image_ref: String,
59+
// Resource requirements for the console pod
60+
pub resource_requirements: Option<ResourceRequirements>,
61+
// Number of console pods to create
62+
pub replicas: Option<i32>,
63+
// The configuration for generating an x509 certificate using cert-manager for console
64+
// to present to incoming connections.
65+
// The dns_names and issuer_ref fields are required.
66+
pub external_certificate_spec: Option<MaterializeCertSpec>,
67+
// Annotations to apply to the pods
68+
pub pod_annotations: Option<BTreeMap<String, String>>,
69+
// Labels to apply to the pods
70+
pub pod_labels: Option<BTreeMap<String, String>>,
71+
72+
// Connection information for the balancerd service to use
73+
pub balancerd: BalancerdRef,
74+
75+
// This can be set to override the randomly chosen resource id
76+
pub resource_id: Option<String>,
77+
}
78+
79+
impl Console {
80+
pub fn name_prefixed(&self, suffix: &str) -> String {
81+
format!("mz{}-{}", self.resource_id(), suffix)
82+
}
83+
84+
pub fn resource_id(&self) -> &str {
85+
&self.status.as_ref().unwrap().resource_id
86+
}
87+
88+
pub fn deployment_name(&self) -> String {
89+
self.name_prefixed("console")
90+
}
91+
92+
pub fn replicas(&self) -> i32 {
93+
self.spec.replicas.unwrap_or(2)
94+
}
95+
96+
pub fn app_name(&self) -> String {
97+
"console".to_owned()
98+
}
99+
100+
pub fn service_name(&self) -> String {
101+
self.name_prefixed("console")
102+
}
103+
104+
pub fn configmap_name(&self) -> String {
105+
self.name_prefixed("console")
106+
}
107+
108+
pub fn external_certificate_name(&self) -> String {
109+
self.name_prefixed("console-external")
110+
}
111+
112+
pub fn external_certificate_secret_name(&self) -> String {
113+
self.name_prefixed("console-external-tls")
114+
}
115+
116+
pub fn status(&self) -> ConsoleStatus {
117+
self.status.clone().unwrap_or_else(|| ConsoleStatus {
118+
resource_id: self
119+
.spec
120+
.resource_id
121+
.clone()
122+
.unwrap_or_else(new_resource_id),
123+
conditions: vec![],
124+
})
125+
}
126+
}
127+
128+
#[derive(Clone, Debug, Default, Deserialize, Serialize, JsonSchema, PartialEq)]
129+
#[serde(rename_all = "camelCase")]
130+
pub struct ConsoleStatus {
131+
/// Resource identifier used as a name prefix to avoid pod name collisions.
132+
pub resource_id: String,
133+
134+
pub conditions: Vec<Condition>,
135+
}
136+
137+
impl ManagedResource for Console {
138+
fn default_labels(&self) -> BTreeMap<String, String> {
139+
BTreeMap::from_iter([(
140+
"materialize.cloud/mz-resource-id".to_owned(),
141+
self.resource_id().to_owned(),
142+
)])
143+
}
144+
}
145+
}

src/orchestratord/src/bin/orchestratord.rs

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ use http::HeaderValue;
1717
use k8s_openapi::{
1818
api::{
1919
apps::v1::Deployment,
20-
core::v1::{Affinity, ResourceRequirements, Service, Toleration},
20+
core::v1::{Affinity, ConfigMap, ResourceRequirements, Service, Toleration},
21+
networking::v1::NetworkPolicy,
2122
},
2223
apiextensions_apiserver::pkg::apis::apiextensions::v1::CustomResourceColumnDefinition,
2324
};
@@ -335,14 +336,14 @@ async fn run(args: Args) -> Result<(), anyhow::Error> {
335336
clusterd_node_selector: args.clusterd_node_selector,
336337
clusterd_affinity: args.clusterd_affinity,
337338
clusterd_tolerations: args.clusterd_tolerations,
338-
console_node_selector: args.console_node_selector,
339-
console_affinity: args.console_affinity,
340-
console_tolerations: args.console_tolerations,
341-
console_default_resources: args.console_default_resources,
339+
console_node_selector: args.console_node_selector.clone(),
340+
console_affinity: args.console_affinity.clone(),
341+
console_tolerations: args.console_tolerations.clone(),
342+
console_default_resources: args.console_default_resources.clone(),
342343
image_pull_policy: args.image_pull_policy,
343344
network_policies_internal_enabled: args.network_policies_internal_enabled,
344345
network_policies_ingress_enabled: args.network_policies_ingress_enabled,
345-
network_policies_ingress_cidrs: args.network_policies_ingress_cidrs,
346+
network_policies_ingress_cidrs: args.network_policies_ingress_cidrs.clone(),
346347
network_policies_egress_enabled: args.network_policies_egress_enabled,
347348
network_policies_egress_cidrs: args.network_policies_egress_cidrs,
348349
environmentd_cluster_replica_sizes: args.environmentd_cluster_replica_sizes,
@@ -399,12 +400,12 @@ async fn run(args: Args) -> Result<(), anyhow::Error> {
399400
enable_security_context: args.enable_security_context,
400401
enable_prometheus_scrape_annotations: args.enable_prometheus_scrape_annotations,
401402
image_pull_policy: args.image_pull_policy,
402-
scheduler_name: args.scheduler_name,
403+
scheduler_name: args.scheduler_name.clone(),
403404
balancerd_node_selector: args.balancerd_node_selector,
404405
balancerd_affinity: args.balancerd_affinity,
405406
balancerd_tolerations: args.balancerd_tolerations,
406407
balancerd_default_resources: args.balancerd_default_resources,
407-
default_certificate_specs: args.default_certificate_specs,
408+
default_certificate_specs: args.default_certificate_specs.clone(),
408409
environmentd_sql_port: args.environmentd_sql_port,
409410
environmentd_http_port: args.environmentd_http_port,
410411
balancerd_sql_port: args.balancerd_sql_port,
@@ -440,6 +441,67 @@ async fn run(args: Args) -> Result<(), anyhow::Error> {
440441
.run(),
441442
);
442443

444+
mz_ore::task::spawn(
445+
|| "console controller",
446+
k8s_controller::Controller::namespaced_all(
447+
client.clone(),
448+
controller::console::Context::new(
449+
controller::console::Config {
450+
enable_security_context: args.enable_security_context,
451+
enable_prometheus_scrape_annotations: args.enable_prometheus_scrape_annotations,
452+
image_pull_policy: args.image_pull_policy,
453+
scheduler_name: args.scheduler_name,
454+
console_node_selector: args.console_node_selector,
455+
console_affinity: args.console_affinity,
456+
console_tolerations: args.console_tolerations,
457+
console_default_resources: args.console_default_resources,
458+
network_policies_ingress_enabled: args.network_policies_ingress_enabled,
459+
network_policies_ingress_cidrs: args.network_policies_ingress_cidrs,
460+
default_certificate_specs: args.default_certificate_specs,
461+
console_http_port: args.console_http_port,
462+
balancerd_http_port: args.balancerd_http_port,
463+
},
464+
client.clone(),
465+
)
466+
.await,
467+
watcher::Config::default().timeout(29),
468+
)
469+
.with_controller(|controller| {
470+
controller
471+
.owns(
472+
Api::<Deployment>::all(client.clone()),
473+
watcher::Config::default()
474+
.labels("materialize.cloud/mz-resource-id")
475+
.timeout(29),
476+
)
477+
.owns(
478+
Api::<Service>::all(client.clone()),
479+
watcher::Config::default()
480+
.labels("materialize.cloud/mz-resource-id")
481+
.timeout(29),
482+
)
483+
.owns(
484+
Api::<Certificate>::all(client.clone()),
485+
watcher::Config::default()
486+
.labels("materialize.cloud/mz-resource-id")
487+
.timeout(29),
488+
)
489+
.owns(
490+
Api::<NetworkPolicy>::all(client.clone()),
491+
watcher::Config::default()
492+
.labels("materialize.cloud/mz-resource-id")
493+
.timeout(29),
494+
)
495+
.owns(
496+
Api::<ConfigMap>::all(client.clone()),
497+
watcher::Config::default()
498+
.labels("materialize.cloud/mz-resource-id")
499+
.timeout(29),
500+
)
501+
})
502+
.run(),
503+
);
504+
443505
info!("All tasks started successfully.");
444506

445507
future::pending().await

src/orchestratord/src/controller.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
// by the Apache License, Version 2.0.
99

1010
pub mod balancer;
11+
pub mod console;
1112
pub mod materialize;

0 commit comments

Comments
 (0)