diff --git a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/connection_status/connection_status.js b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/connection_status/connection_status.js index 5cdbfe596135f..1804bdd1385bb 100644 --- a/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/connection_status/connection_status.js +++ b/x-pack/plugins/remote_clusters/public/application/sections/remote_cluster_list/components/connection_status/connection_status.js @@ -9,7 +9,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { i18n } from '@kbn/i18n'; -import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; +import { EuiHealth, EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; import { SNIFF_MODE, PROXY_MODE } from '../../../../../../common/constants'; @@ -24,7 +24,7 @@ export function ConnectionStatus({ isConnected, mode }) { return ( - @@ -35,7 +35,7 @@ export function ConnectionStatus({ isConnected, mode }) { : i18n.translate('xpack.remoteClusters.connectedStatus.notConnectedAriaLabel', { defaultMessage: 'Not connected', })} - + {!isConnected && mode === SNIFF_MODE && ( diff --git a/x-pack/plugins/remote_clusters/server/routes/api/get_route.ts b/x-pack/plugins/remote_clusters/server/routes/api/get_route.ts index e4541414acfe2..96805e10357cd 100644 --- a/x-pack/plugins/remote_clusters/server/routes/api/get_route.ts +++ b/x-pack/plugins/remote_clusters/server/routes/api/get_route.ts @@ -5,15 +5,16 @@ * 2.0. */ -import { get } from 'lodash'; +import { get, chunk, assign } from 'lodash'; -import type { IndicesResolveClusterResponse } from '@elastic/elasticsearch/lib/api/types'; import { RequestHandler } from '@kbn/core/server'; import { deserializeCluster } from '../../../common/lib'; import { API_BASE_PATH } from '../../../common/constants'; import { licensePreRoutingFactory } from '../../lib/license_pre_routing_factory'; import { RouteDependencies } from '../../types'; +const CLUSTER_STATUS_CHUNK_SIZE = 10; + export const register = (deps: RouteDependencies): void => { const { router, @@ -35,15 +36,32 @@ export const register = (deps: RouteDependencies): void => { const clustersByName = await clusterClient.asCurrentUser.cluster.remoteInfo(); const clusterNames = (clustersByName && Object.keys(clustersByName)) || []; - // Retrieve the cluster information for all the configured remote clusters. - // _none is never a valid index/alias/data-stream name so that way we can avoid - // using * which could be computationally expensive. - let clustersStatus: IndicesResolveClusterResponse = {}; - if (clusterNames.length > 0) { - clustersStatus = await clusterClient.asCurrentUser.indices.resolveCluster({ - name: clusterNames.map((cluster) => `${cluster}:_none`), - }); - } + const clusterNamesChunks = chunk(clusterNames, CLUSTER_STATUS_CHUNK_SIZE); + const promises = clusterNamesChunks.map(async (clustersChunk) => { + try { + return await clusterClient.asCurrentUser.indices.resolveCluster( + { + name: clustersChunk.map((cluster) => `${cluster}:*`), + filter_path: '*.connected', + }, + { + // Set a longer timeout given that sometimes unresponsive clusters + // can take a while to respond. + // We should be able to be more aggresive with this timeout once + // https://github.com/elastic/elasticsearch/issues/114020 is resolved. + requestTimeout: '60s', + } + ); + } catch (error) { + return Promise.resolve(null); + } + }); + + const resolvedClusterStatus = await Promise.all(promises); + // Flatten the resolved cluster status and filter out any null values + const flattenedClusterStatus = resolvedClusterStatus.flat().filter(Boolean); + // Combine the resolved cluster status into a single object + const clusterStatus = assign({}, ...flattenedClusterStatus); const body = clusterNames.map((clusterName: string): any => { const cluster = clustersByName[clusterName]; @@ -70,9 +88,9 @@ export const register = (deps: RouteDependencies): void => { config.isCloudEnabled ), isConfiguredByNode, - // We prioritize the cluster status from the resolve cluster api, and fallback to - // the cluster connected status in case its not present. - isConnected: clustersStatus[clusterName]?.connected || cluster.connected, + // We prioritize the cluster status from the resolve cluster API, and fallback to + // the cluster connected status in case it's not present. + isConnected: clusterStatus[clusterName]?.connected || cluster.connected, }; });