|
@@ -23,6 +23,7 @@ import java.util.Locale;
|
|
|
import java.util.Objects;
|
|
|
import java.util.function.BooleanSupplier;
|
|
|
import java.util.function.Consumer;
|
|
|
+import java.util.function.Function;
|
|
|
|
|
|
/**
|
|
|
* Encapsulates licensing checking for CCR.
|
|
@@ -58,14 +59,13 @@ public final class CcrLicenseChecker {
|
|
|
|
|
|
/**
|
|
|
* Fetches the leader index metadata from the remote cluster. Before fetching the index metadata, the remote cluster is checked for
|
|
|
- * license compatibility with CCR. If the remote cluster is not licensed for CCR, the {@link ActionListener#onFailure(Exception)} method
|
|
|
- * of the specified listener is invoked. Otherwise, the specified consumer is invoked with the leader index metadata fetched from the
|
|
|
- * remote cluster.
|
|
|
+ * license compatibility with CCR. If the remote cluster is not licensed for CCR, the {@code onFailure} consumer is is invoked.
|
|
|
+ * Otherwise, the specified consumer is invoked with the leader index metadata fetched from the remote cluster.
|
|
|
*
|
|
|
* @param client the client
|
|
|
* @param clusterAlias the remote cluster alias
|
|
|
* @param leaderIndex the name of the leader index
|
|
|
- * @param listener the listener
|
|
|
+ * @param onFailure the failure consumer
|
|
|
* @param leaderIndexMetadataConsumer the leader index metadata consumer
|
|
|
* @param <T> the type of response the listener is waiting for
|
|
|
*/
|
|
@@ -73,8 +73,75 @@ public final class CcrLicenseChecker {
|
|
|
final Client client,
|
|
|
final String clusterAlias,
|
|
|
final String leaderIndex,
|
|
|
- final ActionListener<T> listener,
|
|
|
+ final Consumer<Exception> onFailure,
|
|
|
final Consumer<IndexMetaData> leaderIndexMetadataConsumer) {
|
|
|
+
|
|
|
+ final ClusterStateRequest request = new ClusterStateRequest();
|
|
|
+ request.clear();
|
|
|
+ request.metaData(true);
|
|
|
+ request.indices(leaderIndex);
|
|
|
+ checkRemoteClusterLicenseAndFetchClusterState(
|
|
|
+ client,
|
|
|
+ clusterAlias,
|
|
|
+ request,
|
|
|
+ onFailure,
|
|
|
+ leaderClusterState -> leaderIndexMetadataConsumer.accept(leaderClusterState.getMetaData().index(leaderIndex)),
|
|
|
+ licenseCheck -> indexMetadataNonCompliantRemoteLicense(leaderIndex, licenseCheck),
|
|
|
+ e -> indexMetadataUnknownRemoteLicense(leaderIndex, clusterAlias, e));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Fetches the leader cluster state from the remote cluster by the specified cluster state request. Before fetching the cluster state,
|
|
|
+ * the remote cluster is checked for license compliance with CCR. If the remote cluster is not licensed for CCR,
|
|
|
+ * the {@code onFailure} consumer is invoked. Otherwise, the specified consumer is invoked with the leader cluster state fetched from
|
|
|
+ * the remote cluster.
|
|
|
+ *
|
|
|
+ * @param client the client
|
|
|
+ * @param clusterAlias the remote cluster alias
|
|
|
+ * @param request the cluster state request
|
|
|
+ * @param onFailure the failure consumer
|
|
|
+ * @param leaderClusterStateConsumer the leader cluster state consumer
|
|
|
+ * @param <T> the type of response the listener is waiting for
|
|
|
+ */
|
|
|
+ public <T> void checkRemoteClusterLicenseAndFetchClusterState(
|
|
|
+ final Client client,
|
|
|
+ final String clusterAlias,
|
|
|
+ final ClusterStateRequest request,
|
|
|
+ final Consumer<Exception> onFailure,
|
|
|
+ final Consumer<ClusterState> leaderClusterStateConsumer) {
|
|
|
+ checkRemoteClusterLicenseAndFetchClusterState(
|
|
|
+ client,
|
|
|
+ clusterAlias,
|
|
|
+ request,
|
|
|
+ onFailure,
|
|
|
+ leaderClusterStateConsumer,
|
|
|
+ CcrLicenseChecker::clusterStateNonCompliantRemoteLicense,
|
|
|
+ e -> clusterStateUnknownRemoteLicense(clusterAlias, e));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Fetches the leader cluster state from the remote cluster by the specified cluster state request. Before fetching the cluster state,
|
|
|
+ * the remote cluster is checked for license compliance with CCR. If the remote cluster is not licensed for CCR,
|
|
|
+ * the {@code onFailure} consumer is invoked. Otherwise, the specified consumer is invoked with the leader cluster state fetched from
|
|
|
+ * the remote cluster.
|
|
|
+ *
|
|
|
+ * @param client the client
|
|
|
+ * @param clusterAlias the remote cluster alias
|
|
|
+ * @param request the cluster state request
|
|
|
+ * @param onFailure the failure consumer
|
|
|
+ * @param leaderClusterStateConsumer the leader cluster state consumer
|
|
|
+ * @param nonCompliantLicense the supplier for when the license state of the remote cluster is non-compliant
|
|
|
+ * @param unknownLicense the supplier for when the license state of the remote cluster is unknown due to failure
|
|
|
+ * @param <T> the type of response the listener is waiting for
|
|
|
+ */
|
|
|
+ private <T> void checkRemoteClusterLicenseAndFetchClusterState(
|
|
|
+ final Client client,
|
|
|
+ final String clusterAlias,
|
|
|
+ final ClusterStateRequest request,
|
|
|
+ final Consumer<Exception> onFailure,
|
|
|
+ final Consumer<ClusterState> leaderClusterStateConsumer,
|
|
|
+ final Function<RemoteClusterLicenseChecker.LicenseCheck, ElasticsearchStatusException> nonCompliantLicense,
|
|
|
+ final Function<Exception, ElasticsearchStatusException> unknownLicense) {
|
|
|
// we have to check the license on the remote cluster
|
|
|
new RemoteClusterLicenseChecker(client, XPackLicenseState::isCcrAllowedForOperationMode).checkRemoteClusterLicenses(
|
|
|
Collections.singletonList(clusterAlias),
|
|
@@ -83,35 +150,25 @@ public final class CcrLicenseChecker {
|
|
|
@Override
|
|
|
public void onResponse(final RemoteClusterLicenseChecker.LicenseCheck licenseCheck) {
|
|
|
if (licenseCheck.isSuccess()) {
|
|
|
- final Client remoteClient = client.getRemoteClusterClient(clusterAlias);
|
|
|
- final ClusterStateRequest clusterStateRequest = new ClusterStateRequest();
|
|
|
- clusterStateRequest.clear();
|
|
|
- clusterStateRequest.metaData(true);
|
|
|
- clusterStateRequest.indices(leaderIndex);
|
|
|
- final ActionListener<ClusterStateResponse> clusterStateListener = ActionListener.wrap(
|
|
|
- r -> {
|
|
|
- final ClusterState remoteClusterState = r.getState();
|
|
|
- final IndexMetaData leaderIndexMetadata =
|
|
|
- remoteClusterState.getMetaData().index(leaderIndex);
|
|
|
- leaderIndexMetadataConsumer.accept(leaderIndexMetadata);
|
|
|
- },
|
|
|
- listener::onFailure);
|
|
|
+ final Client leaderClient = client.getRemoteClusterClient(clusterAlias);
|
|
|
+ final ActionListener<ClusterStateResponse> clusterStateListener =
|
|
|
+ ActionListener.wrap(s -> leaderClusterStateConsumer.accept(s.getState()), onFailure);
|
|
|
// following an index in remote cluster, so use remote client to fetch leader index metadata
|
|
|
- remoteClient.admin().cluster().state(clusterStateRequest, clusterStateListener);
|
|
|
+ leaderClient.admin().cluster().state(request, clusterStateListener);
|
|
|
} else {
|
|
|
- listener.onFailure(incompatibleRemoteLicense(leaderIndex, licenseCheck));
|
|
|
+ onFailure.accept(nonCompliantLicense.apply(licenseCheck));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void onFailure(final Exception e) {
|
|
|
- listener.onFailure(unknownRemoteLicense(leaderIndex, clusterAlias, e));
|
|
|
+ onFailure.accept(unknownLicense.apply(e));
|
|
|
}
|
|
|
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- private static ElasticsearchStatusException incompatibleRemoteLicense(
|
|
|
+ private static ElasticsearchStatusException indexMetadataNonCompliantRemoteLicense(
|
|
|
final String leaderIndex, final RemoteClusterLicenseChecker.LicenseCheck licenseCheck) {
|
|
|
final String clusterAlias = licenseCheck.remoteClusterLicenseInfo().clusterAlias();
|
|
|
final String message = String.format(
|
|
@@ -127,7 +184,21 @@ public final class CcrLicenseChecker {
|
|
|
return new ElasticsearchStatusException(message, RestStatus.BAD_REQUEST);
|
|
|
}
|
|
|
|
|
|
- private static ElasticsearchStatusException unknownRemoteLicense(
|
|
|
+ private static ElasticsearchStatusException clusterStateNonCompliantRemoteLicense(
|
|
|
+ final RemoteClusterLicenseChecker.LicenseCheck licenseCheck) {
|
|
|
+ final String clusterAlias = licenseCheck.remoteClusterLicenseInfo().clusterAlias();
|
|
|
+ final String message = String.format(
|
|
|
+ Locale.ROOT,
|
|
|
+ "can not fetch remote cluster state as the remote cluster [%s] is not licensed for [ccr]; %s",
|
|
|
+ clusterAlias,
|
|
|
+ RemoteClusterLicenseChecker.buildErrorMessage(
|
|
|
+ "ccr",
|
|
|
+ licenseCheck.remoteClusterLicenseInfo(),
|
|
|
+ RemoteClusterLicenseChecker::isLicensePlatinumOrTrial));
|
|
|
+ return new ElasticsearchStatusException(message, RestStatus.BAD_REQUEST);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static ElasticsearchStatusException indexMetadataUnknownRemoteLicense(
|
|
|
final String leaderIndex, final String clusterAlias, final Exception cause) {
|
|
|
final String message = String.format(
|
|
|
Locale.ROOT,
|
|
@@ -138,4 +209,11 @@ public final class CcrLicenseChecker {
|
|
|
return new ElasticsearchStatusException(message, RestStatus.BAD_REQUEST, cause);
|
|
|
}
|
|
|
|
|
|
+ private static ElasticsearchStatusException clusterStateUnknownRemoteLicense(final String clusterAlias, final Exception cause) {
|
|
|
+ final String message = String.format(
|
|
|
+ Locale.ROOT,
|
|
|
+ "can not fetch remote cluster state as the license state of the remote cluster [%s] could not be determined", clusterAlias);
|
|
|
+ return new ElasticsearchStatusException(message, RestStatus.BAD_REQUEST, cause);
|
|
|
+ }
|
|
|
+
|
|
|
}
|