Update JOSDK to 5.1.0

This also adapts to the breaking changes introduced with JOSDK version 5
[1]:

- Discriminators are obsolete and replaced by generic mechanism
  to identify which resources on the cluster should be associated
  with which dependent resource implementation
- The managed workflow definition is now a separate @Workflow annotation; it is no longer part of @ControllerConfiguration
- InformerConfiguration was renamed to InformerEventSourceConfiguration.
  InformerEventSourceConfiguration doesn’t require EventSourceContext to
  be initialized anymore.
- Server Side Apply (SSA): This was disabled for now, since this
  might require a migration.
- Tests were rewritten to use the new KubernetesMockServer

[1] https://javaoperatorsdk.io/blog/2025/01/06/version-5-released/

Change-Id: I04de0529080855d3748b74a163bab218d9d13102
diff --git a/crd/current/gerritclusters.gerritoperator.google.com-v1.yml b/crd/current/gerritclusters.gerritoperator.google.com-v1.yml
index 1e355b7..a29f059 100644
--- a/crd/current/gerritclusters.gerritoperator.google.com-v1.yml
+++ b/crd/current/gerritclusters.gerritoperator.google.com-v1.yml
@@ -713,6 +713,8 @@
                                 properties:
                                   name:
                                     type: string
+                                  request:
+                                    type: string
                                 type: object
                               type: array
                             limits:
@@ -1480,6 +1482,8 @@
                               properties:
                                 name:
                                   type: string
+                                request:
+                                  type: string
                               type: object
                             type: array
                           limits:
@@ -1947,6 +1951,8 @@
                                         properties:
                                           name:
                                             type: string
+                                          request:
+                                            type: string
                                         type: object
                                       type: array
                                     limits:
@@ -2428,6 +2434,8 @@
                                     properties:
                                       name:
                                         type: string
+                                      request:
+                                        type: string
                                     type: object
                                   type: array
                                 limits:
diff --git a/crd/current/gerritindexers.gerritoperator.google.com-v1.yml b/crd/current/gerritindexers.gerritoperator.google.com-v1.yml
index 8862701..73264f7 100644
--- a/crd/current/gerritindexers.gerritoperator.google.com-v1.yml
+++ b/crd/current/gerritindexers.gerritoperator.google.com-v1.yml
@@ -375,6 +375,8 @@
                       properties:
                         name:
                           type: string
+                        request:
+                          type: string
                       type: object
                     type: array
                   limits:
diff --git a/crd/current/gerritmaintenances.gerritoperator.google.com-v1.yml b/crd/current/gerritmaintenances.gerritoperator.google.com-v1.yml
index a74883c..59a7575 100644
--- a/crd/current/gerritmaintenances.gerritoperator.google.com-v1.yml
+++ b/crd/current/gerritmaintenances.gerritoperator.google.com-v1.yml
@@ -401,6 +401,8 @@
                                 properties:
                                   name:
                                     type: string
+                                  request:
+                                    type: string
                                 type: object
                               type: array
                             limits:
diff --git a/crd/current/gerrits.gerritoperator.google.com-v1.yml b/crd/current/gerrits.gerritoperator.google.com-v1.yml
index 5e22866..b7554c9 100644
--- a/crd/current/gerrits.gerritoperator.google.com-v1.yml
+++ b/crd/current/gerrits.gerritoperator.google.com-v1.yml
@@ -693,6 +693,8 @@
                       properties:
                         name:
                           type: string
+                        request:
+                          type: string
                       type: object
                     type: array
                   limits:
diff --git a/crd/current/gitgcs.gerritoperator.google.com-v1.yml b/crd/current/gitgcs.gerritoperator.google.com-v1.yml
index 038d169..0891f90 100644
--- a/crd/current/gitgcs.gerritoperator.google.com-v1.yml
+++ b/crd/current/gitgcs.gerritoperator.google.com-v1.yml
@@ -366,6 +366,8 @@
                       properties:
                         name:
                           type: string
+                        request:
+                          type: string
                       type: object
                     type: array
                   limits:
diff --git a/crd/current/incomingreplicationtasks.gerritoperator.google.com-v1.yml b/crd/current/incomingreplicationtasks.gerritoperator.google.com-v1.yml
index 3bc86f5..57f8975 100644
--- a/crd/current/incomingreplicationtasks.gerritoperator.google.com-v1.yml
+++ b/crd/current/incomingreplicationtasks.gerritoperator.google.com-v1.yml
@@ -412,6 +412,8 @@
                       properties:
                         name:
                           type: string
+                        request:
+                          type: string
                       type: object
                     type: array
                   limits:
diff --git a/crd/current/receivers.gerritoperator.google.com-v1.yml b/crd/current/receivers.gerritoperator.google.com-v1.yml
index 52fe26e..bb5e1e3 100644
--- a/crd/current/receivers.gerritoperator.google.com-v1.yml
+++ b/crd/current/receivers.gerritoperator.google.com-v1.yml
@@ -538,6 +538,8 @@
                       properties:
                         name:
                           type: string
+                        request:
+                          type: string
                       type: object
                     type: array
                   limits:
diff --git a/helm-charts/gerrit-operator-crds/templates/gerritclusters.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/gerritclusters.gerritoperator.google.com-v1.yml
index ee41302..72a5006 100644
--- a/helm-charts/gerrit-operator-crds/templates/gerritclusters.gerritoperator.google.com-v1.yml
+++ b/helm-charts/gerrit-operator-crds/templates/gerritclusters.gerritoperator.google.com-v1.yml
@@ -713,6 +713,8 @@
                                   properties:
                                     name:
                                       type: string
+                                    request:
+                                      type: string
                                   type: object
                                 type: array
                               limits:
@@ -1480,6 +1482,8 @@
                                 properties:
                                   name:
                                     type: string
+                                  request:
+                                    type: string
                                 type: object
                               type: array
                             limits:
@@ -1947,6 +1951,8 @@
                                           properties:
                                             name:
                                               type: string
+                                            request:
+                                              type: string
                                           type: object
                                         type: array
                                       limits:
@@ -2428,6 +2434,8 @@
                                       properties:
                                         name:
                                           type: string
+                                        request:
+                                          type: string
                                       type: object
                                     type: array
                                   limits:
diff --git a/helm-charts/gerrit-operator-crds/templates/gerritindexers.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/gerritindexers.gerritoperator.google.com-v1.yml
index 965dcbf..62a60ca 100644
--- a/helm-charts/gerrit-operator-crds/templates/gerritindexers.gerritoperator.google.com-v1.yml
+++ b/helm-charts/gerrit-operator-crds/templates/gerritindexers.gerritoperator.google.com-v1.yml
@@ -375,6 +375,8 @@
                         properties:
                           name:
                             type: string
+                          request:
+                            type: string
                         type: object
                       type: array
                     limits:
diff --git a/helm-charts/gerrit-operator-crds/templates/gerritmaintenances.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/gerritmaintenances.gerritoperator.google.com-v1.yml
index 56b2523..1ac5c49 100644
--- a/helm-charts/gerrit-operator-crds/templates/gerritmaintenances.gerritoperator.google.com-v1.yml
+++ b/helm-charts/gerrit-operator-crds/templates/gerritmaintenances.gerritoperator.google.com-v1.yml
@@ -401,6 +401,8 @@
                                   properties:
                                     name:
                                       type: string
+                                    request:
+                                      type: string
                                   type: object
                                 type: array
                               limits:
diff --git a/helm-charts/gerrit-operator-crds/templates/gerrits.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/gerrits.gerritoperator.google.com-v1.yml
index c003990..19100eb 100644
--- a/helm-charts/gerrit-operator-crds/templates/gerrits.gerritoperator.google.com-v1.yml
+++ b/helm-charts/gerrit-operator-crds/templates/gerrits.gerritoperator.google.com-v1.yml
@@ -693,6 +693,8 @@
                         properties:
                           name:
                             type: string
+                          request:
+                            type: string
                         type: object
                       type: array
                     limits:
diff --git a/helm-charts/gerrit-operator-crds/templates/gitgcs.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/gitgcs.gerritoperator.google.com-v1.yml
index 2483cf5..5762728 100644
--- a/helm-charts/gerrit-operator-crds/templates/gitgcs.gerritoperator.google.com-v1.yml
+++ b/helm-charts/gerrit-operator-crds/templates/gitgcs.gerritoperator.google.com-v1.yml
@@ -366,6 +366,8 @@
                         properties:
                           name:
                             type: string
+                          request:
+                            type: string
                         type: object
                       type: array
                     limits:
diff --git a/helm-charts/gerrit-operator-crds/templates/incomingreplicationtasks.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/incomingreplicationtasks.gerritoperator.google.com-v1.yml
index 91ca015..1f2aff0 100644
--- a/helm-charts/gerrit-operator-crds/templates/incomingreplicationtasks.gerritoperator.google.com-v1.yml
+++ b/helm-charts/gerrit-operator-crds/templates/incomingreplicationtasks.gerritoperator.google.com-v1.yml
@@ -412,6 +412,8 @@
                         properties:
                           name:
                             type: string
+                          request:
+                            type: string
                         type: object
                       type: array
                     limits:
diff --git a/helm-charts/gerrit-operator-crds/templates/receivers.gerritoperator.google.com-v1.yml b/helm-charts/gerrit-operator-crds/templates/receivers.gerritoperator.google.com-v1.yml
index f27e3c4..e91e3c4 100644
--- a/helm-charts/gerrit-operator-crds/templates/receivers.gerritoperator.google.com-v1.yml
+++ b/helm-charts/gerrit-operator-crds/templates/receivers.gerritoperator.google.com-v1.yml
@@ -538,6 +538,8 @@
                         properties:
                           name:
                             type: string
+                          request:
+                            type: string
                         type: object
                       type: array
                     limits:
diff --git a/operator/pom.xml b/operator/pom.xml
index 48b1a54..ae73112 100644
--- a/operator/pom.xml
+++ b/operator/pom.xml
@@ -15,12 +15,13 @@
 	<properties>
 		<revision>1.0.0-SNAPSHOT</revision>
 
-		<fabric8.version>6.13.4</fabric8.version>
+		<fabric8.version>7.3.1</fabric8.version>
 		<flogger.version>0.8</flogger.version>
 		<guice.version>7.0.0</guice.version>
-		<javaoperatorsdk.version>4.9.7</javaoperatorsdk.version>
+		<javaoperatorsdk.version>5.1.0</javaoperatorsdk.version>
 		<jetty.version>11.0.25</jetty.version>
 		<log42.version>2.24.3</log42.version>
+		<sundrio.version>0.200.0</sundrio.version>
 		<lombok.version>1.18.38</lombok.version>
 		<maven.compiler.source>17</maven.compiler.source>
 		<maven.compiler.target>17</maven.compiler.target>
@@ -172,6 +173,12 @@
 			<version>${fabric8.version}</version>
 		</dependency>
 		<dependency>
+			<groupId>io.sundr</groupId>
+			<artifactId>builder-annotations</artifactId>
+			<scope>provided</scope>
+			<version>${sundrio.version}</version>
+		</dependency>
+		<dependency>
 			<groupId>org.projectlombok</groupId>
 			<artifactId>lombok</artifactId>
 			<scope>provided</scope>
@@ -231,7 +238,7 @@
 		<dependency>
 			<groupId>org.mockito</groupId>
 			<artifactId>mockito-core</artifactId>
-			<version>5.17.0</version>
+			<version>5.18.0</version>
 			<scope>test</scope>
 		</dependency>
 		<dependency>
@@ -248,7 +255,7 @@
 		<dependency>
 			<groupId>org.junit.jupiter</groupId>
 			<artifactId>junit-jupiter-params</artifactId>
-			<version>5.10.5</version>
+			<version>5.12.0</version>
 			<scope>test</scope>
 		</dependency>
 	</dependencies>
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/network/NetworkMember.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/network/NetworkMember.java
index f1e7ed7..ac39433 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/network/NetworkMember.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/network/NetworkMember.java
@@ -19,7 +19,7 @@
 
 public class NetworkMember {
   private String name;
-  private int httpPort = 8080;
+  private long httpPort = 8080L;
 
   public NetworkMember() {}
 
@@ -36,11 +36,11 @@
     this.name = name;
   }
 
