This is an automated email from the ASF dual-hosted git repository.

mpetrov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 05fa9b6f468 IGNITE-26987 Fix control.sh --kill compute command 
authorization and authorization error propagation (#12525)
05fa9b6f468 is described below

commit 05fa9b6f468c94908056e1fd57a0a6c9ec4b8013
Author: Andrey Nadyktov <[email protected]>
AuthorDate: Fri Dec 5 13:45:40 2025 +0300

    IGNITE-26987 Fix control.sh --kill compute command authorization and 
authorization error propagation (#12525)
---
 .../SecurityCommandHandlerPermissionsTest.java     | 145 +++++++++++++++++++--
 .../apache/ignite/internal/ComputeMXBeanImpl.java  |   2 +-
 .../management/kill/ComputeCancelSessionTask.java  |  17 ++-
 3 files changed, 145 insertions(+), 19 deletions(-)

diff --git 
a/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/SecurityCommandHandlerPermissionsTest.java
 
b/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/SecurityCommandHandlerPermissionsTest.java
index b3a242c22c4..d10e6635a84 100644
--- 
a/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/SecurityCommandHandlerPermissionsTest.java
+++ 
b/modules/control-utility/src/test/java/org/apache/ignite/internal/commandline/SecurityCommandHandlerPermissionsTest.java
@@ -22,31 +22,52 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
 import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.compute.ComputeJob;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.compute.ComputeTaskAdapter;
+import org.apache.ignite.compute.ComputeTaskFuture;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.client.thin.ServicesTest;
+import org.apache.ignite.internal.managers.systemview.GridSystemViewManager;
 import org.apache.ignite.internal.processors.security.impl.TestSecurityData;
 import 
org.apache.ignite.internal.processors.security.impl.TestSecurityPluginProvider;
 import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.lang.IgniteFutureCancelledException;
 import org.apache.ignite.lang.IgniteProductVersion;
 import org.apache.ignite.plugin.security.SecurityPermission;
 import org.apache.ignite.plugin.security.SecurityPermissionSet;
 import org.apache.ignite.plugin.security.SecurityPermissionSetBuilder;
 import org.apache.ignite.services.ServiceConfiguration;
 import org.apache.ignite.services.ServiceDescriptor;
+import org.apache.ignite.spi.systemview.view.ComputeTaskView;
 import org.apache.ignite.util.GridCommandHandlerAbstractTest;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.junit.Test;
 import org.junit.runners.Parameterized;
 
 import static java.util.Arrays.asList;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_BUILD_VER;
 import static 
org.apache.ignite.internal.commandline.ArgumentParser.CMD_PASSWORD;
 import static org.apache.ignite.internal.commandline.ArgumentParser.CMD_USER;
 import static 
org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_OK;
 import static 
org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_UNEXPECTED_ERROR;
+import static 
org.apache.ignite.internal.processors.job.GridJobProcessor.JOBS_VIEW;
+import static 
org.apache.ignite.internal.processors.task.GridTaskProcessor.TASKS_VIEW;
 import static org.apache.ignite.internal.util.IgniteUtils.resolveIgnitePath;
 import static 
org.apache.ignite.plugin.security.SecurityPermission.ADMIN_ROLLING_UPGRADE;
 import static 
org.apache.ignite.plugin.security.SecurityPermission.CACHE_CREATE;
@@ -54,9 +75,11 @@ import static 
org.apache.ignite.plugin.security.SecurityPermission.CACHE_DESTROY
 import static org.apache.ignite.plugin.security.SecurityPermission.CACHE_READ;
 import static 
org.apache.ignite.plugin.security.SecurityPermission.CACHE_REMOVE;
 import static 
org.apache.ignite.plugin.security.SecurityPermission.SERVICE_CANCEL;
+import static org.apache.ignite.plugin.security.SecurityPermission.TASK_CANCEL;
 import static 
org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.ALL_PERMISSIONS;
 import static 
org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.NO_PERMISSIONS;
 import static 
org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.systemPermissions;
+import static org.apache.ignite.testframework.GridTestUtils.waitForCondition;
 
 /** */
 public class SecurityCommandHandlerPermissionsTest extends 
GridCommandHandlerAbstractTest {
@@ -82,6 +105,8 @@ public class SecurityCommandHandlerPermissionsTest extends 
GridCommandHandlerAbs
         persistenceEnable(false);
 
         injectTestSystemOut();
+
+        TestJob.CANCELLED_JOB_CNT.set(0);
     }
 
     /** {@inheritDoc} */
@@ -155,22 +180,22 @@ public class SecurityCommandHandlerPermissionsTest 
extends GridCommandHandlerAbs
 
         List<String> cmdArgs = asList("--rolling-upgrade", "enable", 
targetVerStr);
 
-        assertEquals(EXIT_CODE_UNEXPECTED_ERROR, 
execute(enrichWithConnectionArguments(cmdArgs, TEST_NO_PERMISSIONS_LOGIN)));
+        assertEquals(EXIT_CODE_UNEXPECTED_ERROR, executeOnBehalf(cmdArgs, 
TEST_NO_PERMISSIONS_LOGIN));
 
         assertFalse(ign.context().rollingUpgrade().enabled());
 
-        assertEquals(EXIT_CODE_OK, 
execute(enrichWithConnectionArguments(cmdArgs, TEST_LOGIN)));
+        assertEquals(EXIT_CODE_OK, executeOnBehalf(cmdArgs, TEST_LOGIN));
 
         assertTrue(ign.context().rollingUpgrade().enabled());
         assertEquals(IgniteProductVersion.fromString(targetVerStr), 
ign.context().rollingUpgrade().versions().get2());
 
         cmdArgs = asList("--rolling-upgrade", "disable");
 
-        assertEquals(EXIT_CODE_UNEXPECTED_ERROR, 
execute(enrichWithConnectionArguments(cmdArgs, TEST_NO_PERMISSIONS_LOGIN)));
+        assertEquals(EXIT_CODE_UNEXPECTED_ERROR, executeOnBehalf(cmdArgs, 
TEST_NO_PERMISSIONS_LOGIN));
 
         assertTrue(ign.context().rollingUpgrade().enabled());
 
-        assertEquals(EXIT_CODE_OK, 
execute(enrichWithConnectionArguments(cmdArgs, TEST_LOGIN)));
+        assertEquals(EXIT_CODE_OK, executeOnBehalf(cmdArgs, TEST_LOGIN));
 
         assertFalse(ign.context().rollingUpgrade().enabled());
     }
@@ -198,15 +223,66 @@ public class SecurityCommandHandlerPermissionsTest 
extends GridCommandHandlerAbs
 
         Collection<ServiceDescriptor> svcs = 
ignite.services().serviceDescriptors();
 
-        assertEquals(EXIT_CODE_UNEXPECTED_ERROR, 
execute(enrichWithConnectionArguments(cmdArgs, TEST_NO_PERMISSIONS_LOGIN)));
+        assertEquals(EXIT_CODE_UNEXPECTED_ERROR, executeOnBehalf(cmdArgs, 
TEST_NO_PERMISSIONS_LOGIN));
         assertEquals(1, svcs.size());
 
-        assertEquals(EXIT_CODE_OK, 
execute(enrichWithConnectionArguments(cmdArgs, TEST_LOGIN)));
+        assertEquals(EXIT_CODE_OK, executeOnBehalf(cmdArgs, TEST_LOGIN));
 
         svcs = ignite.services().serviceDescriptors();
         assertEquals(0, svcs.size());
     }
 
