Skip to content

Commit 039a812

Browse files
feat: skip delete (#194)
* chore: remove redundant scope * chore: use background delete if finalizers are present * feat: skip target deletion if annotation is set
1 parent 39e867e commit 039a812

2 files changed

Lines changed: 112 additions & 32 deletions

File tree

src/controller.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ async fn reconcile_deleted_resource(
5151
return Ok(Action::await_change());
5252
}
5353

54+
if resource_sync.has_disable_target_deletion_option_enabled() {
55+
return stop_watches_and_remove_resource_sync_finalizers(
56+
resource_sync,
57+
name,
58+
parent_api,
59+
ctx,
60+
)
61+
.await;
62+
}
63+
5464
let target_name = &resource_sync.spec.target.resource_ref.name;
5565

5666
match target_api.get(target_name).await {
@@ -60,10 +70,12 @@ async fn reconcile_deleted_resource(
6070
.await;
6171
Ok(Action::await_change())
6272
}
63-
Ok(_) => {
64-
target_api
65-
.delete(target_name, &DeleteParams::foreground())
66-
.await?;
73+
Ok(target) => {
74+
let delete_type = match target.metadata.finalizers {
75+
Some(finalizers) if !finalizers.is_empty() => &DeleteParams::background(),
76+
_ => &DeleteParams::foreground(),
77+
};
78+
target_api.delete(target_name, delete_type).await?;
6779

6880
resource_sync
6981
.start_remote_watches_if_not_watching(ctx)
@@ -141,7 +153,7 @@ async fn reconcile_normally(
141153
.get(&resource_sync.spec.source.resource_ref.name)
142154
.await
143155
.map_err(|e| {
144-
crate::Error::ResourceNotFoundError(
156+
Error::ResourceNotFoundError(
145157
resource_sync.spec.source.resource_ref.name.clone(),
146158
source_api.ar.kind,
147159
e,

src/resources.rs

Lines changed: 95 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,26 @@ use schemars::JsonSchema;
1010
use serde::{Deserialize, Serialize};
1111

1212
static FORCE_DELETE_ANNOTATION: &str = "sinker.influxdata.io/force-delete";
13+
static DISABLE_TARGET_DELETION_ANNOTATION: &str = "sinker.influxdata.io/disable-target-deletion";
1314

1415
impl ResourceSync {
15-
pub fn has_force_delete_option_enabled(&self) -> bool {
16+
fn get_boolean_annotation_val(&self, annotation: &str) -> bool {
1617
self.metadata
1718
.annotations
1819
.as_ref()
19-
.map(|annotations| annotations.get(FORCE_DELETE_ANNOTATION))
20+
.map(|annotations| annotations.get(annotation))
2021
.unwrap_or_default()
2122
.cloned()
2223
.unwrap_or_default()
2324
.parse()
2425
.unwrap_or_default()
2526
}
27+
pub fn has_force_delete_option_enabled(&self) -> bool {
28+
self.get_boolean_annotation_val(FORCE_DELETE_ANNOTATION)
29+
}
30+
pub fn has_disable_target_deletion_option_enabled(&self) -> bool {
31+
self.get_boolean_annotation_val(DISABLE_TARGET_DELETION_ANNOTATION)
32+
}
2633
}
2734

2835
#[derive(CustomResource, Debug, Serialize, Deserialize, Default, Clone, JsonSchema)]
@@ -162,31 +169,92 @@ impl SinkerContainer {
162169
#[cfg(test)]
163170
mod tests {
164171
use super::*;
165-
use k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta;
166172
use rstest::rstest;
167-
use std::collections::BTreeMap;
168-
169-
#[rstest]
170-
#[case::no_annotations(
171-
ResourceSync{metadata: Default::default(),spec: Default::default(),status: None,}, false
172-
)]
173-
#[case::force_delete_annotation_not_present(
174-
ResourceSync{metadata: ObjectMeta{annotations: Some(BTreeMap::new()), ..Default::default()},spec: Default::default(),status: None,}, false
175-
)]
176-
#[case::force_delete_annotation_is_false(
177-
ResourceSync{metadata: ObjectMeta{annotations: Some(BTreeMap::from([(FORCE_DELETE_ANNOTATION.to_string(), false.to_string())])), ..Default::default()},spec: Default::default(),status: None,}, false
178-
)]
179-
#[case::force_delete_annotation_is_other(
180-
ResourceSync{metadata: ObjectMeta{annotations: Some(BTreeMap::from([(FORCE_DELETE_ANNOTATION.to_string(), "other".to_string())])), ..Default::default()},spec: Default::default(),status: None,}, false
181-
)]
182-
#[case::force_delete_annotation_is_true(
183-
ResourceSync{metadata: ObjectMeta{annotations: Some(BTreeMap::from([(FORCE_DELETE_ANNOTATION.to_string(), true.to_string())])), ..Default::default()},spec: Default::default(),status: None,}, true
184-
)]
185-
#[tokio::test]
186-
async fn test_resource_sync_has_force_delete_option_enabled(
187-
#[case] resource_sync: ResourceSync,
188-
#[case] expected: bool,
189-
) {
190-
assert_eq!(resource_sync.has_force_delete_option_enabled(), expected);
173+
174+
macro_rules! gen_option_flag_tests {
175+
($test_name:ident, $method:ident, $annotation_key:expr) => {
176+
#[rstest]
177+
#[case::no_annotations(
178+
ResourceSync {
179+
metadata: Default::default(),
180+
spec: Default::default(),
181+
status: None,
182+
},
183+
false
184+
)]
185+
#[case::annotation_not_present(
186+
ResourceSync {
187+
metadata: k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta {
188+
annotations: Some(std::collections::BTreeMap::new()),
189+
..Default::default()
190+
},
191+
spec: Default::default(),
192+
status: None,
193+
},
194+
false
195+
)]
196+
#[case::annotation_is_false(
197+
ResourceSync {
198+
metadata: k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta {
199+
annotations: Some(std::collections::BTreeMap::from([(
200+
$annotation_key.to_string(),
201+
false.to_string()
202+
)])),
203+
..Default::default()
204+
},
205+
spec: Default::default(),
206+
status: None,
207+
},
208+
false
209+
)]
210+
#[case::annotation_is_other(
211+
ResourceSync {
212+
metadata: k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta {
213+
annotations: Some(std::collections::BTreeMap::from([(
214+
$annotation_key.to_string(),
215+
"other".to_string()
216+
)])),
217+
..Default::default()
218+
},
219+
spec: Default::default(),
220+
status: None,
221+
},
222+
false
223+
)]
224+
#[case::annotation_is_true(
225+
ResourceSync {
226+
metadata: k8s_openapi::apimachinery::pkg::apis::meta::v1::ObjectMeta {
227+
annotations: Some(std::collections::BTreeMap::from([(
228+
$annotation_key.to_string(),
229+
true.to_string()
230+
)])),
231+
..Default::default()
232+
},
233+
spec: Default::default(),
234+
status: None,
235+
},
236+
true
237+
)]
238+
#[tokio::test]
239+
async fn $test_name(
240+
#[case] resource_sync: ResourceSync,
241+
#[case] expected: bool,
242+
) {
243+
assert_eq!(resource_sync.$method(), expected);
244+
}
245+
};
191246
}
247+
248+
// Reuse the same cases for both annotation readers:
249+
gen_option_flag_tests!(
250+
test_resource_sync_has_force_delete_option_enabled,
251+
has_force_delete_option_enabled,
252+
FORCE_DELETE_ANNOTATION
253+
);
254+
255+
gen_option_flag_tests!(
256+
test_resource_sync_has_disable_target_deletion_option_enabled,
257+
has_disable_target_deletion_option_enabled,
258+
DISABLE_TARGET_DELETION_ANNOTATION
259+
);
192260
}

0 commit comments

Comments
 (0)