In some contexts is unclear why an autoscaling policy decides to request
more resources, i.e. if there's an unassigned shard that remains unassigned
even after adding more resources. It would be help to have more information
around the decisions taken by the deciders so it is easier to understand and
track them.
x-pack/plugin/autoscaling/src/test/java/org/elasticsearch/xpack/autoscaling/storage/ReactiveStorageDeciderDecisionTests.java
return ClusterState.builder(state).metadata(builder).routingTable(routingTableBuilder.build()).build();
    }
    static ClusterState addDataNodes(DiscoveryNodeRole role, String prefix, ClusterState state, int nodes) {
        DiscoveryNodes.Builder builder = DiscoveryNodes.builder(state.nodes());
        IntStream.range(0, nodes).mapToObj(i -> newDataNode(role, prefix + "_" + i)).forEach(builder::add);
        return ClusterState.builder(state).nodes(builder).build();
    }
    static DiscoveryNode newDataNode(DiscoveryNodeRole role, String nodeName) {
        return new DiscoveryNode(
            nodeName,
            UUIDs.randomBase64UUID(),
            buildNewFakeTransportAddress(),
            Map.of(),
            Set.of(role),
            Version.CURRENT
        );
    }
    private static String randomNodeId(RoutingNodes routingNodes, DiscoveryNodeRole role) {
        return randomFrom(
            StreamSupport.stream(routingNodes.spliterator(), false)
                .map(RoutingNode::node)
                .filter(n -> n.getRoles().contains(role))
                .collect(Collectors.toSet())
        ).getId();
    }
    private static Set<ShardId> shardIds(Iterable<ShardRouting> candidateShards) {
        return StreamSupport.stream(candidateShards.spliterator(), false).map(ShardRouting::shardId).collect(Collectors.toSet());
    }
}