gyfora commented on code in PR #994:
URL: 
https://github.com/apache/flink-kubernetes-operator/pull/994#discussion_r2204019063


##########
flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/reconciler/deployment/SessionReconciler.java:
##########
@@ -120,6 +126,61 @@ private void 
recoverSession(FlinkResourceContext<FlinkDeployment> ctx) throws Ex
                 
.setJobManagerDeploymentStatus(JobManagerDeploymentStatus.DEPLOYING);
     }
 
+    /**
+     * Detects unmanaged jobs running in the session cluster. Unmanaged jobs 
are jobs that exist in
+     * the Flink cluster but are not managed by FlinkSessionJob resources.
+     */
+    private Set<JobID> getUnmanagedJobs(
+            FlinkResourceContext<FlinkDeployment> ctx, Set<FlinkSessionJob> 
sessionJobs) {

Review Comment:
   I don't think that we need to pass sessionJobs here. if the flag is enabled, 
any running job should simply block it. We can simplify this logic a lot



##########
flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/reconciler/deployment/SessionReconciler.java:
##########
@@ -143,13 +204,41 @@ public DeleteControl 
cleanupInternal(FlinkResourceContext<FlinkDeployment> ctx)
             }
             return DeleteControl.noFinalizerRemoval()
                     
.rescheduleAfter(ctx.getOperatorConfig().getReconcileInterval().toMillis());
-        } else {
-            LOG.info("Stopping session cluster");
-            var conf = ctx.getDeployConfig(ctx.getResource().getSpec());
-            ctx.getFlinkService()
-                    .deleteClusterDeployment(
-                            deployment.getMetadata(), deployment.getStatus(), 
conf, true);
-            return DeleteControl.defaultDelete();
         }
