Skip to content

Commit 863016d

Browse files
committed
feat: operator can be restarted
1 parent 75eec9c commit 863016d

File tree

5 files changed

+130
-0
lines changed

5 files changed

+130
-0
lines changed

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ public void stop() throws OperatorException {
137137
if (configurationService.closeClientOnStop()) {
138138
kubernetesClient.close();
139139
}
140+
started = false;
140141
}
141142

142143
/**
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package io.javaoperatorsdk.operator;
2+
3+
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
4+
import io.javaoperatorsdk.operator.sample.informerrelatedbehavior.InformerRelatedBehaviorTestCustomResource;
5+
import org.junit.jupiter.api.Test;
6+
7+
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
8+
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
9+
import io.javaoperatorsdk.operator.sample.restart.RestartTestCustomResource;
10+
import io.javaoperatorsdk.operator.sample.restart.RestartTestReconciler;
11+
12+
import static org.assertj.core.api.Assertions.assertThat;
13+
import static org.awaitility.Awaitility.await;
14+
15+
class OperatorRestartIT {
16+
17+
@Test
18+
void operatorCanBeRestarted() {
19+
try (var client = new KubernetesClientBuilder().build()) {
20+
LocallyRunOperatorExtension.applyCrd(RestartTestCustomResource.class,
21+
client);
22+
Operator operator = new Operator();
23+
var reconciler = new RestartTestReconciler();
24+
operator.register(reconciler);
25+
operator.start();
26+
27+
client.resource(testCustomResource()).createOrReplace();
28+
await().untilAsserted(() -> {
29+
assertThat(reconciler.getNumberOfExecutions()).isGreaterThan(0);
30+
});
31+
var reconcileNumberBeforeStop = reconciler.getNumberOfExecutions();
32+
operator.stop();
33+
operator.start();
34+
35+
await().untilAsserted(() -> {
36+
assertThat(reconciler.getNumberOfExecutions()).isGreaterThan(reconcileNumberBeforeStop);
37+
});
38+
}
39+
}
40+
41+
RestartTestCustomResource testCustomResource() {
42+
RestartTestCustomResource cr = new RestartTestCustomResource();
43+
cr.setMetadata(new ObjectMetaBuilder()
44+
.withName("test1")
45+
.build());
46+
return cr;
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package io.javaoperatorsdk.operator.sample.restart;
2+
3+
import java.util.Map;
4+
5+
import io.fabric8.kubernetes.api.model.ConfigMap;
6+
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
7+
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
8+
import io.javaoperatorsdk.operator.api.reconciler.Context;
9+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
10+
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
11+
12+
@KubernetesDependent(labelSelector = "app=restart-test")
13+
public class ConfigMapDependentResource
14+
extends CRUDKubernetesDependentResource<ConfigMap, RestartTestCustomResource> {
15+
16+
public static final String DATA_KEY = "key";
17+
18+
public ConfigMapDependentResource() {
19+
super(ConfigMap.class);
20+
}
21+
22+
@Override
23+
protected ConfigMap desired(RestartTestCustomResource primary,
24+
Context<RestartTestCustomResource> context) {
25+
return new ConfigMapBuilder()
26+
.withMetadata(new ObjectMetaBuilder()
27+
.withLabels(Map.of("app", "restart-test"))
28+
.withName(primary.getMetadata().getName())
29+
.withNamespace(primary.getMetadata().getNamespace())
30+
.build())
31+
.withData(Map.of(DATA_KEY, primary.getMetadata().getName()))
32+
.build();
33+
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package io.javaoperatorsdk.operator.sample.restart;
2+
3+
import io.fabric8.kubernetes.api.model.Namespaced;
4+
import io.fabric8.kubernetes.client.CustomResource;
5+
import io.fabric8.kubernetes.model.annotation.Group;
6+
import io.fabric8.kubernetes.model.annotation.ShortNames;
7+
import io.fabric8.kubernetes.model.annotation.Version;
8+
9+
@Group("sample.javaoperatorsdk")
10+
@Version("v1")
11+
@ShortNames("rt")
12+
public class RestartTestCustomResource
13+
extends CustomResource<Void, Void>
14+
implements Namespaced {
15+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.javaoperatorsdk.operator.sample.restart;
2+
3+
import java.util.concurrent.atomic.AtomicInteger;
4+
5+
import io.javaoperatorsdk.operator.api.reconciler.Context;
6+
import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
7+
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
8+
import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
9+
import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
10+
import io.javaoperatorsdk.operator.support.TestExecutionInfoProvider;
11+
12+
@ControllerConfiguration(
13+
dependents = @Dependent(type = ConfigMapDependentResource.class))
14+
public class RestartTestReconciler
15+
implements Reconciler<RestartTestCustomResource>, TestExecutionInfoProvider {
16+
17+
private final AtomicInteger numberOfExecutions = new AtomicInteger(0);
18+
19+
@Override
20+
public UpdateControl<RestartTestCustomResource> reconcile(
21+
RestartTestCustomResource resource,
22+
Context<RestartTestCustomResource> context) {
23+
numberOfExecutions.addAndGet(1);
24+
return UpdateControl.noUpdate();
25+
}
26+
27+
public int getNumberOfExecutions() {
28+
return numberOfExecutions.get();
29+
}
30+
31+
}

0 commit comments

Comments
 (0)