Skip to content

Commit 152ff9a

Browse files
committed
reflectors: Use a macro instead
Adding a new reflector now required adding it to four different structs and several impls. Use a simple macro to make it a one-line ordeal.
1 parent e376a95 commit 152ff9a

1 file changed

Lines changed: 113 additions & 187 deletions

File tree

metrics-cache/src/ingest/reflectors.rs

Lines changed: 113 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -15,133 +15,129 @@ use std::time::{Duration, Instant};
1515
use tokio::task::JoinSet;
1616
use tracing::{debug, error, trace};
1717

18-
/// The [`Store`]s where all of the watched Kubernetes kinds that rustik
19-
/// monitors end up. The stores here are not frozen and might update in the
20-
/// background at any time.
21-
#[derive(Clone)]
22-
pub struct Stores {
23-
pub pods: Store<Pod>,
24-
pub nodes: Store<Node>,
25-
pub deployments: Store<Deployment>,
26-
pub daemonsets: Store<DaemonSet>,
27-
pub namespaces: Store<Namespace>,
28-
pub replicasets: Store<ReplicaSet>,
29-
pub persistent_volumes: Store<PersistentVolume>,
30-
pub persistent_volume_claims: Store<PersistentVolumeClaim>,
31-
pub statefulsets: Store<StatefulSet>,
32-
pub(crate) healths: ReflectorHealthHandles,
33-
}
18+
macro_rules! define_reflectors {
19+
(
20+
$(
21+
$field:ident : $resource:ty
22+
),* $(,)?
23+
) => {
24+
/// The [`Store`]s where all of the watched Kubernetes kinds that rustik
25+
/// monitors end up. The stores here are not frozen and might update in
26+
/// the background at any time.
27+
#[derive(Clone)]
28+
pub struct Stores {
29+
pub(crate) healths: ReflectorHealthHandles,
30+
$(
31+
pub $field: Store<$resource>,
32+
)*
33+
}
3434

35-
#[derive(Debug)]
36-
pub struct FrozenStores {
37-
pub pods: Vec<Arc<Pod>>,
38-
pub nodes: Vec<Arc<Node>>,
39-
pub deployments: Vec<Arc<Deployment>>,
40-
pub daemonsets: Vec<Arc<DaemonSet>>,
41-
pub namespaces: Vec<Arc<Namespace>>,
42-
pub replicasets: Vec<Arc<ReplicaSet>>,
43-
pub persistent_volumes: Vec<Arc<PersistentVolume>>,
44-
pub persistent_volume_claims: Vec<Arc<PersistentVolumeClaim>>,
45-
pub statefulsets: Vec<Arc<StatefulSet>>,
46-
}
35+
impl Stores {
36+
pub(crate) fn spawn(client: Client, tasks: &mut JoinSet<()>) -> Self {
37+
let healths = ReflectorHealthHandles::default();
38+
Self {
39+
$(
40+
$field: start_reflector(
41+
Api::all(client.clone()),
42+
WatchConfig::default(),
43+
tasks,
44+
healths.$field.clone(),
45+
),
46+
)*
47+
healths
48+
}
49+
}
50+
51+
pub(crate) fn freeze(&self) -> FrozenStores {
52+
FrozenStores {
53+
$(
54+
$field: self.$field.state(),
55+
)*
56+
}
57+
}
58+
59+
pub(crate) fn freeze_healths(&self) -> FrozenReflectorHealths {
60+
self.healths.freeze()
61+
}
4762

48-
impl Stores {
49-
pub(crate) fn spawn(client: Client, tasks: &mut JoinSet<()>) -> Self {
50-
let healths = ReflectorHealthHandles::default();
51-
52-
Self {
53-
pods: start_reflector(
54-
Api::all(client.clone()),
55-
WatchConfig::default(),
56-
tasks,
57-
healths.pods.clone(),
58-
),
59-
nodes: start_reflector(
60-
Api::all(client.clone()),
61-
WatchConfig::default(),
62-
tasks,
63-
healths.nodes.clone(),
64-
),
65-
deployments: start_reflector(
66-
Api::all(client.clone()),
67-
WatchConfig::default(),
68-
tasks,
69-
healths.deployments.clone(),
70-
),
71-
daemonsets: start_reflector(
72-
Api::all(client.clone()),
73-
WatchConfig::default(),
74-
tasks,
75-
healths.daemonsets.clone(),
76-
),
77-
namespaces: start_reflector(
78-
Api::all(client.clone()),
79-
WatchConfig::default(),
80-
tasks,
81-
healths.namespaces.clone(),
82-
),
83-
replicasets: start_reflector(
84-
Api::all(client.clone()),
85-
WatchConfig::default(),
86-
tasks,
87-
healths.replicasets.clone(),
88-
),
89-
persistent_volumes: start_reflector(
90-
Api::all(client.clone()),
91-
WatchConfig::default(),
92-
tasks,
93-
healths.persistent_volumes.clone(),
94-
),
95-
persistent_volume_claims: start_reflector(
96-
Api::all(client.clone()),
97-
WatchConfig::default(),
98-
tasks,
99-
healths.persistent_volume_claims.clone(),
100-
),
101-
statefulsets: start_reflector(
102-
Api::all(client),
103-
WatchConfig::default(),
104-
tasks,
105-
healths.statefulsets.clone(),
106-
),
107-
healths,
63+
pub(crate) async fn wait_until_all_ready(&self) -> Result<(), WriterDropped> {
64+
tokio::try_join!(
65+
$(
66+
self.$field.wait_until_ready(),
67+
)*
68+
)?;
69+
Ok(())
70+
}
10871
}
109-
}
11072

111-
pub(crate) fn freeze(&self) -> FrozenStores {
112-
FrozenStores {
113-
pods: self.pods.state(),
114-
nodes: self.nodes.state(),
115-
deployments: self.deployments.state(),
116-
daemonsets: self.daemonsets.state(),
117-
namespaces: self.namespaces.state(),
118-
replicasets: self.replicasets.state(),
119-
persistent_volumes: self.persistent_volumes.state(),
120-
persistent_volume_claims: self.persistent_volume_claims.state(),
121-
statefulsets: self.statefulsets.state(),
73+
#[derive(Debug)]
74+
pub struct FrozenStores {
75+
$(
76+
pub $field: Vec<Arc<$resource>>,
77+
)*
12278
}
123-
}
12479

125-
pub(crate) fn freeze_healths(&self) -> FrozenReflectorHealths {
126-
self.healths.freeze()
127-
}
80+
/// The collection of [`ReflectorHealthHandle`]s which are constantly
81+
/// being changed by the reflector as events happen. Thus, we _can not_
82+
/// rely on this for a snapshot; at snapshot-time, it is only used to
83+
/// generate a [`FrozenReflectorHealths`] via [`Self::freeze()`].
84+
#[derive(Clone, Debug, Default)]
85+
pub(crate) struct ReflectorHealthHandles {
86+
$(
87+
$field: ReflectorHealthHandle,
88+
)*
89+
}
90+
91+
impl ReflectorHealthHandles {
92+
fn freeze(&self) -> FrozenReflectorHealths {
93+
FrozenReflectorHealths {
94+
$(
95+
$field: self.$field.freeze(),
96+
)*
97+
}
98+
}
99+
}
100+
101+
#[derive(Clone, Debug)]
102+
pub(crate) struct FrozenReflectorHealths {
103+
$(
104+
pub(crate) $field: ReflectorHealth,
105+
)*
106+
}
107+
108+
const REFLECTOR_COUNT: usize = [$( stringify!($field), )*].len();
109+
110+
// Pardon the "cute" IntoIter here; it avoids having to edit
111+
// crate::snapshot::self_health every time a new reflector is added here.
112+
impl IntoIterator for FrozenReflectorHealths {
113+
type Item = (&'static str, ReflectorHealth);
114+
type IntoIter = std::array::IntoIter<Self::Item, REFLECTOR_COUNT>;
115+
116+
fn into_iter(self) -> Self::IntoIter {
117+
[
118+
$(
119+
(stringify!($field), self.$field),
120+
)*
121+
]
122+
.into_iter()
123+
}
124+
}
128125

129-
pub(crate) async fn wait_until_all_ready(&self) -> Result<(), WriterDropped> {
130-
tokio::try_join!(
131-
self.pods.wait_until_ready(),
132-
self.nodes.wait_until_ready(),
133-
self.deployments.wait_until_ready(),
134-
self.daemonsets.wait_until_ready(),
135-
self.namespaces.wait_until_ready(),
136-
self.replicasets.wait_until_ready(),
137-
self.persistent_volumes.wait_until_ready(),
138-
self.persistent_volume_claims.wait_until_ready(),
139-
self.statefulsets.wait_until_ready(),
140-
)?;
141-
Ok(())
142126
}
143127
}
144128

129+
define_reflectors! {
130+
pods: Pod,
131+
nodes: Node,
132+
deployments: Deployment,
133+
daemonsets: DaemonSet,
134+
namespaces: Namespace,
135+
replicasets: ReplicaSet,
136+
persistent_volumes: PersistentVolume,
137+
persistent_volume_claims: PersistentVolumeClaim,
138+
statefulsets: StatefulSet,
139+
}
140+
145141
/// The inner-state of a reflector. This gets updated by the reflector's
146142
/// `inspect` callback as certain events happen (namely `Init`, `InitDone`, and
147143
/// errors).
@@ -214,76 +210,6 @@ impl ReflectorHealthHandle {
214210
}
215211
}
216212

217-
/// The collection of [`ReflectorHealthHandle`]s which are constantly being
218-
/// changed by the reflector as events happen. Thus, we _can not_ rely on this
219-
/// for a snapshot; at snapshot-time, it is only used to generate a
220-
/// [`FrozenReflectorHealths`] via [`Self::freeze()`].
221-
#[derive(Clone, Debug, Default)]
222-
pub(crate) struct ReflectorHealthHandles {
223-
pods: ReflectorHealthHandle,
224-
nodes: ReflectorHealthHandle,
225-
deployments: ReflectorHealthHandle,
226-
daemonsets: ReflectorHealthHandle,
227-
namespaces: ReflectorHealthHandle,
228-
replicasets: ReflectorHealthHandle,
229-
persistent_volumes: ReflectorHealthHandle,
230-
persistent_volume_claims: ReflectorHealthHandle,
231-
statefulsets: ReflectorHealthHandle,
232-
}
233-
234-
impl ReflectorHealthHandles {
235-
fn freeze(&self) -> FrozenReflectorHealths {
236-
FrozenReflectorHealths {
237-
pods: self.pods.freeze(),
238-
nodes: self.nodes.freeze(),
239-
deployments: self.deployments.freeze(),
240-
daemonsets: self.daemonsets.freeze(),
241-
namespaces: self.namespaces.freeze(),
242-
replicasets: self.replicasets.freeze(),
243-
persistent_volumes: self.persistent_volumes.freeze(),
244-
persistent_volume_claims: self.persistent_volume_claims.freeze(),
245-
statefulsets: self.statefulsets.freeze(),
246-
}
247-
}
248-
}
249-
250-
#[derive(Clone, Debug)]
251-
pub(crate) struct FrozenReflectorHealths {
252-
pub(crate) pods: ReflectorHealth,
253-
pub(crate) nodes: ReflectorHealth,
254-
pub(crate) deployments: ReflectorHealth,
255-
pub(crate) daemonsets: ReflectorHealth,
256-
pub(crate) namespaces: ReflectorHealth,
257-
pub(crate) replicasets: ReflectorHealth,
258-
pub(crate) persistent_volumes: ReflectorHealth,
259-
pub(crate) persistent_volume_claims: ReflectorHealth,
260-
pub(crate) statefulsets: ReflectorHealth,
261-
}
262-
263-
const REFLECTOR_COUNT: usize = 9;
264-
265-
// Pardon the "cute" IntoIter here; it avoids having to edit
266-
// crate::snapshot::self_health every time a new reflector is added here.
267-
impl IntoIterator for FrozenReflectorHealths {
268-
type Item = (&'static str, ReflectorHealth);
269-
type IntoIter = std::array::IntoIter<Self::Item, REFLECTOR_COUNT>;
270-
271-
fn into_iter(self) -> Self::IntoIter {
272-
[
273-
("pods", self.pods),
274-
("nodes", self.nodes),
275-
("deployments", self.deployments),
276-
("daemonsets", self.daemonsets),
277-
("namespaces", self.namespaces),
278-
("replicasets", self.replicasets),
279-
("persistent_volumes", self.persistent_volumes),
280-
("persistent_volume_claims", self.persistent_volume_claims),
281-
("statefulsets", self.statefulsets),
282-
]
283-
.into_iter()
284-
}
285-
}
286-
287213
fn start_reflector<K>(
288214
api: Api<K>,
289215
config: WatchConfig,

0 commit comments

Comments
 (0)