+
+        // Check for unmanaged jobs if the option is enabled (Enabled by 
default)
+        boolean blockOnUnmanagedJobs =
+                ctx.getObserveConfig()
+                        
.getBoolean(KubernetesOperatorConfigOptions.BLOCK_ON_UNMANAGED_JOBS);
+        if (blockOnUnmanagedJobs) {
+            Set<JobID> unmanagedJobs = getUnmanagedJobs(ctx, sessionJobs);
+            if (!unmanagedJobs.isEmpty()) {
+                var error =
+                        String.format(
+                                "The session cluster has unmanaged jobs %s 
that should be cancelled first",
+                                unmanagedJobs.stream()
+                                        .map(JobID::toHexString)
+                                        .collect(Collectors.toList()));
+                LOG.warn(error);
+                if (eventRecorder.triggerEvent(
+                        deployment,
+                        EventRecorder.Type.Warning,
+                        EventRecorder.Reason.CleanupFailed,
+                        EventRecorder.Component.Operator,
+                        error,
+                        ctx.getKubernetesClient())) {
+                    LOG.warn(error);

Review Comment:
   you are logging the error twice, you don't need to log it at all as the 
event triggering already logs it.



##########
flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/reconciler/deployment/SessionReconciler.java:
##########
@@ -120,6 +126,61 @@ private void 
recoverSession(FlinkResourceContext<FlinkDeployment> ctx) throws Ex
                 
.setJobManagerDeploymentStatus(JobManagerDeploymentStatus.DEPLOYING);
     }
 
+    /**
+     * Detects unmanaged jobs running in the session cluster. Unmanaged jobs 
are jobs that exist in
+     * the Flink cluster but are not managed by FlinkSessionJob resources.
+     */
+    private Set<JobID> getUnmanagedJobs(
+            FlinkResourceContext<FlinkDeployment> ctx, Set<FlinkSessionJob> 
sessionJobs) {
+        LOG.info(
+                "Starting unmanaged job detection for session cluster: {}",
+                ctx.getResource().getMetadata().getName());
+        try {
+            // Get all jobs running in the Flink cluster
+            var flinkService = ctx.getFlinkService();
+            var clusterClient = 
flinkService.getClusterClient(ctx.getObserveConfig());
+            var allJobs =
+                    clusterClient
+                            .sendRequest(
+                                    JobsOverviewHeaders.getInstance(),
+                                    EmptyMessageParameters.getInstance(),
+                                    EmptyRequestBody.getInstance())
+                            .get()
+                            .getJobs();
+
+            // Get job IDs managed by FlinkSessionJob resources
+            Set<JobID> managedJobIds =
+                    sessionJobs.stream()
+                            .map(job -> 
job.getStatus().getJobStatus().getJobId())
+                            .filter(jobId -> jobId != null)
+                            .map(JobID::fromHexString)
+                            .collect(Collectors.toSet());
+
+            // Get job IDs that are not managed by FlinkSessionJob resources 
and are currently
+            // running
+            //    FAILED(TerminalState.GLOBALLY)
+            //    CANCELED(TerminalState.GLOBALLY)
+            //    FINISHED(TerminalState.GLOBALLY)
+            // Above terminal states are not considered since they are no 
longer active jobs

Review Comment:
   This comment feels a bit too verbose, enough to say only consider non 
terminal jobs (feels a bit like AI generated)



##########
flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/reconciler/deployment/SessionReconciler.java:
##########
@@ -120,6 +126,61 @@ private void 
recoverSession(FlinkResourceContext<FlinkDeployment> ctx) throws Ex
                 
.setJobManagerDeploymentStatus(JobManagerDeploymentStatus.DEPLOYING);
     }
 
+    /**
+     * Detects unmanaged jobs running in the session cluster. Unmanaged jobs 
are jobs that exist in
+     * the Flink cluster but are not managed by FlinkSessionJob resources.
+     */
+    private Set<JobID> getUnmanagedJobs(
+            FlinkResourceContext<FlinkDeployment> ctx, Set<FlinkSessionJob> 
sessionJobs) {
+        LOG.info(
+                "Starting unmanaged job detection for session cluster: {}",
+                ctx.getResource().getMetadata().getName());

Review Comment:
   this should be on debug level, also no need to include resource name/info in 
the log message. Its in the MDC already



##########
flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/reconciler/deployment/SessionReconciler.java:
##########
@@ -120,6 +126,61 @@ private void 
recoverSession(FlinkResourceContext<FlinkDeployment> ctx) throws Ex
                 
.setJobManagerDeploymentStatus(JobManagerDeploymentStatus.DEPLOYING);
     }
 
+    /**
+     * Detects unmanaged jobs running in the session cluster. Unmanaged jobs 
are jobs that exist in
+     * the Flink cluster but are not managed by FlinkSessionJob resources.
+     */
+    private Set<JobID> getUnmanagedJobs(
+            FlinkResourceContext<FlinkDeployment> ctx, Set<FlinkSessionJob> 
sessionJobs) {

Review Comment:
   We can simply replace this method with something like getNonTerminalJobIds() 
or boolean anyNonTerminalJobs()
   
   That would be enough for this feature.



##########
flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/reconciler/deployment/SessionReconcilerTest.java:
##########
@@ -139,4 +149,164 @@ public void testSetOwnerReference() throws Exception {
                 
deployConfig.get(KubernetesConfigOptions.JOB_MANAGER_OWNER_REFERENCE);
         Assertions.assertEquals(expectedOwnerReferences, or);
     }
+
+    @Test
+    public void testGetUnmanagedJobs() throws Exception {
+        // Create a session cluster deployment with blocking enabled
+        FlinkDeployment deployment = TestUtils.buildSessionCluster();
+        deployment
+                .getSpec()
+                .getFlinkConfiguration()
+                
.put(KubernetesOperatorConfigOptions.BLOCK_ON_UNMANAGED_JOBS.key(), "true");
+
+        assertEquals(
+                "true",
+                deployment
+                        .getSpec()
+                        .getFlinkConfiguration()
+                        
.get(KubernetesOperatorConfigOptions.BLOCK_ON_UNMANAGED_JOBS.key()));
+
+        // First, deploy the session cluster to set up proper state
+        reconciler.reconcile(deployment, flinkService.getContext());
+
+        // Verify deployment is in DEPLOYED state
+        assertEquals(
+                ReconciliationState.DEPLOYED,
+                deployment.getStatus().getReconciliationStatus().getState());
+
+        // Create different types of jobs
+        JobID managedJobId1 = new JobID();
+        JobID managedJobId2 = new JobID();
+        JobID unmanagedRunningJobId1 = new JobID();
+        JobID unmanagedTerminatedJobId = new JobID();
+        JobID unmanagedRunningJobId2 = new JobID();
+
+        // Add a mix of managed and unmanaged jobs to the testing service
+        flinkService
+                .listJobs()
+                .add(
+                        Tuple3.of(
+                                null,
+                                new JobStatusMessage(
+                                        managedJobId1,
+                                        "managed-job-1",
+                                        JobStatus.RUNNING,
+                                        System.currentTimeMillis()),
+                                new Configuration()));
+        flinkService
+                .listJobs()
+                .add(
+                        Tuple3.of(
+                                null,
+                                new JobStatusMessage(
+                                        managedJobId2,
+                                        "managed-job-2",
+                                        JobStatus.RUNNING,
+                                        System.currentTimeMillis()),
+                                new Configuration()));
+        flinkService
+                .listJobs()
+                .add(
+                        Tuple3.of(
+                                null,
+                                new JobStatusMessage(
+                                        unmanagedRunningJobId1,
+                                        "unmanaged-running-job-1",
+                                        JobStatus.RUNNING,
+                                        System.currentTimeMillis()),
+                                new Configuration()));
+        flinkService
+                .listJobs()
+                .add(
+                        Tuple3.of(
+                                null,
+                                new JobStatusMessage(
+                                        unmanagedTerminatedJobId,
+                                        "unmanaged-terminated-job",
+                                        JobStatus.CANCELED,
+                                        System.currentTimeMillis()),
+                                new Configuration()));
+        flinkService
+                .listJobs()
+                .add(
+                        Tuple3.of(
+                                null,
+                                new JobStatusMessage(
+                                        unmanagedRunningJobId2,
+                                        "unmanaged-running-job-2",
+                                        JobStatus.RUNNING,
+                                        System.currentTimeMillis()),
+                                new Configuration()));
+
+        // Create FlinkSessionJob resources for the managed jobs
+        FlinkSessionJob managedSessionJob1 = TestUtils.buildSessionJob();
+        managedSessionJob1.getMetadata().setName("managed-session-job-1");
+        
managedSessionJob1.getStatus().getJobStatus().setJobId(managedJobId1.toHexString());
+        kubernetesClient.resource(managedSessionJob1).createOrReplace();
+
+        FlinkSessionJob managedSessionJob2 = TestUtils.buildSessionJob();
+        managedSessionJob2.getMetadata().setName("managed-session-job-2");
+        
managedSessionJob2.getStatus().getJobStatus().setJobId(managedJobId2.toHexString());
+        kubernetesClient.resource(managedSessionJob2).createOrReplace();
+
+        Set<FlinkSessionJob> sessionJobs = new HashSet<>();
+        sessionJobs.add(managedSessionJob1);
+        sessionJobs.add(managedSessionJob2);
+
+        // Test with blocking enabled - should identify running unmanaged jobs 
correctly
+        var context = 
TestUtils.createContextWithReadyFlinkDeployment(kubernetesClient);
+        var resourceContext = getResourceContext(deployment, context);
+
+        // Use reflection to access the private getUnmanagedJobs method

Review Comment:
   We should not use reflection for this, we can make the method protected with 
the @visiblefor testing annotation



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to