Skip to content

Commit 9ef0cc4

Browse files
committed
feat: non static reference of services (#1865)
1 parent b558471 commit 9ef0cc4

File tree

63 files changed

+651
-632
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+651
-632
lines changed

Diff for: micrometer-support/src/test/java/io/javaoperatorsdk/operator/monitoring/micrometer/AbstractMicrometerMetricsTestFixture.java

+8-16
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,12 @@
33
import java.util.HashSet;
44
import java.util.Set;
55

6-
import org.junit.jupiter.api.AfterAll;
7-
import org.junit.jupiter.api.BeforeAll;
86
import org.junit.jupiter.api.Test;
97
import org.junit.jupiter.api.TestInstance;
108
import org.junit.jupiter.api.extension.RegisterExtension;
119

1210
import io.fabric8.kubernetes.api.model.ConfigMap;
1311
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
14-
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider;
1512
import io.javaoperatorsdk.operator.api.reconciler.*;
1613
import io.javaoperatorsdk.operator.junit.LocallyRunOperatorExtension;
1714
import io.javaoperatorsdk.operator.processing.event.ResourceID;
@@ -23,26 +20,21 @@
2320

2421
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
2522
public abstract class AbstractMicrometerMetricsTestFixture {
26-
@RegisterExtension
27-
LocallyRunOperatorExtension operator =
28-
LocallyRunOperatorExtension.builder().withReconciler(new MetricsCleaningTestReconciler())
29-
.build();
3023

3124
protected final TestSimpleMeterRegistry registry = new TestSimpleMeterRegistry();
3225
protected final MicrometerMetrics metrics = getMetrics();
3326
protected static final String testResourceName = "micrometer-metrics-cr";
3427

35-
protected abstract MicrometerMetrics getMetrics();
3628

37-
@BeforeAll
38-
void setup() {
39-
ConfigurationServiceProvider.overrideCurrent(overrider -> overrider.withMetrics(metrics));
40-
}
29+
@RegisterExtension
30+
LocallyRunOperatorExtension operator =
31+
LocallyRunOperatorExtension.builder()
32+
.withConfigurationService(overrider -> overrider.withMetrics(metrics))
33+
.withReconciler(new MetricsCleaningTestReconciler())
34+
.build();
4135

42-
@AfterAll
43-
void reset() {
44-
ConfigurationServiceProvider.reset();
45-
}
36+
37+
protected abstract MicrometerMetrics getMetrics();
4638

4739
@Test
4840
void properlyHandlesResourceDeletion() throws Exception {

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/ControllerManager.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ class ControllerManager {
2222
@SuppressWarnings("rawtypes")
2323
private final Map<String, Controller> controllers = new HashMap<>();
2424
private boolean started = false;
25+
private final ExecutorServiceManager executorServiceManager;
26+
27+
public ControllerManager(ExecutorServiceManager executorServiceManager) {
28+
this.executorServiceManager = executorServiceManager;
29+
}
30+
2531

2632
public synchronized void shouldStart() {
2733
if (started) {
@@ -33,15 +39,15 @@ public synchronized void shouldStart() {
3339
}
3440

3541
public synchronized void start(boolean startEventProcessor) {
36-
ExecutorServiceManager.boundedExecuteAndWaitForAllToComplete(controllers().stream(), c -> {
42+
executorServiceManager.boundedExecuteAndWaitForAllToComplete(controllers().stream(), c -> {
3743
c.start(startEventProcessor);
3844
return null;
3945
}, c -> "Controller Starter for: " + c.getConfiguration().getName());
4046
started = true;
4147
}
4248

4349
public synchronized void stop() {
44-
ExecutorServiceManager.boundedExecuteAndWaitForAllToComplete(controllers().stream(), c -> {
50+
executorServiceManager.boundedExecuteAndWaitForAllToComplete(controllers().stream(), c -> {
4551
log.debug("closing {}", c);
4652
c.stop();
4753
return null;
@@ -50,7 +56,7 @@ public synchronized void stop() {
5056
}
5157

5258
public synchronized void startEventProcessing() {
53-
ExecutorServiceManager.boundedExecuteAndWaitForAllToComplete(controllers().stream(), c -> {
59+
executorServiceManager.boundedExecuteAndWaitForAllToComplete(controllers().stream(), c -> {
5460
c.startEventProcessing();
5561
return null;
5662
}, c -> "Event processor starter for: " + c.getConfiguration().getName());

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/LeaderElectionManager.java

+38-30
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package io.javaoperatorsdk.operator;
22

3+
import java.util.Arrays;
34
import java.util.Arrays;
45
import java.util.UUID;
56
import java.util.concurrent.CompletableFuture;
67

8+
import io.fabric8.kubernetes.api.model.authorization.v1.SelfSubjectRulesReview;
9+
import io.fabric8.kubernetes.api.model.authorization.v1.SelfSubjectRulesReviewSpecBuilder;
10+
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
711
import org.slf4j.Logger;
812
import org.slf4j.LoggerFactory;
913

@@ -14,8 +18,7 @@
1418
import io.fabric8.kubernetes.client.extended.leaderelection.LeaderElector;
1519
import io.fabric8.kubernetes.client.extended.leaderelection.LeaderElectorBuilder;
1620
import io.fabric8.kubernetes.client.extended.leaderelection.resourcelock.LeaseLock;
17-
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider;
18-
import io.javaoperatorsdk.operator.api.config.ExecutorServiceManager;
21+
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
1922
import io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration;
2023

2124
public class LeaderElectionManager {
@@ -30,45 +33,49 @@ public class LeaderElectionManager {
3033
private String identity;
3134
private CompletableFuture<?> leaderElectionFuture;
3235
private KubernetesClient client;
33-
private String leaseName;
36+
private final ConfigurationService configurationService;
3437
private String leaseNamespace;
3538

36-
public LeaderElectionManager(ControllerManager controllerManager) {
39+
public LeaderElectionManager(KubernetesClient kubernetesClient,
40+
ControllerManager controllerManager,
41+
ConfigurationService configurationService) {
42+
this.kubernetesClient = kubernetesClient;
3743
this.controllerManager = controllerManager;
44+
this.configurationService = configurationService;
45+
}
46+
47+
public boolean isLeaderElectionEnabled() {
48+
return configurationService.getLeaderElectionConfiguration().isPresent();
3849
}
3950

40-
public void init(LeaderElectionConfiguration config, KubernetesClient client) {
41-
this.client = client;
51+
public void init(LeaderElectionConfiguration config) {
4252
this.identity = identity(config);
43-
this.leaseName = config.getLeaseName();
4453
leaseNamespace =
45-
config.getLeaseNamespace().orElseGet(
46-
() -> ConfigurationServiceProvider.instance().getClientConfiguration().getNamespace());
54+
config.getLeaseNamespace().orElseGet(
55+
() -> configurationService.getClientConfiguration().getNamespace());
4756
if (leaseNamespace == null) {
4857
final var message =
49-
"Lease namespace is not set and cannot be inferred. Leader election cannot continue.";
58+
"Lease namespace is not set and cannot be inferred. Leader election cannot continue.";
5059
log.error(message);
5160
throw new IllegalArgumentException(message);
5261
}
53-
final var lock = new LeaseLock(leaseNamespace, leaseName, identity);
62+
final var lock = new LeaseLock(leaseNamespace, config.getLeaseName(), identity);
5463
// releaseOnCancel is not used in the underlying implementation
55-
leaderElector =
56-
new LeaderElectorBuilder(
57-
client, ExecutorServiceManager.instance().executorService())
58-
.withConfig(new LeaderElectionConfig(
59-
lock,
60-
config.getLeaseDuration(),
61-
config.getRenewDeadline(),
62-
config.getRetryPeriod(),
63-
leaderCallbacks(),
64-
true,
65-
config.getLeaseName()))
64+
leaderElector = new LeaderElectorBuilder(
65+
kubernetesClient, configurationService.getExecutorServiceManager().cachingExecutorService())
66+
.withConfig(
67+
new LeaderElectionConfig(
68+
lock,
69+
config.getLeaseDuration(),
70+
config.getRenewDeadline(),
71+
config.getRetryPeriod(),
72+
leaderCallbacks(),
73+
true,
74+
config.getLeaseName()))
6675
.build();
6776
}
6877

69-
public boolean isLeaderElectionEnabled() {
70-
return leaderElector != null;
71-
}
78+
7279

7380
private LeaderCallbacks leaderCallbacks() {
7481
return new LeaderCallbacks(
@@ -99,6 +106,7 @@ private String identity(LeaderElectionConfiguration config) {
99106

100107
public void start() {
101108
if (isLeaderElectionEnabled()) {
109+
init(configurationService.getLeaderElectionConfiguration().orElseThrow());
102110
checkLeaseAccess();
103111
leaderElectionFuture = leaderElector.start();
104112
}
@@ -117,13 +125,13 @@ private void checkLeaseAccess() {
117125
var reviewResult = client.resource(review).create();
118126
log.debug("SelfSubjectRulesReview result: {}", reviewResult);
119127
var foundRule = reviewResult.getStatus().getResourceRules().stream()
120-
.filter(rule -> rule.getApiGroups().contains("coordination.k8s.io")
121-
&& rule.getResources().contains("leases")
122-
&& (rule.getVerbs().containsAll(verbs)) || rule.getVerbs().contains("*"))
123-
.findAny();
128+
.filter(rule -> rule.getApiGroups().contains("coordination.k8s.io")
129+
&& rule.getResources().contains("leases")
130+
&& (rule.getVerbs().containsAll(verbs)) || rule.getVerbs().contains("*"))
131+
.findAny();
124132
if (foundRule.isEmpty()) {
125133
throw new OperatorException(NO_PERMISSION_TO_LEASE_RESOURCE_MESSAGE +
126-
" in namespace: " + leaseNamespace);
134+
" in namespace: " + leaseNamespace);
127135
}
128136
}
129137
}

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

+25-20
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@
1414
import io.fabric8.kubernetes.client.KubernetesClient;
1515
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
1616
import io.fabric8.kubernetes.client.Version;
17+
import io.javaoperatorsdk.operator.api.config.BaseConfigurationService;
1718
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
1819
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceOverrider;
19-
import io.javaoperatorsdk.operator.api.config.ConfigurationServiceProvider;
2020
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
2121
import io.javaoperatorsdk.operator.api.config.ControllerConfigurationOverrider;
22-
import io.javaoperatorsdk.operator.api.config.ExecutorServiceManager;
2322
import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
2423
import io.javaoperatorsdk.operator.processing.Controller;
2524
import io.javaoperatorsdk.operator.processing.LifecycleAware;
@@ -29,17 +28,18 @@ public class Operator implements LifecycleAware {
2928
private static final Logger log = LoggerFactory.getLogger(Operator.class);
3029
private static final int DEFAULT_MAX_CONCURRENT_REQUEST = 512;
3130
private final KubernetesClient kubernetesClient;
32-
private final ControllerManager controllerManager = new ControllerManager();
33-
private final LeaderElectionManager leaderElectionManager =
34-
new LeaderElectionManager(controllerManager);
31+
private final ControllerManager controllerManager;
32+
private final LeaderElectionManager leaderElectionManager;
33+
private final ConfigurationService configurationService;
3534
private volatile boolean started = false;
3635

36+
3737
public Operator() {
3838
this((KubernetesClient) null);
3939
}
4040

4141
public Operator(KubernetesClient kubernetesClient) {
42-
this(kubernetesClient, ConfigurationServiceProvider.instance());
42+
this(kubernetesClient, new BaseConfigurationService());
4343
}
4444

4545
/**
@@ -56,7 +56,8 @@ public Operator(Consumer<ConfigurationServiceOverrider> overrider) {
5656
}
5757

5858
public Operator(KubernetesClient client, Consumer<ConfigurationServiceOverrider> overrider) {
59-
this(client, ConfigurationServiceProvider.overrideCurrent(overrider));
59+
this(client, ConfigurationService
60+
.newOverriddenConfigurationService(new BaseConfigurationService(), overrider));
6061
}
6162

6263
/**
@@ -67,15 +68,19 @@ public Operator(KubernetesClient client, Consumer<ConfigurationServiceOverrider>
6768
* @param configurationService provides configuration
6869
*/
6970
public Operator(KubernetesClient kubernetesClient, ConfigurationService configurationService) {
71+
this.configurationService = configurationService;
72+
final var executorServiceManager = configurationService.getExecutorServiceManager();
73+
controllerManager = new ControllerManager(executorServiceManager);
7074
this.kubernetesClient =
7175
kubernetesClient != null ? kubernetesClient
7276
: new KubernetesClientBuilder()
7377
.withConfig(new ConfigBuilder()
7478
.withMaxConcurrentRequests(DEFAULT_MAX_CONCURRENT_REQUEST).build())
7579
.build();
76-
ConfigurationServiceProvider.set(configurationService);
77-
configurationService.getLeaderElectionConfiguration()
78-
.ifPresent(c -> leaderElectionManager.init(c, this.kubernetesClient));
80+
81+
82+
leaderElectionManager =
83+
new LeaderElectionManager(kubernetesClient, controllerManager, configurationService);
7984
}
8085

8186
/**
@@ -86,8 +91,7 @@ public Operator(KubernetesClient kubernetesClient, ConfigurationService configur
8691
*/
8792
@Deprecated(forRemoval = true)
8893
public void installShutdownHook() {
89-
installShutdownHook(
90-
Duration.ofSeconds(ConfigurationServiceProvider.instance().getTerminationTimeoutSeconds()));
94+
installShutdownHook(Duration.ofSeconds(configurationService.getTerminationTimeoutSeconds()));
9195
}
9296

9397
/**
@@ -123,9 +127,8 @@ public synchronized void start() {
123127
if (started) {
124128
return;
125129
}
126-
ExecutorServiceManager.init();
127130
controllerManager.shouldStart();
128-
final var version = ConfigurationServiceProvider.instance().getVersion();
131+
final var version = configurationService.getVersion();
129132
log.info(
130133
"Operator SDK {} (commit: {}) built on {} starting...",
131134
version.getSdkVersion(),
@@ -149,12 +152,11 @@ public void stop(Duration gracefulShutdownTimeout) throws OperatorException {
149152
if (!started) {
150153
return;
151154
}
152-
final var configurationService = ConfigurationServiceProvider.instance();
153155
log.info(
154156
"Operator SDK {} is shutting down...", configurationService.getVersion().getSdkVersion());
155157
controllerManager.stop();
156158

157-
ExecutorServiceManager.stop(gracefulShutdownTimeout);
159+
configurationService.getExecutorServiceManager().stop(gracefulShutdownTimeout);
158160
leaderElectionManager.stop();
159161
if (configurationService.closeClientOnStop()) {
160162
kubernetesClient.close();
@@ -179,8 +181,7 @@ public void stop() throws OperatorException {
179181
*/
180182
public <P extends HasMetadata> RegisteredController<P> register(Reconciler<P> reconciler)
181183
throws OperatorException {
182-
final var controllerConfiguration =
183-
ConfigurationServiceProvider.instance().getConfigurationFor(reconciler);
184+
final var controllerConfiguration = configurationService.getConfigurationFor(reconciler);
184185
return register(reconciler, controllerConfiguration);
185186
}
186187

@@ -210,7 +211,7 @@ public <P extends HasMetadata> RegisteredController<P> register(Reconciler<P> re
210211
" reconciler named " + ReconcilerUtils.getNameFor(reconciler)
211212
+ " because its configuration cannot be found.\n" +
212213
" Known reconcilers are: "
213-
+ ConfigurationServiceProvider.instance().getKnownReconcilerNames());
214+
+ configurationService.getKnownReconcilerNames());
214215
}
215216

216217
final var controller = new Controller<>(reconciler, configuration, kubernetesClient);
@@ -239,7 +240,7 @@ public <P extends HasMetadata> RegisteredController<P> register(Reconciler<P> re
239240
public <P extends HasMetadata> RegisteredController<P> register(Reconciler<P> reconciler,
240241
Consumer<ControllerConfigurationOverrider<P>> configOverrider) {
241242
final var controllerConfiguration =
242-
ConfigurationServiceProvider.instance().getConfigurationFor(reconciler);
243+
configurationService.getConfigurationFor(reconciler);
243244
var configToOverride = ControllerConfigurationOverrider.override(controllerConfiguration);
244245
configOverrider.accept(configToOverride);
245246
return register(reconciler, configToOverride.build());
@@ -264,4 +265,8 @@ public RuntimeInfo getRuntimeInfo() {
264265
boolean isStarted() {
265266
return started;
266267
}
268+
269+
public ConfigurationService getConfigurationService() {
270+
return configurationService;
271+
}
267272
}

Diff for: operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/BaseConfigurationService.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ protected <P extends HasMetadata> ControllerConfiguration<P> configFor(Reconcile
107107
" annotation for reconciler: " + reconciler);
108108
}
109109
Class<Reconciler<P>> reconcilerClass = (Class<Reconciler<P>>) reconciler.getClass();
110-
final var resourceClass = ConfigurationServiceProvider.instance().getResourceClassResolver()
111-
.getResourceClass(reconcilerClass);
110+
final var resourceClass = getResourceClassResolver().getResourceClass(reconcilerClass);
112111

113112
final var name = ReconcilerUtils.getNameFor(reconciler);
114113
final var generationAware = valueOrDefault(
@@ -152,7 +151,7 @@ protected <P extends HasMetadata> ControllerConfiguration<P> configFor(Reconcile
152151
io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration::labelSelector,
153152
Constants.NO_VALUE_SET),
154153
null,
155-
Utils.instantiate(annotation.itemStore(), ItemStore.class, context));
154+
Utils.instantiate(annotation.itemStore(), ItemStore.class, context), this);
156155

157156
ResourceEventFilter<P> answer = deprecatedEventFilter(annotation);
158157
config.setEventFilter(answer != null ? answer : ResourceEventFilters.passthrough());

0 commit comments

Comments
 (0)