3535import org .elasticsearch .cluster .routing .IndexShardRoutingTable ;
3636import org .elasticsearch .cluster .routing .RecoverySource ;
3737import org .elasticsearch .cluster .routing .RoutingChangesObserver ;
38+ import org .elasticsearch .cluster .routing .RoutingNode ;
3839import org .elasticsearch .cluster .routing .RoutingNodes ;
3940import org .elasticsearch .cluster .routing .RoutingTable ;
4041import org .elasticsearch .cluster .routing .ShardRouting ;
4445import org .elasticsearch .cluster .routing .allocation .RoutingAllocation ;
4546import org .elasticsearch .cluster .routing .allocation .ShardAllocationDecision ;
4647import org .elasticsearch .cluster .routing .allocation .command .MoveAllocationCommand ;
48+ import org .elasticsearch .cluster .routing .allocation .decider .AllocationDecider ;
4749import org .elasticsearch .cluster .routing .allocation .decider .AllocationDeciders ;
50+ import org .elasticsearch .cluster .routing .allocation .decider .Decision ;
4851import org .elasticsearch .cluster .routing .allocation .decider .ThrottlingAllocationDecider ;
4952import org .elasticsearch .common .Randomness ;
5053import org .elasticsearch .common .UUIDs ;
100103import static org .hamcrest .Matchers .aMapWithSize ;
101104import static org .hamcrest .Matchers .allOf ;
102105import static org .hamcrest .Matchers .anyOf ;
106+ import static org .hamcrest .Matchers .arrayWithSize ;
103107import static org .hamcrest .Matchers .equalTo ;
104108import static org .hamcrest .Matchers .everyItem ;
105109import static org .hamcrest .Matchers .hasEntry ;
@@ -575,6 +579,7 @@ public void allocate(RoutingAllocation allocation) {
575579 allocation .routingNodes ().getRelocatingShardCount (),
576580 equalTo (0 )
577581 );
582+ assertThat (allocation .routingNodes ().node ("node-2" ).started (), arrayWithSize (2 ));
578583 }
579584
580585 @ Override
@@ -595,9 +600,20 @@ public ShardAllocationDecision decideShardAllocation(ShardRouting shard, Routing
595600
596601 final var dataNodeIds = clusterState .nodes ().getDataNodes ().keySet ();
597602 for (var nodeId : List .of ("node-0" , "node-1" )) {
603+ final var desiredBalanceInput = new DesiredBalanceInput (
604+ randomInt (),
605+ new RoutingAllocation (new AllocationDeciders (List .of (new AllocationDecider () {
606+ @ Override
607+ public Decision canAllocate (ShardRouting shardRouting , RoutingNode node , RoutingAllocation allocation ) {
608+ // Move command works every decision except NO
609+ return randomFrom (Decision .YES , Decision .THROTTLE , Decision .THROTTLE );
610+ }
611+ })), clusterState , ClusterInfo .EMPTY , SnapshotShardSizeInfo .EMPTY , 0L ),
612+ List .of ()
613+ );
598614 var desiredBalance = desiredBalanceComputer .compute (
599615 DesiredBalance .BECOME_MASTER_INITIAL ,
600- createInput ( clusterState ) ,
616+ desiredBalanceInput ,
601617 queue (
602618 new MoveAllocationCommand (index .getName (), 0 , nodeId , "node-2" ),
603619 new MoveAllocationCommand (index .getName (), 1 , nodeId , "node-2" )
@@ -618,6 +634,67 @@ public ShardAllocationDecision decideShardAllocation(ShardRouting shard, Routing
618634 }
619635 }
620636
637+ public void testCannotApplyMoveCommand () {
638+ var desiredBalanceComputer = createDesiredBalanceComputer (new ShardsAllocator () {
639+ @ Override
640+ public void allocate (RoutingAllocation allocation ) {
641+ assertThat (
642+ "unexpected relocating shards: " + allocation .routingNodes (),
643+ allocation .routingNodes ().getRelocatingShardCount (),
644+ equalTo (0 )
645+ );
646+ assertThat (allocation .routingNodes ().node ("node-2" ).isEmpty (), equalTo (true ));
647+ }
648+
649+ @ Override
650+ public ShardAllocationDecision decideShardAllocation (ShardRouting shard , RoutingAllocation allocation ) {
651+ throw new AssertionError ("only used for allocation explain" );
652+ }
653+ });
654+ var clusterState = createInitialClusterState (3 );
655+ var index = clusterState .metadata ().getProject ().index (TEST_INDEX ).getIndex ();
656+
657+ var changes = new RoutingChangesObserver .DelegatingRoutingChangesObserver ();
658+ var routingNodes = clusterState .mutableRoutingNodes ();
659+ for (var iterator = routingNodes .unassigned ().iterator (); iterator .hasNext ();) {
660+ var shardRouting = iterator .next ();
661+ routingNodes .startShard (iterator .initialize (shardRouting .primary () ? "node-0" : "node-1" , null , 0L , changes ), changes , 0L );
662+ }
663+ clusterState = rebuildRoutingTable (clusterState , routingNodes );
664+
665+ final var dataNodeIds = clusterState .nodes ().getDataNodes ().keySet ();
666+ final var desiredBalanceInput = new DesiredBalanceInput (
667+ randomInt (),
668+ new RoutingAllocation (new AllocationDeciders (List .of (new AllocationDecider () {
669+ @ Override
670+ public Decision canAllocate (ShardRouting shardRouting , RoutingNode node , RoutingAllocation allocation ) {
671+ return Decision .NO ;
672+ }
673+ })), clusterState , ClusterInfo .EMPTY , SnapshotShardSizeInfo .EMPTY , 0L ),
674+ List .of ()
675+ );
676+ var desiredBalance = desiredBalanceComputer .compute (
677+ DesiredBalance .BECOME_MASTER_INITIAL ,
678+ desiredBalanceInput ,
679+ queue (
680+ new MoveAllocationCommand (index .getName (), 0 , randomFrom ("node-0" , "node-1" ), "node-2" ),
681+ new MoveAllocationCommand (index .getName (), 1 , randomFrom ("node-0" , "node-1" ), "node-2" )
682+ ),
683+ input -> true
684+ );
685+
686+ final Set <String > expectedNodeIds = Set .of ("node-0" , "node-1" );
687+ assertDesiredAssignments (
688+ desiredBalance ,
689+ Map .of (
690+ new ShardId (index , 0 ),
691+ new ShardAssignment (expectedNodeIds , 2 , 0 , 0 ),
692+ new ShardId (index , 1 ),
693+ new ShardAssignment (expectedNodeIds , 2 , 0 , 0 )
694+ )
695+ );
696+ }
697+
621698 public void testDesiredBalanceShouldConvergeInABigCluster () {
622699 var nodes = randomIntBetween (3 , 7 );
623700 var nodeIds = new ArrayList <String >(nodes );
0 commit comments