+    /** */
+    @Test
+    public void testTaskCancel() throws Exception {
+        IgniteEx ignite = startGrid(
+            0,
+            userData(TEST_NO_PERMISSIONS_LOGIN, NO_PERMISSIONS),
+            userData(TEST_LOGIN, SecurityPermissionSetBuilder.create()
+                .defaultAllowAll(false)
+                .appendTaskPermissions(TestTask.class.getName(), TASK_CANCEL)
+                .build())
+        );
+
+        ComputeTaskFuture<ComputeJobResult> fut = 
ignite.compute().executeAsync(new TestTask(), null);
+
+        GridSystemViewManager viewMgr = ignite.context().systemView();
+
+        assertTrue(waitForCondition(() -> viewMgr.view(TASKS_VIEW).size() >= 
1, getTestTimeout()));
+        assertTrue(waitForCondition(() -> viewMgr.view(JOBS_VIEW).size() >= 1, 
getTestTimeout()));
+
+        Iterator<ComputeTaskView> iter = 
viewMgr.<ComputeTaskView>view(TASKS_VIEW).iterator();
+
+        String sesId = iter.next().sessionId().toString();
+
+        assertFalse(iter.hasNext());
+
+        Collection<String> cmdArgs = asList("--kill", "compute", sesId);
+
+        assertEquals(EXIT_CODE_UNEXPECTED_ERROR, executeOnBehalf(cmdArgs, 
TEST_NO_PERMISSIONS_LOGIN));
+
+        assertFalse(fut.isDone());
+
+        assertEquals(0, TestJob.CANCELLED_JOB_CNT.get());
+
+        assertTrue(waitForCondition(() -> viewMgr.view(TASKS_VIEW).size() >= 
1, getTestTimeout()));
+        assertTrue(waitForCondition(() -> viewMgr.view(JOBS_VIEW).size() >= 1, 
getTestTimeout()));
+
+        assertEquals(EXIT_CODE_OK, executeOnBehalf(cmdArgs, TEST_LOGIN));
+
+        try {
+            assertTrue(fut.get(getTestTimeout(), MILLISECONDS).isCancelled());
+        }
+        catch (Exception e) {
+            assertTrue(X.hasCause(e, IgniteFutureCancelledException.class));
+        }
+
+        assertTrue(waitForCondition(() -> viewMgr.view(TASKS_VIEW).size() == 
0, getTestTimeout()));
+        assertTrue(waitForCondition(() -> viewMgr.view(JOBS_VIEW).size() == 0, 
getTestTimeout()));
+
+        assertEquals(1, TestJob.CANCELLED_JOB_CNT.get());
+    }
+
     /** */
     protected IgniteEx startGrid(int idx, TestSecurityData... userData) throws 
