Skip to content

Commit 360be15

Browse files
committed
glue parent finalizer handling
Signed-off-by: Attila Mészáros <[email protected]>
1 parent b40605f commit 360be15

File tree

3 files changed

+52
-38
lines changed

3 files changed

+52
-38
lines changed

src/main/java/io/csviri/operator/resourceglue/reconciler/glue/GlueReconciler.java

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.csviri.operator.resourceglue.dependent.GenericResourceDiscriminator;
1919
import io.csviri.operator.resourceglue.templating.GenericTemplateHandler;
2020
import io.fabric8.kubernetes.api.model.GenericKubernetesResource;
21+
import io.fabric8.kubernetes.api.model.HasMetadata;
2122
import io.fabric8.kubernetes.client.KubernetesClientException;
2223
import io.fabric8.kubernetes.client.dsl.base.PatchContext;
2324
import io.fabric8.kubernetes.client.dsl.base.PatchType;
@@ -51,6 +52,9 @@ public UpdateControl<Glue> reconcile(Glue primary,
5152
log.debug("Reconciling glue. name: {} namespace: {}",
5253
primary.getMetadata().getName(), primary.getMetadata().getNamespace());
5354
registerRelatedResourceInformers(context, primary);
55+
if (deletedGlueIfParentMarkedForDeletion(context, primary)) {
56+
return UpdateControl.noUpdate();
57+
}
5458
addFinalizersToParentResource(primary, context);
5559
if (ownersBeingDeleted(primary, context)) {
5660
return UpdateControl.noUpdate();
@@ -63,6 +67,16 @@ public UpdateControl<Glue> reconcile(Glue primary,
6367
return UpdateControl.noUpdate();
6468
}
6569

70+
private boolean deletedGlueIfParentMarkedForDeletion(Context<Glue> context, Glue primary) {
71+
var parent = getParentRelatedResource(primary, context);
72+
if (parent.map(HasMetadata::isMarkedForDeletion).orElse(false)) {
73+
context.getClient().resource(primary).delete();
74+
return true;
75+
} else {
76+
return false;
77+
}
78+
}
79+
6680

6781
/**
6882
* If a parent gets deleted, the glue is reconciled still, but we don't want that in that case.
@@ -217,25 +231,14 @@ private Condition toCondition(ConditionSpec condition) {
217231

218232
// todo docs
219233
private void addFinalizersToParentResource(Glue primary, Context<Glue> context) {
220-
var parentRelated = primary.getSpec().getRelatedResources().stream()
221-
.filter(r -> r.getName().equals(PARENT_RELATED_RESOURCE_NAME))
222-
.findAny();
223-
parentRelated.ifPresent(r -> {
224-
var relatedResources = Utils.getRelatedResources(primary, r, context);
225-
if (relatedResources.size() > 1) {
226-
throw new IllegalStateException(
227-
"parent related resource contains more resourceNames for glue name: "
228-
+ primary.getMetadata().getName()
229-
+ " namespace: " + primary.getMetadata().getNamespace());
230-
}
231-
// theoretically can happen that parent was deleted meanwhile
232-
if (relatedResources.isEmpty()) {
233-
return;
234-
}
235-
var parent = relatedResources.entrySet().iterator().next().getValue();
234+
var parent = getParentRelatedResource(primary, context);
235+
236+
parent.ifPresent(p -> {
237+
log.warn("Adding finalizer to parent. Glue name: {} namespace: {}",
238+
primary.getMetadata().getName(), primary.getMetadata().getNamespace());
236239
String finalizer = parentFinalizer(primary.getMetadata().getName());
237-
if (!parent.getMetadata().getFinalizers().contains(finalizer)) {
238-
var res = getResourceForSSAFrom(parent);
240+
if (!p.getMetadata().getFinalizers().contains(finalizer)) {
241+
var res = getResourceForSSAFrom(p);
239242
res.getMetadata().getFinalizers().add(finalizer);
240243
context.getClient().resource(res)
241244
.patch(new PatchContext.Builder()
@@ -248,33 +251,43 @@ private void addFinalizersToParentResource(Glue primary, Context<Glue> context)
248251
}
249252

250253
private void removeFinalizerForParent(Glue primary, Context<Glue> context) {
254+
var parent = getParentRelatedResource(primary, context);
255+
parent.ifPresentOrElse(p -> {
256+
log.warn("Removing finalizer from parent. Glue name: {} namespace: {}",
257+
primary.getMetadata().getName(), primary.getMetadata().getNamespace());
258+
String finalizer = parentFinalizer(primary.getMetadata().getName());
259+
if (p.getMetadata().getFinalizers().contains(finalizer)) {
260+
var res = getResourceForSSAFrom(p);
261+
context.getClient().resource(res)
262+
.patch(new PatchContext.Builder()
263+
.withFieldManager(context.getControllerConfiguration().fieldManager())
264+
.withForce(true)
265+
.withPatchType(PatchType.SERVER_SIDE_APPLY)
266+
.build());
267+
}
268+
}, () -> log.warn(
269+
"Parent resource expected to be present on cleanup. Glue name: {} namespace: {}",
270+
primary.getMetadata().getName(), primary.getMetadata().getNamespace()));
271+
}
272+
273+
private Optional<GenericKubernetesResource> getParentRelatedResource(Glue primary,
274+
Context<Glue> context) {
251275
var parentRelated = primary.getSpec().getRelatedResources().stream()
252276
.filter(r -> r.getName().equals(PARENT_RELATED_RESOURCE_NAME))
253277
.findAny();
254-
parentRelated.ifPresent(r -> {
278+
279+
return parentRelated.flatMap(r -> {
255280
var relatedResources = Utils.getRelatedResources(primary, r, context);
256281
if (relatedResources.size() > 1) {
257282
throw new IllegalStateException(
258283
"parent related resource contains more resourceNames for glue name: "
259284
+ primary.getMetadata().getName()
260285
+ " namespace: " + primary.getMetadata().getNamespace());
261286
}
262-
// theoretically can happen that parent was deleted meanwhile
263287
if (relatedResources.isEmpty()) {
264-
log.warn("Parent resource expected to be present on cleanup. Glue name: {} namespace: {}",
265-
primary.getMetadata().getName(), primary.getMetadata().getNamespace());
266-
return;
267-
}
268-
var parent = relatedResources.entrySet().iterator().next().getValue();
269-
String finalizer = parentFinalizer(primary.getMetadata().getName());
270-
if (parent.getMetadata().getFinalizers().contains(finalizer)) {
271-
var res = getResourceForSSAFrom(parent);
272-
context.getClient().resource(res)
273-
.patch(new PatchContext.Builder()
274-
.withFieldManager(context.getControllerConfiguration().fieldManager())
275-
.withForce(true)
276-
.withPatchType(PatchType.SERVER_SIDE_APPLY)
277-
.build());
288+
return Optional.empty();
289+
} else {
290+
return Optional.of(relatedResources.entrySet().iterator().next().getValue());
278291
}
279292
});
280293
}

src/main/java/io/csviri/operator/resourceglue/reconciler/glue/InformerRegister.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class InformerRegister {
2424

2525
private final Map<GroupVersionKind, Set<String>> gvkOfInformerToGlue = new HashMap<>();
2626
private final Map<String, Set<GroupVersionKind>> glueToInformerGVK = new HashMap<>();
27-
private final Map<GroupVersionKind, RelatedResourceSecondaryToPrimaryMapper> relatedResourceMappers =
27+
private final Map<GroupVersionKind, RelatedAndOwnedResourceSecondaryToPrimaryMapper> relatedResourceMappers =
2828
new ConcurrentHashMap<>();
2929

3030
// todo test related resources deleting
@@ -71,9 +71,10 @@ public void registerInformerForRelatedResource(Context<Glue> context,
7171
public InformerEventSource<GenericKubernetesResource, Glue> registerInformer(
7272
Context<Glue> context, GroupVersionKind gvk, Glue glue) {
7373

74-
RelatedResourceSecondaryToPrimaryMapper mapper;
74+
RelatedAndOwnedResourceSecondaryToPrimaryMapper mapper;
7575
synchronized (this) {
76-
relatedResourceMappers.putIfAbsent(gvk, new RelatedResourceSecondaryToPrimaryMapper());
76+
relatedResourceMappers.putIfAbsent(gvk,
77+
new RelatedAndOwnedResourceSecondaryToPrimaryMapper());
7778
mapper = relatedResourceMappers.get(gvk);
7879
markEventSource(gvk, glue);
7980
}

src/main/java/io/csviri/operator/resourceglue/reconciler/glue/RelatedResourceSecondaryToPrimaryMapper.java renamed to src/main/java/io/csviri/operator/resourceglue/reconciler/glue/RelatedAndOwnedResourceSecondaryToPrimaryMapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper;
1212
import io.javaoperatorsdk.operator.processing.event.source.informer.Mappers;
1313

14-
public class RelatedResourceSecondaryToPrimaryMapper
14+
public class RelatedAndOwnedResourceSecondaryToPrimaryMapper
1515
implements SecondaryToPrimaryMapper<GenericKubernetesResource> {
1616

1717
private final Map<ResourceID, Set<ResourceID>> secondaryToPrimaryMap = new ConcurrentHashMap<>();

0 commit comments

Comments
 (0)