Skip to content

Commit 4a0c0b8

Browse files
committed
feat: Add simple CR applier
This implements are very simple CR applier. This commit is a first step towards maintaining CRs in our operator. It is not refined and is missing various features to be usable in the real world.
1 parent 8098b86 commit 4a0c0b8

File tree

10 files changed

+554
-704
lines changed

10 files changed

+554
-704
lines changed

Cargo.lock

Lines changed: 200 additions & 176 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.nix

Lines changed: 250 additions & 491 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@ const_format = "0.2.34"
2323
futures = { version = "0.3", features = ["compat"] }
2424
h2 = "0.4"
2525
hex = "0.4"
26-
kube-runtime = { version = "1.0", features = ["unstable-runtime-stream-control"] }
27-
ldap3 = { version = "0.11", default-features = false, features = ["gssapi", "tls"] }
26+
kube-runtime = { version = "2.0.1", features = [
27+
"unstable-runtime-stream-control",
28+
] }
29+
ldap3 = { version = "0.11", default-features = false, features = [
30+
"gssapi",
31+
"tls",
32+
] }
2833
libc = "0.2"
2934
native-tls = "0.2"
3035
openssl = "0.10"
@@ -54,5 +59,7 @@ uuid = { version = "1.10.0", features = ["v4"] }
5459
yasna = "0.5"
5560

5661
[patch."https://github.com/stackabletech/operator-rs.git"]
62+
stackable-operator = { path = "../operator-rs/crates/stackable-operator" }
63+
# stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "feat/crd-maintenance" }
5764
# stackable-operator = { path = "../operator-rs/crates/stackable-operator" }
5865
# stackable-operator = { git = "https://github.com/stackabletech//operator-rs.git", branch = "main" }

Tiltfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ k8s_yaml(helm(
2828
namespace="stackable-operators",
2929
set=[
3030
'image.repository=' + registry + '/' + operator_name,
31-
'telemetry.consoleLog.level=trace,h2=off',
31+
'telemetry.consoleLog.level=info',
3232
],
3333
))

deploy/helm/secret-operator/templates/roles.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ rules:
122122
- secretclasses
123123
- truststores
124124
verbs:
125+
- create
126+
- patch
125127
- get
126128
- watch
127129
- list

rust/operator-binary/src/crd/secret_class/v1alpha1_impl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use stackable_operator::{
22
k8s_openapi::api::core::v1::{ConfigMap, Secret},
33
kube::api::PartialObjectMeta,
4-
schemars::{self, schema::Schema},
4+
schemars::{Schema, SchemaGenerator},
55
};
66