Exception {
         String login = getTestIgniteInstanceName(idx);
@@ -228,13 +304,13 @@ public class SecurityCommandHandlerPermissionsTest 
extends GridCommandHandlerAbs
 
         ignite.createCache(DEFAULT_CACHE_NAME);
 
-        assertEquals(EXIT_CODE_UNEXPECTED_ERROR, 
execute(enrichWithConnectionArguments(cmdArgs, TEST_NO_PERMISSIONS_LOGIN)));
+        assertEquals(EXIT_CODE_UNEXPECTED_ERROR, executeOnBehalf(cmdArgs, 
TEST_NO_PERMISSIONS_LOGIN));
 
-        // We are losing command failure cause for --cache clear commnad. See 
IGNITE-21023 for more details.
+        // We are losing command failure cause for --cache clear command. See 
IGNITE-21023 for more details.
         if (!cmdArgs.containsAll(Arrays.asList("--cache", "clear")))
             assertTrue(testOut.toString().contains("Authorization failed"));
 
-        assertEquals(EXIT_CODE_OK, 
execute(enrichWithConnectionArguments(cmdArgs, TEST_LOGIN)));
+        assertEquals(EXIT_CODE_OK, executeOnBehalf(cmdArgs, TEST_LOGIN));
     }
 
     /** */
@@ -276,4 +352,55 @@ public class SecurityCommandHandlerPermissionsTest extends 
GridCommandHandlerAbs
             new Permissions()
         );
     }
