use of org.apache.pulsar.broker.web.RestException in project incubator-pulsar by apache.
the class TopicLookup method lookupTopicAsync.
@GET
@Path("{topic-domain}/{property}/{cluster}/{namespace}/{topic}")
@Produces(MediaType.APPLICATION_JSON)
public void lookupTopicAsync(@PathParam("topic-domain") String topicDomain, @PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, @Suspended AsyncResponse asyncResponse) {
String topicName = Codec.decode(encodedTopic);
TopicDomain domain = null;
try {
domain = TopicDomain.getEnum(topicDomain);
} catch (IllegalArgumentException e) {
log.error("[{}] Invalid topic-domain {}", clientAppId(), topicDomain, e);
throw new RestException(Status.METHOD_NOT_ALLOWED, "Unsupported topic domain " + topicDomain);
}
TopicName topic = TopicName.get(domain.value(), property, cluster, namespace, topicName);
if (!pulsar().getBrokerService().getLookupRequestSemaphore().tryAcquire()) {
log.warn("No broker was found available for topic {}", topic);
asyncResponse.resume(new WebApplicationException(Response.Status.SERVICE_UNAVAILABLE));
return;
}
try {
validateClusterOwnership(topic.getCluster());
checkConnect(topic);
validateGlobalNamespaceOwnership(topic.getNamespaceObject());
} catch (WebApplicationException we) {
// Validation checks failed
log.error("Validation check failed: {}", we.getMessage());
completeLookupResponseExceptionally(asyncResponse, we);
return;
} catch (Throwable t) {
// Validation checks failed with unknown error
log.error("Validation check failed: {}", t.getMessage(), t);
completeLookupResponseExceptionally(asyncResponse, new RestException(t));
return;
}
CompletableFuture<Optional<LookupResult>> lookupFuture = pulsar().getNamespaceService().getBrokerServiceUrlAsync(topic, authoritative);
lookupFuture.thenAccept(optionalResult -> {
if (optionalResult == null || !optionalResult.isPresent()) {
log.warn("No broker was found available for topic {}", topic);
completeLookupResponseExceptionally(asyncResponse, new WebApplicationException(Response.Status.SERVICE_UNAVAILABLE));
return;
}
LookupResult result = optionalResult.get();
// We have found either a broker that owns the topic, or a broker to which we should redirect the client to
if (result.isRedirect()) {
boolean newAuthoritative = this.isLeaderBroker();
URI redirect;
try {
String redirectUrl = isRequestHttps() ? result.getLookupData().getHttpUrlTls() : result.getLookupData().getHttpUrl();
checkNotNull(redirectUrl, "Redirected cluster's service url is not configured");
redirect = new URI(String.format("%s%s%s?authoritative=%s", redirectUrl, "/lookup/v2/destination/", topic.getLookupName(), newAuthoritative));
} catch (URISyntaxException | NullPointerException e) {
log.error("Error in preparing redirect url for {}: {}", topic, e.getMessage(), e);
completeLookupResponseExceptionally(asyncResponse, e);
return;
}
if (log.isDebugEnabled()) {
log.debug("Redirect lookup for topic {} to {}", topic, redirect);
}
completeLookupResponseExceptionally(asyncResponse, new WebApplicationException(Response.temporaryRedirect(redirect).build()));
} else {
// Found broker owning the topic
if (log.isDebugEnabled()) {
log.debug("Lookup succeeded for topic {} -- broker: {}", topic, result.getLookupData());
}
completeLookupResponseSuccessfully(asyncResponse, result.getLookupData());
}
}).exceptionally(exception -> {
log.warn("Failed to lookup broker for topic {}: {}", topic, exception.getMessage(), exception);
completeLookupResponseExceptionally(asyncResponse, exception);
return null;
});
}
use of org.apache.pulsar.broker.web.RestException in project incubator-pulsar by apache.
the class Namespaces method getTopics.
@GET
@Path("/{property}/{namespace}/topics")
@ApiOperation(value = "Get the list of all the topics under a certain namespace.", response = String.class, responseContainer = "Set")
@ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist") })
public List<String> getTopics(@PathParam("property") String property, @PathParam("namespace") String namespace) {
validateAdminAccessOnProperty(property);
validateNamespaceName(property, namespace);
// Validate that namespace exists, throws 404 if it doesn't exist
getNamespacePolicies(namespaceName);
try {
return pulsar().getNamespaceService().getListOfTopics(namespaceName);
} catch (Exception e) {
log.error("Failed to get topics list for namespace {}", namespaceName, e);
throw new RestException(e);
}
}
use of org.apache.pulsar.broker.web.RestException in project incubator-pulsar by apache.
the class NonPersistentTopics method createPartitionedTopic.
@PUT
@Path("/{property}/{namespace}/{topic}/partitions")
@ApiOperation(value = "Create a partitioned topic.", notes = "It needs to be called before creating a producer on a partitioned topic.")
@ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 409, message = "Partitioned topic already exist") })
public void createPartitionedTopic(@PathParam("property") String property, @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, int numPartitions, @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) {
validateTopicName(property, namespace, encodedTopic);
validateAdminAccessOnProperty(topicName.getProperty());
if (numPartitions <= 1) {
throw new RestException(Status.NOT_ACCEPTABLE, "Number of partitions should be more than 1");
}
try {
String path = path(PARTITIONED_TOPIC_PATH_ZNODE, namespaceName.toString(), domain(), topicName.getEncodedLocalName());
byte[] data = jsonMapper().writeValueAsBytes(new PartitionedTopicMetadata(numPartitions));
zkCreateOptimistic(path, data);
// we wait for the data to be synced in all quorums and the observers
Thread.sleep(PARTITIONED_TOPIC_WAIT_SYNC_TIME_MS);
log.info("[{}] Successfully created partitioned topic {}", clientAppId(), topicName);
} catch (KeeperException.NodeExistsException e) {
log.warn("[{}] Failed to create already existing partitioned topic {}", clientAppId(), topicName);
throw new RestException(Status.CONFLICT, "Partitioned topic already exist");
} catch (Exception e) {
log.error("[{}] Failed to create partitioned topic {}", clientAppId(), topicName, e);
throw new RestException(e);
}
}
use of org.apache.pulsar.broker.web.RestException in project incubator-pulsar by apache.
the class AdminTest method properties.
@Test
void properties() throws Exception {
assertEquals(properties.getProperties(), Lists.newArrayList());
verify(properties, times(1)).validateSuperUserAccess();
Set<String> allowedClusters = Sets.newHashSet();
PropertyAdmin propertyAdmin = new PropertyAdmin(Lists.newArrayList("role1", "role2"), allowedClusters);
properties.createProperty("test-property", propertyAdmin);
verify(properties, times(2)).validateSuperUserAccess();
assertEquals(properties.getProperties(), Lists.newArrayList("test-property"));
verify(properties, times(3)).validateSuperUserAccess();
assertEquals(properties.getPropertyAdmin("test-property"), propertyAdmin);
verify(properties, times(4)).validateSuperUserAccess();
PropertyAdmin newPropertyAdmin = new PropertyAdmin(Lists.newArrayList("role1", "other-role"), allowedClusters);
properties.updateProperty("test-property", newPropertyAdmin);
verify(properties, times(5)).validateSuperUserAccess();
// Wait for updateProperty to take effect
Thread.sleep(100);
assertEquals(properties.getPropertyAdmin("test-property"), newPropertyAdmin);
assertNotSame(properties.getPropertyAdmin("test-property"), propertyAdmin);
verify(properties, times(7)).validateSuperUserAccess();
// Check creating existing property
try {
properties.createProperty("test-property", propertyAdmin);
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.CONFLICT.getStatusCode());
}
// Check non-existing property
try {
properties.getPropertyAdmin("non-existing");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
}
try {
properties.updateProperty("xxx-non-existing", newPropertyAdmin);
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
}
// Check deleting non-existing property
try {
properties.deleteProperty("non-existing");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
}
// Test zk failures
mockZookKeeper.failNow(Code.SESSIONEXPIRED);
try {
properties.getProperties();
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
mockZookKeeper.failNow(Code.SESSIONEXPIRED);
try {
properties.getPropertyAdmin("my-property");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
mockZookKeeper.failNow(Code.SESSIONEXPIRED);
try {
properties.updateProperty("my-property", newPropertyAdmin);
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
mockZookKeeper.failNow(Code.SESSIONEXPIRED);
try {
properties.createProperty("test", propertyAdmin);
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
mockZookKeeper.failNow(Code.SESSIONEXPIRED);
try {
properties.deleteProperty("my-property");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
properties.createProperty("error-property", propertyAdmin);
mockZookKeeper.failAfter(2, Code.SESSIONEXPIRED);
try {
properties.deleteProperty("error-property");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
properties.deleteProperty("test-property");
properties.deleteProperty("error-property");
assertEquals(properties.getProperties(), Lists.newArrayList());
// Create a namespace to test deleting a non-empty property
clusters.createCluster("use", new ClusterData());
newPropertyAdmin = new PropertyAdmin(Lists.newArrayList("role1", "other-role"), Sets.newHashSet("use"));
properties.createProperty("my-property", newPropertyAdmin);
namespaces.createNamespace("my-property", "use", "my-namespace", new BundlesData());
try {
properties.deleteProperty("my-property");
fail("should have failed");
} catch (RestException e) {
// Ok
}
// Check name validation
try {
properties.createProperty("test&", propertyAdmin);
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.PRECONDITION_FAILED.getStatusCode());
}
namespaces.deleteNamespace("my-property", "use", "my-namespace", false);
properties.deleteProperty("my-property");
}
use of org.apache.pulsar.broker.web.RestException in project incubator-pulsar by apache.
the class AdminTest method clusters.
@Test
void clusters() throws Exception {
assertEquals(clusters.getClusters(), Lists.newArrayList());
verify(clusters, never()).validateSuperUserAccess();
clusters.createCluster("use", new ClusterData("http://broker.messaging.use.example.com"));
verify(clusters, times(1)).validateSuperUserAccess();
// ensure to read from ZooKeeper directly
clusters.clustersListCache().clear();
assertEquals(clusters.getClusters(), Lists.newArrayList("use"));
// Check creating existing cluster
try {
clusters.createCluster("use", new ClusterData("http://broker.messaging.use.example.com"));
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.CONFLICT.getStatusCode());
}
// Check deleting non-existing cluster
try {
clusters.deleteCluster("usc");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
}
assertEquals(clusters.getCluster("use"), new ClusterData("http://broker.messaging.use.example.com"));
verify(clusters, times(4)).validateSuperUserAccess();
clusters.updateCluster("use", new ClusterData("http://new-broker.messaging.use.example.com"));
verify(clusters, times(5)).validateSuperUserAccess();
assertEquals(clusters.getCluster("use"), new ClusterData("http://new-broker.messaging.use.example.com"));
verify(clusters, times(6)).validateSuperUserAccess();
try {
clusters.getNamespaceIsolationPolicies("use");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), 404);
}
NamespaceIsolationData policyData = new NamespaceIsolationData();
policyData.namespaces = new ArrayList<String>();
policyData.namespaces.add("dummy/colo/ns");
policyData.primary = new ArrayList<String>();
policyData.primary.add("localhost" + ":" + BROKER_WEBSERVICE_PORT);
policyData.secondary = new ArrayList<String>();
policyData.auto_failover_policy = new AutoFailoverPolicyData();
policyData.auto_failover_policy.policy_type = AutoFailoverPolicyType.min_available;
policyData.auto_failover_policy.parameters = new HashMap<String, String>();
policyData.auto_failover_policy.parameters.put("min_limit", "1");
policyData.auto_failover_policy.parameters.put("usage_threshold", "90");
clusters.setNamespaceIsolationPolicy("use", "policy1", policyData);
clusters.getNamespaceIsolationPolicies("use");
try {
clusters.deleteCluster("use");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), 412);
}
clusters.deleteNamespaceIsolationPolicy("use", "policy1");
assertTrue(clusters.getNamespaceIsolationPolicies("use").isEmpty());
clusters.deleteCluster("use");
verify(clusters, times(13)).validateSuperUserAccess();
assertEquals(clusters.getClusters(), Lists.newArrayList());
try {
clusters.getCluster("use");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), 404);
}
try {
clusters.updateCluster("use", new ClusterData());
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), 404);
}
try {
clusters.getNamespaceIsolationPolicies("use");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), 404);
}
// Test zk failures
mockZookKeeper.failNow(Code.SESSIONEXPIRED);
configurationCache.clustersListCache().clear();
try {
clusters.getClusters();
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
mockZookKeeper.failNow(Code.SESSIONEXPIRED);
try {
clusters.createCluster("test", new ClusterData("http://broker.messaging.test.example.com"));
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
mockZookKeeper.failNow(Code.SESSIONEXPIRED);
try {
clusters.updateCluster("test", new ClusterData("http://broker.messaging.test.example.com"));
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
mockZookKeeper.failNow(Code.SESSIONEXPIRED);
try {
clusters.getCluster("test");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
mockZookKeeper.failAfter(0, Code.SESSIONEXPIRED);
try {
clusters.deleteCluster("use");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
mockZookKeeper.failAfter(1, Code.SESSIONEXPIRED);
try {
clusters.deleteCluster("use");
fail("should have failed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
}
// Check name validations
try {
clusters.createCluster("bf@", new ClusterData("http://dummy.messaging.example.com"));
fail("should have filed");
} catch (RestException e) {
assertEquals(e.getResponse().getStatus(), Status.PRECONDITION_FAILED.getStatusCode());
}
}
Aggregations