77
use crate::crd::secret_class::v1alpha1::{
@@ -113,7 +113,7 @@ impl CertificateKeyGeneration {
113113
// - '3072'
114114
// - '4096'
115115
// type: string
116-
pub fn tls_key_length_schema(_: &mut schemars::gen::SchemaGenerator) -> Schema {
116+
pub fn tls_key_length_schema(_: &mut SchemaGenerator) -> Schema {
117117
serde_json::from_value(serde_json::json!({
118118
"type": "integer",
119119
"enum": [

rust/operator-binary/src/crd/secret_class/v1alpha2_impl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use stackable_operator::{
22
k8s_openapi::api::core::v1::{ConfigMap, Secret},
33
kube::api::PartialObjectMeta,
4-
schemars::{self, schema::Schema},
4+
schemars::{Schema, SchemaGenerator},
55
shared::time::Duration,
66
};
77

@@ -131,7 +131,7 @@ impl CertificateKeyGeneration {
131131
// - '3072'
132132
// - '4096'
133133
// type: string
134-
pub fn tls_key_length_schema(_: &mut schemars::gen::SchemaGenerator) -> Schema {
134+
pub fn tls_key_length_schema(_: &mut SchemaGenerator) -> Schema {
135135
serde_json::from_value(serde_json::json!({
136136
"type": "integer",
137137
"enum": [

rust/operator-binary/src/main.rs

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,25 @@ use grpc::csi::v1::{
1616
};
1717
use stackable_operator::{
1818
YamlSchema,
19-
cli::{CommonOptions, ProductOperatorRun},
19+
cli::{CommonOptions, RunArguments},
20+
client::Client,
21+
crd::maintainer::{
22+
CustomResourceDefinitionMaintainer, CustomResourceDefinitionMaintainerOptions,
23+
},
2024
shared::yaml::SerializeOptions,
2125
telemetry::Tracing,
26+
webhook::WebhookServer,
27+
};
28+
use tokio::{
29+
signal::unix::{SignalKind, signal},
30+
sync::oneshot,
2231
};
23-
use tokio::signal::unix::{SignalKind, signal};
2432
use tokio_stream::wrappers::UnixListenerStream;
2533
use tonic::transport::Server;
2634
use utils::{TonicUnixStream, uds_bind_private};
2735
use webhooks::conversion::conversion_webhook;
2836

29-
use crate::crd::{SecretClass, TrustStore};
37+
use crate::crd::{SecretClass, SecretClassVersion, TrustStore, TrustStoreVersion, v1alpha2};
3038

3139
mod backend;
3240
mod crd;
@@ -62,7 +70,7 @@ struct SecretOperatorRun {
6270
privileged: bool,
6371

6472
#[clap(flatten)]
65-
common: ProductOperatorRun,
73+
common: RunArguments,
6674
}
6775

6876
mod built_info {
@@ -83,7 +91,7 @@ async fn main() -> anyhow::Result<()> {
8391
csi_endpoint,
8492
privileged,
8593
common:
86-
ProductOperatorRun {
94+
RunArguments {
8795
common:
8896
CommonOptions {
8997
telemetry,
@@ -92,7 +100,7 @@ async fn main() -> anyhow::Result<()> {
92100
product_config: _,
93101
watch_namespace,
94102
operator_environment,
95-
disable_crd_maintenance,
103+
maintenance,
96104
},
97105
}) => {
98106
// NOTE (@NickLarsenNZ): Before stackable-telemetry was used:
@@ -122,6 +130,27 @@ async fn main() -> anyhow::Result<()> {
122130
{
123131
let _ = std::fs::remove_file(&csi_endpoint);
124132
}
133+
134+
let (conversion_webhook, certificate_rx) = conversion_webhook(&operator_environment)
135+
.await
136+
.context("failed to create conversion webhook")?;
137+
138+
let (maintainer, initial_reconcile_rx) = CustomResourceDefinitionMaintainer::new(
139+
client.as_kube_client(),
140+
certificate_rx,
141+
[
142+
SecretClass::merged_crd(SecretClassVersion::V1Alpha2).unwrap(),
143+
TrustStore::merged_crd(TrustStoreVersion::V1Alpha1).unwrap(),
144+
],
145+
CustomResourceDefinitionMaintainerOptions {
146+
operator_service_name: operator_environment.operator_service_name,
147+
operator_namespace: operator_environment.operator_namespace,
148+
field_manager: OPERATOR_NAME.to_owned(),
149+
webhook_https_port: WebhookServer::DEFAULT_HTTPS_PORT,
150+
disabled: maintenance.disable_crd_maintenance,
151+
},
152+
);
153+
125154
let mut sigterm = signal(SignalKind::terminate())?;
126155
let csi_server = Server::builder()
127156
.add_service(
@@ -151,19 +180,42 @@ async fn main() -> anyhow::Result<()> {
151180
let truststore_controller =
152181
truststore_controller::start(&client, &watch_namespace).map(anyhow::Ok);
153182

154-
let conversion_webhook = conversion_webhook(
155-
client.as_kube_client(),
156-
operator_environment,
157-
disable_crd_maintenance,
158-
)
159-
.await
160-
.context("failed to create conversion webhook")?;
161183
let conversion_webhook = conversion_webhook
162184
.run()
163185
.map_err(|err| anyhow!(err).context("failed to run conversion webhook"));
164186

165-
try_join!(csi_server, truststore_controller, conversion_webhook,)?;
187+
let maintainer = maintainer
188+
.run()
189+
.map_err(|err| anyhow!(err).context("failed to run CRD maintainer"));
190+
191+
let cr_applier = apply_crs(initial_reconcile_rx, client.clone())
192+
.map_err(|err| anyhow!(err).context("failed to apply default custom resources"));
193+
194+
try_join!(
195+
csi_server,
196+
truststore_controller,
197+
conversion_webhook,
198+
maintainer,
199+
cr_applier,
200+
)?;
166201
}
167202
}
168203
Ok(())
169204
}
205+
206+
async fn apply_crs(
207+
initial_reconcile_rx: oneshot::Receiver<()>,
208+
client: Client,
209+
) -> anyhow::Result<()> {
210+
initial_reconcile_rx.await?;
211+
212+
tracing::info!("applying default custom resources");
213+
214+
let deserializer = serde_yaml::Deserializer::from_slice(include_bytes!("secretclass.yaml"));
215+
let tls_secret_class: v1alpha2::SecretClass =
216+
serde_yaml::with::singleton_map_recursive::deserialize(deserializer)?;
217+
218+
client.create_if_missing(&tls_secret_class).await?;
219+
220+
Ok(())
221+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
apiVersion: secrets.stackable.tech/v1alpha2
3+
kind: SecretClass
4+
metadata:
5+
name: tls
6+
spec:
7+
backend:
8+
autoTls:
9+
ca:
10+
secret:
11+
name: secret-provisioner-tls-ca
12+
namespace: stackable-operator
13+
autoGenerate: true
Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
use stackable_operator::{
22
cli::OperatorEnvironmentOptions,
3-
kube::Client,
43
webhook::{
5-
constants::DEFAULT_SOCKET_ADDRESS,
64
servers::{ConversionWebhookOptions, ConversionWebhookServer},
5+
x509_cert::Certificate,
76
},
87
};
8+
use tokio::sync::mpsc;
99

10-
use crate::{
11-
OPERATOR_NAME,
12-
crd::{SecretClass, SecretClassVersion, TrustStore, TrustStoreVersion},
13-
};
10+
use crate::crd::{SecretClass, SecretClassVersion, TrustStore, TrustStoreVersion};
1411

1512
pub async fn conversion_webhook(
16-
client: Client,
17-
operator_environment: OperatorEnvironmentOptions,
18-
disable_crd_management: bool,
19-
) -> anyhow::Result<ConversionWebhookServer> {
13+
operator_environment: &OperatorEnvironmentOptions,
14+
) -> anyhow::Result<(ConversionWebhookServer, mpsc::Receiver<Certificate>)> {
2015
let crds_and_handlers = [
2116
(
2217
SecretClass::merged_crd(SecretClassVersion::V1Alpha2)?,
@@ -29,12 +24,10 @@ pub async fn conversion_webhook(
2924
];
3025

3126
let options = ConversionWebhookOptions {
32-
socket_addr: DEFAULT_SOCKET_ADDRESS,
33-
field_manager: OPERATOR_NAME.to_owned(),
34-
namespace: operator_environment.operator_namespace,
35-
service_name: operator_environment.operator_service_name,
36-
maintain_crds: !disable_crd_management,
27+
socket_addr: ConversionWebhookServer::DEFAULT_SOCKET_ADDRESS,
28+
namespace: operator_environment.operator_namespace.clone(),
29+
service_name: operator_environment.operator_service_name.clone(),
3730
};
3831

39-
Ok(ConversionWebhookServer::new(crds_and_handlers, options, client).await?)
32+
Ok(ConversionWebhookServer::new(crds_and_handlers, options).await?)
4033
}

0 commit comments

Comments
 (0)