+
+    /** */
+    private int executeOnBehalf(Collection<String> cmdArgs, String login) {
+        return execute(enrichWithConnectionArguments(cmdArgs, login));
+    }
+
+    /** */
+    private static class TestTask extends ComputeTaskAdapter<Object, 
ComputeJobResult> {
+        /** {@inheritDoc} */
+        @Override public @NotNull Map<? extends ComputeJob, ClusterNode> map(
+            List<ClusterNode> subgrid,
+            @Nullable Object arg
+        ) throws IgniteException {
+            return subgrid.stream().filter(g -> 
!g.isClient()).collect(Collectors.toMap(ignored -> new TestJob(), srv -> srv));
+        }
+
+        /** {@inheritDoc} */
+        @Override public @Nullable ComputeJobResult 
reduce(List<ComputeJobResult> results) throws IgniteException {
+            assertTrue(results.size() == 1);
+
+            return results.get(0);
+        }
+    }
+
+    /** */
+    private static class TestJob implements ComputeJob {
+        /** */
+        private final CountDownLatch jobBlockedLatch = new CountDownLatch(1);
+
+        /** */
+        private static final AtomicInteger CANCELLED_JOB_CNT = new 
AtomicInteger();
+
+        /** {@inheritDoc} */
+        @Override public void cancel() {
+            jobBlockedLatch.countDown();
+
+            CANCELLED_JOB_CNT.incrementAndGet();
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object execute() throws IgniteException {
+            try {
+                assertTrue(jobBlockedLatch.await(5_000, MILLISECONDS));
+            }
+            catch (InterruptedException e) {
+                throw new IgniteException(e);
+            }
+
+            return null;
+        }
+    }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/ComputeMXBeanImpl.java 
b/modules/core/src/main/java/org/apache/ignite/internal/ComputeMXBeanImpl.java
index aa556c7f39a..7256ab2cafb 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/ComputeMXBeanImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/ComputeMXBeanImpl.java
@@ -52,7 +52,7 @@ public class ComputeMXBeanImpl implements ComputeMXBean {
     }
 
     /**
-     * Kills compute task by the session idenitifier.
+     * Kills compute task by the session identifier.
      *
      * @param sesId Session id.
      */
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/management/kill/ComputeCancelSessionTask.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/management/kill/ComputeCancelSessionTask.java
index 2ffc7be8138..03ef27182e7 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/management/kill/ComputeCancelSessionTask.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/management/kill/ComputeCancelSessionTask.java
@@ -17,14 +17,14 @@
 
 package org.apache.ignite.internal.management.kill;
 
-import java.util.List;
-import org.apache.ignite.compute.ComputeJobResult;
 import org.apache.ignite.internal.ComputeMXBeanImpl;
 import org.apache.ignite.internal.processors.task.GridInternal;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.visor.VisorJob;
 import org.apache.ignite.internal.visor.VisorOneNodeTask;
-import org.jetbrains.annotations.Nullable;
+import org.apache.ignite.plugin.security.SecurityPermissionSet;
+
+import static 
org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.NO_PERMISSIONS;
 
 /**
  * Cancels given tasks sessions on all cluster nodes.
@@ -39,12 +39,6 @@ public class ComputeCancelSessionTask extends 
VisorOneNodeTask<KillComputeComman
         return new ComputeCancelSessionJob(arg, debug);
     }
 
-    /** {@inheritDoc} */
-    @Nullable @Override protected Void reduce0(List<ComputeJobResult> results) 
{
-        // No-op, just awaiting all jobs done.
-        return null;
-    }
-
     /**
      * Job that cancel tasks.
      */
@@ -67,6 +61,11 @@ public class ComputeCancelSessionTask extends 
VisorOneNodeTask<KillComputeComman
             return null;
         }
 
+        /** {@inheritDoc} */
+        @Override public SecurityPermissionSet requiredPermissions() {
+            return NO_PERMISSIONS;
+        }
+
         /** {@inheritDoc} */
         @Override public String toString() {
             return S.toString(ComputeCancelSessionJob.class, this);

Reply via email to