4444import org .elasticsearch .xpack .core .ml .job .persistence .AnomalyDetectorsIndex ;
4545import org .elasticsearch .xpack .core .ml .job .process .autodetect .state .ModelSizeStats ;
4646import org .elasticsearch .xpack .core .ml .job .process .autodetect .state .ModelSnapshot ;
47+ import org .elasticsearch .xpack .core .ml .utils .ExceptionsHelper ;
4748import org .elasticsearch .xpack .ml .MachineLearning ;
4849import org .elasticsearch .xpack .ml .job .categorization .CategorizationAnalyzerTests ;
4950import org .elasticsearch .xpack .ml .job .persistence .JobConfigProvider ;
@@ -497,7 +498,7 @@ public void testPutJob_AddsCreateTime() throws IOException {
497498 MockClientBuilder mockClientBuilder = new MockClientBuilder ("jobmanager-test" );
498499 JobManager jobManager = createJobManager (mockClientBuilder .build ());
499500
500- PutJobAction .Request putJobRequest = new PutJobAction .Request (createJob ());
501+ PutJobAction .Request putJobRequest = new PutJobAction .Request (createJobFoo ());
501502
502503 doAnswer (invocation -> {
503504 AckedClusterStateUpdateTask <Boolean > task = (AckedClusterStateUpdateTask <Boolean >) invocation .getArguments ()[1 ];
@@ -544,7 +545,7 @@ public void testJobExists_GivenMissingJob() {
544545
545546 doAnswer (invocationOnMock -> {
546547 ActionListener listener = (ActionListener ) invocationOnMock .getArguments ()[2 ];
547- listener .onResponse ( false );
548+ listener .onFailure ( ExceptionsHelper . missingJobException ( "non-job" ) );
548549 return null ;
549550 }).when (jobConfigProvider ).jobExists (anyString (), anyBoolean (), any ());
550551
@@ -579,18 +580,43 @@ public void testJobExists_GivenJobIsInClusterState() {
579580 Collections .singleton (MachineLearningField .MAX_MODEL_MEMORY_LIMIT ));
580581 when (clusterService .getClusterSettings ()).thenReturn (clusterSettings );
581582
583+
584+ JobManager jobManager = new JobManager (environment , environment .settings (), jobResultsProvider , clusterService ,
585+ auditor , threadPool , mock (Client .class ), updateJobProcessNotifier , jobConfigProvider );
586+
587+ AtomicBoolean jobExistsHolder = new AtomicBoolean ();
588+ AtomicReference <Exception > exceptionHolder = new AtomicReference <>();
589+ jobManager .jobExists ("cs-job" , ActionListener .wrap (
590+ jobExistsHolder ::set ,
591+ exceptionHolder ::set
592+ ));
593+
594+ assertTrue (jobExistsHolder .get ());
595+ assertNull (exceptionHolder .get ());
596+ verify (jobConfigProvider , never ()).jobExists (anyString (), anyBoolean (), any ());
597+ }
598+
599+ public void testJobExists_GivenJobIsInIndex () {
600+ ClusterState clusterState = ClusterState .builder (new ClusterName ("_name" )).build ();
601+ when (clusterService .state ()).thenReturn (clusterState );
602+
603+ ClusterSettings clusterSettings = new ClusterSettings (environment .settings (),
604+ Collections .singleton (MachineLearningField .MAX_MODEL_MEMORY_LIMIT ));
605+ when (clusterService .getClusterSettings ()).thenReturn (clusterSettings );
606+
607+ JobConfigProvider jobConfigProvider = mock (JobConfigProvider .class );
582608 doAnswer (invocationOnMock -> {
583609 ActionListener listener = (ActionListener ) invocationOnMock .getArguments ()[2 ];
584- listener .onResponse (false );
610+ listener .onResponse (true );
585611 return null ;
586- }).when (jobConfigProvider ).jobExists (anyString ( ), anyBoolean (), any ());
612+ }).when (jobConfigProvider ).jobExists (eq ( "index-job" ), anyBoolean (), any ());
587613
588614 JobManager jobManager = new JobManager (environment , environment .settings (), jobResultsProvider , clusterService ,
589615 auditor , threadPool , mock (Client .class ), updateJobProcessNotifier , jobConfigProvider );
590616
591617 AtomicBoolean jobExistsHolder = new AtomicBoolean ();
592618 AtomicReference <Exception > exceptionHolder = new AtomicReference <>();
593- jobManager .jobExists ("cs -job" , ActionListener .wrap (
619+ jobManager .jobExists ("index -job" , ActionListener .wrap (
594620 jobExistsHolder ::set ,
595621 exceptionHolder ::set
596622 ));
@@ -603,7 +629,7 @@ public void testPutJob_ThrowsIfJobExistsInClusterState() throws IOException {
603629 MockClientBuilder mockClientBuilder = new MockClientBuilder ("jobmanager-test" );
604630 JobManager jobManager = createJobManager (mockClientBuilder .build ());
605631
606- PutJobAction .Request putJobRequest = new PutJobAction .Request (createJob ());
632+ PutJobAction .Request putJobRequest = new PutJobAction .Request (createJobFoo ());
607633
608634 MlMetadata .Builder mlMetadata = new MlMetadata .Builder ();
609635 mlMetadata .putJob (buildJobBuilder ("foo" ).build (), false );
@@ -623,6 +649,54 @@ public void onFailure(Exception e) {
623649 });
624650 }
625651
652+ public void testPutJob_ThrowsIfIdIsTheSameAsAGroup () throws IOException {
653+ MockClientBuilder mockClientBuilder = new MockClientBuilder ("jobmanager-test" );
654+ JobManager jobManager = createJobManager (mockClientBuilder .build ());
655+
656+
657+ MlMetadata .Builder mlMetadata = new MlMetadata .Builder ();
658+ Job .Builder jobBuilder = buildJobBuilder ("job-with-group-foo" );
659+ jobBuilder .setGroups (Collections .singletonList ("foo" ));
660+ mlMetadata .putJob (jobBuilder .build (), false );
661+ ClusterState clusterState = ClusterState .builder (new ClusterName ("name" ))
662+ .metaData (MetaData .builder ().putCustom (MlMetadata .TYPE , mlMetadata .build ())).build ();
663+
664+ // job id cannot be a group
665+ PutJobAction .Request putJobRequest = new PutJobAction .Request (createJobFoo ());
666+ jobManager .putJob (putJobRequest , analysisRegistry , clusterState , new ActionListener <PutJobAction .Response >() {
667+ @ Override
668+ public void onResponse (PutJobAction .Response response ) {
669+ fail ("should have got an error" );
670+ }
671+
672+ @ Override
673+ public void onFailure (Exception e ) {
674+ assertTrue (e instanceof ResourceAlreadyExistsException );
675+ assertEquals ("job and group names must be unique but job [foo] and group [foo] have the same name" , e .getMessage ());
676+ }
677+ });
678+
679+ // the job's groups cannot be job Ids
680+ jobBuilder = buildJobBuilder ("job-with-clashing-group-name" );
681+ jobBuilder .setCreateTime (null );
682+ jobBuilder .setGroups (Collections .singletonList ("job-with-group-foo" ));
683+ putJobRequest = new PutJobAction .Request (jobBuilder );
684+
685+ jobManager .putJob (putJobRequest , analysisRegistry , clusterState , new ActionListener <PutJobAction .Response >() {
686+ @ Override
687+ public void onResponse (PutJobAction .Response response ) {
688+ fail ("should have got an error" );
689+ }
690+
691+ @ Override
692+ public void onFailure (Exception e ) {
693+ assertTrue (e instanceof ResourceAlreadyExistsException );
694+ assertEquals ("job and group names must be unique but job [job-with-group-foo] and " +
695+ "group [job-with-group-foo] have the same name" , e .getMessage ());
696+ }
697+ });
698+ }
699+
626700 public void testNotifyFilterChangedGivenNoop () {
627701 MlFilter filter = MlFilter .builder ("my_filter" ).build ();
628702 MockClientBuilder mockClientBuilder = new MockClientBuilder ("jobmanager-test" );
@@ -900,7 +974,7 @@ public void testRevertSnapshot_GivenJobInClusterState() {
900974 verify (jobConfigProvider , never ()).updateJob (any (), any (), any (), any ());
901975 }
902976
903- private Job .Builder createJob () {
977+ private Job .Builder createJobFoo () {
904978 Detector .Builder d1 = new Detector .Builder ("info_content" , "domain" );
905979 d1 .setOverFieldName ("client" );
906980 AnalysisConfig .Builder ac = new AnalysisConfig .Builder (Collections .singletonList (d1 .build ()));
0 commit comments