Skip to content

Commit faf1a73

Browse files
feat: Support ignore annotations on StatefulSets
1 parent 7d3005f commit faf1a73

6 files changed

Lines changed: 159 additions & 73 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ All notable changes to this project will be documented in this file.
66

77
### Added
88

9-
- Support the `restarter.stackable.tech/ignore` annotation on ConfigMaps and Secrets to exclude
10-
them from the restarter controller ([#410]).
9+
- Support the annotation `restarter.stackable.tech/ignore` on ConfigMaps and Secrets and the
10+
annotations `restarter.stackable.tech/ignore-configmap.x` and
11+
`restarter.stackable.tech/ignore-secret.x` on StatefulSets to exclude ConfigMaps and Secrets from
12+
the restarter controller ([#410]).
1113

1214
[#410]: https://github.com/stackabletech/commons-operator/pull/410
1315

rust/operator-binary/src/restart_controller/statefulset.rs

Lines changed: 75 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
use std::{collections::BTreeMap, future::Future, sync::Arc, time::Duration};
1+
use std::{
2+
collections::{BTreeMap, BTreeSet},
3+
future::Future,
4+
sync::Arc,
5+
time::Duration,
6+
};
27

38
use futures::{Stream, StreamExt, TryStream, stream};
49
use serde_json::json;
@@ -128,13 +133,16 @@ pub async fn start<F>(
128133
trigger_all(
129134
{
130135
let cm_reader = cm_store.as_reader();
131-
reflector(cm_store, metadata_watcher(cms, watcher::Config::default()))
132-
.inspect(move |_| {
133-
if let Some(tx) = cm_store_tx.take() {
134-
tx.init(cm_reader.clone());
135-
}
136-
})
137-
.touched_objects()
136+
reflector(
137+
cm_store,
138+
metadata_watcher(cms, watcher::Config::default().labels("restarter.stackable.tech/ignore != true"))
139+
)
140+
.inspect(move |_| {
141+
if let Some(tx) = cm_store_tx.take() {
142+
tx.init(cm_reader.clone());
143+
}
144+
})
145+
.touched_objects()
138146
},
139147
sts_store.as_reader(),
140148
),
@@ -143,7 +151,7 @@ pub async fn start<F>(
143151
let secret_reader = secret_store.as_reader();
144152
reflector(
145153
secret_store,
146-
metadata_watcher(secrets, watcher::Config::default()),
154+
metadata_watcher(secrets, watcher::Config::default().labels("restarter.stackable.tech/ignore != true")),
147155
)
148156
.inspect(move |_| {
149157
if let Some(tx) = secret_store_tx.take() {
@@ -235,6 +243,32 @@ pub async fn get_updated_restarter_annotations(
235243
let ns = sts.metadata.namespace.as_deref().expect(
236244
"A StatefulSet observed by a reflector (so send by Kubernetes) always has a namespace set",
237245
);
246+
247+
let ignored_config_maps = sts
248+
.metadata
249+
.annotations
250+
.iter()
251+
.flatten()
252+
.filter(|annotation| {
253+
annotation
254+
.0
255+
.starts_with("restarter.stackable.tech/ignore-configmap.")
256+
})
257+
.map(|x| x.1)
258+
.collect::<BTreeSet<_>>();
259+
let ignored_secrets = sts
260+
.metadata
261+
.annotations
262+
.iter()
263+
.flatten()
264+
.filter(|annotation| {
265+
annotation
266+
.0
267+
.starts_with("restarter.stackable.tech/ignore-secret.")
268+
})
269+
.map(|x| x.1)
270+
.collect::<BTreeSet<_>>();
271+
238272
let mut annotations = BTreeMap::<String, String>::new();
239273
let pod_specs = sts
240274
.spec
@@ -269,25 +303,24 @@ pub async fn get_updated_restarter_annotations(
269303
})
270304
.map(|cm_ref| cm_ref.within(ns));
271305
let cms = ctx.cms.get().await.context(ConfigMapsUninitializedSnafu)?;
272-
annotations.extend(cm_refs.flat_map(|cm_ref| cms.get(&cm_ref)).flat_map(|cm| {
273-
Some((
274-
format!(
275-
"configmap.restarter.stackable.tech/{}",
276-
cm.metadata.name.as_ref()?
277-
),
278-
format!(
279-
"{}/{}",
280-
cm.metadata.uid.as_ref()?,
281-
if cm.annotations().get("restarter.stackable.tech/ignore")
282-
== Some(&"true".to_owned())
283-
{
284-
"any"
285-
} else {
286-
cm.metadata.resource_version.as_ref()?
287-
}
288-
),
289-
))
290-
}));
306+
annotations.extend(
307+
cm_refs
308+
.map(|cm_ref| (cm_ref.name.clone(), cms.get(&cm_ref)))
309+
.map(|(cm_name, cm)| {
310+
(
311+
format!("configmap.restarter.stackable.tech/{cm_name}",),
312+
if let Some(cm) = cm
313+
&& let Some(uid) = &cm.metadata.uid
314+
&& let Some(resource_version) = &cm.metadata.resource_version
315+
&& !ignored_config_maps.contains(&cm_name)
316+
{
317+
format!("{uid}/{resource_version}",)
318+
} else {
319+
"changes-ignored".to_owned()
320+
},
321+
)
322+
}),
323+
);
291324
let secret_refs = pod_specs
292325
.flat_map(|pod_spec| {
293326
find_pod_refs(
@@ -313,25 +346,20 @@ pub async fn get_updated_restarter_annotations(
313346
let secrets = ctx.secrets.get().await.context(SecretsUninitializedSnafu)?;
314347
annotations.extend(
315348
secret_refs
316-
.flat_map(|secret_ref| secrets.get(&secret_ref))
317-
.flat_map(|secret| {
318-
Some((
319-
format!(
320-
"secret.restarter.stackable.tech/{}",
321-
secret.metadata.name.as_ref()?
322-
),
323-
format!(
324-
"{}/{}",
325-
secret.metadata.uid.as_ref()?,
326-
if secret.annotations().get("restarter.stackable.tech/ignore")
327-
== Some(&"true".to_owned())
328-
{
329-
"any"
330-
} else {
331-
secret.metadata.resource_version.as_ref()?
332-
}
333-
),
334-
))
349+
.map(|secret_ref| (secret_ref.name.clone(), secrets.get(&secret_ref)))
350+
.map(|(secret_name, secret)| {
351+
(
352+
format!("secret.restarter.stackable.tech/{secret_name}",),
353+
if let Some(secret) = secret
354+
&& let Some(uid) = &secret.metadata.uid
355+
&& let Some(resource_version) = &secret.metadata.resource_version
356+
&& !ignored_secrets.contains(&secret_name)
357+
{
358+
format!("{uid}/{resource_version}",)
359+
} else {
360+
"changes-ignored".to_owned()
361+
},
362+
)
335363
}),
336364
);
337365
Ok(annotations)

tests/templates/kuttl/restarter/10-create-test-resources.yaml

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ stringData:
1616
apiVersion: v1
1717
kind: ConfigMap
1818
metadata:
19-
name: configmap-ignored
19+
name: configmap-self-ignored
2020
annotations:
2121
restarter.stackable.tech/ignore: "true"
2222
data:
@@ -25,18 +25,34 @@ data:
2525
apiVersion: v1
2626
kind: Secret
2727
metadata:
28-
name: secret-ignored
28+
name: secret-self-ignored
2929
annotations:
3030
restarter.stackable.tech/ignore: "true"
3131
stringData:
3232
revision: "1"
3333
---
34+
apiVersion: v1
35+
kind: ConfigMap
36+
metadata:
37+
name: configmap-ignored-in-statefulset
38+
data:
39+
revision: "1"
40+
---
41+
apiVersion: v1
42+
kind: Secret
43+
metadata:
44+
name: secret-ignored-in-statefulset
45+
stringData:
46+
revision: "1"
47+
---
3448
apiVersion: apps/v1
3549
kind: StatefulSet
3650
metadata:
3751
name: test
3852
labels:
3953
restarter.stackable.tech/enabled: "true"
54+
restarter.stackable.tech/ignore-configmap.0: configmap-ignored-in-statefulset
55+
restarter.stackable.tech/ignore-secret.0: secret-ignored-in-statefulset
4056
spec:
4157
selector:
4258
matchLabels:
@@ -56,12 +72,18 @@ spec:
5672
- name: secret-not-ignored
5773
secret:
5874
secretName: secret-not-ignored
59-
- name: configmap-ignored
75+
- name: configmap-self-ignored
76+
configMap:
77+
name: configmap-self-ignored
78+
- name: secret-self-ignored
79+
secret:
80+
secretName: secret-self-ignored
81+
- name: configmap-ignored-in-statefulset
6082
configMap:
61-
name: configmap-ignored
62-
- name: secret-ignored
83+
name: configmap-ignored-in-statefulset
84+
- name: secret-ignored-in-statefulset
6385
secret:
64-
secretName: secret-ignored
86+
secretName: secret-ignored-in-statefulset
6587
containers:
6688
- name: test
6789
image: alpine
@@ -78,16 +100,28 @@ spec:
78100
name: secret-not-ignored
79101
# Use a subPath, so that changes are only visible after a restart.
80102
subPath: revision
81-
- mountPath: /config/configmap-ignored
82-
name: configmap-ignored
83-
- mountPath: /config/secret-ignored
84-
name: secret-ignored
85-
- mountPath: /config/configmap-ignored-subpath/revision
86-
name: configmap-ignored
103+
- mountPath: /config/configmap-self-ignored
104+
name: configmap-self-ignored
105+
- mountPath: /config/secret-self-ignored
106+
name: secret-self-ignored
107+
- mountPath: /config/configmap-self-ignored-subpath/revision
108+
name: configmap-self-ignored
109+
# Use a subPath, so that changes are only visible after a restart.
110+
subPath: revision
111+
- mountPath: /config/secret-self-ignored-subpath/revision
112+
name: secret-self-ignored
113+
# Use a subPath, so that changes are only visible after a restart.
114+
subPath: revision
115+
- mountPath: /config/configmap-ignored-in-statefulset
116+
name: configmap-ignored-in-statefulset
117+
- mountPath: /config/secret-ignored-in-statefulset
118+
name: secret-ignored-in-statefulset
119+
- mountPath: /config/configmap-ignored-in-statefulset-subpath/revision
120+
name: configmap-ignored-in-statefulset
87121
# Use a subPath, so that changes are only visible after a restart.
88122
subPath: revision
89-
- mountPath: /config/secret-ignored-subpath/revision
90-
name: secret-ignored
123+
- mountPath: /config/secret-ignored-in-statefulset-subpath/revision
124+
name: secret-ignored-in-statefulset
91125
# Use a subPath, so that changes are only visible after a restart.
92126
subPath: revision
93127
terminationGracePeriodSeconds: 5

tests/templates/kuttl/restarter/20-assert.yaml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ commands:
1212
1313
assert_revision 1 configmap-not-ignored-subpath
1414
assert_revision 1 secret-not-ignored-subpath
15-
assert_revision 1 configmap-ignored-subpath
16-
assert_revision 1 secret-ignored-subpath
17-
assert_revision 2 configmap-ignored
18-
assert_revision 2 secret-ignored
15+
assert_revision 1 configmap-self-ignored-subpath
16+
assert_revision 1 secret-self-ignored-subpath
17+
assert_revision 2 configmap-self-ignored
18+
assert_revision 2 secret-self-ignored
19+
assert_revision 1 configmap-ignored-in-statefulset-subpath
20+
assert_revision 1 secret-ignored-in-statefulset-subpath
21+
assert_revision 2 configmap-ignored-in-statefulset
22+
assert_revision 2 secret-ignored-in-statefulset

tests/templates/kuttl/restarter/20-hot-reload.yaml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,27 @@
22
apiVersion: v1
33
kind: ConfigMap
44
metadata:
5-
name: configmap-ignored
5+
name: configmap-self-ignored
66
data:
77
revision: "2"
88
---
99
apiVersion: v1
1010
kind: Secret
1111
metadata:
12-
name: secret-ignored
12+
name: secret-self-ignored
13+
stringData:
14+
revision: "2"
15+
---
16+
apiVersion: v1
17+
kind: ConfigMap
18+
metadata:
19+
name: configmap-ignored-in-statefulset
20+
data:
21+
revision: "2"
22+
---
23+
apiVersion: v1
24+
kind: Secret
25+
metadata:
26+
name: secret-ignored-in-statefulset
1327
stringData:
1428
revision: "2"

tests/templates/kuttl/restarter/21-assert.yaml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ commands:
1010
1111
assert_revision 2 configmap-not-ignored-subpath
1212
assert_revision 2 secret-not-ignored-subpath
13-
assert_revision 2 configmap-ignored-subpath
14-
assert_revision 2 secret-ignored-subpath
15-
assert_revision 2 configmap-ignored
16-
assert_revision 2 secret-ignored
13+
assert_revision 2 configmap-self-ignored-subpath
14+
assert_revision 2 secret-self-ignored-subpath
15+
assert_revision 2 configmap-self-ignored
16+
assert_revision 2 secret-self-ignored
17+
assert_revision 2 configmap-ignored-in-statefulset-subpath
18+
assert_revision 2 secret-ignored-in-statefulset-subpath
19+
assert_revision 2 configmap-ignored-in-statefulset
20+
assert_revision 2 secret-ignored-in-statefulset

0 commit comments

Comments
 (0)