Skip to content

Commit d36eb31

Browse files
committed
feat: comparable resource version utils
1 parent 9ecb404 commit d36eb31

File tree

2 files changed

+127
-2
lines changed

2 files changed

+127
-2
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package io.javaoperatorsdk.operator.api.reconciler;
2+
3+
import java.util.function.UnaryOperator;
4+
5+
import io.fabric8.kubernetes.api.model.HasMetadata;
6+
import io.fabric8.kubernetes.client.dsl.base.PatchContext;
7+
import io.fabric8.kubernetes.client.dsl.base.PatchType;
8+
import io.javaoperatorsdk.operator.processing.event.source.informer.ManagedInformerEventSource;
9+
10+
public class ReconcilerUtils {
11+
// toto namespace handling
12+
// todo compare resource version if multiple event sources provide the same resource
13+
// for json patch make sense to retry (json merge patch?)
14+
15+
public static <R extends HasMetadata> R ssa(Context<? extends HasMetadata> context, R resource) {
16+
return handleResourcePatch(
17+
context,
18+
resource,
19+
r ->
20+
context
21+
.getClient()
22+
.resource(r)
23+
.patch(
24+
new PatchContext.Builder()
25+
.withForce(true)
26+
.withFieldManager(context.getControllerConfiguration().fieldManager())
27+
.withPatchType(PatchType.SERVER_SIDE_APPLY)
28+
.build()));
29+
}
30+
31+
public static <R extends HasMetadata> R ssaStatus(
32+
Context<? extends HasMetadata> context, R resource) {
33+
return handleResourcePatch(
34+
context,
35+
resource,
36+
r ->
37+
context
38+
.getClient()
39+
.resource(r)
40+
.subresource("status")
41+
.patch(
42+
new PatchContext.Builder()
43+
.withForce(true)
44+
.withFieldManager(context.getControllerConfiguration().fieldManager())
45+
.withPatchType(PatchType.SERVER_SIDE_APPLY)
46+
.build()));
47+
}
48+
49+
public static <P extends HasMetadata> P ssaPrimary(Context<P> context, P resource) {
50+
return handleResourcePatch(
51+
resource,
52+
r ->
53+
context
54+
.getClient()
55+
.resource(r)
56+
.patch(
57+
new PatchContext.Builder()
58+
.withForce(true)
59+
.withFieldManager(context.getControllerConfiguration().fieldManager())
60+
.withPatchType(PatchType.SERVER_SIDE_APPLY)
61+
.build()),
62+
true,
63+
context.eventSourceRetriever().getControllerEventSource());
64+
}
65+
66+
public static <P extends HasMetadata> P ssaStatusPrimary(Context<P> context, P resource) {
67+
return handleResourcePatch(
68+
resource,
69+
r ->
70+
context
71+
.getClient()
72+
.resource(r)
73+
.subresource("status")
74+
.patch(
75+
new PatchContext.Builder()
76+
.withForce(true)
77+
.withFieldManager(context.getControllerConfiguration().fieldManager())
78+
.withPatchType(PatchType.SERVER_SIDE_APPLY)
79+
.build()),
80+
true,
81+
context.eventSourceRetriever().getControllerEventSource());
82+
}
83+
84+
public static <R extends HasMetadata> R handleResourcePatch(
85+
Context<?> context, R resource, UnaryOperator<R> updateOperation) {
86+
var esList = context.eventSourceRetriever().getEventSourcesFor(resource.getClass());
87+
if (esList.isEmpty()) {
88+
throw new IllegalStateException("No event source found for type: " + resource.getClass());
89+
}
90+
if (esList.size() > 1) {
91+
throw new IllegalStateException(
92+
"Multiple event sources found for: "
93+
+ resource.getClass()
94+
+ " please provide the target event source");
95+
}
96+
var es = esList.get(0);
97+
if (es instanceof ManagedInformerEventSource mes) {
98+
return handleResourcePatch(resource, updateOperation, true, mes);
99+
} else {
100+
throw new IllegalStateException(
101+
"Target event source must be a subclass off "
102+
+ ManagedInformerEventSource.class.getName());
103+
}
104+
}
105+
106+
@SuppressWarnings("unchecked")
107+
private static <R extends HasMetadata> R handleResourcePatch(
108+
R resource,
109+
UnaryOperator<R> updateOperation,
110+
boolean doNotLock,
111+
ManagedInformerEventSource ies) {
112+
var resourceVersion = resource.getMetadata().getResourceVersion();
113+
try {
114+
if (resourceVersion != null && doNotLock) {
115+
resource.getMetadata().setResourceVersion(null);
116+
}
117+
return (R) ies.updateAndCacheResource(resource, updateOperation);
118+
} finally {
119+
if (resourceVersion != null && doNotLock) {
120+
resource.getMetadata().setResourceVersion(resourceVersion);
121+
}
122+
}
123+
}
124+
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/ReconciliationDispatcher.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import io.javaoperatorsdk.operator.api.reconciler.Context;
3636
import io.javaoperatorsdk.operator.api.reconciler.DefaultContext;
3737
import io.javaoperatorsdk.operator.api.reconciler.DeleteControl;
38-
import io.javaoperatorsdk.operator.api.reconciler.ReconcileUtils;
38+
import io.javaoperatorsdk.operator.api.reconciler.ReconcilerUtils;
3939
import io.javaoperatorsdk.operator.api.reconciler.RetryInfo;
4040
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
4141
import io.javaoperatorsdk.operator.processing.Controller;
@@ -420,7 +420,8 @@ public R patchStatus(Context<R> context, R resource, R originalResource) {
420420
var managedFields = resource.getMetadata().getManagedFields();
421421
try {
422422
resource.getMetadata().setManagedFields(null);
423-
return ReconcileUtils.serverSideApplyPrimaryStatus(context, resource);
423+
var res = resource(resource);
424+
return ReconcilerUtils.ssaStatusPrimary(context, resource);
424425
} finally {
425426
resource.getMetadata().setManagedFields(managedFields);
426427
}

0 commit comments

Comments
 (0)