2222import java .util .Arrays ;
2323import java .util .Collection ;
2424import java .util .Collections ;
25+ import java .util .Iterator ;
2526import java .util .List ;
27+ import java .util .Map ;
2628import java .util .UUID ;
29+ import java .util .concurrent .CountDownLatch ;
30+ import java .util .concurrent .atomic .AtomicInteger ;
31+ import java .util .stream .Collectors ;
32+
2733import org .apache .ignite .Ignite ;
34+ import org .apache .ignite .IgniteException ;
35+ import org .apache .ignite .cluster .ClusterNode ;
36+ import org .apache .ignite .compute .ComputeJob ;
37+ import org .apache .ignite .compute .ComputeJobResult ;
38+ import org .apache .ignite .compute .ComputeTaskAdapter ;
39+ import org .apache .ignite .compute .ComputeTaskFuture ;
2840import org .apache .ignite .configuration .IgniteConfiguration ;
2941import org .apache .ignite .internal .IgniteEx ;
3042import org .apache .ignite .internal .client .thin .ServicesTest ;
43+ import org .apache .ignite .internal .managers .systemview .GridSystemViewManager ;
3144import org .apache .ignite .internal .processors .security .impl .TestSecurityData ;
3245import org .apache .ignite .internal .processors .security .impl .TestSecurityPluginProvider ;
3346import org .apache .ignite .internal .util .typedef .F ;
47+ import org .apache .ignite .internal .util .typedef .X ;
48+ import org .apache .ignite .lang .IgniteFutureCancelledException ;
3449import org .apache .ignite .lang .IgniteProductVersion ;
3550import org .apache .ignite .plugin .security .SecurityPermission ;
3651import org .apache .ignite .plugin .security .SecurityPermissionSet ;
3752import org .apache .ignite .plugin .security .SecurityPermissionSetBuilder ;
3853import org .apache .ignite .services .ServiceConfiguration ;
3954import org .apache .ignite .services .ServiceDescriptor ;
55+ import org .apache .ignite .spi .systemview .view .ComputeTaskView ;
4056import org .apache .ignite .util .GridCommandHandlerAbstractTest ;
57+ import org .jetbrains .annotations .NotNull ;
58+ import org .jetbrains .annotations .Nullable ;
4159import org .junit .Test ;
4260import org .junit .runners .Parameterized ;
4361
4462import static java .util .Arrays .asList ;
63+ import static java .util .concurrent .TimeUnit .MILLISECONDS ;
4564import static org .apache .ignite .internal .IgniteNodeAttributes .ATTR_BUILD_VER ;
4665import static org .apache .ignite .internal .commandline .ArgumentParser .CMD_PASSWORD ;
4766import static org .apache .ignite .internal .commandline .ArgumentParser .CMD_USER ;
4867import static org .apache .ignite .internal .commandline .CommandHandler .EXIT_CODE_OK ;
4968import static org .apache .ignite .internal .commandline .CommandHandler .EXIT_CODE_UNEXPECTED_ERROR ;
69+ import static org .apache .ignite .internal .processors .job .GridJobProcessor .JOBS_VIEW ;
70+ import static org .apache .ignite .internal .processors .task .GridTaskProcessor .TASKS_VIEW ;
5071import static org .apache .ignite .internal .util .IgniteUtils .resolveIgnitePath ;
5172import static org .apache .ignite .plugin .security .SecurityPermission .ADMIN_ROLLING_UPGRADE ;
5273import static org .apache .ignite .plugin .security .SecurityPermission .CACHE_CREATE ;
5374import static org .apache .ignite .plugin .security .SecurityPermission .CACHE_DESTROY ;
5475import static org .apache .ignite .plugin .security .SecurityPermission .CACHE_READ ;
5576import static org .apache .ignite .plugin .security .SecurityPermission .CACHE_REMOVE ;
5677import static org .apache .ignite .plugin .security .SecurityPermission .SERVICE_CANCEL ;
78+ import static org .apache .ignite .plugin .security .SecurityPermission .TASK_CANCEL ;
5779import static org .apache .ignite .plugin .security .SecurityPermissionSetBuilder .ALL_PERMISSIONS ;
5880import static org .apache .ignite .plugin .security .SecurityPermissionSetBuilder .NO_PERMISSIONS ;
5981import static org .apache .ignite .plugin .security .SecurityPermissionSetBuilder .systemPermissions ;
82+ import static org .apache .ignite .testframework .GridTestUtils .waitForCondition ;
6083
6184/** */
6285public class SecurityCommandHandlerPermissionsTest extends GridCommandHandlerAbstractTest {
@@ -82,6 +105,8 @@ public static List<String> commandHandlers() {
82105 persistenceEnable (false );
83106
84107 injectTestSystemOut ();
108+
109+ TestJob .CANCELLED_JOB_CNT .set (0 );
85110 }
86111
87112 /** {@inheritDoc} */
@@ -155,22 +180,22 @@ public void testRollingUpgrade() throws Exception {
155180
156181 List <String > cmdArgs = asList ("--rolling-upgrade" , "enable" , targetVerStr );
157182
158- assertEquals (EXIT_CODE_UNEXPECTED_ERROR , execute ( enrichWithConnectionArguments ( cmdArgs , TEST_NO_PERMISSIONS_LOGIN ) ));
183+ assertEquals (EXIT_CODE_UNEXPECTED_ERROR , executeOnBehalf ( cmdArgs , TEST_NO_PERMISSIONS_LOGIN ));
159184
160185 assertFalse (ign .context ().rollingUpgrade ().enabled ());
161186
162- assertEquals (EXIT_CODE_OK , execute ( enrichWithConnectionArguments ( cmdArgs , TEST_LOGIN ) ));
187+ assertEquals (EXIT_CODE_OK , executeOnBehalf ( cmdArgs , TEST_LOGIN ));
163188
164189 assertTrue (ign .context ().rollingUpgrade ().enabled ());
165190 assertEquals (IgniteProductVersion .fromString (targetVerStr ), ign .context ().rollingUpgrade ().versions ().get2 ());
166191
167192 cmdArgs = asList ("--rolling-upgrade" , "disable" );
168193
169- assertEquals (EXIT_CODE_UNEXPECTED_ERROR , execute ( enrichWithConnectionArguments ( cmdArgs , TEST_NO_PERMISSIONS_LOGIN ) ));
194+ assertEquals (EXIT_CODE_UNEXPECTED_ERROR , executeOnBehalf ( cmdArgs , TEST_NO_PERMISSIONS_LOGIN ));
170195
171196 assertTrue (ign .context ().rollingUpgrade ().enabled ());
172197
173- assertEquals (EXIT_CODE_OK , execute ( enrichWithConnectionArguments ( cmdArgs , TEST_LOGIN ) ));
198+ assertEquals (EXIT_CODE_OK , executeOnBehalf ( cmdArgs , TEST_LOGIN ));
174199
175200 assertFalse (ign .context ().rollingUpgrade ().enabled ());
176201 }
@@ -198,15 +223,66 @@ public void testServiceCancel() throws Exception {
198223
199224 Collection <ServiceDescriptor > svcs = ignite .services ().serviceDescriptors ();
200225
201- assertEquals (EXIT_CODE_UNEXPECTED_ERROR , execute ( enrichWithConnectionArguments ( cmdArgs , TEST_NO_PERMISSIONS_LOGIN ) ));
226+ assertEquals (EXIT_CODE_UNEXPECTED_ERROR , executeOnBehalf ( cmdArgs , TEST_NO_PERMISSIONS_LOGIN ));
202227 assertEquals (1 , svcs .size ());
203228
204- assertEquals (EXIT_CODE_OK , execute ( enrichWithConnectionArguments ( cmdArgs , TEST_LOGIN ) ));
229+ assertEquals (EXIT_CODE_OK , executeOnBehalf ( cmdArgs , TEST_LOGIN ));
205230
206231 svcs = ignite .services ().serviceDescriptors ();
207232 assertEquals (0 , svcs .size ());
208233 }
209234
235+ /** */
236+ @ Test
237+ public void testTaskCancel () throws Exception {
238+ IgniteEx ignite = startGrid (
239+ 0 ,
240+ userData (TEST_NO_PERMISSIONS_LOGIN , NO_PERMISSIONS ),
241+ userData (TEST_LOGIN , SecurityPermissionSetBuilder .create ()
242+ .defaultAllowAll (false )
243+ .appendTaskPermissions (TestTask .class .getName (), TASK_CANCEL )
244+ .build ())
245+ );
246+
247+ ComputeTaskFuture <ComputeJobResult > fut = ignite .compute ().executeAsync (new TestTask (), null );
248+
249+ GridSystemViewManager viewMgr = ignite .context ().systemView ();
250+
251+ assertTrue (waitForCondition (() -> viewMgr .view (TASKS_VIEW ).size () >= 1 , getTestTimeout ()));
252+ assertTrue (waitForCondition (() -> viewMgr .view (JOBS_VIEW ).size () >= 1 , getTestTimeout ()));
253+
254+ Iterator <ComputeTaskView > iter = viewMgr .<ComputeTaskView >view (TASKS_VIEW ).iterator ();
255+
256+ String sesId = iter .next ().sessionId ().toString ();
257+
258+ assertFalse (iter .hasNext ());
259+
260+ Collection <String > cmdArgs = asList ("--kill" , "compute" , sesId );
261+
262+ assertEquals (EXIT_CODE_UNEXPECTED_ERROR , executeOnBehalf (cmdArgs , TEST_NO_PERMISSIONS_LOGIN ));
263+
264+ assertFalse (fut .isDone ());
265+
266+ assertEquals (0 , TestJob .CANCELLED_JOB_CNT .get ());
267+
268+ assertTrue (waitForCondition (() -> viewMgr .view (TASKS_VIEW ).size () >= 1 , getTestTimeout ()));
269+ assertTrue (waitForCondition (() -> viewMgr .view (JOBS_VIEW ).size () >= 1 , getTestTimeout ()));
270+
271+ assertEquals (EXIT_CODE_OK , executeOnBehalf (cmdArgs , TEST_LOGIN ));
272+
273+ try {
274+ assertTrue (fut .get (getTestTimeout (), MILLISECONDS ).isCancelled ());
275+ }
276+ catch (Exception e ) {
277+ assertTrue (X .hasCause (e , IgniteFutureCancelledException .class ));
278+ }
279+
280+ assertTrue (waitForCondition (() -> viewMgr .view (TASKS_VIEW ).size () == 0 , getTestTimeout ()));
281+ assertTrue (waitForCondition (() -> viewMgr .view (JOBS_VIEW ).size () == 0 , getTestTimeout ()));
282+
283+ assertEquals (1 , TestJob .CANCELLED_JOB_CNT .get ());
284+ }
285+
210286 /** */
211287 protected IgniteEx startGrid (int idx , TestSecurityData ... userData ) throws Exception {
212288 String login = getTestIgniteInstanceName (idx );
@@ -228,13 +304,13 @@ private void checkCommandPermissions(Collection<String> cmdArgs, SecurityPermiss
228304
229305 ignite .createCache (DEFAULT_CACHE_NAME );
230306
231- assertEquals (EXIT_CODE_UNEXPECTED_ERROR , execute ( enrichWithConnectionArguments ( cmdArgs , TEST_NO_PERMISSIONS_LOGIN ) ));
307+ assertEquals (EXIT_CODE_UNEXPECTED_ERROR , executeOnBehalf ( cmdArgs , TEST_NO_PERMISSIONS_LOGIN ));
232308
233- // We are losing command failure cause for --cache clear commnad . See IGNITE-21023 for more details.
309+ // We are losing command failure cause for --cache clear command . See IGNITE-21023 for more details.
234310 if (!cmdArgs .containsAll (Arrays .asList ("--cache" , "clear" )))
235311 assertTrue (testOut .toString ().contains ("Authorization failed" ));
236312
237- assertEquals (EXIT_CODE_OK , execute ( enrichWithConnectionArguments ( cmdArgs , TEST_LOGIN ) ));
313+ assertEquals (EXIT_CODE_OK , executeOnBehalf ( cmdArgs , TEST_LOGIN ));
238314 }
239315
240316 /** */
@@ -276,4 +352,55 @@ private TestSecurityData userData(String login, SecurityPermissionSet perms) {
276352 new Permissions ()
277353 );
278354 }
355+
356+ /** */
357+ private int executeOnBehalf (Collection <String > cmdArgs , String login ) {
358+ return execute (enrichWithConnectionArguments (cmdArgs , login ));
359+ }
360+
361+ /** */
362+ private static class TestTask extends ComputeTaskAdapter <Object , ComputeJobResult > {
363+ /** {@inheritDoc} */
364+ @ Override public @ NotNull Map <? extends ComputeJob , ClusterNode > map (
365+ List <ClusterNode > subgrid ,
366+ @ Nullable Object arg
367+ ) throws IgniteException {
368+ return subgrid .stream ().filter (g -> !g .isClient ()).collect (Collectors .toMap (ignored -> new TestJob (), srv -> srv ));
369+ }
370+
371+ /** {@inheritDoc} */
372+ @ Override public @ Nullable ComputeJobResult reduce (List <ComputeJobResult > results ) throws IgniteException {
373+ assertTrue (results .size () == 1 );
374+
375+ return results .get (0 );
376+ }
377+ }
378+
379+ /** */
380+ private static class TestJob implements ComputeJob {
381+ /** */
382+ private final CountDownLatch jobBlockedLatch = new CountDownLatch (1 );
383+
384+ /** */
385+ private static final AtomicInteger CANCELLED_JOB_CNT = new AtomicInteger ();
386+
387+ /** {@inheritDoc} */
388+ @ Override public void cancel () {
389+ jobBlockedLatch .countDown ();
390+
391+ CANCELLED_JOB_CNT .incrementAndGet ();
392+ }
393+
394+ /** {@inheritDoc} */
395+ @ Override public Object execute () throws IgniteException {
396+ try {
397+ assertTrue (jobBlockedLatch .await (5_000 , MILLISECONDS ));
398+ }
399+ catch (InterruptedException e ) {
400+ throw new IgniteException (e );
401+ }
402+
403+ return null ;
404+ }
405+ }
279406}
0 commit comments