Skip to content

Commit 700878d

Browse files
committed
feat: SSA based dependent resource matching and create/update
1 parent f976c5c commit 700878d

File tree

124 files changed

+2750
-786
lines changed

Some content is hidden

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

124 files changed

+2750
-786
lines changed

caffeine-bounded-cache-support/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<artifactId>java-operator-sdk</artifactId>
77
<groupId>io.javaoperatorsdk</groupId>
8-
<version>4.3.6-SNAPSHOT</version>
8+
<version>4.4.0-SNAPSHOT</version>
99
</parent>
1010
<modelVersion>4.0.0</modelVersion>
1111

cm.yaml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: test1
5+
namespace: default
6+
ownerReferences:
7+
- apiVersion: v1
8+
kind: ConfigMap
9+
name: kube-root-ca.crt
10+
uid: 1ef74cb4-dbbd-45ef-9caf-aa76186594ea
11+
data:
12+
key1: "val1"
13+
# key2: "val2"
14+

cm2.yaml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: test1
5+
namespace: default
6+
data:
7+
key3: "val3"
8+
9+

micrometer-support/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<artifactId>java-operator-sdk</artifactId>
77
<groupId>io.javaoperatorsdk</groupId>
8-
<version>4.3.6-SNAPSHOT</version>
8+
<version>4.4.0-SNAPSHOT</version>
99
</parent>
1010
<modelVersion>4.0.0</modelVersion>
1111

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 {

operator-framework-bom/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>io.javaoperatorsdk</groupId>
77
<artifactId>operator-framework-bom</artifactId>
8-
<version>4.3.6-SNAPSHOT</version>
8+
<version>4.4.0-SNAPSHOT</version>
99
<name>Operator SDK - Bill of Materials</name>
1010
<packaging>pom</packaging>
1111
<description>Java SDK for implementing Kubernetes operators</description>

operator-framework-core/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>io.javaoperatorsdk</groupId>
88
<artifactId>java-operator-sdk</artifactId>
9-
<version>4.3.6-SNAPSHOT</version>
9+
<version>4.4.0-SNAPSHOT</version>
1010
<relativePath>../pom.xml</relativePath>
1111
</parent>
1212

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());

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

+31-23
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77
import org.slf4j.Logger;
88
import org.slf4j.LoggerFactory;
99

10-
import io.fabric8.kubernetes.api.model.authorization.v1.*;
10+
import io.fabric8.kubernetes.api.model.authorization.v1.SelfSubjectRulesReview;
11+
import io.fabric8.kubernetes.api.model.authorization.v1.SelfSubjectRulesReviewSpecBuilder;
1112
import io.fabric8.kubernetes.client.KubernetesClient;
1213
import io.fabric8.kubernetes.client.extended.leaderelection.LeaderCallbacks;
1314
import io.fabric8.kubernetes.client.extended.leaderelection.LeaderElectionConfig;
1415
import io.fabric8.kubernetes.client.extended.leaderelection.LeaderElector;
1516
import io.fabric8.kubernetes.client.extended.leaderelection.LeaderElectorBuilder;
1617
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;
18+
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
1919
import io.javaoperatorsdk.operator.api.config.LeaderElectionConfiguration;
2020

2121
public class LeaderElectionManager {
@@ -24,51 +24,58 @@ public class LeaderElectionManager {
2424

2525
public static final String NO_PERMISSION_TO_LEASE_RESOURCE_MESSAGE =
2626
"No permission to lease resource.";
27+
public static final String UNIVERSAL_VERB = "*";
28+
public static final String COORDINATION_GROUP = "coordination.k8s.io";
29+
public static final String LEASES_RESOURCE = "leases";
2730

2831
private LeaderElector leaderElector = null;
2932
private final ControllerManager controllerManager;
3033
private String identity;
3134
private CompletableFuture<?> leaderElectionFuture;
32-
private KubernetesClient client;
33-
private String leaseName;
35+
private KubernetesClient kubernetesClient;
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;
3845
}
3946

40-
public void init(LeaderElectionConfiguration config, KubernetesClient client) {
41-
this.client = client;
47+
public boolean isLeaderElectionEnabled() {
48+
return configurationService.getLeaderElectionConfiguration().isPresent();
49+
}
50+
51+
private void init(LeaderElectionConfiguration config) {
4252
this.identity = identity(config);
43-
this.leaseName = config.getLeaseName();
4453
leaseNamespace =
4554
config.getLeaseNamespace().orElseGet(
46-
() -> ConfigurationServiceProvider.instance().getClientConfiguration().getNamespace());
55+
() -> configurationService.getClientConfiguration().getNamespace());
4756
if (leaseNamespace == null) {
4857
final var message =
4958
"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(
64+
leaderElector = new LeaderElectorBuilder(
65+
kubernetesClient, configurationService.getExecutorServiceManager().cachingExecutorService())
66+
.withConfig(
67+
new LeaderElectionConfig(
5968
lock,
6069
config.getLeaseDuration(),
6170
config.getRenewDeadline(),
6271
config.getRetryPeriod(),
6372
leaderCallbacks(),
6473
true,
6574
config.getLeaseName()))
66-
.build();
75+
.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
}
@@ -114,12 +122,12 @@ private void checkLeaseAccess() {
114122
var verbs = Arrays.asList("create", "update", "get");
115123
SelfSubjectRulesReview review = new SelfSubjectRulesReview();
116124
review.setSpec(new SelfSubjectRulesReviewSpecBuilder().withNamespace(leaseNamespace).build());
117-
var reviewResult = client.resource(review).create();
125+
var reviewResult = kubernetesClient.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("*"))
128+
.filter(rule -> rule.getApiGroups().contains(COORDINATION_GROUP)
129+
&& rule.getResources().contains(LEASES_RESOURCE)
130+
&& (rule.getVerbs().containsAll(verbs)) || rule.getVerbs().contains(UNIVERSAL_VERB))
123131
.findAny();
124132
if (foundRule.isEmpty()) {
125133
throw new OperatorException(NO_PERMISSION_TO_LEASE_RESOURCE_MESSAGE +

0 commit comments

Comments
 (0)