Search in sources :

Example 6 with AuthenticationDataSource

use of org.apache.pulsar.broker.authentication.AuthenticationDataSource in project incubator-pulsar by apache.

the class TopicLookup method lookupTopicAsync.

/**
 * Lookup broker-service address for a given namespace-bundle which contains given topic.
 *
 * a. Returns broker-address if namespace-bundle is already owned by any broker
 * b. If current-broker receives lookup-request and if it's not a leader
 * then current broker redirects request to leader by returning leader-service address.
 * c. If current-broker is leader then it finds out least-loaded broker to own namespace bundle and
 * redirects request by returning least-loaded broker.
 * d. If current-broker receives request to own the namespace-bundle then it owns a bundle and returns
 * success(connect) response to client.
 *
 * @param pulsarService
 * @param topicName
 * @param authoritative
 * @param clientAppId
 * @param requestId
 * @return
 */
public static CompletableFuture<ByteBuf> lookupTopicAsync(PulsarService pulsarService, TopicName topicName, boolean authoritative, String clientAppId, AuthenticationDataSource authenticationData, long requestId) {
    final CompletableFuture<ByteBuf> validationFuture = new CompletableFuture<>();
    final CompletableFuture<ByteBuf> lookupfuture = new CompletableFuture<>();
    final String cluster = topicName.getCluster();
    // (1) validate cluster
    getClusterDataIfDifferentCluster(pulsarService, cluster, clientAppId).thenAccept(differentClusterData -> {
        if (differentClusterData != null) {
            if (log.isDebugEnabled()) {
                log.debug("[{}] Redirecting the lookup call to {}/{} cluster={}", clientAppId, differentClusterData.getBrokerServiceUrl(), differentClusterData.getBrokerServiceUrlTls(), cluster);
            }
            validationFuture.complete(newLookupResponse(differentClusterData.getBrokerServiceUrl(), differentClusterData.getBrokerServiceUrlTls(), true, LookupType.Redirect, requestId, false));
        } else {
            // (2) authorize client
            try {
                checkAuthorization(pulsarService, topicName, clientAppId, authenticationData);
            } catch (RestException authException) {
                log.warn("Failed to authorized {} on cluster {}", clientAppId, topicName.toString());
                validationFuture.complete(newLookupErrorResponse(ServerError.AuthorizationError, authException.getMessage(), requestId));
                return;
            } catch (Exception e) {
                log.warn("Unknown error while authorizing {} on cluster {}", clientAppId, topicName.toString());
                validationFuture.completeExceptionally(e);
                return;
            }
            // (3) validate global namespace
            checkLocalOrGetPeerReplicationCluster(pulsarService, topicName.getNamespaceObject()).thenAccept(peerClusterData -> {
                if (peerClusterData == null) {
                    // (4) all validation passed: initiate lookup
                    validationFuture.complete(null);
                    return;
                }
                // request should be redirect to the peer-cluster
                if (StringUtils.isBlank(peerClusterData.getBrokerServiceUrl()) && StringUtils.isBlank(peerClusterData.getBrokerServiceUrl())) {
                    validationFuture.complete(newLookupErrorResponse(ServerError.MetadataError, "Redirected cluster's brokerService url is not configured", requestId));
                    return;
                }
                validationFuture.complete(newLookupResponse(peerClusterData.getBrokerServiceUrl(), peerClusterData.getBrokerServiceUrlTls(), true, LookupType.Redirect, requestId, false));
            }).exceptionally(ex -> {
                validationFuture.complete(newLookupErrorResponse(ServerError.MetadataError, ex.getMessage(), requestId));
                return null;
            });
        }
    }).exceptionally(ex -> {
        validationFuture.completeExceptionally(ex);
        return null;
    });
    // Initiate lookup once validation completes
    validationFuture.thenAccept(validaitonFailureResponse -> {
        if (validaitonFailureResponse != null) {
            lookupfuture.complete(validaitonFailureResponse);
        } else {
            pulsarService.getNamespaceService().getBrokerServiceUrlAsync(topicName, authoritative).thenAccept(lookupResult -> {
                if (log.isDebugEnabled()) {
                    log.debug("[{}] Lookup result {}", topicName.toString(), lookupResult);
                }
                if (!lookupResult.isPresent()) {
                    lookupfuture.complete(newLookupErrorResponse(ServerError.ServiceNotReady, "No broker was available to own " + topicName, requestId));
                    return;
                }
                LookupData lookupData = lookupResult.get().getLookupData();
                if (lookupResult.get().isRedirect()) {
                    boolean newAuthoritative = isLeaderBroker(pulsarService);
                    lookupfuture.complete(newLookupResponse(lookupData.getBrokerUrl(), lookupData.getBrokerUrlTls(), newAuthoritative, LookupType.Redirect, requestId, false));
                } else {
                    // When running in standalone mode we want to redirect the client through the service
                    // url, so that the advertised address configuration is not relevant anymore.
                    boolean redirectThroughServiceUrl = pulsarService.getConfiguration().isRunningStandalone();
                    lookupfuture.complete(newLookupResponse(lookupData.getBrokerUrl(), lookupData.getBrokerUrlTls(), true, /* authoritative */
                    LookupType.Connect, requestId, redirectThroughServiceUrl));
                }
            }).exceptionally(ex -> {
                if (ex instanceof CompletionException && ex.getCause() instanceof IllegalStateException) {
                    log.info("Failed to lookup {} for topic {} with error {}", clientAppId, topicName.toString(), ex.getCause().getMessage());
                } else {
                    log.warn("Failed to lookup {} for topic {} with error {}", clientAppId, topicName.toString(), ex.getMessage(), ex);
                }
                lookupfuture.complete(newLookupErrorResponse(ServerError.ServiceNotReady, ex.getMessage(), requestId));
                return null;
            });
        }
    }).exceptionally(ex -> {
        if (ex instanceof CompletionException && ex.getCause() instanceof IllegalStateException) {
            log.info("Failed to lookup {} for topic {} with error {}", clientAppId, topicName.toString(), ex.getCause().getMessage());
        } else {
            log.warn("Failed to lookup {} for topic {} with error {}", clientAppId, topicName.toString(), ex.getMessage(), ex);
        }
        lookupfuture.complete(newLookupErrorResponse(ServerError.ServiceNotReady, ex.getMessage(), requestId));
        return null;
    });
    return lookupfuture;
}
Also used : PathParam(javax.ws.rs.PathParam) Encoded(javax.ws.rs.Encoded) TopicName(org.apache.pulsar.common.naming.TopicName) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET) URISyntaxException(java.net.URISyntaxException) Path(javax.ws.rs.Path) LoggerFactory(org.slf4j.LoggerFactory) LookupType(org.apache.pulsar.common.api.proto.PulsarApi.CommandLookupTopicResponse.LookupType) CompletableFuture(java.util.concurrent.CompletableFuture) ApiResponses(io.swagger.annotations.ApiResponses) StringUtils(dlshade.org.apache.commons.lang3.StringUtils) ServerError(org.apache.pulsar.common.api.proto.PulsarApi.ServerError) MediaType(javax.ws.rs.core.MediaType) QueryParam(javax.ws.rs.QueryParam) ByteBuf(io.netty.buffer.ByteBuf) DefaultValue(javax.ws.rs.DefaultValue) RestException(org.apache.pulsar.broker.web.RestException) NoSwaggerDocumentation(org.apache.pulsar.broker.web.NoSwaggerDocumentation) URI(java.net.URI) NamespaceBundle(org.apache.pulsar.common.naming.NamespaceBundle) TopicDomain(org.apache.pulsar.common.naming.TopicDomain) Status(javax.ws.rs.core.Response.Status) Logger(org.slf4j.Logger) Commands.newLookupErrorResponse(org.apache.pulsar.common.api.Commands.newLookupErrorResponse) PulsarWebResource(org.apache.pulsar.broker.web.PulsarWebResource) AsyncResponse(javax.ws.rs.container.AsyncResponse) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) LookupData(org.apache.pulsar.common.lookup.data.LookupData) CompletionException(java.util.concurrent.CompletionException) PulsarService(org.apache.pulsar.broker.PulsarService) Suspended(javax.ws.rs.container.Suspended) AuthenticationDataSource(org.apache.pulsar.broker.authentication.AuthenticationDataSource) Response(javax.ws.rs.core.Response) ApiResponse(io.swagger.annotations.ApiResponse) Codec(org.apache.pulsar.common.util.Codec) Optional(java.util.Optional) WebApplicationException(javax.ws.rs.WebApplicationException) Commands.newLookupResponse(org.apache.pulsar.common.api.Commands.newLookupResponse) CompletableFuture(java.util.concurrent.CompletableFuture) CompletionException(java.util.concurrent.CompletionException) RestException(org.apache.pulsar.broker.web.RestException) ByteBuf(io.netty.buffer.ByteBuf) LookupData(org.apache.pulsar.common.lookup.data.LookupData) URISyntaxException(java.net.URISyntaxException) RestException(org.apache.pulsar.broker.web.RestException) CompletionException(java.util.concurrent.CompletionException) WebApplicationException(javax.ws.rs.WebApplicationException)

Aggregations

AuthenticationDataSource (org.apache.pulsar.broker.authentication.AuthenticationDataSource)6 RoleToken (com.yahoo.athenz.auth.token.RoleToken)3 InetSocketAddress (java.net.InetSocketAddress)3 ArrayList (java.util.ArrayList)3 AuthenticationException (javax.naming.AuthenticationException)3 AuthenticationDataCommand (org.apache.pulsar.broker.authentication.AuthenticationDataCommand)3 Test (org.testng.annotations.Test)3 Preconditions.checkNotNull (com.google.common.base.Preconditions.checkNotNull)2 IOException (java.io.IOException)2 CompletableFuture (java.util.concurrent.CompletableFuture)2 TopicName (org.apache.pulsar.common.naming.TopicName)2 Logger (org.slf4j.Logger)2 LoggerFactory (org.slf4j.LoggerFactory)2 StringUtils (dlshade.org.apache.commons.lang3.StringUtils)1 ByteBuf (io.netty.buffer.ByteBuf)1 ApiResponse (io.swagger.annotations.ApiResponse)1 ApiResponses (io.swagger.annotations.ApiResponses)1 URI (java.net.URI)1 URISyntaxException (java.net.URISyntaxException)1 Map (java.util.Map)1