-  public int getHttpPort() {
+  public long getHttpPort() {
     return httpPort;
   }
 
-  public void setHttpPort(int httpPort) {
+  public void setHttpPort(long httpPort) {
     this.httpPort = httpPort;
   }
 
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/network/NetworkMemberWithSsh.java b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/network/NetworkMemberWithSsh.java
index 32f8b31..530ece2 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/network/NetworkMemberWithSsh.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/api/model/network/NetworkMemberWithSsh.java
@@ -18,7 +18,7 @@
 import java.util.Objects;
 
 public class NetworkMemberWithSsh extends NetworkMember {
-  private int sshPort = 29418;
+  private long sshPort = 29418L;
 
   public NetworkMemberWithSsh() {}
 
@@ -27,11 +27,11 @@
     this.sshPort = serviceConfig.getSshPort();
   }
 
-  public int getSshPort() {
+  public long getSshPort() {
     return sshPort;
   }
 
-  public void setSshPort(int sshPort) {
+  public void setSshPort(long sshPort) {
     this.sshPort = sshPort;
   }
 
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritClusterMultisiteReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritClusterMultisiteReconciler.java
index 5bcd914..8f9d297 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritClusterMultisiteReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritClusterMultisiteReconciler.java
@@ -14,70 +14,36 @@
 
 package com.google.gerrit.k8s.operator.cluster;
 
-import static com.google.gerrit.k8s.operator.cluster.GerritClusterMultisiteReconciler.CLUSTER_MANAGED_GERRIT_EVENT_SOURCE;
-import static com.google.gerrit.k8s.operator.cluster.GerritClusterMultisiteReconciler.CLUSTER_MANAGED_GERRIT_NETWORK_EVENT_SOURCE;
-
 import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
 import com.google.gerrit.k8s.operator.api.model.cluster.GerritClusterStatus;
-import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
 import com.google.gerrit.k8s.operator.api.model.gerrit.GerritTemplate;
-import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
 import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedGerrit;
 import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedGerritCondition;
 import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedGerritNetwork;
 import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedGerritNetworkCondition;
 import com.google.inject.Singleton;
-import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
-import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
-import io.javaoperatorsdk.operator.api.reconciler.EventSourceInitializer;
 import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
 import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import io.javaoperatorsdk.operator.api.reconciler.Workflow;
 import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
-import io.javaoperatorsdk.operator.processing.event.source.EventSource;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
 @Singleton
-@ControllerConfiguration(
+@Workflow(
     dependents = {
       @Dependent(
           name = "gerrits",
           type = ClusterManagedGerrit.class,
-          reconcilePrecondition = ClusterManagedGerritCondition.class,
-          useEventSourceWithName = CLUSTER_MANAGED_GERRIT_EVENT_SOURCE),
+          reconcilePrecondition = ClusterManagedGerritCondition.class),
       @Dependent(
           type = ClusterManagedGerritNetwork.class,
-          reconcilePrecondition = ClusterManagedGerritNetworkCondition.class,
-          useEventSourceWithName = CLUSTER_MANAGED_GERRIT_NETWORK_EVENT_SOURCE)
+          reconcilePrecondition = ClusterManagedGerritNetworkCondition.class)
     })
-public class GerritClusterMultisiteReconciler
-    implements Reconciler<GerritCluster>, EventSourceInitializer<GerritCluster> {
-  public static final String CLUSTER_MANAGED_GERRIT_EVENT_SOURCE = "cluster-managed-gerrit";
-
-  public static final String CLUSTER_MANAGED_GERRIT_NETWORK_EVENT_SOURCE =
-      "cluster-managed-gerrit-network";
-
-  @Override
-  public Map<String, EventSource> prepareEventSources(EventSourceContext<GerritCluster> context) {
-    InformerEventSource<Gerrit, GerritCluster> clusterManagedGerritEventSource =
-        new InformerEventSource<>(
-            InformerConfiguration.from(Gerrit.class, context).build(), context);
-
-    InformerEventSource<GerritNetwork, GerritCluster> clusterManagedGerritNetworkEventSource =
-        new InformerEventSource<>(
-            InformerConfiguration.from(GerritNetwork.class, context).build(), context);
-
-    Map<String, EventSource> eventSources = new HashMap<>();
-    eventSources.put(CLUSTER_MANAGED_GERRIT_EVENT_SOURCE, clusterManagedGerritEventSource);
-    eventSources.put(
-        CLUSTER_MANAGED_GERRIT_NETWORK_EVENT_SOURCE, clusterManagedGerritNetworkEventSource);
-    return eventSources;
-  }
+public class GerritClusterMultisiteReconciler implements Reconciler<GerritCluster> {
 
   @Override
   public UpdateControl<GerritCluster> reconcile(
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritClusterReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritClusterReconciler.java
index 6419232..8d759c9 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritClusterReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/GerritClusterReconciler.java
@@ -14,23 +14,10 @@
 
 package com.google.gerrit.k8s.operator.cluster;
 
-import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.CLUSTER_MANAGED_GERRIT_EVENT_SOURCE;
-import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.CLUSTER_MANAGED_GERRIT_MAINTENANCE_EVENT_SOURCE;
-import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.CLUSTER_MANAGED_GERRIT_NETWORK_EVENT_SOURCE;
-import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.CLUSTER_MANAGED_INC_REPL_TASK_EVENT_SOURCE;
-import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.CLUSTER_MANAGED_RECEIVER_EVENT_SOURCE;
-import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.CM_EVENT_SOURCE;
-import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.PVC_EVENT_SOURCE;
-
 import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
 import com.google.gerrit.k8s.operator.api.model.cluster.GerritClusterStatus;
-import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
 import com.google.gerrit.k8s.operator.api.model.gerrit.GerritTemplate;
-import com.google.gerrit.k8s.operator.api.model.maintenance.GerritMaintenance;
-import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
-import com.google.gerrit.k8s.operator.api.model.receiver.Receiver;
 import com.google.gerrit.k8s.operator.api.model.receiver.ReceiverTemplate;
-import com.google.gerrit.k8s.operator.api.model.tasks.incomingrepl.IncomingReplicationTask;
 import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedGerrit;
 import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedGerritCondition;
 import com.google.gerrit.k8s.operator.cluster.dependent.ClusterManagedGerritMaintenance;
@@ -45,117 +32,43 @@
 import com.google.gerrit.k8s.operator.cluster.dependent.SharedPVC;
 import com.google.gerrit.k8s.operator.cluster.dependent.SharedPVCCondition;
 import com.google.inject.Singleton;
-import io.fabric8.kubernetes.api.model.ConfigMap;
-import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
-import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
-import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
-import io.javaoperatorsdk.operator.api.reconciler.EventSourceInitializer;
 import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
 import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import io.javaoperatorsdk.operator.api.reconciler.Workflow;
 import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
-import io.javaoperatorsdk.operator.processing.event.source.EventSource;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
 @Singleton
-@ControllerConfiguration(
+@Workflow(
     dependents = {
       @Dependent(
           name = "shared-pvc",
           type = SharedPVC.class,
-          reconcilePrecondition = SharedPVCCondition.class,
-          useEventSourceWithName = PVC_EVENT_SOURCE),
+          reconcilePrecondition = SharedPVCCondition.class),
       @Dependent(
           type = NfsIdmapdConfigMap.class,
-          reconcilePrecondition = NfsWorkaroundCondition.class,
-          useEventSourceWithName = CM_EVENT_SOURCE),
+          reconcilePrecondition = NfsWorkaroundCondition.class),
       @Dependent(
           name = "gerrits",
           type = ClusterManagedGerrit.class,
-          reconcilePrecondition = ClusterManagedGerritCondition.class,
-          useEventSourceWithName = CLUSTER_MANAGED_GERRIT_EVENT_SOURCE),
+          reconcilePrecondition = ClusterManagedGerritCondition.class),
       @Dependent(
           name = "receiver",
           type = ClusterManagedReceiver.class,
-          reconcilePrecondition = ClusterManagedReceiverCondition.class,
-          useEventSourceWithName = CLUSTER_MANAGED_RECEIVER_EVENT_SOURCE),
+          reconcilePrecondition = ClusterManagedReceiverCondition.class),
       @Dependent(
           type = ClusterManagedGerritNetwork.class,
-          reconcilePrecondition = ClusterManagedGerritNetworkCondition.class,
-          useEventSourceWithName = CLUSTER_MANAGED_GERRIT_NETWORK_EVENT_SOURCE),
-      @Dependent(
-          type = ClusterManagedIncomingReplicationTask.class,
-          useEventSourceWithName = CLUSTER_MANAGED_INC_REPL_TASK_EVENT_SOURCE),
+          reconcilePrecondition = ClusterManagedGerritNetworkCondition.class),
+      @Dependent(type = ClusterManagedIncomingReplicationTask.class),
       @Dependent(
           type = ClusterManagedGerritMaintenance.class,
-          reconcilePrecondition = ClusterManagedGerritMaintenanceCondition.class,
-          useEventSourceWithName = CLUSTER_MANAGED_GERRIT_MAINTENANCE_EVENT_SOURCE),
+          reconcilePrecondition = ClusterManagedGerritMaintenanceCondition.class),
     })
-public class GerritClusterReconciler
-    implements Reconciler<GerritCluster>, EventSourceInitializer<GerritCluster> {
-  public static final String CM_EVENT_SOURCE = "cm-event-source";
-  public static final String PVC_EVENT_SOURCE = "pvc-event-source";
-  public static final String CLUSTER_MANAGED_GERRIT_EVENT_SOURCE = "cluster-managed-gerrit";
-  public static final String CLUSTER_MANAGED_RECEIVER_EVENT_SOURCE = "cluster-managed-receiver";
-  public static final String CLUSTER_MANAGED_GERRIT_NETWORK_EVENT_SOURCE =
-      "cluster-managed-gerrit-network";
-  public static final String CLUSTER_MANAGED_INC_REPL_TASK_EVENT_SOURCE =
-      "cluster-managed-incoming-repl-task";
-  public static final String CLUSTER_MANAGED_GERRIT_MAINTENANCE_EVENT_SOURCE =
-      "cluster-managed-gerrit-maintenance";
-
-  @Override
-  public Map<String, EventSource> prepareEventSources(EventSourceContext<GerritCluster> context) {
-    InformerEventSource<ConfigMap, GerritCluster> cmEventSource =
-        new InformerEventSource<>(
-            InformerConfiguration.from(ConfigMap.class, context).build(), context);
-
-    InformerEventSource<PersistentVolumeClaim, GerritCluster> pvcEventSource =
-        new InformerEventSource<>(
-            InformerConfiguration.from(PersistentVolumeClaim.class, context).build(), context);
-
-    InformerEventSource<Gerrit, GerritCluster> clusterManagedGerritEventSource =
-        new InformerEventSource<>(
-            InformerConfiguration.from(Gerrit.class, context).build(), context);
-
-    InformerEventSource<Receiver, GerritCluster> clusterManagedReceiverEventSource =
-        new InformerEventSource<>(
-            InformerConfiguration.from(Receiver.class, context).build(), context);
-
-    InformerEventSource<GerritNetwork, GerritCluster> clusterManagedGerritNetworkEventSource =
-        new InformerEventSource<>(
-            InformerConfiguration.from(GerritNetwork.class, context).build(), context);
-
-    InformerEventSource<IncomingReplicationTask, GerritCluster>
-        clusterManagedIncomingReplTaskEventSource =
-            new InformerEventSource<>(
-                InformerConfiguration.from(IncomingReplicationTask.class, context).build(),
-                context);
-
-    InformerEventSource<GerritMaintenance, GerritCluster>
-        clusterManagedGerritMaintenanceEventSource =
-            new InformerEventSource<>(
-                InformerConfiguration.from(GerritMaintenance.class, context).build(), context);
-
-    Map<String, EventSource> eventSources = new HashMap<>();
-    eventSources.put(CM_EVENT_SOURCE, cmEventSource);
-    eventSources.put(PVC_EVENT_SOURCE, pvcEventSource);
-    eventSources.put(CLUSTER_MANAGED_GERRIT_EVENT_SOURCE, clusterManagedGerritEventSource);
-    eventSources.put(CLUSTER_MANAGED_RECEIVER_EVENT_SOURCE, clusterManagedReceiverEventSource);
-    eventSources.put(
-        CLUSTER_MANAGED_GERRIT_NETWORK_EVENT_SOURCE, clusterManagedGerritNetworkEventSource);
-    eventSources.put(
-        CLUSTER_MANAGED_INC_REPL_TASK_EVENT_SOURCE, clusterManagedIncomingReplTaskEventSource);
-    eventSources.put(
-        CLUSTER_MANAGED_GERRIT_MAINTENANCE_EVENT_SOURCE,
-        clusterManagedGerritMaintenanceEventSource);
-    return eventSources;
-  }
+public class GerritClusterReconciler implements Reconciler<GerritCluster> {
 
   @Override
   public UpdateControl<GerritCluster> reconcile(
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/NfsIdmapdConfigMap.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/NfsIdmapdConfigMap.java
index 8e63d16..fe0b44d 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/NfsIdmapdConfigMap.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/NfsIdmapdConfigMap.java
@@ -23,7 +23,7 @@
 import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
 import java.util.Map;
 
-@KubernetesDependent(resourceDiscriminator = NfsIdmapdConfigMapDiscriminator.class)
+@KubernetesDependent
 public class NfsIdmapdConfigMap
     extends CRUDReconcileAddKubernetesDependentResource<ConfigMap, GerritCluster> {
   public static final String NFS_IDMAPD_CM_NAME = "nfs-idmapd-config";
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/NfsIdmapdConfigMapDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/NfsIdmapdConfigMapDiscriminator.java
deleted file mode 100644
index 52ca139..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/NfsIdmapdConfigMapDiscriminator.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) 2023 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.cluster.dependent;
-
-import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.CM_EVENT_SOURCE;
-
-import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
-import io.fabric8.kubernetes.api.model.ConfigMap;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class NfsIdmapdConfigMapDiscriminator
-    implements ResourceDiscriminator<ConfigMap, GerritCluster> {
-  @Override
-  public Optional<ConfigMap> distinguish(
-      Class<ConfigMap> resource, GerritCluster primary, Context<GerritCluster> context) {
-    InformerEventSource<ConfigMap, GerritCluster> ies =
-        (InformerEventSource<ConfigMap, GerritCluster>)
-            context
-                .eventSourceRetriever()
-                .getResourceEventSourceFor(ConfigMap.class, CM_EVENT_SOURCE);
-
-    return ies.get(
-        new ResourceID(
-            NfsIdmapdConfigMap.NFS_IDMAPD_CM_NAME, primary.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/SharedPVC.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/SharedPVC.java
index a0cca49..ca869cb 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/SharedPVC.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/SharedPVC.java
@@ -25,7 +25,7 @@
 import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
 import java.util.Map;
 
-@KubernetesDependent(resourceDiscriminator = SharedPVCDiscriminator.class)
+@KubernetesDependent
 public class SharedPVC extends CRUDKubernetesDependentPVCResource<GerritCluster> {
 
   public static final String SHARED_PVC_NAME = "shared-pvc";
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/SharedPVCDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/SharedPVCDiscriminator.java
deleted file mode 100644
index 83d5295..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/cluster/dependent/SharedPVCDiscriminator.java
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) 2022 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.cluster.dependent;
-
-import static com.google.gerrit.k8s.operator.cluster.GerritClusterReconciler.PVC_EVENT_SOURCE;
-
-import com.google.gerrit.k8s.operator.api.model.cluster.GerritCluster;
-import io.fabric8.kubernetes.api.model.PersistentVolumeClaim;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class SharedPVCDiscriminator
-    implements ResourceDiscriminator<PersistentVolumeClaim, GerritCluster> {
-  @Override
-  public Optional<PersistentVolumeClaim> distinguish(
-      Class<PersistentVolumeClaim> resource,
-      GerritCluster primary,
-      Context<GerritCluster> context) {
-    InformerEventSource<PersistentVolumeClaim, GerritCluster> ies =
-        (InformerEventSource<PersistentVolumeClaim, GerritCluster>)
-            context
-                .eventSourceRetriever()
-                .getResourceEventSourceFor(PersistentVolumeClaim.class, PVC_EVENT_SOURCE);
-
-    return ies.get(new ResourceID(SharedPVC.SHARED_PVC_NAME, primary.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/GerritReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/GerritReconciler.java
index abc0d87..4ee4d99 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/GerritReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/GerritReconciler.java
@@ -32,20 +32,21 @@
 import io.fabric8.kubernetes.api.model.Secret;
 import io.fabric8.kubernetes.api.model.Service;
 import io.fabric8.kubernetes.client.KubernetesClient;
-import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
+import io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
-import io.javaoperatorsdk.operator.api.reconciler.EventSourceInitializer;
 import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
 import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import io.javaoperatorsdk.operator.api.reconciler.Workflow;
 import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
 import io.javaoperatorsdk.operator.processing.dependent.workflow.WorkflowReconcileResult;
 import io.javaoperatorsdk.operator.processing.event.ResourceID;
 import io.javaoperatorsdk.operator.processing.event.source.EventSource;
 import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper;
 import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
@@ -53,7 +54,7 @@
 import java.util.stream.Collectors;
 
 @Singleton
-@ControllerConfiguration(
+@Workflow(
     dependents = {
       @Dependent(
           name = "fluentbit-configmap",
@@ -82,7 +83,7 @@
           useEventSourceWithName = GERRIT_SERVICE_EVENT_SOURCE,
           dependsOn = {"gerrit-statefulset"})
     })
-public class GerritReconciler implements Reconciler<Gerrit>, EventSourceInitializer<Gerrit> {
+public class GerritReconciler implements Reconciler<Gerrit> {
   public static final String GERRIT_SECRET_EVENT_SOURCE = "gerrit-secret-event-source";
   public static final String CONFIG_MAP_EVENT_SOURCE = "configmap-event-source";
   public static final String GERRIT_SERVICE_EVENT_SOURCE = "gerrit-service-event-source";
@@ -96,27 +97,34 @@
   }
 
   @Override
-  public Map<String, EventSource> prepareEventSources(EventSourceContext<Gerrit> context) {
-    Map<String, EventSource> eventSources = new HashMap<>();
+  public List<EventSource<?, Gerrit>> prepareEventSources(EventSourceContext<Gerrit> context) {
+    List<EventSource<?, Gerrit>> eventSources = new ArrayList<>();
 
     InformerEventSource<ConfigMap, Gerrit> configmapEventSource =
         new InformerEventSource<>(
-            InformerConfiguration.from(ConfigMap.class, context).build(), context);
-    eventSources.put(CONFIG_MAP_EVENT_SOURCE, configmapEventSource);
+            InformerEventSourceConfiguration.from(ConfigMap.class, Gerrit.class)
+                .withName(CONFIG_MAP_EVENT_SOURCE)
+                .build(),
+            context);
+    eventSources.add(configmapEventSource);
 
     InformerEventSource<Service, Gerrit> gerritServiceEventSource =
         new InformerEventSource<>(
-            InformerConfiguration.from(Service.class, context).build(), context);
-    eventSources.put(GERRIT_SERVICE_EVENT_SOURCE, gerritServiceEventSource);
+            InformerEventSourceConfiguration.from(Service.class, Gerrit.class)
+                .withName(GERRIT_SERVICE_EVENT_SOURCE)
+                .build(),
+            context);
+    eventSources.add(gerritServiceEventSource);
 
     SecondaryToPrimaryMapper<Secret> secretMapper = new SecretToGerritMapper(context);
     InformerEventSource<Secret, Gerrit> moduleMetaDataEventSource =
         new InformerEventSource<>(
-            InformerConfiguration.from(Secret.class, context)
+            InformerEventSourceConfiguration.from(Secret.class, Gerrit.class)
+                .withName(GERRIT_SECRET_EVENT_SOURCE)
                 .withSecondaryToPrimaryMapper(secretMapper)
                 .build(),
             context);
-    eventSources.put(GERRIT_SECRET_EVENT_SOURCE, moduleMetaDataEventSource);
+    eventSources.add(moduleMetaDataEventSource);
     return eventSources;
   }
 
@@ -131,7 +139,7 @@
       status = new GerritStatus();
     }
     Optional<WorkflowReconcileResult> result =
-        context.managedDependentResourceContext().getWorkflowReconcileResult();
+        context.managedWorkflowAndDependentResourceContext().getWorkflowReconcileResult();
     if (result.isPresent()) {
       status.setReady(result.get().allDependentResourcesReady());
     } else {
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMap.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMap.java
index fc46634..43e77bf 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMap.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMap.java
@@ -25,7 +25,7 @@
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.Config;
 
-@KubernetesDependent(resourceDiscriminator = FluentBitConfigMapDiscriminator.class)
+@KubernetesDependent
 public class FluentBitConfigMap extends CRUDKubernetesDependentResource<ConfigMap, Gerrit> {
   private static final String FLUENT_BIT_SERVICE_CONFIG =
       """
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMapDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMapDiscriminator.java
deleted file mode 100644
index 88e8255..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/FluentBitConfigMapDiscriminator.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2024 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.gerrit.dependent;
-
-import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
-import io.fabric8.kubernetes.api.model.ConfigMap;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class FluentBitConfigMapDiscriminator implements ResourceDiscriminator<ConfigMap, Gerrit> {
-  @Override
-  public Optional<ConfigMap> distinguish(
-      Class<ConfigMap> resource, Gerrit primary, Context<Gerrit> context) {
-    InformerEventSource<ConfigMap, Gerrit> ies =
-        (InformerEventSource<ConfigMap, Gerrit>)
-            context.eventSourceRetriever().getResourceEventSourceFor(ConfigMap.class);
-
-    return ies.get(
-        new ResourceID(FluentBitConfigMap.getName(primary), primary.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritConfigMap.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritConfigMap.java
index f7687fe..219bd13 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritConfigMap.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritConfigMap.java
@@ -32,7 +32,7 @@
 import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
 import java.util.Map;
 
-@KubernetesDependent(resourceDiscriminator = GerritConfigMapDiscriminator.class)
+@KubernetesDependent
 public class GerritConfigMap
     extends CRUDReconcileAddKubernetesDependentResource<ConfigMap, Gerrit> {
   private static final String DEFAULT_HEALTHCHECK_CONFIG =
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritConfigMapDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritConfigMapDiscriminator.java
deleted file mode 100644
index 17edc62..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritConfigMapDiscriminator.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2022 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.gerrit.dependent;
-
-import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
-import io.fabric8.kubernetes.api.model.ConfigMap;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class GerritConfigMapDiscriminator implements ResourceDiscriminator<ConfigMap, Gerrit> {
-  @Override
-  public Optional<ConfigMap> distinguish(
-      Class<ConfigMap> resource, Gerrit primary, Context<Gerrit> context) {
-    InformerEventSource<ConfigMap, Gerrit> ies =
-        (InformerEventSource<ConfigMap, Gerrit>)
-            context.eventSourceRetriever().getResourceEventSourceFor(ConfigMap.class);
-
-    return ies.get(
-        new ResourceID(GerritConfigMap.getName(primary), primary.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritHeadlessService.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritHeadlessService.java
index 585f2d0..17b0f20 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritHeadlessService.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritHeadlessService.java
@@ -25,7 +25,7 @@
 import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
 import java.util.concurrent.TimeUnit;
 
-@KubernetesDependent(resourceDiscriminator = GerritHeadlessServiceDiscriminator.class)
+@KubernetesDependent
 public class GerritHeadlessService extends GerritAbstractService {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritHeadlessServiceDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritHeadlessServiceDiscriminator.java
deleted file mode 100644
index 7064f3d..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritHeadlessServiceDiscriminator.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (C) 2024 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.gerrit.dependent;
-
-import static com.google.gerrit.k8s.operator.gerrit.GerritReconciler.GERRIT_SERVICE_EVENT_SOURCE;
-
-import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
-import io.fabric8.kubernetes.api.model.Service;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class GerritHeadlessServiceDiscriminator implements ResourceDiscriminator<Service, Gerrit> {
-  @Override
-  public Optional<Service> distinguish(
-      Class<Service> aClass, Gerrit gerrit, Context<Gerrit> context) {
-    InformerEventSource<Service, Gerrit> ies =
-        (InformerEventSource<Service, Gerrit>)
-            context
-                .eventSourceRetriever()
-                .getResourceEventSourceFor(Service.class, GERRIT_SERVICE_EVENT_SOURCE);
-
-    return ies.get(
-        new ResourceID(
-            new GerritHeadlessService().getName(gerrit), gerrit.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritInitConfigMap.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritInitConfigMap.java
index 2c783bf..e255aaa 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritInitConfigMap.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritInitConfigMap.java
@@ -35,7 +35,7 @@
 import java.util.Locale;
 import java.util.Map;
 
-@KubernetesDependent(resourceDiscriminator = GerritInitConfigMapDiscriminator.class)
+@KubernetesDependent
 public class GerritInitConfigMap
     extends CRUDReconcileAddKubernetesDependentResource<ConfigMap, Gerrit> {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritInitConfigMapDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritInitConfigMapDiscriminator.java
deleted file mode 100644
index e5b2f8e..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritInitConfigMapDiscriminator.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2022 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.gerrit.dependent;
-
-import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
-import io.fabric8.kubernetes.api.model.ConfigMap;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class GerritInitConfigMapDiscriminator implements ResourceDiscriminator<ConfigMap, Gerrit> {
-  @Override
-  public Optional<ConfigMap> distinguish(
-      Class<ConfigMap> resource, Gerrit primary, Context<Gerrit> context) {
-    InformerEventSource<ConfigMap, Gerrit> ies =
-        (InformerEventSource<ConfigMap, Gerrit>)
-            context.eventSourceRetriever().getResourceEventSourceFor(ConfigMap.class);
-
-    return ies.get(
-        new ResourceID(GerritInitConfigMap.getName(primary), primary.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritService.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritService.java
index 25c94bb..80edcf2 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritService.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritService.java
@@ -19,7 +19,7 @@
 import io.fabric8.kubernetes.api.model.ServiceSpecBuilder;
 import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
 
-@KubernetesDependent(resourceDiscriminator = GerritServiceDiscriminator.class)
+@KubernetesDependent
 public class GerritService extends GerritAbstractService {
   private static final String SERVICE_SUFFIX = "-service";
 
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritServiceDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritServiceDiscriminator.java
deleted file mode 100644
index f832835..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritServiceDiscriminator.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2024 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.gerrit.dependent;
-
-import static com.google.gerrit.k8s.operator.gerrit.GerritReconciler.GERRIT_SERVICE_EVENT_SOURCE;
-
-import com.google.gerrit.k8s.operator.api.model.gerrit.Gerrit;
-import io.fabric8.kubernetes.api.model.Service;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class GerritServiceDiscriminator implements ResourceDiscriminator<Service, Gerrit> {
-  @Override
-  public Optional<Service> distinguish(
-      Class<Service> aClass, Gerrit gerrit, Context<Gerrit> context) {
-    InformerEventSource<Service, Gerrit> ies =
-        (InformerEventSource<Service, Gerrit>)
-            context
-                .eventSourceRetriever()
-                .getResourceEventSourceFor(Service.class, GERRIT_SERVICE_EVENT_SOURCE);
-
-    return ies.get(
-        new ResourceID(new GerritService().getName(gerrit), gerrit.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/gitgc/GitGarbageCollectionReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/gitgc/GitGarbageCollectionReconciler.java
index 39182d0..e372493 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/gitgc/GitGarbageCollectionReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/gitgc/GitGarbageCollectionReconciler.java
@@ -23,30 +23,26 @@
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import io.fabric8.kubernetes.client.KubernetesClient;
-import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
+import io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
 import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
-import io.javaoperatorsdk.operator.api.reconciler.ErrorStatusHandler;
 import io.javaoperatorsdk.operator.api.reconciler.ErrorStatusUpdateControl;
 import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
-import io.javaoperatorsdk.operator.api.reconciler.EventSourceInitializer;
+import io.javaoperatorsdk.operator.api.reconciler.EventSourceUtils;
 import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
 import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
 import io.javaoperatorsdk.operator.processing.event.ResourceID;
 import io.javaoperatorsdk.operator.processing.event.source.EventSource;
 import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper;
 import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
+import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import java.util.stream.Collectors;
 
 @Singleton
 @ControllerConfiguration
 @Deprecated
-public class GitGarbageCollectionReconciler
-    implements Reconciler<GitGarbageCollection>,
-        EventSourceInitializer<GitGarbageCollection>,
-        ErrorStatusHandler<GitGarbageCollection> {
+public class GitGarbageCollectionReconciler implements Reconciler<GitGarbageCollection> {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
   private final KubernetesClient client;
 
@@ -59,8 +55,11 @@
   }
 
   @Override
-  public Map<String, EventSource> prepareEventSources(
+  public List<EventSource<?, GitGarbageCollection>> prepareEventSources(
       EventSourceContext<GitGarbageCollection> context) {
+    List<EventSource<?, GitGarbageCollection>> eventSources = new ArrayList<>();
+    eventSources.addAll(EventSourceUtils.dependentEventSources(context, dependentCronJob));
+
     final SecondaryToPrimaryMapper<GitGarbageCollection> specificProjectGitGcMapper =
         (GitGarbageCollection gc) ->
             context
@@ -71,10 +70,12 @@
 
     InformerEventSource<GitGarbageCollection, GitGarbageCollection> gitGcEventSource =
         new InformerEventSource<>(
-            InformerConfiguration.from(GitGarbageCollection.class, context)
+            InformerEventSourceConfiguration.from(
+                    GitGarbageCollection.class, GitGarbageCollection.class)
                 .withSecondaryToPrimaryMapper(specificProjectGitGcMapper)
                 .build(),
             context);
+    eventSources.add(gitGcEventSource);
 
     final SecondaryToPrimaryMapper<GerritCluster> gerritClusterMapper =
         (GerritCluster cluster) ->
@@ -86,13 +87,12 @@
 
     InformerEventSource<GerritCluster, GitGarbageCollection> gerritClusterEventSource =
         new InformerEventSource<>(
-            InformerConfiguration.from(GerritCluster.class, context)
+            InformerEventSourceConfiguration.from(GerritCluster.class, GitGarbageCollection.class)
                 .withSecondaryToPrimaryMapper(gerritClusterMapper)
                 .build(),
             context);
-
-    return EventSourceInitializer.nameEventSources(
-        gitGcEventSource, gerritClusterEventSource, dependentCronJob.initEventSource(context));
+    eventSources.add(gerritClusterEventSource);
+    return eventSources;
   }
 
   @Override
@@ -103,7 +103,7 @@
     }
 
     dependentCronJob.reconcile(gitGc, context);
-    return UpdateControl.updateStatus(updateGitGcStatus(gitGc));
+    return UpdateControl.patchStatus(updateGitGcStatus(gitGc));
   }
 
   private GitGarbageCollection updateGitGcStatus(GitGarbageCollection gitGc) {
@@ -147,6 +147,6 @@
     }
     gitGc.setStatus(status);
 
-    return ErrorStatusUpdateControl.updateStatus(gitGc);
+    return ErrorStatusUpdateControl.patchStatus(gitGc);
   }
 }
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/indexer/GerritIndexerReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/indexer/GerritIndexerReconciler.java
index 3431381..a4dc41b 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/indexer/GerritIndexerReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/indexer/GerritIndexerReconciler.java
@@ -19,13 +19,13 @@
 import com.google.gerrit.k8s.operator.indexer.dependent.GerritIndexerJob;
 import com.google.inject.Singleton;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
 import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import io.javaoperatorsdk.operator.api.reconciler.Workflow;
 import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
 
 @Singleton
-@ControllerConfiguration(
+@Workflow(
     dependents = {
       @Dependent(name = "gerrit-indexer-configmap", type = GerritIndexerConfigMap.class),
       @Dependent(
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/maintenance/GerritMaintenanceReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/maintenance/GerritMaintenanceReconciler.java
index 8b95011..eeb4357 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/maintenance/GerritMaintenanceReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/maintenance/GerritMaintenanceReconciler.java
@@ -18,13 +18,13 @@
 import com.google.gerrit.k8s.operator.maintenance.dependent.GerritMaintenanceCronJobs;
 import com.google.inject.Singleton;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
 import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import io.javaoperatorsdk.operator.api.reconciler.Workflow;
 import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
 
 @Singleton
-@ControllerConfiguration(
+@Workflow(
     dependents = {
       @Dependent(name = "gerrit-maintenance-cronjobs", type = GerritMaintenanceCronJobs.class)
     })
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/GerritAmbassadorReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/GerritAmbassadorReconciler.java
index b67760a..ee0ab23 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/GerritAmbassadorReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/GerritAmbassadorReconciler.java
@@ -41,18 +41,17 @@
 import com.google.gerrit.k8s.operator.network.ambassador.dependent.TLSContextCondition;
 import com.google.inject.Singleton;
 import io.getambassador.v2.Mapping;
-import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
+import io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
-import io.javaoperatorsdk.operator.api.reconciler.EventSourceInitializer;
 import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
 import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import io.javaoperatorsdk.operator.api.reconciler.Workflow;
 import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
 import io.javaoperatorsdk.operator.processing.event.source.EventSource;
 import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Provides an Ambassador-based implementation for GerritNetworkReconciler.
@@ -101,7 +100,7 @@
  * https://gerrit.googlesource.com/plugins/replication/+/refs/heads/master/src/main/resources/Documentation/config.md
  */
 @Singleton
-@ControllerConfiguration(
+@Workflow(
     dependents = {
       @Dependent(
           name = GERRIT_MAPPING,
@@ -144,21 +143,22 @@
           type = GerritClusterHost.class,
           reconcilePrecondition = CreateHostCondition.class),
     })
-public class GerritAmbassadorReconciler
-    implements Reconciler<GerritNetwork>, EventSourceInitializer<GerritNetwork> {
+public class GerritAmbassadorReconciler implements Reconciler<GerritNetwork> {
 
   public static final String MAPPING_EVENT_SOURCE = "mapping-event-source";
 
   // Because we have multiple dependent resources of the same type `Mapping`, we need to specify
   // a named event source.
   @Override
-  public Map<String, EventSource> prepareEventSources(EventSourceContext<GerritNetwork> context) {
+  public List<EventSource<?, GerritNetwork>> prepareEventSources(
+      EventSourceContext<GerritNetwork> context) {
     InformerEventSource<Mapping, GerritNetwork> mappingEventSource =
         new InformerEventSource<>(
-            InformerConfiguration.from(Mapping.class, context).build(), context);
+            InformerEventSourceConfiguration.from(Mapping.class, GerritNetwork.class).build(),
+            context);
 
-    Map<String, EventSource> eventSources = new HashMap<>();
-    eventSources.put(MAPPING_EVENT_SOURCE, mappingEventSource);
+    List<EventSource<?, GerritNetwork>> eventSources = new ArrayList<>();
+    eventSources.add(mappingEventSource);
     return eventSources;
   }
 
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMapping.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMapping.java
index ec4974a..05a6f4f 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMapping.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMapping.java
@@ -21,7 +21,7 @@
 import io.javaoperatorsdk.operator.api.reconciler.Context;
 import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
 
-@KubernetesDependent(resourceDiscriminator = GerritClusterMappingDiscriminator.class)
+@KubernetesDependent
 public class GerritClusterMapping extends AbstractAmbassadorDependentResource<Mapping>
     implements MappingDependentResourceInterface {
 
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingDiscriminator.java
deleted file mode 100644
index 7dfc5c4..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingDiscriminator.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2023 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.network.ambassador.dependent;
-
-import static com.google.gerrit.k8s.operator.network.ambassador.dependent.GerritClusterMapping.GERRIT_MAPPING;
-
-import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
-import io.getambassador.v2.Mapping;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class GerritClusterMappingDiscriminator
-    implements ResourceDiscriminator<Mapping, GerritNetwork> {
-  @Override
-  public Optional<Mapping> distinguish(
-      Class<Mapping> resource, GerritNetwork network, Context<GerritNetwork> context) {
-    InformerEventSource<Mapping, GerritNetwork> ies =
-        (InformerEventSource<Mapping, GerritNetwork>)
-            context.eventSourceRetriever().getResourceEventSourceFor(Mapping.class);
-    return ies.get(new ResourceID(GERRIT_MAPPING, network.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingGETReplica.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingGETReplica.java
index 0698f81..4ebd448 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingGETReplica.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingGETReplica.java
@@ -24,7 +24,7 @@
 import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
 import java.util.HashMap;
 
-@KubernetesDependent(resourceDiscriminator = GerritClusterMappingGETReplicaDiscriminator.class)
+@KubernetesDependent
 public class GerritClusterMappingGETReplica extends AbstractAmbassadorDependentResource<Mapping>
     implements MappingDependentResourceInterface {
 
@@ -53,7 +53,7 @@
             .withNewQueryParameters()
             .withAdditionalProperties(
                 new HashMap<String, Object>(ImmutableMap.of("service", "git-upload-pack")))
-            .endV2QueryParameters()
+            .endQueryParameters()
             .withMethod("GET")
             .withPrefix(INFO_REFS_PATTERN)
             .withPrefixRegex(true)
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingGETReplicaDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingGETReplicaDiscriminator.java
deleted file mode 100644
index 2aa4b37..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingGETReplicaDiscriminator.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2023 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.network.ambassador.dependent;
-
-import static com.google.gerrit.k8s.operator.network.ambassador.dependent.GerritClusterMappingGETReplica.GERRIT_MAPPING_GET_REPLICA;
-
-import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
-import io.getambassador.v2.Mapping;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class GerritClusterMappingGETReplicaDiscriminator
-    implements ResourceDiscriminator<Mapping, GerritNetwork> {
-  @Override
-  public Optional<Mapping> distinguish(
-      Class<Mapping> resource, GerritNetwork network, Context<GerritNetwork> context) {
-    InformerEventSource<Mapping, GerritNetwork> ies =
-        (InformerEventSource<Mapping, GerritNetwork>)
-            context.eventSourceRetriever().getResourceEventSourceFor(Mapping.class);
-    return ies.get(
-        new ResourceID(GERRIT_MAPPING_GET_REPLICA, network.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPOSTReplica.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPOSTReplica.java
index eea964d..8fba245 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPOSTReplica.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPOSTReplica.java
@@ -22,7 +22,7 @@
 import io.javaoperatorsdk.operator.api.reconciler.Context;
 import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
 
-@KubernetesDependent(resourceDiscriminator = GerritClusterMappingPOSTReplicaDiscriminator.class)
+@KubernetesDependent
 public class GerritClusterMappingPOSTReplica extends AbstractAmbassadorDependentResource<Mapping>
     implements MappingDependentResourceInterface {
 
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPOSTReplicaDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPOSTReplicaDiscriminator.java
deleted file mode 100644
index bb09abd..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPOSTReplicaDiscriminator.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2023 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.network.ambassador.dependent;
-
-import static com.google.gerrit.k8s.operator.network.ambassador.dependent.GerritClusterMappingPOSTReplica.GERRIT_MAPPING_POST_REPLICA;
-
-import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
-import io.getambassador.v2.Mapping;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class GerritClusterMappingPOSTReplicaDiscriminator
-    implements ResourceDiscriminator<Mapping, GerritNetwork> {
-  @Override
-  public Optional<Mapping> distinguish(
-      Class<Mapping> resource, GerritNetwork network, Context<GerritNetwork> context) {
-    InformerEventSource<Mapping, GerritNetwork> ies =
-        (InformerEventSource<Mapping, GerritNetwork>)
-            context.eventSourceRetriever().getResourceEventSourceFor(Mapping.class);
-    return ies.get(
-        new ResourceID(GERRIT_MAPPING_POST_REPLICA, network.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPrimary.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPrimary.java
index f17ce20..816f654 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPrimary.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPrimary.java
@@ -20,7 +20,7 @@
 import io.javaoperatorsdk.operator.api.reconciler.Context;
 import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
 
-@KubernetesDependent(resourceDiscriminator = GerritClusterMappingPrimaryDiscriminator.class)
+@KubernetesDependent
 public class GerritClusterMappingPrimary extends AbstractAmbassadorDependentResource<Mapping>
     implements MappingDependentResourceInterface {
 
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPrimaryDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPrimaryDiscriminator.java
deleted file mode 100644
index 6dd38d0..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingPrimaryDiscriminator.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2023 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.network.ambassador.dependent;
-
-import static com.google.gerrit.k8s.operator.network.ambassador.dependent.GerritClusterMappingPrimary.GERRIT_MAPPING_PRIMARY;
-
-import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
-import io.getambassador.v2.Mapping;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class GerritClusterMappingPrimaryDiscriminator
-    implements ResourceDiscriminator<Mapping, GerritNetwork> {
-  @Override
-  public Optional<Mapping> distinguish(
-      Class<Mapping> resource, GerritNetwork network, Context<GerritNetwork> context) {
-    InformerEventSource<Mapping, GerritNetwork> ies =
-        (InformerEventSource<Mapping, GerritNetwork>)
-            context.eventSourceRetriever().getResourceEventSourceFor(Mapping.class);
-    return ies.get(new ResourceID(GERRIT_MAPPING_PRIMARY, network.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiver.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiver.java
index ac56422..124f38c 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiver.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiver.java
@@ -24,7 +24,7 @@
 import io.javaoperatorsdk.operator.api.reconciler.Context;
 import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
 
-@KubernetesDependent(resourceDiscriminator = GerritClusterMappingReceiverDiscriminator.class)
+@KubernetesDependent
 public class GerritClusterMappingReceiver extends AbstractAmbassadorDependentResource<Mapping>
     implements MappingDependentResourceInterface {
 
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiverDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiverDiscriminator.java
deleted file mode 100644
index d59fadb..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiverDiscriminator.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2023 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.network.ambassador.dependent;
-
-import static com.google.gerrit.k8s.operator.network.ambassador.dependent.GerritClusterMappingReceiver.GERRIT_MAPPING_RECEIVER;
-
-import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
-import io.getambassador.v2.Mapping;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class GerritClusterMappingReceiverDiscriminator
-    implements ResourceDiscriminator<Mapping, GerritNetwork> {
-  @Override
-  public Optional<Mapping> distinguish(
-      Class<Mapping> resource, GerritNetwork network, Context<GerritNetwork> context) {
-    InformerEventSource<Mapping, GerritNetwork> ies =
-        (InformerEventSource<Mapping, GerritNetwork>)
-            context.eventSourceRetriever().getResourceEventSourceFor(Mapping.class);
-    return ies.get(new ResourceID(GERRIT_MAPPING_RECEIVER, network.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiverGET.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiverGET.java
index da3815c..3675af8 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiverGET.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiverGET.java
@@ -25,7 +25,7 @@
 import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
 import java.util.HashMap;
 
-@KubernetesDependent(resourceDiscriminator = GerritClusterMappingReceiverGETDiscriminator.class)
+@KubernetesDependent
 public class GerritClusterMappingReceiverGET extends AbstractAmbassadorDependentResource<Mapping>
     implements MappingDependentResourceInterface {
 
@@ -53,7 +53,7 @@
             .withNewQueryParameters()
             .withAdditionalProperties(
                 new HashMap<String, Object>(ImmutableMap.of("service", "git-receive-pack")))
-            .endV2QueryParameters()
+            .endQueryParameters()
             .withMethod("GET")
             .withPrefix(INFO_REFS_PATTERN)
             .withPrefixRegex(true)
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiverGETDiscriminator.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiverGETDiscriminator.java
deleted file mode 100644
index 3128be9..0000000
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ambassador/dependent/GerritClusterMappingReceiverGETDiscriminator.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2023 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.k8s.operator.network.ambassador.dependent;
-
-import static com.google.gerrit.k8s.operator.network.ambassador.dependent.GerritClusterMappingReceiverGET.GERRIT_MAPPING_RECEIVER_GET;
-
-import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
-import io.getambassador.v2.Mapping;
-import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ResourceDiscriminator;
-import io.javaoperatorsdk.operator.processing.event.ResourceID;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.Optional;
-
-public class GerritClusterMappingReceiverGETDiscriminator
-    implements ResourceDiscriminator<Mapping, GerritNetwork> {
-  @Override
-  public Optional<Mapping> distinguish(
-      Class<Mapping> resource, GerritNetwork network, Context<GerritNetwork> context) {
-    InformerEventSource<Mapping, GerritNetwork> ies =
-        (InformerEventSource<Mapping, GerritNetwork>)
-            context.eventSourceRetriever().getResourceEventSourceFor(Mapping.class);
-    return ies.get(
-        new ResourceID(GERRIT_MAPPING_RECEIVER_GET, network.getMetadata().getNamespace()));
-  }
-}
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ingress/GerritIngressReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ingress/GerritIngressReconciler.java
index 48ec5fd..afe71e8 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/ingress/GerritIngressReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/ingress/GerritIngressReconciler.java
@@ -19,13 +19,13 @@
 import com.google.gerrit.k8s.operator.network.ingress.dependent.GerritClusterIngress;
 import com.google.inject.Singleton;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
 import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import io.javaoperatorsdk.operator.api.reconciler.Workflow;
 import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
 
 @Singleton
-@ControllerConfiguration(
+@Workflow(
     dependents = {
       @Dependent(
           name = "gerrit-ingress",
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/GerritIstioReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/GerritIstioReconciler.java
index 9d0a509..a45aa71 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/GerritIstioReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/GerritIstioReconciler.java
@@ -14,10 +14,6 @@
 
 package com.google.gerrit.k8s.operator.network.istio;
 
-import static com.google.gerrit.k8s.operator.network.istio.GerritIstioReconciler.ISTIO_DESTINATION_RULE_EVENT_SOURCE;
-import static com.google.gerrit.k8s.operator.network.istio.GerritIstioReconciler.ISTIO_SERVICE_ENTRIES_EVENT_SOURCE;
-import static com.google.gerrit.k8s.operator.network.istio.GerritIstioReconciler.ISTIO_VIRTUAL_SERVICE_EVENT_SOURCE;
-
 import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
 import com.google.gerrit.k8s.operator.network.GerritClusterIngressCondition;
 import com.google.gerrit.k8s.operator.network.istio.dependent.GerritClusterIstioGateway;
@@ -25,35 +21,23 @@
 import com.google.gerrit.k8s.operator.network.istio.dependent.GerritIstioServiceEntries;
 import com.google.gerrit.k8s.operator.network.istio.dependent.GerritIstioVirtualService;
 import com.google.inject.Singleton;
-import io.fabric8.istio.api.networking.v1beta1.DestinationRule;
-import io.fabric8.istio.api.networking.v1beta1.ServiceEntry;
-import io.fabric8.istio.api.networking.v1beta1.VirtualService;
-import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
-import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
-import io.javaoperatorsdk.operator.api.reconciler.EventSourceInitializer;
 import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
 import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import io.javaoperatorsdk.operator.api.reconciler.Workflow;
 import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
-import io.javaoperatorsdk.operator.processing.event.source.EventSource;
-import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.HashMap;
-import java.util.Map;
 
 @Singleton
-@ControllerConfiguration(
+@Workflow(
     dependents = {
       @Dependent(
           name = "gerrit-destination-rules",
           type = GerritIstioDestinationRule.class,
-          reconcilePrecondition = GerritClusterIngressCondition.class,
-          useEventSourceWithName = ISTIO_DESTINATION_RULE_EVENT_SOURCE),
+          reconcilePrecondition = GerritClusterIngressCondition.class),
       @Dependent(
           name = "gerrit-service-entries",
           type = GerritIstioServiceEntries.class,
-          reconcilePrecondition = GerritClusterIngressCondition.class,
-          useEventSourceWithName = ISTIO_SERVICE_ENTRIES_EVENT_SOURCE),
+          reconcilePrecondition = GerritClusterIngressCondition.class),
       @Dependent(
           name = "gerrit-istio-gateway",
           type = GerritClusterIstioGateway.class,
@@ -62,38 +46,9 @@
           name = "gerrit-istio-virtual-service",
           type = GerritIstioVirtualService.class,
           reconcilePrecondition = GerritClusterIngressCondition.class,
-          dependsOn = {"gerrit-istio-gateway"},
-          useEventSourceWithName = ISTIO_VIRTUAL_SERVICE_EVENT_SOURCE)
+          dependsOn = {"gerrit-istio-gateway"})
     })
-public class GerritIstioReconciler
-    implements Reconciler<GerritNetwork>, EventSourceInitializer<GerritNetwork> {
-  public static final String ISTIO_DESTINATION_RULE_EVENT_SOURCE =
-      "gerrit-cluster-istio-destination-rule";
-  public static final String ISTIO_SERVICE_ENTRIES_EVENT_SOURCE =
-      "gerrit-cluster-istio-service-entries";
-  public static final String ISTIO_VIRTUAL_SERVICE_EVENT_SOURCE =
-      "gerrit-cluster-istio-virtual-service";
-
-  @Override
-  public Map<String, EventSource> prepareEventSources(EventSourceContext<GerritNetwork> context) {
-    InformerEventSource<DestinationRule, GerritNetwork> gerritIstioDestinationRuleEventSource =
-        new InformerEventSource<>(
-            InformerConfiguration.from(DestinationRule.class, context).build(), context);
-
-    InformerEventSource<ServiceEntry, GerritNetwork> gerritIstioServiceEntriesEventSource =
-        new InformerEventSource<>(
-            InformerConfiguration.from(ServiceEntry.class, context).build(), context);
-
-    InformerEventSource<VirtualService, GerritNetwork> virtualServiceEventSource =
-        new InformerEventSource<>(
-            InformerConfiguration.from(VirtualService.class, context).build(), context);
-
-    Map<String, EventSource> eventSources = new HashMap<>();
-    eventSources.put(ISTIO_DESTINATION_RULE_EVENT_SOURCE, gerritIstioDestinationRuleEventSource);
-    eventSources.put(ISTIO_SERVICE_ENTRIES_EVENT_SOURCE, gerritIstioServiceEntriesEventSource);
-    eventSources.put(ISTIO_VIRTUAL_SERVICE_EVENT_SOURCE, virtualServiceEventSource);
-    return eventSources;
-  }
+public class GerritIstioReconciler implements Reconciler<GerritNetwork> {
 
   @Override
   public UpdateControl<GerritNetwork> reconcile(
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritClusterIstioGateway.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritClusterIstioGateway.java
index e4cc3d7..3130ff0 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritClusterIstioGateway.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritClusterIstioGateway.java
@@ -17,11 +17,11 @@
 import com.google.gerrit.k8s.operator.api.model.network.GerritNetwork;
 import com.google.gerrit.k8s.operator.cluster.GerritClusterLabelFactory;
 import com.google.gerrit.k8s.operator.util.CRUDReconcileAddKubernetesDependentResource;
+import io.fabric8.istio.api.api.networking.v1alpha3.Server;
+import io.fabric8.istio.api.api.networking.v1alpha3.ServerBuilder;
+import io.fabric8.istio.api.api.networking.v1alpha3.ServerTLSSettingsTLSmode;
 import io.fabric8.istio.api.networking.v1beta1.Gateway;
 import io.fabric8.istio.api.networking.v1beta1.GatewayBuilder;
-import io.fabric8.istio.api.networking.v1beta1.Server;
-import io.fabric8.istio.api.networking.v1beta1.ServerBuilder;
-import io.fabric8.istio.api.networking.v1beta1.ServerTLSSettingsTLSmode;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
 import java.util.ArrayList;
 import java.util.List;
@@ -59,7 +59,7 @@
         new ServerBuilder()
             .withNewPort()
             .withName("http")
-            .withNumber(80)
+            .withNumber(80L)
             .withProtocol("HTTP")
             .endPort()
             .withHosts(gerritClusterHost)
@@ -73,7 +73,7 @@
           new ServerBuilder()
               .withNewPort()
               .withName("https")
-              .withNumber(443)
+              .withNumber(443L)
               .withProtocol("HTTPS")
               .endPort()
               .withHosts(gerritClusterHost)
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioDestinationRule.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioDestinationRule.java
index 4158d79..b875b8e 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioDestinationRule.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioDestinationRule.java
@@ -19,11 +19,11 @@
 import com.google.gerrit.k8s.operator.cluster.GerritClusterLabelFactory;
 import com.google.gerrit.k8s.operator.gerrit.dependent.GerritService;
 import com.google.gerrit.k8s.operator.util.CRUDReconcileAddKubernetesDependentResource;
+import io.fabric8.istio.api.api.networking.v1alpha3.LoadBalancerSettingsSimpleLB;
+import io.fabric8.istio.api.api.networking.v1alpha3.TrafficPolicy;
+import io.fabric8.istio.api.api.networking.v1alpha3.TrafficPolicyBuilder;
 import io.fabric8.istio.api.networking.v1beta1.DestinationRule;
 import io.fabric8.istio.api.networking.v1beta1.DestinationRuleBuilder;
-import io.fabric8.istio.api.networking.v1beta1.LoadBalancerSettingsSimpleLB;
-import io.fabric8.istio.api.networking.v1beta1.TrafficPolicy;
-import io.fabric8.istio.api.networking.v1beta1.TrafficPolicyBuilder;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
 import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
 import io.javaoperatorsdk.operator.processing.dependent.BulkDependentResource;
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioServiceEntries.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioServiceEntries.java
index aa57362..3795472 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioServiceEntries.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioServiceEntries.java
@@ -25,11 +25,11 @@
 import com.google.gerrit.k8s.operator.gerrit.dependent.GerritService;
 import com.google.gerrit.k8s.operator.gerrit.dependent.GerritStatefulSet;
 import com.google.gerrit.k8s.operator.util.CRUDReconcileAddKubernetesDependentResource;
+import io.fabric8.istio.api.api.networking.v1alpha3.ServiceEntryLocation;
+import io.fabric8.istio.api.api.networking.v1alpha3.ServiceEntryResolution;
+import io.fabric8.istio.api.api.networking.v1alpha3.ServicePortBuilder;
 import io.fabric8.istio.api.networking.v1beta1.ServiceEntry;
 import io.fabric8.istio.api.networking.v1beta1.ServiceEntryBuilder;
-import io.fabric8.istio.api.networking.v1beta1.ServiceEntryLocation;
-import io.fabric8.istio.api.networking.v1beta1.ServiceEntryResolution;
-import io.fabric8.istio.api.networking.v1beta1.ServicePortBuilder;
 import io.fabric8.kubernetes.api.model.apps.StatefulSet;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
 import io.javaoperatorsdk.operator.api.reconciler.dependent.Deleter;
@@ -66,17 +66,17 @@
             List.of(
                 new ServicePortBuilder()
                     .withName("ssh-primary")
-                    .withNumber(SSH_PORT)
+                    .withNumber(Integer.toUnsignedLong(SSH_PORT))
                     .withProtocol("TCP")
                     .build(),
                 new ServicePortBuilder()
                     .withName("http")
-                    .withNumber(HTTP_PORT)
+                    .withNumber(Integer.toUnsignedLong(HTTP_PORT))
                     .withProtocol("HTTP")
                     .build(),
                 new ServicePortBuilder()
                     .withName("jgroups")
-                    .withNumber(JGROUPS_PORT)
+                    .withNumber(Integer.toUnsignedLong(JGROUPS_PORT))
                     .withProtocol("TCP")
                     .build()))
         .endSpec()
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioVirtualService.java b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioVirtualService.java
index dff1a91..554c8ec 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioVirtualService.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/network/istio/dependent/GerritIstioVirtualService.java
@@ -29,18 +29,18 @@
 import com.google.gerrit.k8s.operator.gerrit.dependent.GerritService;
 import com.google.gerrit.k8s.operator.receiver.dependent.ReceiverService;
 import com.google.gerrit.k8s.operator.util.CRUDReconcileAddKubernetesDependentResource;
-import io.fabric8.istio.api.networking.v1beta1.HTTPMatchRequest;
-import io.fabric8.istio.api.networking.v1beta1.HTTPMatchRequestBuilder;
-import io.fabric8.istio.api.networking.v1beta1.HTTPRoute;
-import io.fabric8.istio.api.networking.v1beta1.HTTPRouteBuilder;
-import io.fabric8.istio.api.networking.v1beta1.HTTPRouteDestination;
-import io.fabric8.istio.api.networking.v1beta1.HTTPRouteDestinationBuilder;
-import io.fabric8.istio.api.networking.v1beta1.L4MatchAttributesBuilder;
-import io.fabric8.istio.api.networking.v1beta1.RouteDestination;
-import io.fabric8.istio.api.networking.v1beta1.RouteDestinationBuilder;
-import io.fabric8.istio.api.networking.v1beta1.StringMatchBuilder;
-import io.fabric8.istio.api.networking.v1beta1.TCPRoute;
-import io.fabric8.istio.api.networking.v1beta1.TCPRouteBuilder;
+import io.fabric8.istio.api.api.networking.v1alpha3.HTTPMatchRequest;
+import io.fabric8.istio.api.api.networking.v1alpha3.HTTPMatchRequestBuilder;
+import io.fabric8.istio.api.api.networking.v1alpha3.HTTPRoute;
+import io.fabric8.istio.api.api.networking.v1alpha3.HTTPRouteBuilder;
+import io.fabric8.istio.api.api.networking.v1alpha3.HTTPRouteDestination;
+import io.fabric8.istio.api.api.networking.v1alpha3.HTTPRouteDestinationBuilder;
+import io.fabric8.istio.api.api.networking.v1alpha3.L4MatchAttributesBuilder;
+import io.fabric8.istio.api.api.networking.v1alpha3.RouteDestination;
+import io.fabric8.istio.api.api.networking.v1alpha3.RouteDestinationBuilder;
+import io.fabric8.istio.api.api.networking.v1alpha3.StringMatchBuilder;
+import io.fabric8.istio.api.api.networking.v1alpha3.TCPRoute;
+import io.fabric8.istio.api.api.networking.v1alpha3.TCPRouteBuilder;
 import io.fabric8.istio.api.networking.v1beta1.VirtualService;
 import io.fabric8.istio.api.networking.v1beta1.VirtualServiceBuilder;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/receiver/ReceiverReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/receiver/ReceiverReconciler.java
index 25502bd..e15f542 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/receiver/ReceiverReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/receiver/ReceiverReconciler.java
@@ -23,24 +23,23 @@
 import com.google.inject.Singleton;
 import io.fabric8.kubernetes.api.model.Secret;
 import io.fabric8.kubernetes.client.KubernetesClient;
-import io.javaoperatorsdk.operator.api.config.informer.InformerConfiguration;
+import io.javaoperatorsdk.operator.api.config.informer.InformerEventSourceConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.EventSourceContext;
-import io.javaoperatorsdk.operator.api.reconciler.EventSourceInitializer;
 import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
 import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import io.javaoperatorsdk.operator.api.reconciler.Workflow;
 import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
 import io.javaoperatorsdk.operator.processing.event.ResourceID;
 import io.javaoperatorsdk.operator.processing.event.source.EventSource;
 import io.javaoperatorsdk.operator.processing.event.source.SecondaryToPrimaryMapper;
 import io.javaoperatorsdk.operator.processing.event.source.informer.InformerEventSource;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.stream.Collectors;
 
 @Singleton
-@ControllerConfiguration(
+@Workflow(
     dependents = {
       @Dependent(name = "receiver-deployment", type = ReceiverDeployment.class),
       @Dependent(
@@ -48,7 +47,7 @@
           type = ReceiverService.class,
           dependsOn = {"receiver-deployment"})
     })
-public class ReceiverReconciler implements Reconciler<Receiver>, EventSourceInitializer<Receiver> {
+public class ReceiverReconciler implements Reconciler<Receiver> {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
   private static final String SECRET_EVENT_SOURCE_NAME = "secret-event-source";
   private final KubernetesClient client;
@@ -59,7 +58,8 @@
   }
 
   @Override
-  public Map<String, EventSource> prepareEventSources(EventSourceContext<Receiver> context) {
+  public List<EventSource<?, Receiver>> prepareEventSources(EventSourceContext<Receiver> context) {
+    List<EventSource<?, Receiver>> eventSources = new ArrayList<>();
     final SecondaryToPrimaryMapper<Secret> secretMapper =
         (Secret secret) ->
             context
@@ -75,13 +75,12 @@
 
     InformerEventSource<Secret, Receiver> secretEventSource =
         new InformerEventSource<>(
-            InformerConfiguration.from(Secret.class, context)
+            InformerEventSourceConfiguration.from(Secret.class, Receiver.class)
                 .withSecondaryToPrimaryMapper(secretMapper)
                 .build(),
             context);
 
-    Map<String, EventSource> eventSources = new HashMap<>();
-    eventSources.put(SECRET_EVENT_SOURCE_NAME, secretEventSource);
+    eventSources.add(secretEventSource);
     return eventSources;
   }
 
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/IncomingReplicationTaskReconciler.java b/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/IncomingReplicationTaskReconciler.java
index 48d7abb..8fc92b1 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/IncomingReplicationTaskReconciler.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/IncomingReplicationTaskReconciler.java
@@ -19,13 +19,13 @@
 import com.google.gerrit.k8s.operator.tasks.incomingrepl.dependent.IncomingReplicationTaskCronJob;
 import com.google.inject.Singleton;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
-import io.javaoperatorsdk.operator.api.reconciler.ControllerConfiguration;
 import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
 import io.javaoperatorsdk.operator.api.reconciler.UpdateControl;
+import io.javaoperatorsdk.operator.api.reconciler.Workflow;
 import io.javaoperatorsdk.operator.api.reconciler.dependent.Dependent;
 
 @Singleton
-@ControllerConfiguration(
+@Workflow(
     dependents = {
       @Dependent(
           name = "incoming-repl-task-configmap",
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/util/CRUDReconcileAddKubernetesDependentResource.java b/operator/src/main/java/com/google/gerrit/k8s/operator/util/CRUDReconcileAddKubernetesDependentResource.java
index 6e1cd79..aec8a0f 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/util/CRUDReconcileAddKubernetesDependentResource.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/util/CRUDReconcileAddKubernetesDependentResource.java
@@ -35,7 +35,6 @@
 
   @Override
   public Result<R> match(R actualResource, R desired, P primary, Context<P> context) {
-    return GenericKubernetesResourceMatcher.match(
-        desired, actualResource, false, false, true, context);
+    return GenericKubernetesResourceMatcher.match(desired, actualResource, false, true, context);
   }
 }
diff --git a/operator/src/main/java/com/google/gerrit/k8s/operator/util/KubernetesDependentCustomResource.java b/operator/src/main/java/com/google/gerrit/k8s/operator/util/KubernetesDependentCustomResource.java
index 9b2f516..946e9ce 100644
--- a/operator/src/main/java/com/google/gerrit/k8s/operator/util/KubernetesDependentCustomResource.java
+++ b/operator/src/main/java/com/google/gerrit/k8s/operator/util/KubernetesDependentCustomResource.java
@@ -39,8 +39,7 @@
 
   @Override
   public Result<R> match(R actualResource, R desired, P primary, Context<P> context) {
-    return GenericKubernetesResourceMatcher.match(
-        desired, actualResource, true, false, true, context);
+    return GenericKubernetesResourceMatcher.match(desired, actualResource, false, true, context);
   }
 
   @Override
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritTest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritTest.java
index 86179a7..6fa4f27 100644
--- a/operator/src/test/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritTest.java
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/gerrit/dependent/GerritTest.java
@@ -21,7 +21,7 @@
 import io.fabric8.kubernetes.api.model.ConfigMap;
 import io.fabric8.kubernetes.api.model.Service;
 import io.fabric8.kubernetes.api.model.apps.StatefulSet;
-import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
+import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
 import io.javaoperatorsdk.operator.ReconcilerUtils;
 import io.javaoperatorsdk.operator.api.config.BaseConfigurationService;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
@@ -33,7 +33,6 @@
 import java.util.Map;
 import java.util.stream.Stream;
 import org.junit.Rule;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.TestInstance;
 import org.junit.jupiter.api.TestInstance.Lifecycle;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -42,12 +41,7 @@
 
 @TestInstance(Lifecycle.PER_CLASS)
 public class GerritTest {
-  @Rule public KubernetesServer kubernetesServer = new KubernetesServer();
-
-  @BeforeAll
-  public void setup() throws Exception {
-    kubernetesServer.before();
-  }
+  @Rule public KubernetesMockServer kubernetesServer = new KubernetesMockServer();
 
   @ParameterizedTest
   @MethodSource("provideYamlManifests")
@@ -60,7 +54,7 @@
       String expectedHeadlessServiceOutputFile) {
     Gerrit gerrit = ReconcilerUtils.loadYaml(Gerrit.class, this.getClass(), inputFile);
     Context<Gerrit> context =
-        getContext(new GerritReconciler(kubernetesServer.getClient()), gerrit);
+        getContext(new GerritReconciler(kubernetesServer.createClient()), gerrit);
 
     ConfigMap expectedGerritCm =
         ReconcilerUtils.loadYaml(
@@ -106,7 +100,7 @@
         new Controller<Gerrit>(
             reconciler,
             new BaseConfigurationService().getConfigurationFor(reconciler),
-            kubernetesServer.getClient());
+            kubernetesServer.createClient());
 
     return new DefaultContext<Gerrit>(
         new GenericRetryExecution(new GenericRetry()), controller, primary);
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/gitgc/dependent/GitGarbageCollectionTest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/gitgc/dependent/GitGarbageCollectionTest.java
index f175256..bafcb24 100644
--- a/operator/src/test/java/com/google/gerrit/k8s/operator/gitgc/dependent/GitGarbageCollectionTest.java
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/gitgc/dependent/GitGarbageCollectionTest.java
@@ -21,7 +21,7 @@
 import com.google.gerrit.k8s.operator.gitgc.GitGarbageCollectionReconciler;
 import io.fabric8.kubernetes.api.model.HasMetadata;
 import io.fabric8.kubernetes.api.model.batch.v1.CronJob;
-import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
+import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
 import io.javaoperatorsdk.operator.ReconcilerUtils;
 import io.javaoperatorsdk.operator.api.config.BaseConfigurationService;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
@@ -33,7 +33,6 @@
 import java.net.HttpURLConnection;
 import java.util.stream.Stream;
 import org.junit.Rule;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.TestInstance;
 import org.junit.jupiter.api.TestInstance.Lifecycle;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -47,12 +46,7 @@
           "/apis/%s/namespaces/gerrit/%s/gerrit",
           HasMetadata.getApiVersion(GerritCluster.class),
           HasMetadata.getPlural(GerritCluster.class));
-  @Rule public KubernetesServer kubernetesServer = new KubernetesServer();
-
-  @BeforeAll
-  public void setup() throws Exception {
-    kubernetesServer.before();
-  }
+  @Rule public KubernetesMockServer kubernetesServer = new KubernetesMockServer();
 
   @ParameterizedTest
   @MethodSource("provideYamlManifests")
@@ -72,7 +66,7 @@
         .once();
 
     Context<GitGarbageCollection> context =
-        getContext(new GitGarbageCollectionReconciler(kubernetesServer.getClient()), input);
+        getContext(new GitGarbageCollectionReconciler(kubernetesServer.createClient()), input);
     GitGarbageCollectionCronJob dependentCronjob = new GitGarbageCollectionCronJob();
     assertThat(dependentCronjob.desired(input, context))
         .isEqualTo(ReconcilerUtils.loadYaml(CronJob.class, this.getClass(), expectedCronJob));
@@ -84,7 +78,7 @@
         new Controller<GitGarbageCollection>(
             reconciler,
             new BaseConfigurationService().getConfigurationFor(reconciler),
-            kubernetesServer.getClient());
+            kubernetesServer.createClient());
 
     return new DefaultContext<GitGarbageCollection>(
         new GenericRetryExecution(new GenericRetry()), controller, primary);
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/indexer/dependent/GerritIndexerTest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/indexer/dependent/GerritIndexerTest.java
index 21579e7..0058c1e 100644
--- a/operator/src/test/java/com/google/gerrit/k8s/operator/indexer/dependent/GerritIndexerTest.java
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/indexer/dependent/GerritIndexerTest.java
@@ -25,7 +25,7 @@
 import io.fabric8.kubernetes.api.model.ConfigMap;
 import io.fabric8.kubernetes.api.model.HasMetadata;
 import io.fabric8.kubernetes.api.model.batch.v1.Job;
-import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
+import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
 import io.javaoperatorsdk.operator.ReconcilerUtils;
 import io.javaoperatorsdk.operator.api.config.BaseConfigurationService;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
@@ -56,12 +56,11 @@
       String.format(
           "/apis/%s/namespaces/gerrit/%s/gerrit",
           HasMetadata.getApiVersion(Gerrit.class), HasMetadata.getPlural(Gerrit.class));
-  @Rule public KubernetesServer kubernetesServer = new KubernetesServer();
+  @Rule public KubernetesMockServer kubernetesServer = new KubernetesMockServer();
 
   @BeforeAll
   public void setup() throws Exception {
     OperatorContext.createInstance(ClusterMode.HIGH_AVAILABILITY, "cluster.local");
-    kubernetesServer.before();
   }
 
   @ParameterizedTest
@@ -110,7 +109,7 @@
         new Controller<GerritIndexer>(
             reconciler,
             new BaseConfigurationService().getConfigurationFor(reconciler),
-            kubernetesServer.getClient());
+            kubernetesServer.createClient());
 
     return new DefaultContext<GerritIndexer>(
         new GenericRetryExecution(new GenericRetry()), controller, primary);
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/server/AdmissionWebhookAbstractTest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/server/AdmissionWebhookAbstractTest.java
index 49ee9ea..91c2202 100644
--- a/operator/src/test/java/com/google/gerrit/k8s/operator/server/AdmissionWebhookAbstractTest.java
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/server/AdmissionWebhookAbstractTest.java
@@ -35,7 +35,7 @@
 import io.fabric8.kubernetes.api.model.admission.v1.AdmissionRequest;
 import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview;
 import io.fabric8.kubernetes.client.CustomResource;
-import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
+import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.HttpURLConnection;
@@ -65,14 +65,12 @@
           NAMESPACE,
           HasMetadata.getPlural(GerritCluster.class));
 
-  @Rule protected KubernetesServer kubernetesServer = new KubernetesServer();
+  @Rule protected KubernetesMockServer kubernetesServer = new KubernetesMockServer();
 
   @BeforeAll
   public void setup() throws Exception {
     server = new TestAdmissionWebhookServer();
 
-    kubernetesServer.before();
-
     OperatorContext.createInstance(getClusterMode(), "cluster.local");
     server.registerWebhook(new GerritClusterAdmissionWebhook(getClusterMode()));
     server.registerWebhook(new GerritAdmissionWebhook(getClusterMode()));
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/server/GerritClusterAdmissionWebhookTest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/server/GerritClusterAdmissionWebhookTest.java
index 76c6fbf..7524ee8 100644
--- a/operator/src/test/java/com/google/gerrit/k8s/operator/server/GerritClusterAdmissionWebhookTest.java
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/server/GerritClusterAdmissionWebhookTest.java
@@ -48,7 +48,7 @@
     cfg.fromText(TestGerrit.DEFAULT_GERRIT_CONFIG);
     GerritTemplate gerrit1 = TestGerrit.createGerritTemplate("gerrit1", GerritMode.PRIMARY, cfg);
     TestGerritCluster gerritCluster =
-        new TestGerritCluster(kubernetesServer.getClient(), NAMESPACE);
+        new TestGerritCluster(kubernetesServer.createClient(), NAMESPACE);
     gerritCluster.addGerrit(gerrit1);
     GerritCluster cluster = gerritCluster.build();
 
@@ -80,7 +80,7 @@
     cfg.fromText(TestGerrit.DEFAULT_GERRIT_CONFIG);
     GerritTemplate gerrit = TestGerrit.createGerritTemplate("gerrit1", GerritMode.PRIMARY, cfg);
     TestGerritCluster gerritCluster =
-        new TestGerritCluster(kubernetesServer.getClient(), NAMESPACE);
+        new TestGerritCluster(kubernetesServer.createClient(), NAMESPACE);
     gerritCluster.addGerrit(gerrit);
 
     ReceiverTemplate receiver = new ReceiverTemplate();
@@ -110,7 +110,7 @@
     cfg.fromText(TestGerrit.DEFAULT_GERRIT_CONFIG);
     GerritTemplate gerrit1 = TestGerrit.createGerritTemplate("gerrit1", GerritMode.PRIMARY, cfg);
     TestGerritCluster gerritCluster =
-        new TestGerritCluster(kubernetesServer.getClient(), NAMESPACE);
+        new TestGerritCluster(kubernetesServer.createClient(), NAMESPACE);
     gerritCluster.addGerrit(gerrit1);
 
     HttpURLConnection http = sendAdmissionRequest(gerritCluster.build());
@@ -138,7 +138,7 @@
     cfg.fromText(TestGerrit.DEFAULT_GERRIT_CONFIG);
 
     TestGerritCluster gerritCluster =
-        new TestGerritCluster(kubernetesServer.getClient(), NAMESPACE);
+        new TestGerritCluster(kubernetesServer.createClient(), NAMESPACE);
     GerritTemplate primary = TestGerrit.createGerritTemplate("gerrit", GerritMode.PRIMARY, cfg);
     GerritTemplate replica = TestGerrit.createGerritTemplate("gerrit", GerritMode.REPLICA, cfg);
     gerritCluster.addGerrit(primary);
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/server/GerritMultisiteClusterAdmissionWebhookTest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/server/GerritMultisiteClusterAdmissionWebhookTest.java
index de97552..b0cef7e 100644
--- a/operator/src/test/java/com/google/gerrit/k8s/operator/server/GerritMultisiteClusterAdmissionWebhookTest.java
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/server/GerritMultisiteClusterAdmissionWebhookTest.java
@@ -43,7 +43,7 @@
     cfg.fromText(TestGerrit.DEFAULT_GERRIT_CONFIG);
 
     TestGerritCluster gerritCluster =
-        new TestGerritCluster(kubernetesServer.getClient(), NAMESPACE);
+        new TestGerritCluster(kubernetesServer.createClient(), NAMESPACE);
     GerritTemplate primary = TestGerrit.createGerritTemplate("gerrit", GerritMode.PRIMARY, cfg);
     GerritTemplate replica = TestGerrit.createGerritTemplate("gerrit", GerritMode.REPLICA, cfg);
     gerritCluster.addGerrit(primary);
@@ -68,7 +68,7 @@
     cfg.fromText(TestGerrit.DEFAULT_GERRIT_CONFIG);
 
     TestGerritCluster gerritCluster =
-        new TestGerritCluster(kubernetesServer.getClient(), NAMESPACE);
+        new TestGerritCluster(kubernetesServer.createClient(), NAMESPACE);
     GerritTemplate replica = TestGerrit.createGerritTemplate("gerrit", GerritMode.REPLICA, cfg);
     gerritCluster.addGerrit(replica);
 
@@ -92,7 +92,7 @@
     cfg.fromText(TestGerrit.DEFAULT_GERRIT_CONFIG);
 
     TestGerritCluster gerritCluster =
-        new TestGerritCluster(kubernetesServer.getClient(), NAMESPACE);
+        new TestGerritCluster(kubernetesServer.createClient(), NAMESPACE);
     GerritTemplate primary = TestGerrit.createGerritTemplate("gerrit", GerritMode.PRIMARY, cfg);
     primary.getSpec().setReplicas(1);
     gerritCluster.addGerrit(primary);
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/server/GitGcAdmissionWebhookTest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/server/GitGcAdmissionWebhookTest.java
index 0fc1407..358e22b 100644
--- a/operator/src/test/java/com/google/gerrit/k8s/operator/server/GitGcAdmissionWebhookTest.java
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/server/GitGcAdmissionWebhookTest.java
@@ -30,7 +30,7 @@
 import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
 import io.fabric8.kubernetes.api.model.admission.v1.AdmissionRequest;
 import io.fabric8.kubernetes.api.model.admission.v1.AdmissionReview;
-import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
+import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
 import jakarta.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -60,15 +60,13 @@
           HasMetadata.getPlural(GitGarbageCollection.class));
   private TestAdmissionWebhookServer server;
 
-  @Rule public KubernetesServer kubernetesServer = new KubernetesServer();
+  @Rule public KubernetesMockServer kubernetesServer = new KubernetesMockServer();
 
   @BeforeAll
   public void setup() throws Exception {
     server = new TestAdmissionWebhookServer();
 
-    kubernetesServer.before();
-
-    GitGcAdmissionWebhook webhook = new GitGcAdmissionWebhook(kubernetesServer.getClient());
+    GitGcAdmissionWebhook webhook = new GitGcAdmissionWebhook(kubernetesServer.createClient());
     server.registerWebhook(webhook);
     server.start();
   }
diff --git a/operator/src/test/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskTest.java b/operator/src/test/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskTest.java
index 4c9cf7e..ec805ec 100644
--- a/operator/src/test/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskTest.java
+++ b/operator/src/test/java/com/google/gerrit/k8s/operator/tasks/incomingrepl/dependent/IncomingReplicationTaskTest.java
@@ -24,7 +24,7 @@
 import io.fabric8.kubernetes.api.model.Secret;
 import io.fabric8.kubernetes.api.model.SecretBuilder;
 import io.fabric8.kubernetes.api.model.batch.v1.CronJob;
-import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
+import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
 import io.javaoperatorsdk.operator.ReconcilerUtils;
 import io.javaoperatorsdk.operator.api.config.BaseConfigurationService;
 import io.javaoperatorsdk.operator.api.reconciler.Context;
@@ -37,7 +37,6 @@
 import java.util.Map;
 import java.util.stream.Stream;
 import org.junit.Rule;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.TestInstance;
 import org.junit.jupiter.api.TestInstance.Lifecycle;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -46,12 +45,7 @@
 
 @TestInstance(Lifecycle.PER_CLASS)
 public class IncomingReplicationTaskTest {
-  @Rule public KubernetesServer kubernetesServer = new KubernetesServer();
-
-  @BeforeAll
-  public void setup() throws Exception {
-    kubernetesServer.before();
-  }
+  @Rule public KubernetesMockServer kubernetesServer = new KubernetesMockServer();
 
   @ParameterizedTest
   @MethodSource("provideYamlManifests")
@@ -113,7 +107,7 @@
         new Controller<IncomingReplicationTask>(
             reconciler,
             new BaseConfigurationService().getConfigurationFor(reconciler),
-            kubernetesServer.getClient());
+            kubernetesServer.createClient());
 
     return new DefaultContext<IncomingReplicationTask>(
         new GenericRetryExecution(new GenericRetry()), controller, primary);
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gerrit/dependent/statefulset_es_primary.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gerrit/dependent/statefulset_es_primary.yaml
index b1b5da8..3c797c9 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gerrit/dependent/statefulset_es_primary.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gerrit/dependent/statefulset_es_primary.yaml
@@ -158,21 +158,21 @@
       serviceAccount: gerrit
       terminationGracePeriodSeconds: 30
       volumes:
-      - name: shared
-        persistentVolumeClaim:
-          claimName: shared-pvc
       - name: tmp
         emptyDir:
           sizeLimit: 500Mi
-      - name: gerrit-secure-config
-        secret:
-          secretName: gerrit-secure-config
-      - configMap:
-          name: gerrit-configmap
-        name: gerrit-config
       - configMap:
           name: gerrit-init-configmap
         name: gerrit-init-config
+      - configMap:
+          name: gerrit-configmap
+        name: gerrit-config
+      - name: gerrit-secure-config
+        secret:
+          secretName: gerrit-secure-config
+      - name: shared
+        persistentVolumeClaim:
+          claimName: shared-pvc
   updateStrategy:
     rollingUpdate:
       partition: 0
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gerrit/dependent/statefulset_ha_primary.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gerrit/dependent/statefulset_ha_primary.yaml
index 28b366b..67800cf 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gerrit/dependent/statefulset_ha_primary.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gerrit/dependent/statefulset_ha_primary.yaml
@@ -152,21 +152,21 @@
       serviceAccount: gerrit
       terminationGracePeriodSeconds: 30
       volumes:
-      - name: shared
-        persistentVolumeClaim:
-          claimName: shared-pvc
       - name: tmp
         emptyDir:
           sizeLimit: 500Mi
-      - name: gerrit-secure-config
-        secret:
-          secretName: gerrit-secure-config
-      - configMap:
-          name: gerrit-configmap
-        name: gerrit-config
       - configMap:
           name: gerrit-init-configmap
         name: gerrit-init-config
+      - configMap:
+          name: gerrit-configmap
+        name: gerrit-config
+      - name: gerrit-secure-config
+        secret:
+          secretName: gerrit-secure-config
+      - name: shared
+        persistentVolumeClaim:
+          claimName: shared-pvc
   updateStrategy:
     rollingUpdate:
       partition: 0
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/gerrit/dependent/statefulset_single_primary.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/gerrit/dependent/statefulset_single_primary.yaml
index 7086159..31a82c8 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/gerrit/dependent/statefulset_single_primary.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/gerrit/dependent/statefulset_single_primary.yaml
@@ -140,21 +140,21 @@
       serviceAccount: gerrit
       terminationGracePeriodSeconds: 30
       volumes:
-      - name: shared
-        persistentVolumeClaim:
-          claimName: shared-pvc
       - name: tmp
         emptyDir:
           sizeLimit: 500Mi
-      - name: gerrit-secure-config
-        secret:
-          secretName: gerrit-secure-config
-      - configMap:
-          name: gerrit-configmap
-        name: gerrit-config
       - configMap:
           name: gerrit-init-configmap
         name: gerrit-init-config
+      - configMap:
+          name: gerrit-configmap
+        name: gerrit-config
+      - name: gerrit-secure-config
+        secret:
+          secretName: gerrit-secure-config
+      - name: shared
+        persistentVolumeClaim:
+          claimName: shared-pvc
   updateStrategy:
     rollingUpdate:
       partition: 0
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment.yaml
index 08f8270..801c0b7 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment.yaml
@@ -120,12 +120,12 @@
           mountPath: /var/apache/credentials/.htpasswd
           subPath: .htpasswd
       volumes:
-      - name: shared
-        persistentVolumeClaim:
-          claimName: shared-pvc
       - name: apache-credentials
         secret:
           secretName: apache-credentials
+      - name: shared
+        persistentVolumeClaim:
+          claimName: shared-pvc
       - name: apache-run-dir
         emptyDir:
           sizeLimit: 50Mi
diff --git a/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment_minimal.yaml b/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment_minimal.yaml
index c282acf..c2e6024 100644
--- a/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment_minimal.yaml
+++ b/operator/src/test/resources/com/google/gerrit/k8s/operator/receiver/dependent/deployment_minimal.yaml
@@ -81,12 +81,12 @@
           mountPath: /var/apache/credentials/.htpasswd
           subPath: .htpasswd
       volumes:
-      - name: shared
-        persistentVolumeClaim:
-          claimName: shared-pvc
       - name: apache-credentials
         secret:
           secretName: apache-credentials
+      - name: shared
+        persistentVolumeClaim:
+          claimName: shared-pvc
       - name: apache-run-dir
         emptyDir:
           sizeLimit: 50Mi