diff --git a/bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.java b/bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.java index 6fe35deef281b..56d5b0921a3f7 100644 --- a/bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.java +++ b/bouncy-castle/bcfips-include-test/src/test/java/org/apache/pulsar/client/TlsProducerConsumerTest.java @@ -48,10 +48,10 @@ public void testTlsLargeSizeMessage() throws Exception { internalSetUpForClient(true, pulsar.getBrokerServiceUrlTls()); internalSetUpForNamespace(); - Consumer consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + Consumer consumer = pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscribe(); - Producer producer = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic1") + Producer producer = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic1") .create(); for (int i = 0; i < 10; i++) { byte[] message = new byte[messageSize]; @@ -83,7 +83,7 @@ public void testTlsClientAuthOverBinaryProtocol() throws Exception { // Test 1 - Using TLS on binary protocol without sending certs - expect failure internalSetUpForClient(false, pulsar.getBrokerServiceUrlTls()); try { - pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe(); Assert.fail("Server should have failed the TLS handshake since client didn't ."); } catch (Exception ex) { @@ -94,7 +94,7 @@ public void testTlsClientAuthOverBinaryProtocol() throws Exception { // Test 2 - Using TLS on binary protocol - sending certs internalSetUpForClient(true, pulsar.getBrokerServiceUrlTls()); try { - pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe(); log.info("second test success: with certs set, consumer sub success"); } catch (Exception ex) { @@ -113,7 +113,7 @@ public void testTlsClientAuthOverHTTPProtocol() throws Exception { // Test 1 - Using TLS on https without sending certs - expect failure internalSetUpForClient(false, pulsar.getWebServiceAddressTls()); try { - pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe(); Assert.fail("Server should have failed the TLS handshake since client didn't ."); } catch (Exception ex) { @@ -124,7 +124,7 @@ public void testTlsClientAuthOverHTTPProtocol() throws Exception { // Test 2 - Using TLS on https - sending certs internalSetUpForClient(true, pulsar.getWebServiceAddressTls()); try { - pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe(); log.info("second test success: with certs set, consumer sub success"); } catch (Exception ex) { diff --git a/conf/broker.conf b/conf/broker.conf index 664176599eb45..0447b3e05acd4 100644 --- a/conf/broker.conf +++ b/conf/broker.conf @@ -198,10 +198,6 @@ allowAutoTopicCreation=true # The type of topic that is allowed to be automatically created.(partitioned/non-partitioned) allowAutoTopicCreationType=non-partitioned -# If 'allowAutoTopicCreation' is true and the name of the topic contains 'cluster', -# the topic cannot be automatically created. -allowAutoTopicCreationWithLegacyNamingScheme=true - # If 'strictSubscriptionNameVerification' is true, the new subscription name can only contain (a-zA-Z_0-9) and these # special chars -=:. strictlyVerifySubscriptionName=false diff --git a/conf/standalone.conf b/conf/standalone.conf index 571cc0fbbe839..15038c6aa4f22 100644 --- a/conf/standalone.conf +++ b/conf/standalone.conf @@ -1311,10 +1311,6 @@ allowAutoTopicCreation=true # The type of topic that is allowed to be automatically created.(partitioned/non-partitioned) allowAutoTopicCreationType=non-partitioned -# If 'allowAutoTopicCreation' is true and the name of the topic contains 'cluster', -# the topic cannot be automatically created. -allowAutoTopicCreationWithLegacyNamingScheme=true - # If 'strictSubscriptionNameVerification' is true, the new subscription name can only contain (a-zA-Z_0-9) and these # special chars -=:. strictlyVerifySubscriptionName=false diff --git a/managed-ledger/src/test/java/org/apache/bookkeeper/mledger/impl/ManagedLedgerBkTest.java b/managed-ledger/src/test/java/org/apache/bookkeeper/mledger/impl/ManagedLedgerBkTest.java index 1ba3c0f1ed332..77e089be54906 100644 --- a/managed-ledger/src/test/java/org/apache/bookkeeper/mledger/impl/ManagedLedgerBkTest.java +++ b/managed-ledger/src/test/java/org/apache/bookkeeper/mledger/impl/ManagedLedgerBkTest.java @@ -542,7 +542,7 @@ public void testOfflineTopicBacklog() throws Exception { ManagedLedgerConfig config = new ManagedLedgerConfig(); config.setEnsembleSize(1).setWriteQuorumSize(1).setAckQuorumSize(1).setMetadataEnsembleSize(1) .setMetadataAckQuorumSize(1); - ManagedLedger ledger = factory.open("property/cluster/namespace/my-ledger", config); + ManagedLedger ledger = factory.open("property/namespace/my-ledger", config); ManagedCursor cursor = ledger.openCursor("c1"); int num = 1; @@ -560,7 +560,7 @@ public void testOfflineTopicBacklog() throws Exception { ManagedLedgerOfflineBacklog offlineTopicBacklog = new ManagedLedgerOfflineBacklog( DigestType.CRC32, "".getBytes(StandardCharsets.UTF_8), "", false); PersistentOfflineTopicStats offlineTopicStats = offlineTopicBacklog.getEstimatedUnloadedTopicBacklog( - (ManagedLedgerFactoryImpl) factory, "property/cluster/namespace/my-ledger"); + (ManagedLedgerFactoryImpl) factory, "property/namespace/my-ledger"); assertNotNull(offlineTopicStats); } diff --git a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java index e6fd0ae2a71c3..10d1a089c8b7e 100644 --- a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java +++ b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/ServiceConfiguration.java @@ -2360,11 +2360,6 @@ The max allowed delay for delayed delivery (in milliseconds). If the broker rece doc = "The type of topic that is allowed to be automatically created.(partitioned/non-partitioned)" ) private TopicType allowAutoTopicCreationType = TopicType.NON_PARTITIONED; - @FieldContext(category = CATEGORY_SERVER, dynamic = true, - doc = "If 'allowAutoTopicCreation' is true and the name of the topic contains 'cluster'," - + "the topic cannot be automatically created." - ) - private boolean allowAutoTopicCreationWithLegacyNamingScheme = true; @FieldContext(category = CATEGORY_SERVER, dynamic = true, doc = "If 'strictSubscriptionNameVerification' is true, the new subscription name can only contain" + " (a-zA-Z_0-9) and these special chars -=:." diff --git a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java index e4f2ac7e8cd16..ab5399c34eb82 100644 --- a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java +++ b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authorization/PulsarAuthorizationProvider.java @@ -462,19 +462,7 @@ private CompletableFuture updateSubscriptionPermissionAsync(NamespaceName } private CompletableFuture checkAuthorization(TopicName topicName, String role, AuthAction action) { - return checkPermission(topicName, role, action).thenCompose(permission -> - permission ? checkCluster(topicName) : CompletableFuture.completedFuture(false)); - } - - private CompletableFuture checkCluster(TopicName topicName) { - if (topicName.isGlobal() || conf.getClusterName().equals(topicName.getCluster())) { - return CompletableFuture.completedFuture(true); - } - if (log.isDebugEnabled()) { - log.debug("Topic [{}] does not belong to local cluster [{}]", topicName.toString(), conf.getClusterName()); - } - return pulsarResources.getClusterResources().listAsync() - .thenApply(clusters -> clusters.contains(topicName.getCluster())); + return checkPermission(topicName, role, action); } public CompletableFuture checkPermission(TopicName topicName, String role, AuthAction action) { diff --git a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/resources/TenantResources.java b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/resources/TenantResources.java index f82ea0da2c04c..f7dce102c1500 100644 --- a/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/resources/TenantResources.java +++ b/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/resources/TenantResources.java @@ -19,7 +19,6 @@ package org.apache.pulsar.broker.resources; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -48,8 +47,8 @@ public CompletableFuture> listTenantsAsync() { public CompletableFuture deleteTenantAsync(String tenantName) { return getChildrenAsync(joinPath(BASE_POLICIES_PATH, tenantName)) - .thenCompose(clusters -> FutureUtil.waitForAll(clusters.stream() - .map(cluster -> getCache().delete(joinPath(BASE_POLICIES_PATH, tenantName, cluster))) + .thenCompose(namespaces -> FutureUtil.waitForAll(namespaces.stream() + .map(ns -> getCache().delete(joinPath(BASE_POLICIES_PATH, tenantName, ns))) .collect(Collectors.toList())) ).thenCompose(__ -> deleteAsync(joinPath(BASE_POLICIES_PATH, tenantName))); } @@ -85,26 +84,14 @@ public CompletableFuture tenantExistsAsync(String tenantName) { public List getListOfNamespaces(String tenant) throws MetadataStoreException { List namespaces = new ArrayList<>(); - // this will return a cluster in v1 and a namespace in v2 - for (String clusterOrNamespace : getChildren(joinPath(BASE_POLICIES_PATH, tenant))) { - // Then get the list of namespaces - final List children = getChildren(joinPath(BASE_POLICIES_PATH, tenant, clusterOrNamespace)); - if (children == null || children.isEmpty()) { - String namespace = NamespaceName.get(tenant, clusterOrNamespace).toString(); - // if the length is 0 then this is probably a leftover cluster from namespace created - // with the v1 admin format (prop/cluster/ns) and then deleted, so no need to add it to the list - try { - if (get(joinPath(BASE_POLICIES_PATH, namespace)).isPresent()) { - namespaces.add(namespace); - } - } catch (MetadataStoreException.ContentDeserializationException e) { - // not a namespace node + for (String ns : getChildren(joinPath(BASE_POLICIES_PATH, tenant))) { + String namespace = NamespaceName.get(tenant, ns).toString(); + try { + if (get(joinPath(BASE_POLICIES_PATH, namespace)).isPresent()) { + namespaces.add(namespace); } - - } else { - children.forEach(ns -> { - namespaces.add(NamespaceName.get(tenant, clusterOrNamespace, ns).toString()); - }); + } catch (MetadataStoreException.ContentDeserializationException e) { + // not a namespace node } } @@ -112,97 +99,64 @@ public List getListOfNamespaces(String tenant) throws MetadataStoreExcep } public CompletableFuture> getListOfNamespacesAsync(String tenant) { - // this will return a cluster in v1 and a namespace in v2 return getChildrenAsync(joinPath(BASE_POLICIES_PATH, tenant)) - .thenCompose(clusterOrNamespaces -> clusterOrNamespaces.stream().map(key -> - getChildrenAsync(joinPath(BASE_POLICIES_PATH, tenant, key)) - .thenCompose(children -> { - if (children == null || children.isEmpty()) { - String namespace = NamespaceName.get(tenant, key).toString(); - // if the length is 0 then this is probably a leftover cluster from namespace - // created with the v1 admin format (prop/cluster/ns) and then deleted, so no - // need to add it to the list - return getAsync(joinPath(BASE_POLICIES_PATH, namespace)) - .thenApply(opt -> opt.isPresent() ? Collections.singletonList(namespace) - : new ArrayList()) - .exceptionally(ex -> { - Throwable cause = FutureUtil.unwrapCompletionException(ex); - if (cause instanceof MetadataStoreException - .ContentDeserializationException) { - return new ArrayList<>(); - } - throw FutureUtil.wrapToCompletionException(ex); - }); - } else { - CompletableFuture> ret = new CompletableFuture(); - ret.complete(children.stream().map(ns -> NamespaceName.get(tenant, key, ns) - .toString()).collect(Collectors.toList())); - return ret; - } - })).reduce(CompletableFuture.completedFuture(new ArrayList<>()), - (accumulator, n) -> accumulator.thenCompose(namespaces -> n.thenApply(m -> { - namespaces.addAll(m); - return namespaces; - })))); - } - - public CompletableFuture> getActiveNamespaces(String tenant, String cluster) { - return getChildrenAsync(joinPath(BASE_POLICIES_PATH, tenant, cluster)); + .thenCompose(nsList -> nsList.stream().map(key -> { + String namespace = NamespaceName.get(tenant, key).toString(); + return getAsync(joinPath(BASE_POLICIES_PATH, namespace)) + .thenApply(opt -> opt.isPresent() + ? List.of(namespace) + : new ArrayList()) + .exceptionally(ex -> { + Throwable cause = FutureUtil.unwrapCompletionException(ex); + if (cause instanceof MetadataStoreException + .ContentDeserializationException) { + return new ArrayList<>(); + } + throw FutureUtil.wrapToCompletionException(ex); + }); + }).reduce(CompletableFuture.completedFuture(new ArrayList<>()), + (accumulator, n) -> accumulator.thenCompose(namespaces -> n.thenApply(m -> { + namespaces.addAll(m); + return namespaces; + })))); } public CompletableFuture hasActiveNamespace(String tenant) { CompletableFuture activeNamespaceFuture = new CompletableFuture<>(); - getChildrenAsync(joinPath(BASE_POLICIES_PATH, tenant)).thenAccept(clusterOrNamespaceList -> { - if (clusterOrNamespaceList == null || clusterOrNamespaceList.isEmpty()) { + getChildrenAsync(joinPath(BASE_POLICIES_PATH, tenant)).thenAccept(nsList -> { + if (nsList == null || nsList.isEmpty()) { activeNamespaceFuture.complete(null); return; } List> activeNamespaceListFuture = new ArrayList<>(); - clusterOrNamespaceList.forEach(clusterOrNamespace -> { - // get list of active V1 namespace + nsList.forEach(ns -> { CompletableFuture checkNs = new CompletableFuture<>(); activeNamespaceListFuture.add(checkNs); - getChildrenAsync(joinPath(BASE_POLICIES_PATH, tenant, clusterOrNamespace)) - .whenComplete((children, ex) -> { - if (ex != null) { - checkNs.completeExceptionally(ex); - return; - } - if (children != null && !children.isEmpty()) { - checkNs.completeExceptionally( - new IllegalStateException("The tenant still has active namespaces")); - return; - } - String namespace = NamespaceName.get(tenant, clusterOrNamespace).toString(); - // if the length is 0 then this is probably a leftover cluster from namespace - // created - // with the v1 admin format (prop/cluster/ns) and then deleted, so no need to - // add it to the list - getAsync(joinPath(BASE_POLICIES_PATH, namespace)).thenApply(data -> { - if (data.isPresent()) { - checkNs.completeExceptionally(new IllegalStateException( - "The tenant still has active namespaces")); - } else { - checkNs.complete(null); - } - return null; - }).exceptionally(ex2 -> { - if (ex2.getCause() instanceof MetadataStoreException.ContentDeserializationException) { - // it's not a valid namespace-node - checkNs.complete(null); - } else { - checkNs.completeExceptionally(ex2); - } - return null; - }); - }); - FutureUtil.waitForAll(activeNamespaceListFuture).thenAccept(r -> { - activeNamespaceFuture.complete(null); - }).exceptionally(ex -> { - activeNamespaceFuture.completeExceptionally(ex.getCause()); + String namespace = NamespaceName.get(tenant, ns).toString(); + getAsync(joinPath(BASE_POLICIES_PATH, namespace)).thenApply(data -> { + if (data.isPresent()) { + checkNs.completeExceptionally(new IllegalStateException( + "The tenant still has active namespaces")); + } else { + checkNs.complete(null); + } + return null; + }).exceptionally(ex2 -> { + if (ex2.getCause() instanceof MetadataStoreException.ContentDeserializationException) { + // it's not a valid namespace-node + checkNs.complete(null); + } else { + checkNs.completeExceptionally(ex2); + } return null; }); }); + FutureUtil.waitForAll(activeNamespaceListFuture).thenAccept(r -> { + activeNamespaceFuture.complete(null); + }).exceptionally(ex -> { + activeNamespaceFuture.completeExceptionally(ex.getCause()); + return null; + }); }).exceptionally(ex -> { activeNamespaceFuture.completeExceptionally(ex.getCause()); return null; diff --git a/pulsar-broker-common/src/test/java/org/apache/pulsar/broker/resources/TopicResourcesTest.java b/pulsar-broker-common/src/test/java/org/apache/pulsar/broker/resources/TopicResourcesTest.java index 13c8f8d01c019..05632fba683ab 100644 --- a/pulsar-broker-common/src/test/java/org/apache/pulsar/broker/resources/TopicResourcesTest.java +++ b/pulsar-broker-common/src/test/java/org/apache/pulsar/broker/resources/TopicResourcesTest.java @@ -57,16 +57,6 @@ public void testListenerInvokedWhenTopicCreated() { verify(listener).onTopicEvent("persistent://tenant/namespace/topic", NotificationType.Created); } - @Test - public void testListenerInvokedWhenTopicV1Created() { - TopicListener listener = mock(TopicListener.class); - when(listener.getNamespaceName()).thenReturn(NamespaceName.get("tenant/cluster/namespace")); - topicResources.registerPersistentTopicListener(listener); - topicResources.handleNotification(new Notification(NotificationType.Created, - "/managed-ledgers/tenant/cluster/namespace/persistent/topic")); - verify(listener).onTopicEvent("persistent://tenant/cluster/namespace/topic", NotificationType.Created); - } - @Test public void testListenerInvokedWhenTopicDeleted() { TopicListener listener = mock(TopicListener.class); diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/PulsarClusterMetadataSetup.java b/pulsar-broker/src/main/java/org/apache/pulsar/PulsarClusterMetadataSetup.java index 31b12795e20c4..383cb89fbb31a 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/PulsarClusterMetadataSetup.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/PulsarClusterMetadataSetup.java @@ -377,12 +377,6 @@ private static void initializeCluster(Arguments arguments, int bundleNumberForDe resources.getClusterResources().createCluster(arguments.cluster, clusterData); } - // Create marker for "global" cluster - ClusterData globalClusterData = ClusterData.builder().build(); - if (!resources.getClusterResources().clusterExists("global")) { - resources.getClusterResources().createCluster("global", globalClusterData); - } - // Create public tenant, allowed to use this same cluster, along with other clusters createTenantIfAbsent(resources, TopicName.PUBLIC_TENANT, arguments.cluster); diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java index 62b2987487abd..5670579372590 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/PulsarService.java @@ -94,7 +94,6 @@ import org.apache.pulsar.broker.loadbalance.LoadResourceQuotaUpdaterTask; import org.apache.pulsar.broker.loadbalance.LoadSheddingTask; import org.apache.pulsar.broker.loadbalance.extensions.ExtensibleLoadManagerImpl; -import org.apache.pulsar.broker.lookup.v1.TopicLookup; import org.apache.pulsar.broker.namespace.NamespaceService; import org.apache.pulsar.broker.protocol.ProtocolHandlers; import org.apache.pulsar.broker.qos.DefaultMonotonicClock; @@ -160,7 +159,6 @@ import org.apache.pulsar.common.naming.NamespaceBundle; import org.apache.pulsar.common.naming.NamespaceName; import org.apache.pulsar.common.naming.TopicName; -import org.apache.pulsar.common.naming.TopicVersion; import org.apache.pulsar.common.policies.data.ClusterDataImpl; import org.apache.pulsar.common.policies.data.OffloadPoliciesImpl; import org.apache.pulsar.common.protocol.schema.SchemaStorage; @@ -1205,14 +1203,12 @@ private void addWebServerHandlers(WebService webService, // Add admin rest resources webService.addRestResource("/", false, vipAttributeMap, false, VipStatus.class); - webService.addRestResources("/admin", - true, attributeMap, false, "org.apache.pulsar.broker.admin.v1"); webService.addRestResources("/admin/v2", true, attributeMap, true, "org.apache.pulsar.broker.admin.v2"); webService.addRestResources("/admin/v3", true, attributeMap, true, "org.apache.pulsar.broker.admin.v3"); webService.addRestResource("/lookup", - true, attributeMap, true, TopicLookup.class, + true, attributeMap, true, org.apache.pulsar.broker.lookup.v2.TopicLookup.class); webService.addRestResource("/topics", true, attributeMap, true, Topics.class); @@ -1302,14 +1298,13 @@ private void addWebSocketServiceHandler(WebService webService, this.webSocketService.start(); addWebSocketServlet(new WebSocketProducerServlet(webSocketService), attributeMap, - WebSocketProducerServlet.SERVLET_PATH, WebSocketProducerServlet.SERVLET_PATH_V2); + WebSocketProducerServlet.SERVLET_PATH); addWebSocketServlet(new WebSocketConsumerServlet(webSocketService), attributeMap, - WebSocketConsumerServlet.SERVLET_PATH, WebSocketConsumerServlet.SERVLET_PATH_V2); + WebSocketConsumerServlet.SERVLET_PATH); addWebSocketServlet(new WebSocketReaderServlet(webSocketService), attributeMap, - WebSocketReaderServlet.SERVLET_PATH, - WebSocketReaderServlet.SERVLET_PATH_V2); + WebSocketReaderServlet.SERVLET_PATH); addWebSocketServlet(new WebSocketMultiTopicConsumerServlet(webSocketService), attributeMap, WebSocketMultiTopicConsumerServlet.SERVLET_PATH); @@ -2265,7 +2260,7 @@ private TopicPoliciesService initTopicPoliciesService() throws Exception { * * @return CompletableFuture */ - public CompletableFuture runHealthCheck(TopicVersion topicVersion, String clientId) { + public CompletableFuture runHealthCheck(String clientId) { if (!isRunning()) { return CompletableFuture.failedFuture(new PulsarServerException("Broker is not running")); } @@ -2273,7 +2268,7 @@ public CompletableFuture runHealthCheck(TopicVersion topicVersion, String if (localHealthChecker == null) { return CompletableFuture.failedFuture(new PulsarServerException("Broker is not running")); } - return localHealthChecker.checkHealth(topicVersion, clientId); + return localHealthChecker.checkHealth(clientId); } @VisibleForTesting diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java index 9ea5b4c33cc09..ea8e584c6e398 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -56,8 +57,6 @@ import org.apache.pulsar.client.admin.PulsarAdmin; import org.apache.pulsar.client.admin.PulsarAdminException; import org.apache.pulsar.client.admin.internal.TopicsImpl; -import org.apache.pulsar.common.naming.Constants; -import org.apache.pulsar.common.naming.NamespaceBundle; import org.apache.pulsar.common.naming.NamespaceName; import org.apache.pulsar.common.naming.TopicDomain; import org.apache.pulsar.common.naming.TopicName; @@ -117,15 +116,8 @@ public void validateSuperUserAccess() { // This is a stub method for Mockito @Override - protected void validateAdminAccessForTenant(String property) { - super.validateAdminAccessForTenant(property); - } - - // This is a stub method for Mockito - @Override - protected void validateBundleOwnership(String property, String cluster, String namespace, boolean authoritative, - boolean readOnly, NamespaceBundle bundle) { - super.validateBundleOwnership(property, cluster, namespace, authoritative, readOnly, bundle); + protected void validateAdminAccessForTenant(String tenant) { + super.validateAdminAccessForTenant(tenant); } // This is a stub method for Mockito @@ -214,11 +206,11 @@ private CompletableFuture tryCreatePartitionAsync(final int partition) { return result; } - protected void validateNamespaceName(String property, String namespace) { + protected void validateNamespaceName(String tenant, String namespace) { try { - this.namespaceName = NamespaceName.get(property, namespace); + this.namespaceName = NamespaceName.get(tenant, namespace); } catch (IllegalArgumentException e) { - log.warn("[{}] Invalid namespace name [{}/{}]", clientAppId(), property, namespace); + log.warn("[{}] Invalid namespace name [{}/{}]", clientAppId(), tenant, namespace); throw new RestException(Status.PRECONDITION_FAILED, "Namespace name is not valid"); } } @@ -235,29 +227,19 @@ protected void validateGlobalNamespaceOwnership() { throw new RestException(Status.SERVICE_UNAVAILABLE, "Failed to validate global cluster configuration"); } } - @Deprecated - protected void validateNamespaceName(String property, String cluster, String namespace) { - try { - this.namespaceName = NamespaceName.get(property, cluster, namespace); - } catch (IllegalArgumentException e) { - log.warn("[{}] Invalid namespace name [{}/{}/{}]", clientAppId(), property, cluster, namespace); - throw new RestException(Status.PRECONDITION_FAILED, "Namespace name is not valid"); - } - } - - protected void validateTopicName(String property, String namespace, String encodedTopic) { + protected void validateTopicName(String tenant, String namespace, String encodedTopic) { String topic = Codec.decode(encodedTopic); try { - this.namespaceName = NamespaceName.get(property, namespace); + this.namespaceName = NamespaceName.get(tenant, namespace); this.topicName = TopicName.get(domain(), namespaceName, topic); } catch (IllegalArgumentException e) { - log.warn("[{}] Invalid topic name [{}://{}/{}/{}]", clientAppId(), domain(), property, namespace, topic); + log.warn("[{}] Invalid topic name [{}://{}/{}/{}]", clientAppId(), domain(), tenant, namespace, topic); throw new RestException(Status.PRECONDITION_FAILED, "Topic name is not valid"); } } - protected void validatePersistentTopicName(String property, String namespace, String encodedTopic) { - validateTopicName(property, namespace, encodedTopic); + protected void validatePersistentTopicName(String tenant, String namespace, String encodedTopic) { + validateTopicName(tenant, namespace, encodedTopic); if (topicName.getDomain() != TopicDomain.persistent) { throw new RestException(Status.NOT_ACCEPTABLE, "Need to provide a persistent topic name"); } @@ -282,27 +264,6 @@ protected CompletableFuture validatePartitionedTopicMetadataAsync() { }); } - @Deprecated - protected void validateTopicName(String property, String cluster, String namespace, String encodedTopic) { - String topic = Codec.decode(encodedTopic); - try { - this.namespaceName = NamespaceName.get(property, cluster, namespace); - this.topicName = TopicName.get(domain(), namespaceName, topic); - } catch (IllegalArgumentException e) { - log.warn("[{}] Invalid topic name {}://{}/{}/{}/{}", clientAppId(), domain(), property, cluster, - namespace, topic); - throw new RestException(Status.PRECONDITION_FAILED, "Topic name is not valid"); - } - } - - @Deprecated - protected void validatePersistentTopicName(String property, String cluster, String namespace, String encodedTopic) { - validateTopicName(property, cluster, namespace, encodedTopic); - if (topicName.getDomain() != TopicDomain.persistent) { - throw new RestException(Status.NOT_ACCEPTABLE, "Need to provide a persistent topic name"); - } - } - protected WorkerService validateAndGetWorkerService() { try { return pulsar().getWorkerService(); @@ -453,10 +414,7 @@ protected ObjectReader objectReader() { protected Set clusters() { try { - // Remove "global" cluster from returned list - Set clusters = clusterResources().list().stream() - .filter(cluster -> !Constants.GLOBAL_CLUSTER.equals(cluster)).collect(Collectors.toSet()); - return clusters; + return new HashSet<>(clusterResources().list()); } catch (Exception e) { throw new RestException(e); } @@ -464,11 +422,7 @@ protected Set clusters() { protected CompletableFuture> clustersAsync() { return clusterResources().listAsync() - .thenApply(list -> - list.stream() - .filter(cluster -> !Constants.GLOBAL_CLUSTER.equals(cluster)) - .collect(Collectors.toSet()) - ); + .thenApply(HashSet::new); } protected void setServletContext(ServletContext servletContext) { @@ -487,7 +441,6 @@ protected CompletableFuture getPartitionedTopicMetadat // serve/redirect request else fail partitioned-metadata-request so, client fails while creating // producer/consumer return validateTopicOperationAsync(topicName, TopicOperation.LOOKUP) - .thenCompose(__ -> validateClusterOwnershipAsync(topicName.getCluster())) .thenCompose(__ -> validateGlobalNamespaceOwnershipAsync(topicName.getNamespaceObject())) .thenCompose(__ -> { if (checkAllowAutoCreation) { @@ -507,12 +460,6 @@ protected CompletableFuture validateClusterExistsAsync(String cluster) { }); } - protected Policies getNamespacePolicies(String tenant, String cluster, String namespace) { - NamespaceName ns = NamespaceName.get(tenant, cluster, namespace); - - return getNamespacePolicies(ns); - } - /** * Directly get the replication clusters for a namespace, without checking allowed clusters. */ diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/BrokersBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/BrokersBase.java index 3ee2a1285d3b8..47b78bda80695 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/BrokersBase.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/BrokersBase.java @@ -51,7 +51,6 @@ import org.apache.pulsar.broker.loadbalance.LeaderBroker; import org.apache.pulsar.broker.web.RestException; import org.apache.pulsar.common.conf.InternalConfigurationData; -import org.apache.pulsar.common.naming.TopicVersion; import org.apache.pulsar.common.policies.data.BrokerInfo; import org.apache.pulsar.common.policies.data.BrokerOperation; import org.apache.pulsar.common.policies.data.NamespaceOwnershipStatus; @@ -365,8 +364,6 @@ public void isReady(@Suspended AsyncResponse asyncResponse) { @ApiResponse(code = 500, message = "Internal server error"), @ApiResponse(code = 503, message = "Service unavailable")}) public void healthCheck(@Suspended AsyncResponse asyncResponse, - @ApiParam(value = "Topic Version") - @QueryParam("topicVersion") TopicVersion topicVersion, @QueryParam("brokerId") String brokerId) { if (pulsar().getState() == State.Closed || pulsar().getState() == State.Closing) { asyncResponse.resume(Response.status(Status.SERVICE_UNAVAILABLE).build()); @@ -377,7 +374,7 @@ public void healthCheck(@Suspended AsyncResponse asyncResponse, .thenCompose(__ -> maybeRedirectToBroker( StringUtils.isBlank(brokerId) ? pulsar().getBrokerId() : brokerId)) .thenAccept(__ -> checkDeadlockedThreads()) - .thenCompose(__ -> internalRunHealthCheck(topicVersion)) + .thenCompose(__ -> internalRunHealthCheck()) .thenAccept(__ -> { LOG.info("[{}] Successfully run health check.", clientAppId()); asyncResponse.resume(Response.ok("ok").build()); @@ -414,8 +411,8 @@ private void checkDeadlockedThreads() { } } - private CompletableFuture internalRunHealthCheck(TopicVersion topicVersion) { - return pulsar().runHealthCheck(topicVersion, clientAppId()); + private CompletableFuture internalRunHealthCheck() { + return pulsar().runHealthCheck(clientAppId()); } private CompletableFuture internalDeleteDynamicConfigurationOnMetadataAsync(String configName) { diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/ClustersBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/ClustersBase.java index 0ae18fc2e54f3..e91eedae1b9a9 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/ClustersBase.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/ClustersBase.java @@ -57,7 +57,6 @@ import org.apache.pulsar.broker.admin.AdminResource; import org.apache.pulsar.broker.web.RestException; import org.apache.pulsar.client.admin.PulsarAdmin; -import org.apache.pulsar.common.naming.Constants; import org.apache.pulsar.common.naming.NamedEntity; import org.apache.pulsar.common.naming.NamespaceName; import org.apache.pulsar.common.policies.data.BrokerNamespaceIsolationData; @@ -93,10 +92,7 @@ public class ClustersBase extends AdminResource { }) public void getClusters(@Suspended AsyncResponse asyncResponse) { clusterResources().listAsync() - .thenApply(clusters -> clusters.stream() - // Remove "global" cluster from returned list - .filter(cluster -> !Constants.GLOBAL_CLUSTER.equals(cluster)) - .collect(Collectors.toSet())) + .thenApply(HashSet::new) .thenAccept(asyncResponse::resume) .exceptionally(ex -> { log.error("[{}] Failed to get clusters {}", clientAppId(), ex); diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java index 8cf45f08cdac2..0f626eb738581 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/NamespacesBase.java @@ -468,27 +468,14 @@ private CompletableFuture precheckWhenDeleteNamespace(NamespaceName ns throw new RestException(Status.METHOD_NOT_ALLOWED, "Broker doesn't allow forced deletion of namespaces"); } - // ensure that non-global namespace is directed to the correct cluster - if (!nsName.isGlobal()) { - return validateClusterOwnershipAsync(nsName.getCluster()); - } else { - return CompletableFuture.completedFuture(null); - } + return CompletableFuture.completedFuture(null); }) .thenCompose(__ -> namespaceResources().getPoliciesAsync(nsName)) .thenCompose(policiesOpt -> { if (policiesOpt.isEmpty()) { throw new RestException(Status.NOT_FOUND, "Namespace " + nsName + " does not exist."); } - if (!nsName.isGlobal()) { - return CompletableFuture.completedFuture(null); - } Policies policies = policiesOpt.get(); - // Just keep the behavior of V1 namespace being the same as before. - if (!nsName.isV2() && policies.replication_clusters.isEmpty() - && policies.allowed_clusters.isEmpty()) { - return CompletableFuture.completedFuture(policies); - } String cluster = policies.getClusterThatCanDeleteNamespace(); if (cluster == null) { // There are still more than one clusters configured for the global namespace @@ -562,63 +549,51 @@ protected CompletableFuture internalDeleteNamespaceBundleAsync(String bund clientAppId(), namespaceName, bundleRange, authoritative, force); return validateNamespaceOperationAsync(namespaceName, NamespaceOperation.DELETE_BUNDLE) .thenCompose(__ -> validatePoliciesReadOnlyAccessAsync()) - .thenCompose(__ -> { - if (!namespaceName.isGlobal()) { - return validateClusterOwnershipAsync(namespaceName.getCluster()); - } - return CompletableFuture.completedFuture(null); - }) .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) .thenCompose(policies -> { CompletableFuture future = CompletableFuture.completedFuture(null); - if (namespaceName.isGlobal()) { - // Just keep the behavior of V1 namespace being the same as before. - if (!namespaceName.isV2() && policies.replication_clusters.isEmpty() - && policies.allowed_clusters.isEmpty()) { - return CompletableFuture.completedFuture(null); - } - String cluster = policies.getClusterThatCanDeleteNamespace(); - if (cluster == null) { - // There are still more than one clusters configured for the global namespace - throw new RestException(Status.PRECONDITION_FAILED, "Cannot delete the global namespace " - + namespaceName - + ". There are still more than one replication clusters configured."); - } - if (!cluster.equals(config().getClusterName())) { // No need to change. - // the only replication cluster is other cluster, redirect - future = clusterResources().getClusterAsync(cluster) - .thenCompose(clusterData -> { - if (clusterData.isEmpty()) { - throw new RestException(Status.NOT_FOUND, - "Cluster " + cluster + " does not exist"); - } - ClusterData replClusterData = clusterData.get(); - URL replClusterUrl; - try { - if (!config().isTlsEnabled() || !isRequestHttps()) { - replClusterUrl = new URL(replClusterData.getServiceUrl()); - } else if (StringUtils.isNotBlank(replClusterData.getServiceUrlTls())) { - replClusterUrl = new URL(replClusterData.getServiceUrlTls()); - } else { - throw new RestException(Status.PRECONDITION_FAILED, - "The replication cluster does not provide TLS encrypted " - + "service"); - } - } catch (MalformedURLException malformedURLException) { - throw new RestException(malformedURLException); + String cluster = policies.getClusterThatCanDeleteNamespace(); + if (cluster == null) { + // There are still more than one clusters configured for the global namespace + throw new RestException(Status.PRECONDITION_FAILED, "Cannot delete the global namespace " + + namespaceName + + ". There are still more than one replication clusters configured."); + } + if (!cluster.equals(config().getClusterName())) { + // the only replication cluster is other cluster, redirect + future = clusterResources().getClusterAsync(cluster) + .thenCompose(clusterData -> { + if (clusterData.isEmpty()) { + throw new RestException(Status.NOT_FOUND, + "Cluster " + cluster + " does not exist"); + } + ClusterData replClusterData = clusterData.get(); + URL replClusterUrl; + try { + if (!config().isTlsEnabled() || !isRequestHttps()) { + replClusterUrl = new URL(replClusterData.getServiceUrl()); + } else if (StringUtils.isNotBlank(replClusterData.getServiceUrlTls())) { + replClusterUrl = new URL(replClusterData.getServiceUrlTls()); + } else { + throw new RestException(Status.PRECONDITION_FAILED, + "The replication cluster does not provide TLS encrypted " + + "service"); } + } catch (MalformedURLException malformedURLException) { + throw new RestException(malformedURLException); + } - URI redirect = - UriBuilder.fromUri(uri.getRequestUri()).host(replClusterUrl.getHost()) - .port(replClusterUrl.getPort()) - .replaceQueryParam("authoritative", false).build(); - if (log.isDebugEnabled()) { - log.debug("[{}] Redirecting the rest call to {}: cluster={}", - clientAppId(), redirect, cluster); - } - throw new WebApplicationException(Response.temporaryRedirect(redirect).build()); - }); - } + URI redirect = + UriBuilder.fromUri(uri.getRequestUri()).host(replClusterUrl.getHost()) + .port(replClusterUrl.getPort()) + .replaceQueryParam("authoritative", false).build(); + if (log.isDebugEnabled()) { + log.debug("[{}] Redirecting the rest call to {}: cluster={}", + clientAppId(), redirect, cluster); + } + throw new WebApplicationException( + Response.temporaryRedirect(redirect).build()); + }); } return future .thenCompose(__ -> @@ -817,12 +792,7 @@ protected CompletableFuture internalRevokePermissionsOnSubscriptionAsync(S */ protected CompletableFuture> internalGetNamespaceReplicationClustersAsync() { return validateNamespacePolicyOperationAsync(namespaceName, PolicyName.REPLICATION, PolicyOperation.READ) - .thenAccept(__ -> { - if (!namespaceName.isGlobal()) { - throw new RestException(Status.PRECONDITION_FAILED, - "Cannot get the replication clusters for a non-global namespace"); - } - }).thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) + .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) .thenApply(policies -> policies.replication_clusters); } @@ -835,17 +805,7 @@ protected CompletableFuture internalSetNamespaceReplicationClusters(List replicationClusterSet = Sets.newHashSet(clusterIds); - if (replicationClusterSet.contains("global")) { - throw new RestException(Status.PRECONDITION_FAILED, - "Cannot specify global in the list of replication clusters"); - } - return replicationClusterSet; + return Sets.newHashSet(clusterIds); }).thenCompose(replicationClusterSet -> clustersAsync() .thenCompose(clusters -> { List> futures = @@ -1340,14 +1300,8 @@ protected CompletableFuture internalUnloadNamespaceAsync() { return validateSuperUserAccessAsync() .thenCompose(__ -> { log.info("[{}] Unloading namespace {}", clientAppId(), namespaceName); - if (namespaceName.isGlobal()) { - // check cluster ownership for a given global namespace: redirect if peer-cluster owns it - return validateGlobalNamespaceOwnershipAsync(namespaceName); - } else { - return validateClusterOwnershipAsync(namespaceName.getCluster()) - .thenCompose(ignore -> validateClusterForTenantAsync(namespaceName.getTenant(), - namespaceName.getCluster())); - } + // check cluster ownership for a given global namespace: redirect if peer-cluster owns it + return validateGlobalNamespaceOwnershipAsync(namespaceName); }) .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) .thenCompose(policies -> { @@ -1371,13 +1325,8 @@ protected CompletableFuture internalSetBookieAffinityGroupAsync(BookieAffi return validateSuperUserAccessAsync().thenCompose(__ -> { log.info("[{}] Setting bookie affinity group {} for namespace {}", clientAppId(), bookieAffinityGroup, this.namespaceName); - if (namespaceName.isGlobal()) { - // check cluster ownership for a given global namespace: redirect if peer-cluster owns it - return validateGlobalNamespaceOwnershipAsync(namespaceName); - } else { - return validateClusterOwnershipAsync(namespaceName.getCluster()).thenCompose( - unused -> validateClusterForTenantAsync(namespaceName.getTenant(), namespaceName.getCluster())); - } + // check cluster ownership for a given global namespace: redirect if peer-cluster owns it + return validateGlobalNamespaceOwnershipAsync(namespaceName); }).thenCompose(__ -> getDefaultBundleDataAsync().thenCompose( defaultBundleData -> getLocalPolicies().setLocalPoliciesWithCreateAsync(namespaceName, oldPolicies -> oldPolicies.map(policies -> new LocalPolicies(policies.bundles, bookieAffinityGroup, @@ -1394,13 +1343,8 @@ protected CompletableFuture internalDeleteBookieAffinityGroupAsync() { protected CompletableFuture internalGetBookieAffinityGroupAsync() { return validateSuperUserAccessAsync().thenCompose(__ -> { - if (namespaceName.isGlobal()) { - // check cluster ownership for a given global namespace: redirect if peer-cluster owns it - return validateGlobalNamespaceOwnershipAsync(namespaceName); - } else { - return validateClusterOwnershipAsync(namespaceName.getCluster()).thenCompose( - unused -> validateClusterForTenantAsync(namespaceName.getTenant(), namespaceName.getCluster())); - } + // check cluster ownership for a given global namespace: redirect if peer-cluster owns it + return validateGlobalNamespaceOwnershipAsync(namespaceName); }).thenCompose(__ -> getLocalPolicies().getLocalPoliciesAsync(namespaceName)) .thenApply(policies -> policies.orElseThrow(() -> new RestException(Status.NOT_FOUND, "Namespace local-policies does not exist")).bookieAffinityGroup); @@ -1505,14 +1449,8 @@ public CompletableFuture internalUnloadNamespaceBundleAsync(String bundleR ) .thenCompose(isOwnedByLocalCluster -> { if (!isOwnedByLocalCluster) { - if (namespaceName.isGlobal()) { - // check cluster ownership for a given global namespace: redirect if peer-cluster owns it - return validateGlobalNamespaceOwnershipAsync(namespaceName); - } else { - return validateClusterOwnershipAsync(namespaceName.getCluster()) - .thenCompose(__ -> validateClusterForTenantAsync(namespaceName.getTenant(), - namespaceName.getCluster())); - } + // check cluster ownership for a given global namespace: redirect if peer-cluster owns it + return validateGlobalNamespaceOwnershipAsync(namespaceName); } else { return CompletableFuture.completedFuture(null); } @@ -1562,14 +1500,8 @@ protected CompletableFuture internalSplitNamespaceBundleAsync(String bundl } }) .thenCompose(__ -> { - if (namespaceName.isGlobal()) { - // check cluster ownership for a given global namespace: redirect if peer-cluster owns it - return validateGlobalNamespaceOwnershipAsync(namespaceName); - } else { - return validateClusterOwnershipAsync(namespaceName.getCluster()) - .thenCompose(ignore -> validateClusterForTenantAsync(namespaceName.getTenant(), - namespaceName.getCluster())); - } + // check cluster ownership for a given global namespace: redirect if peer-cluster owns it + return validateGlobalNamespaceOwnershipAsync(namespaceName); }) .thenCompose(__ -> validatePoliciesReadOnlyAccessAsync()) .thenCompose(__ -> getBundleRangeAsync(bundleName)) @@ -1940,13 +1872,8 @@ protected void internalClearNamespaceBundleBacklog(String bundleRange, boolean a Policies policies = getNamespacePolicies(namespaceName); - if (namespaceName.isGlobal()) { - // check cluster ownership for a given global namespace: redirect if peer-cluster owns it - validateGlobalNamespaceOwnership(namespaceName); - } else { - validateClusterOwnership(namespaceName.getCluster()); - validateClusterForTenant(namespaceName.getTenant(), namespaceName.getCluster()); - } + // check cluster ownership for a given global namespace: redirect if peer-cluster owns it + validateGlobalNamespaceOwnership(namespaceName); validateNamespaceBundleOwnership(namespaceName, policies.bundles, bundleRange, authoritative, true); @@ -2007,13 +1934,8 @@ protected void internalClearNamespaceBundleBacklogForSubscription(String subscri Policies policies = getNamespacePolicies(namespaceName); - if (namespaceName.isGlobal()) { - // check cluster ownership for a given global namespace: redirect if peer-cluster owns it - validateGlobalNamespaceOwnership(namespaceName); - } else { - validateClusterOwnership(namespaceName.getCluster()); - validateClusterForTenant(namespaceName.getTenant(), namespaceName.getCluster()); - } + // check cluster ownership for a given global namespace: redirect if peer-cluster owns it + validateGlobalNamespaceOwnership(namespaceName); validateNamespaceBundleOwnership(namespaceName, policies.bundles, bundleRange, authoritative, true); @@ -2051,15 +1973,7 @@ protected CompletableFuture internalUnsubscribeNamespaceBundleAsync(String checkNotNull(bundleRange, "BundleRange should not be null"); return validateNamespaceOperationAsync(namespaceName, NamespaceOperation.UNSUBSCRIBE) - .thenCompose(__ -> { - if (namespaceName.isGlobal()) { - // check cluster ownership for a given global namespace: redirect if peer-cluster owns it - return validateGlobalNamespaceOwnershipAsync(namespaceName); - } - return validateClusterOwnershipAsync(namespaceName.getCluster()) - .thenCompose(unused -> validateClusterForTenantAsync(namespaceName.getTenant(), - namespaceName.getCluster())); - }) + .thenCompose(__ -> validateGlobalNamespaceOwnershipAsync(namespaceName)) .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) .thenCompose(policies -> validateNamespaceBundleOwnershipAsync(namespaceName, policies.bundles, bundleRange, @@ -3227,14 +3141,8 @@ protected CompletableFuture internalSetNamespaceAllowedClusters(List FutureUtil.waitForAll(clusterIds.stream().map(clusterId -> validateClusterForTenantAsync(namespaceName.getTenant(), clusterId)) .collect(Collectors.toList()))) - // Allowed clusters should include all the existed replication clusters and could not contain global - // cluster. .thenCompose(__ -> { checkNotNull(clusterIds, "ClusterIds should not be null"); - if (clusterIds.contains("global")) { - throw new RestException(Status.PRECONDITION_FAILED, - "Cannot specify global in the list of allowed clusters"); - } return getNamespacePoliciesAsync(this.namespaceName).thenApply(nsPolicies -> { Set clusterSet = Sets.newHashSet(clusterIds); if (!Policies.checkNewAllowedClusters(nsPolicies, clusterSet)){ @@ -3271,12 +3179,7 @@ protected CompletableFuture internalSetNamespaceAllowedClusters(List> internalGetNamespaceAllowedClustersAsync() { return validateNamespacePolicyOperationAsync(namespaceName, PolicyName.ALLOW_CLUSTERS, PolicyOperation.READ) - .thenAccept(__ -> { - if (!namespaceName.isGlobal()) { - throw new RestException(Status.PRECONDITION_FAILED, - "Cannot get the allowed clusters for a non-global namespace"); - } - }).thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) + .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) .thenApply(policies -> policies.allowed_clusters); } diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java index be98f7102b6f2..fed59cf06e217 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/PersistentTopicsBase.java @@ -3359,12 +3359,6 @@ protected CompletableFuture internalSetReplicationClusters(List cl } Set replicationClustersSet = Sets.newHashSet(clusterIds); return validatePoliciesReadOnlyAccessAsync() - .thenAccept(__ -> { - if (replicationClustersSet.contains("global")) { - throw new RestException(Status.PRECONDITION_FAILED, - "Cannot specify global in the list of replication clusters"); - } - }) .thenCompose(__ -> { // Set a topic-level replicated clusters that do not contain local cluster is not meaningful, except // the following scenario: User has two clusters, which enabled Geo-Replication through a global diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/ResourceQuotasBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/ResourceQuotasBase.java index 8e4d6f3211d67..a1a3ce6558392 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/ResourceQuotasBase.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/ResourceQuotasBase.java @@ -70,11 +70,6 @@ private CompletableFuture getNamespaceBundleRangeAsync(String b return CompletableFuture.completedFuture(null); } }); - if (!namespaceName.isGlobal()) { - ret = ret.thenCompose(__ -> validateClusterOwnershipAsync(namespaceName.getCluster())) - .thenCompose(__ -> validateClusterForTenantAsync(namespaceName.getTenant(), - namespaceName.getCluster())); - } return ret .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) .thenApply(policies -> validateNamespaceBundleRange(namespaceName, policies.bundles, bundleRange)); diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TenantsBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TenantsBase.java index ca16259c79333..f6f4298a5bfd7 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TenantsBase.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TenantsBase.java @@ -18,7 +18,6 @@ */ package org.apache.pulsar.broker.admin.impl; -import static org.apache.pulsar.common.naming.Constants.GLOBAL_CLUSTER; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; @@ -293,7 +292,7 @@ private CompletableFuture validateClustersAsync(TenantInfo info) { return clusterResources().listAsync().thenAccept(availableClusters -> { List nonexistentClusters = allowedClusters.stream() - .filter(cluster -> !(availableClusters.contains(cluster) || GLOBAL_CLUSTER.equals(cluster))) + .filter(cluster -> !availableClusters.contains(cluster)) .collect(Collectors.toList()); if (nonexistentClusters.size() > 0) { log.warn("[{}] Failed to validate due to clusters {} do not exist", clientAppId(), nonexistentClusters); diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TransactionsBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TransactionsBase.java index e3764c896862a..c3093d84cd4e6 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TransactionsBase.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/impl/TransactionsBase.java @@ -522,13 +522,13 @@ protected void checkTransactionCoordinatorEnabled() { } } - protected void validateTopicName(String property, String namespace, String encodedTopic) { + protected void validateTopicName(String tenant, String namespace, String encodedTopic) { String topic = Codec.decode(encodedTopic); try { - this.namespaceName = NamespaceName.get(property, namespace); + this.namespaceName = NamespaceName.get(tenant, namespace); this.topicName = TopicName.get(TopicDomain.persistent.toString(), namespaceName, topic); } catch (IllegalArgumentException e) { - log.warn("[{}] Failed to validate topic name {}://{}/{}/{}", clientAppId(), domain(), property, namespace, + log.warn("[{}] Failed to validate topic name {}://{}/{}/{}", clientAppId(), domain(), tenant, namespace, topic, e); throw new RestException(Response.Status.PRECONDITION_FAILED, "Topic name is not valid"); } diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/BrokerStats.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/BrokerStats.java deleted file mode 100644 index a228f249fa6c2..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/BrokerStats.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.admin.v1; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import java.util.Collection; -import java.util.Map; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import org.apache.pulsar.broker.admin.impl.BrokerStatsBase; -import org.apache.pulsar.broker.loadbalance.ResourceUnit; - -@Path("/broker-stats") -@Api(value = "/broker-stats", description = "Stats for broker", tags = "broker-stats", hidden = true) -@Produces(MediaType.APPLICATION_JSON) -public class BrokerStats extends BrokerStatsBase { - - @GET - @Path("/broker-resource-availability/{property}/{cluster}/{namespace}") - @ApiOperation(value = "Broker availability report", notes = "This API gives the current broker availability in " - + "percent, each resource percentage usage is calculated and then" - + "sum of all of the resource usage percent is called broker-resource-availability" - + "

THIS API IS ONLY FOR USE BY TESTING FOR CONFIRMING NAMESPACE ALLOCATION ALGORITHM", - response = ResourceUnit.class, responseContainer = "Map") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 409, message = "Load-manager doesn't support operation") }) - public Map> getBrokerResourceAvailability(@PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - return internalBrokerResourceAvailability(namespaceName); - } -} diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Brokers.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Brokers.java deleted file mode 100644 index 356f29e9429ea..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Brokers.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.admin.v1; - -import io.swagger.annotations.Api; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import org.apache.pulsar.broker.admin.impl.BrokersBase; - -@Path("/brokers") -@Api(value = "/brokers", description = "BrokersBase admin apis", tags = "brokers", hidden = true) -@Produces(MediaType.APPLICATION_JSON) -public class Brokers extends BrokersBase { -} diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Clusters.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Clusters.java deleted file mode 100644 index 41ae0717764c9..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Clusters.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.admin.v1; - -import io.swagger.annotations.Api; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import org.apache.pulsar.broker.admin.impl.ClustersBase; - -@Path("/clusters") -@Api(value = "/clusters", description = "Cluster admin apis", tags = "clusters", hidden = true) -@Produces(MediaType.APPLICATION_JSON) -public class Clusters extends ClustersBase { -} diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Functions.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Functions.java deleted file mode 100644 index 16df1118171c1..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Functions.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.admin.v1; - -import io.swagger.annotations.Api; -import javax.ws.rs.Consumes; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - -@Path("/functions") -@Api(value = "/functions", description = "Functions admin apis", tags = "functions", hidden = true) -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -public class Functions extends org.apache.pulsar.broker.admin.v2.Functions{ -} diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Namespaces.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Namespaces.java deleted file mode 100644 index 3cd3a587100c1..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Namespaces.java +++ /dev/null @@ -1,1833 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.admin.v1; - -import static org.apache.pulsar.common.policies.data.PoliciesUtil.getBundles; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.container.AsyncResponse; -import javax.ws.rs.container.Suspended; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import org.apache.commons.lang3.StringUtils; -import org.apache.pulsar.broker.admin.impl.NamespacesBase; -import org.apache.pulsar.broker.web.RestException; -import org.apache.pulsar.common.api.proto.CommandGetTopicsOfNamespace.Mode; -import org.apache.pulsar.common.naming.NamespaceBundleSplitAlgorithm; -import org.apache.pulsar.common.naming.NamespaceName; -import org.apache.pulsar.common.policies.data.AuthAction; -import org.apache.pulsar.common.policies.data.AutoSubscriptionCreationOverride; -import org.apache.pulsar.common.policies.data.AutoTopicCreationOverride; -import org.apache.pulsar.common.policies.data.BacklogQuota; -import org.apache.pulsar.common.policies.data.BacklogQuota.BacklogQuotaType; -import org.apache.pulsar.common.policies.data.BookieAffinityGroupData; -import org.apache.pulsar.common.policies.data.BundlesData; -import org.apache.pulsar.common.policies.data.NamespaceOperation; -import org.apache.pulsar.common.policies.data.PersistencePolicies; -import org.apache.pulsar.common.policies.data.Policies; -import org.apache.pulsar.common.policies.data.PolicyName; -import org.apache.pulsar.common.policies.data.PolicyOperation; -import org.apache.pulsar.common.policies.data.PublishRate; -import org.apache.pulsar.common.policies.data.RetentionPolicies; -import org.apache.pulsar.common.policies.data.SchemaAutoUpdateCompatibilityStrategy; -import org.apache.pulsar.common.policies.data.SubscriptionAuthMode; -import org.apache.pulsar.common.policies.data.TenantOperation; -import org.apache.pulsar.common.policies.data.impl.DispatchRateImpl; -import org.apache.pulsar.common.util.FutureUtil; -import org.apache.pulsar.metadata.api.MetadataStoreException; -import org.apache.pulsar.metadata.api.MetadataStoreException.NotFoundException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Path("/namespaces") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -@Api(value = "/namespaces", description = "Namespaces admin apis", tags = "namespaces", hidden = true) -@SuppressWarnings("deprecation") -public class Namespaces extends NamespacesBase { - - @GET - @Path("/{property}") - @ApiOperation(value = "Get the list of all the namespaces for a certain property.", - response = String.class, responseContainer = "Set") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property doesn't exist")}) - public void getTenantNamespaces(@Suspended AsyncResponse response, - @PathParam("property") String property) { - internalGetTenantNamespaces(property) - .thenAccept(response::resume) - .exceptionally(ex -> { - log.error("[{}] Failed to get namespaces list: {}", clientAppId(), ex); - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}") - @ApiOperation(hidden = true, value = "Get the list of all the namespaces for a certain property on single cluster.", - response = String.class, responseContainer = "Set") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Tenant or cluster doesn't exist")}) - public List getNamespacesForCluster(@PathParam("property") String tenant, - @PathParam("cluster") String cluster) { - validateTenantOperation(tenant, TenantOperation.LIST_NAMESPACES); - List namespaces = new ArrayList<>(); - if (!clusters().contains(cluster)) { - log.warn("[{}] Failed to get namespace list for tenant: {}/{} - Cluster does not exist", clientAppId(), - tenant, cluster); - throw new RestException(Status.NOT_FOUND, "Cluster does not exist"); - } - try { - for (String namespace : clusterResources().getNamespacesForCluster(tenant, cluster)) { - namespaces.add(NamespaceName.get(tenant, cluster, namespace).toString()); - } - } catch (NotFoundException e) { - // NoNode means there are no namespaces for this property on the specified cluster, returning empty list - } catch (Exception e) { - log.error("[{}] Failed to get namespaces list: {}", clientAppId(), e); - throw new RestException(e); - } - - namespaces.sort(null); - return namespaces; - } - - @GET - @Path("/{property}/{cluster}/{namespace}/destinations") - @ApiOperation(hidden = true, 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 or operate permission on the namespace"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist")}) - public void getTopics(@Suspended AsyncResponse response, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @QueryParam("mode") @DefaultValue("PERSISTENT") Mode mode, - @ApiParam(value = "Include system topic") - @QueryParam("includeSystemTopic") boolean includeSystemTopic) { - validateNamespaceName(property, cluster, namespace); - validateNamespaceOperationAsync(NamespaceName.get(property, namespace), NamespaceOperation.GET_TOPICS) - // Validate that namespace exists, throws 404 if it doesn't exist - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenCompose(policies -> internalGetListOfTopics(response, policies, mode)) - .thenApply(topics -> filterSystemTopic(topics, includeSystemTopic)) - .thenAccept(response::resume) - .exceptionally(ex -> { - log.error("Failed to get topics list for namespace {}", namespaceName, ex); - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}") - @ApiOperation(hidden = true, value = "Get the dump all the policies specified for a namespace.", - response = Policies.class) - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist")}) - public void getPolicies(@Suspended AsyncResponse response, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespacePolicyOperationAsync(NamespaceName.get(property, namespace), PolicyName.ALL, - PolicyOperation.READ) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(response::resume) - .exceptionally(ex -> { - log.error("Failed to get policies for namespace {}", namespaceName, ex); - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @SuppressWarnings("deprecation") - @PUT - @Path("/{property}/{cluster}/{namespace}") - @ApiOperation(hidden = true, value = "Creates a new empty namespace with no policies attached.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 409, message = "Namespace already exists"), - @ApiResponse(code = 412, message = "Namespace name is not valid") }) - public void createNamespace(@Suspended AsyncResponse response, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - BundlesData initialBundles) { - validateNamespaceName(property, cluster, namespace); - - CompletableFuture ret; - if (!namespaceName.isGlobal()) { - // If the namespace is non global, make sure property has the access on the cluster. For global namespace, - // same check is made at the time of setting replication. - ret = validateClusterForTenantAsync(namespaceName.getTenant(), namespaceName.getCluster()); - } else { - ret = CompletableFuture.completedFuture(null); - } - ret.thenApply(__ -> { - Policies policies = new Policies(); - if (initialBundles != null && initialBundles.getNumBundles() > 0) { - if (initialBundles.getBoundaries() == null || initialBundles.getBoundaries().size() == 0) { - policies.bundles = getBundles(initialBundles.getNumBundles()); - } else { - policies.bundles = validateBundlesData(initialBundles); - } - } else { - int defaultNumberOfBundles = config().getDefaultNumberOfNamespaceBundles(); - policies.bundles = getBundles(defaultNumberOfBundles); - } - return policies; - }).thenCompose(this::internalCreateNamespace) - .thenAccept(__ -> response.resume(Response.noContent().build())) - .exceptionally(ex -> { - Throwable root = FutureUtil.unwrapCompletionException(ex); - if (root instanceof MetadataStoreException.AlreadyExistsException) { - response.resume(new RestException(Status.CONFLICT, "Namespace already exists")); - } else { - log.error("[{}] Failed to create namespace {}", clientAppId(), namespaceName, ex); - resumeAsyncResponseExceptionally(response, ex); - } - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}") - @ApiOperation(hidden = true, value = "Delete a namespace and all the topics under it.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 405, message = "Broker doesn't allow forced deletion of namespaces"), - @ApiResponse(code = 409, message = "Namespace is not empty") }) - public void deleteNamespace(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @QueryParam("force") @DefaultValue("false") boolean force, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateNamespaceName(property, cluster, namespace); - internalDeleteNamespaceAsync(force) - .thenAccept(__ -> { - log.info("[{}] Successful delete namespace {}", clientAppId(), namespace); - asyncResponse.resume(Response.noContent().build()); - }) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to delete namespace {}", clientAppId(), namespaceName, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/{bundle}") - @ApiOperation(hidden = true, value = "Delete a namespace bundle and all the topics under it.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 409, message = "Namespace bundle is not empty")}) - public void deleteNamespaceBundle(@Suspended AsyncResponse response, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("bundle") String bundleRange, - @QueryParam("force") @DefaultValue("false") boolean force, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateNamespaceName(property, cluster, namespace); - internalDeleteNamespaceBundleAsync(bundleRange, authoritative, force) - .thenRun(() -> response.resume(Response.noContent().build())) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to delete namespace bundle {}", clientAppId(), namespaceName, ex); - } - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/permissions") - @ApiOperation(hidden = true, value = "Retrieve the permissions for a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 409, message = "Namespace is not empty") }) - public void getPermissions(@Suspended AsyncResponse response, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespaceOperationAsync(NamespaceName.get(property, namespace), NamespaceOperation.GET_PERMISSION) - .thenCompose(__ -> getAuthorizationService().getPermissionsAsync(namespaceName)) - .thenAccept(permissions -> response.resume(permissions)) - .exceptionally(ex -> { - log.error("Failed to get permissions for namespace {}", namespaceName, ex); - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/permissions/subscription") - @ApiOperation(value = "Retrieve the permissions for a subscription.") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 409, message = "Namespace is not empty")}) - public void getPermissionOnSubscription(@Suspended AsyncResponse response, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespaceOperationAsync(NamespaceName.get(property, namespace), NamespaceOperation.GET_PERMISSION) - .thenCompose(__ -> getAuthorizationService().getSubscriptionPermissionsAsync(namespaceName)) - .thenAccept(permissions -> response.resume(permissions)) - .exceptionally(ex -> { - log.error("[{}] Failed to get permissions on subscription for namespace {}: {} ", - clientAppId(), namespaceName, - ex.getCause().getMessage(), ex); - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/permissions/{role}") - @ApiOperation(hidden = true, value = "Grant a new permission to a role on a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 409, message = "Concurrent modification"), - @ApiResponse(code = 501, message = "Authorization is not enabled")}) - public void grantPermissionOnNamespace(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("role") String role, Set actions) { - validateNamespaceName(property, cluster, namespace); - internalGrantPermissionOnNamespaceAsync(role, actions) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to grant permissions for namespace {}: {}", - clientAppId(), namespaceName, ex.getCause().getMessage(), ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/permissions/subscription/{subscription}") - @ApiOperation(hidden = true, value = "Grant a new permission to roles for a subscription. " - + "[Tenant admin is allowed to perform this operation]") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 409, message = "Concurrent modification"), - @ApiResponse(code = 501, message = "Authorization is not enabled")}) - public void grantPermissionOnSubscription(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("subscription") String subscription, - Set roles) { - validateNamespaceName(property, cluster, namespace); - internalGrantPermissionOnSubscriptionAsync(subscription, roles) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to grant permission on subscription for role {}:{} - " - + "namespaceName {}: {}", - clientAppId(), roles, subscription, namespaceName, ex.getCause().getMessage(), ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/permissions/{role}") - @ApiOperation(hidden = true, value = "Revoke all permissions to a role on a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist") }) - public void revokePermissionsOnNamespace(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("role") String role) { - validateNamespaceName(property, cluster, namespace); - internalRevokePermissionsOnNamespaceAsync(role) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to revoke permission on role {} - namespace {}: {}", - clientAppId(), role, namespace, ex.getCause().getMessage(), ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/permissions/{subscription}/{role}") - @ApiOperation(hidden = true, value = "Revoke subscription admin-api access permission for a role.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist") }) - public void revokePermissionOnSubscription(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("subscription") String subscription, @PathParam("role") String role) { - validateNamespaceName(property, cluster, namespace); - internalRevokePermissionsOnSubscriptionAsync(subscription, role) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to revoke permission on subscription for role {}:{} - namespace {}: {}", - clientAppId(), role, subscription, namespace, ex.getCause().getMessage(), ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/replication") - @ApiOperation(hidden = true, value = "Get the replication clusters for a namespace.", - response = String.class, responseContainer = "List") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 412, message = "Namespace is not global")}) - public void getNamespaceReplicationClusters(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespacePolicyOperationAsync(NamespaceName.get(property, namespace), - PolicyName.REPLICATION, PolicyOperation.READ) - .thenCompose(__ -> internalGetNamespaceReplicationClustersAsync()) - .thenAccept(asyncResponse::resume) - .exceptionally(e -> { - log.error("[{}] Failed to get namespace replication clusters on namespace {}", clientAppId(), - namespace, e); - resumeAsyncResponseExceptionally(asyncResponse, e); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/replication") - @ApiOperation(hidden = true, value = "Set the replication clusters for a namespace. " - + "When removing a cluster:" - + " with shared configuration store, data will be deleted from the removed cluster; " - + "with separate configuration store, only replication stops but data is preserved.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 409, message = "Peer-cluster can't be part of replication-cluster"), - @ApiResponse(code = 412, message = "Namespace is not global or invalid cluster ids") }) - public void setNamespaceReplicationClusters(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, List clusterIds, - @QueryParam("compareTopicPartitions") boolean compareTopicPartitions) { - validateNamespaceName(property, cluster, namespace); - internalSetNamespaceReplicationClusters(clusterIds, compareTopicPartitions) - .thenAccept(asyncResponse::resume) - .exceptionally(e -> { - log.error("[{}] Failed to set namespace replication clusters on namespace {}", clientAppId(), - namespace, e); - resumeAsyncResponseExceptionally(asyncResponse, e); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/messageTTL") - @ApiOperation(hidden = true, value = "Get the message TTL for the namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist") }) - public void getNamespaceMessageTTL(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespacePolicyOperationAsync(NamespaceName.get(property, namespace), PolicyName.TTL, - PolicyOperation.READ) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(policies -> asyncResponse.resume(policies.message_ttl_in_seconds)) - .exceptionally(ex -> { - log.error("Failed to get namespace message TTL for namespace {}", namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/messageTTL") - @ApiOperation(hidden = true, value = "Set message TTL in seconds for namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 412, message = "Invalid TTL") }) - public void setNamespaceMessageTTL(@Suspended AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - int messageTTL) { - validateNamespaceName(property, cluster, namespace); - internalSetNamespaceMessageTTLAsync(messageTTL) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("Failed to set namespace message TTL for namespace {}", namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/messageTTL") - @ApiOperation(value = "Remove message TTL in seconds for namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Tenant or cluster or namespace doesn't exist"), - @ApiResponse(code = 412, message = "Invalid TTL") }) - public void removeNamespaceMessageTTL(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalSetNamespaceMessageTTLAsync(null) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("Failed to remove namespace message TTL for namespace {}", namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/subscriptionExpirationTime") - @ApiOperation(hidden = true, value = "Get the subscription expiration time for the namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist") }) - public void getSubscriptionExpirationTime(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateAdminAccessForTenantAsync(property) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(policies -> asyncResponse.resume(policies.subscription_expiration_time_minutes)) - .exceptionally(ex -> { - log.error("[{}] Failed to get subscription expiration time for namespace {}: {} ", clientAppId(), - namespaceName, ex.getCause().getMessage(), ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/subscriptionExpirationTime") - @ApiOperation(hidden = true, value = "Set subscription expiration time in minutes for namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 412, message = "Invalid expiration time") }) - public void setSubscriptionExpirationTime(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, int expirationTime) { - validateNamespaceName(property, cluster, namespace); - internalSetSubscriptionExpirationTimeAsync(expirationTime) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to set subscription expiration time for namespace {}: {} ", clientAppId(), - namespaceName, ex.getCause().getMessage(), ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/subscriptionExpirationTime") - @ApiOperation(hidden = true, value = "Remove subscription expiration time for namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist") }) - public void removeSubscriptionExpirationTime(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalSetSubscriptionExpirationTimeAsync(null) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to remove subscription expiration time for namespace {}: {} ", clientAppId(), - namespaceName, ex.getCause().getMessage(), ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/antiAffinity") - @ApiOperation(value = "Set anti-affinity group for a namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 412, message = "Invalid antiAffinityGroup") }) - public void setNamespaceAntiAffinityGroup(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, String antiAffinityGroup) { - validateNamespaceName(property, cluster, namespace); - internalSetNamespaceAntiAffinityGroupAsync(antiAffinityGroup) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to set namespace anti-affinity group, tenant: {}, namespace: {}, " - + "antiAffinityGroup: {}", clientAppId(), property, namespace, antiAffinityGroup, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/antiAffinity") - @ApiOperation(value = "Get anti-affinity group of a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist") }) - public void getNamespaceAntiAffinityGroup(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalGetNamespaceAntiAffinityGroupAsync() - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - log.error("[{}] Failed to get namespace anti-affinity group, tenant: {}, namespace: {}", - clientAppId(), property, namespace, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("{cluster}/antiAffinity/{group}") - @ApiOperation(value = "Get all namespaces that are grouped by given anti-affinity group in a given cluster." - + " api can be only accessed by admin of any of the existing property") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 412, message = "Cluster not exist/Anti-affinity group can't be empty.")}) - public void getAntiAffinityNamespaces(@Suspended AsyncResponse asyncResponse, - @PathParam("cluster") String cluster, - @PathParam("group") String antiAffinityGroup, - @QueryParam("property") String property) { - internalGetAntiAffinityNamespacesAsync(cluster, antiAffinityGroup, property) - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - log.error("[{}] Failed to get all namespaces in cluster of given anti-affinity group, cluster: {}, " - + "tenant: {}, antiAffinityGroup: {}", clientAppId(), cluster, property, antiAffinityGroup, - ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/antiAffinity") - @ApiOperation(value = "Remove anti-affinity group of a namespace.") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification")}) - public void removeNamespaceAntiAffinityGroup(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalRemoveNamespaceAntiAffinityGroupAsync() - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to remove namespace anti-affinity group, tenant: {}, namespace: {}", - clientAppId(), property, namespace, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/deduplication") - @ApiOperation(hidden = true, value = "Enable or disable broker side deduplication for all topics in a namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist") }) - public void modifyDeduplication(@Suspended AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - boolean enableDeduplication) { - validateNamespaceName(property, cluster, namespace); - internalModifyDeduplicationAsync(enableDeduplication) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("Failed to modify broker deduplication config for namespace {}", namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/autoTopicCreation") - @ApiOperation(value = "Get autoTopicCreation info in a namespace") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Tenant or cluster or namespace doesn't exist")}) - public void getAutoTopicCreation(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalGetAutoTopicCreationAsync() - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - log.error("Failed to get autoTopicCreation info for namespace {}", namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/autoTopicCreation") - @ApiOperation(value = "Override broker's allowAutoTopicCreation setting for a namespace") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Tenant or cluster or namespace doesn't exist"), - @ApiResponse(code = 406, message = "The number of partitions should be less than or equal to" - + " maxNumPartitionsPerPartitionedTopic"), - @ApiResponse(code = 400, message = "Invalid autoTopicCreation override")}) - public void setAutoTopicCreation(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - AutoTopicCreationOverride autoTopicCreationOverride) { - validateNamespaceName(property, cluster, namespace); - internalSetAutoTopicCreationAsync(autoTopicCreationOverride) - .thenAccept(__ -> { - String autoOverride = (autoTopicCreationOverride != null - && autoTopicCreationOverride.isAllowAutoTopicCreation()) ? "enabled" : "disabled"; - log.info("[{}] Successfully {} autoTopicCreation on namespace {}", clientAppId(), - autoOverride, namespaceName); - asyncResponse.resume(Response.noContent().build()); - }) - .exceptionally(e -> { - Throwable ex = FutureUtil.unwrapCompletionException(e); - log.error("[{}] Failed to set autoTopicCreation status on namespace {}", clientAppId(), - namespaceName, - ex); - if (ex instanceof NotFoundException) { - asyncResponse.resume(new RestException(Status.NOT_FOUND, "Namespace does not exist")); - } else { - resumeAsyncResponseExceptionally(asyncResponse, ex); - } - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/autoTopicCreation") - @ApiOperation(value = "Remove override of broker's allowAutoTopicCreation in a namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Tenant or cluster or namespace doesn't exist") }) - public void removeAutoTopicCreation(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalSetAutoTopicCreationAsync(null) - .thenAccept(__ -> { - log.info("[{}] Successfully remove autoTopicCreation on namespace {}", - clientAppId(), namespaceName); - asyncResponse.resume(Response.noContent().build()); - }) - .exceptionally(e -> { - Throwable ex = FutureUtil.unwrapCompletionException(e); - log.error("[{}] Failed to remove autoTopicCreation status on namespace {}", clientAppId(), - namespaceName, ex); - if (ex instanceof NotFoundException) { - asyncResponse.resume(new RestException(Status.NOT_FOUND, "Namespace does not exist")); - } else { - resumeAsyncResponseExceptionally(asyncResponse, ex); - } - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/autoSubscriptionCreation") - @ApiOperation(value = "Override broker's allowAutoSubscriptionCreation setting for a namespace") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Tenant or cluster or namespace doesn't exist"), - @ApiResponse(code = 400, message = "Invalid autoSubscriptionCreation override")}) - public void setAutoSubscriptionCreation( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - AutoSubscriptionCreationOverride autoSubscriptionCreationOverride) { - validateNamespaceName(property, cluster, namespace); - internalSetAutoSubscriptionCreationAsync(autoSubscriptionCreationOverride) - .thenAccept(__ -> { - log.info("[{}] Successfully set autoSubscriptionCreation on namespace {}", - clientAppId(), namespaceName); - asyncResponse.resume(Response.noContent().build()); - }) - .exceptionally(e -> { - Throwable ex = FutureUtil.unwrapCompletionException(e); - log.error("[{}] Failed to set autoSubscriptionCreation on namespace {}", clientAppId(), - namespaceName, ex); - if (ex instanceof NotFoundException) { - asyncResponse.resume(new RestException(Status.NOT_FOUND, "Namespace does not exist")); - } else { - resumeAsyncResponseExceptionally(asyncResponse, ex); - } - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/autoSubscriptionCreation") - @ApiOperation(value = "Get autoSubscriptionCreation info in a namespace") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist")}) - public void getAutoSubscriptionCreation(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalGetAutoSubscriptionCreationAsync() - .thenAccept(asyncResponse::resume) - .exceptionally(e -> { - Throwable ex = FutureUtil.unwrapCompletionException(e); - log.error("Failed to get autoSubscriptionCreation for namespace {}", namespaceName, ex); - if (ex instanceof NotFoundException) { - asyncResponse.resume(new RestException(Status.NOT_FOUND, "Namespace does not exist")); - } else { - resumeAsyncResponseExceptionally(asyncResponse, ex); - } - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/autoSubscriptionCreation") - @ApiOperation(value = "Remove override of broker's allowAutoSubscriptionCreation in a namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Tenant or cluster or namespace doesn't exist") }) - public void removeAutoSubscriptionCreation(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalSetAutoSubscriptionCreationAsync(null) - .thenAccept(__ -> { - log.info("[{}] Successfully set autoSubscriptionCreation on namespace {}", - clientAppId(), namespaceName); - asyncResponse.resume(Response.noContent().build()); - }) - .exceptionally(e -> { - Throwable ex = FutureUtil.unwrapCompletionException(e); - log.error("[{}] Failed to remove autoSubscriptionCreation on namespace {}", clientAppId(), - namespaceName, ex); - if (ex instanceof NotFoundException) { - asyncResponse.resume(new RestException(Status.NOT_FOUND, "Namespace does not exist")); - } else { - resumeAsyncResponseExceptionally(asyncResponse, ex); - } - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/bundles") - @ApiOperation(hidden = true, value = "Get the bundles split data.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 412, message = "Namespace is not setup to split in bundles") }) - public void getBundlesData(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validatePoliciesReadOnlyAccessAsync() - .thenCompose(__ -> validateNamespaceOperationAsync(NamespaceName.get(property, namespace), - NamespaceOperation.GET_BUNDLE)) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(policies -> asyncResponse.resume(policies.bundles)) - .exceptionally(ex -> { - log.error("[{}] Failed to get bundle data for namespace {} ", clientAppId(), - namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @PUT - @Path("/{property}/{cluster}/{namespace}/unload") - @ApiOperation(hidden = true, value = "Unload namespace", - notes = "Unload an active namespace from the current broker serving it." - + " Performing this operation will let the brokerremoves all producers," - + " consumers, and connections using this namespace, and close all topics " - + "(includingtheir persistent store). During that operation, the namespace is marked " - + "as tentatively unavailable until thebroker completes the unloading action. " - + "This operation requires strictly super user privileges, since it wouldresult in" - + " non-persistent message loss and unexpected connection closure to the clients.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 412, message = "Namespace is already unloaded or Namespace has bundles activated")}) - public void unloadNamespace(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace) { - try { - validateNamespaceName(property, cluster, namespace); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - return; - } - internalUnloadNamespaceAsync() - .thenAccept(__ -> { - log.info("[{}] Successfully unloaded all the bundles in namespace {}", clientAppId(), - namespaceName); - asyncResponse.resume(Response.noContent().build()); - }) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to unload namespace {}", clientAppId(), namespaceName, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @PUT - @Path("/{property}/{cluster}/{namespace}/{bundle}/unload") - @ApiOperation(hidden = true, value = "Unload a namespace bundle") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 404, message = "Namespace doesn't exist"), - @ApiResponse(code = 403, message = "Don't have admin permission") }) - public void unloadNamespaceBundle(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("bundle") String bundleRange, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @QueryParam("destinationBroker") String destinationBroker) { - validateNamespaceName(property, cluster, namespace); - internalUnloadNamespaceBundleAsync(bundleRange, destinationBroker, authoritative) - .thenAccept(__ -> { - log.info("[{}] Successfully unloaded namespace bundle {}", - clientAppId(), bundleRange); - asyncResponse.resume(Response.noContent().build()); - }) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to unload namespace bundle {}/{}", - clientAppId(), namespaceName, bundleRange, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @PUT - @Path("/{property}/{cluster}/{namespace}/{bundle}/split") - @ApiOperation(hidden = true, value = "Split a namespace bundle") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 404, message = "Namespace doesn't exist"), - @ApiResponse(code = 403, message = "Don't have admin permission") }) - public void splitNamespaceBundle( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("bundle") String bundleRange, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @QueryParam("unload") @DefaultValue("false") boolean unload, - @QueryParam("splitAlgorithmName") String splitAlgorithmName, - @ApiParam("splitBoundaries") List splitBoundaries) { - validateNamespaceName(property, cluster, namespace); - if (StringUtils.isEmpty(splitAlgorithmName)) { - splitAlgorithmName = NamespaceBundleSplitAlgorithm.RANGE_EQUALLY_DIVIDE_NAME; - } - internalSplitNamespaceBundleAsync(bundleRange, - authoritative, unload, splitAlgorithmName, splitBoundaries) - .thenAccept(__ -> { - log.info("[{}] Successfully split namespace bundle {}", clientAppId(), bundleRange); - asyncResponse.resume(Response.noContent().build()); - }) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to split namespace bundle {}/{}", - clientAppId(), namespaceName, bundleRange, ex); - } - Throwable realCause = FutureUtil.unwrapCompletionException(ex); - if (realCause instanceof IllegalArgumentException) { - asyncResponse.resume(new RestException(Response.Status.PRECONDITION_FAILED, - "Split bundle failed due to invalid request")); - } else { - resumeAsyncResponseExceptionally(asyncResponse, ex); - } - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/{bundle}/topicHashPositions") - @ApiOperation(value = "Get hash positions for topics") - @ApiResponses(value = { - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist")}) - public void getTopicHashPositions( - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("bundle") String bundle, - @QueryParam("topics") List topics, - @Suspended AsyncResponse asyncResponse) { - validateNamespaceName(property, cluster, namespace); - internalGetTopicHashPositionsAsync(bundle, topics) - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] {} Failed to get topic list for bundle {}.", clientAppId(), - namespaceName, bundle); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/publishRate") - @ApiOperation(hidden = true, value = "Set publish-rate throttling for all topics of the namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission") }) - public void setPublishRate(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, PublishRate publishRate) { - validateNamespaceName(property, cluster, namespace); - internalSetPublishRateAsync(publishRate) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/publishRate") - @ApiOperation(hidden = true, - value = "Get publish-rate configured for the namespace, null means publish-rate not configured, " - + "-1 means msg-publish-rate or byte-publish-rate not configured in publish-rate yet") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist")}) - public void getPublishRate(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalGetPublishRateAsync() - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - log.error("Failed to get publish rate for namespace {}", namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/dispatchRate") - @ApiOperation(hidden = true, value = "Set dispatch-rate throttling for all topics of the namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission") }) - public void setDispatchRate(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, DispatchRateImpl dispatchRate) { - validateNamespaceName(property, cluster, namespace); - internalSetTopicDispatchRateAsync(dispatchRate) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to update the dispatchRate for cluster on namespace {}", clientAppId(), - namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/dispatchRate") - @ApiOperation(hidden = true, - value = "Get dispatch-rate configured for the namespace, null means dispatch-rate not configured, " - + "-1 means msg-dispatch-rate or byte-dispatch-rate not configured in dispatch-rate yet") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist")}) - public void getDispatchRate(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespacePolicyOperationAsync(namespaceName, PolicyName.RATE, PolicyOperation.READ) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(policies -> asyncResponse.resume( - policies.topicDispatchRate.get(pulsar().getConfiguration().getClusterName()))) - .exceptionally(ex -> { - log.error("[{}] Failed to get dispatch-rate configured for the namespace {}", clientAppId(), - namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/subscriptionDispatchRate") - @ApiOperation(value = "Set Subscription dispatch-rate throttling for all topics of the namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission") }) - public void setSubscriptionDispatchRate(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - DispatchRateImpl dispatchRate) { - validateNamespaceName(property, cluster, namespace); - internalSetSubscriptionDispatchRateAsync(dispatchRate) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to set the subscription dispatchRate for cluster on namespace {}", - clientAppId(), namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/subscriptionDispatchRate") - @ApiOperation(value = "Get subscription dispatch-rate configured for the namespace, null means subscription " - + "dispatch-rate not configured, -1 means msg-dispatch-rate or byte-dispatch-rate not configured " - + "in dispatch-rate yet") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist")}) - public void getSubscriptionDispatchRate(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalGetSubscriptionDispatchRateAsync() - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - log.error("[{}] Failed to get the subscription dispatchRate for cluster on namespace {}", - clientAppId(), namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/subscriptionDispatchRate") - @ApiOperation(value = "Delete subscription dispatch-rate throttling for all topics of the namespace") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 409, message = "Concurrent modification")}) - public void deleteSubscriptionDispatchRate(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalDeleteSubscriptionDispatchRateAsync() - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to delete the subscription dispatchRate for cluster on namespace {}", - clientAppId(), namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{tenant}/{cluster}/{namespace}/replicatorDispatchRate") - @ApiOperation(value = "Set replicator dispatch-rate throttling for all topics of the namespace") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission")}) - public void setReplicatorDispatchRate(@Suspended AsyncResponse asyncResponse, - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @ApiParam(value = "Replicator dispatch rate for all topics of the specified namespace") - DispatchRateImpl dispatchRate) { - validateNamespaceName(tenant, cluster, namespace); - internalSetReplicatorDispatchRate(asyncResponse, dispatchRate); - } - - @GET - @Path("/{tenant}/{cluster}/{namespace}/replicatorDispatchRate") - @ApiOperation(value = "Get replicator dispatch-rate configured for the namespace, null means replicator " - + "dispatch-rate not configured, -1 means msg-dispatch-rate or byte-dispatch-rate not configured " - + "in dispatch-rate yet") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist") }) - public void getReplicatorDispatchRate( - @Suspended final AsyncResponse asyncResponse, - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(tenant, cluster, namespace); - internalGetReplicatorDispatchRate(asyncResponse); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/backlogQuotaMap") - @ApiOperation(hidden = true, value = "Get backlog quota map on a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist") }) - public void getBacklogQuotaMap( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalGetBacklogQuotaMap(asyncResponse); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/backlogQuota") - @ApiOperation(hidden = true, value = " Set a backlog quota for all the topics on a namespace.") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification"), - @ApiResponse(code = 412, message = "Specified backlog quota exceeds retention quota." - + " Increase retention quota and retry request")}) - public void setBacklogQuota( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @QueryParam("backlogQuotaType") BacklogQuotaType backlogQuotaType, - BacklogQuota backlogQuota) { - validateNamespaceName(property, cluster, namespace); - internalSetBacklogQuota(asyncResponse, backlogQuotaType, backlogQuota); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/backlogQuota") - @ApiOperation(hidden = true, value = "Remove a backlog quota policy from a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification") }) - public void removeBacklogQuota( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @QueryParam("backlogQuotaType") BacklogQuotaType backlogQuotaType) { - validateNamespaceName(property, cluster, namespace); - internalRemoveBacklogQuota(asyncResponse, backlogQuotaType); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/retention") - @ApiOperation(hidden = true, value = "Get retention config on a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist") }) - public void getRetention(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespacePolicyOperationAsync(namespaceName, PolicyName.RETENTION, PolicyOperation.READ) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(policies -> asyncResponse.resume(policies.retention_policies)) - .exceptionally(ex -> { - log.error("[{}] Failed to get retention config on a namespace {}", clientAppId(), namespaceName, - ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/retention") - @ApiOperation(hidden = true, value = " Set retention configuration on a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification"), - @ApiResponse(code = 412, message = "Retention Quota must exceed backlog quota") }) - public void setRetention(@PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, RetentionPolicies retention) { - validateNamespaceName(property, cluster, namespace); - internalSetRetention(retention); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/persistence") - @ApiOperation(hidden = true, value = "Set the persistence configuration for all the topics on a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification"), - @ApiResponse(code = 400, message = "Invalid persistence policies") }) - public void setPersistence(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - PersistencePolicies persistence) { - validateNamespaceName(property, cluster, namespace); - internalSetPersistenceAsync(persistence) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to update the persistence for a namespace {}", clientAppId(), namespaceName, - ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/persistence/bookieAffinity") - @ApiOperation(hidden = true, value = "Set the bookie-affinity-group to namespace-local policy.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification") }) - public void setBookieAffinityGroup(@Suspended AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - BookieAffinityGroupData bookieAffinityGroup) { - validateNamespaceName(property, cluster, namespace); - internalSetBookieAffinityGroupAsync(bookieAffinityGroup) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to set bookie affinity group for namespace {}", clientAppId(), - namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/persistence/bookieAffinity") - @ApiOperation(hidden = true, value = "Get the bookie-affinity-group from namespace-local policy.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification") }) - public void getBookieAffinityGroup(@Suspended AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalGetBookieAffinityGroupAsync() - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - log.error("[{}] Failed to get bookie affinity group for namespace {}", clientAppId(), - namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/persistence/bookieAffinity") - @ApiOperation(hidden = true, value = "Delete the bookie-affinity-group from namespace-local policy.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification") }) - public void deleteBookieAffinityGroup(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalDeleteBookieAffinityGroupAsync() - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to delete bookie affinity group for namespace {}", clientAppId(), - namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/persistence") - @ApiOperation(hidden = true, value = "Get the persistence configuration for a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification") }) - public void getPersistence( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespacePolicyOperationAsync(namespaceName, PolicyName.PERSISTENCE, PolicyOperation.READ) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(policies -> asyncResponse.resume(policies.persistence)) - .exceptionally(ex -> { - log.error("[{}] Failed to get persistence configuration for a namespace {}", clientAppId(), - namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/clearBacklog") - @ApiOperation(hidden = true, value = "Clear backlog for all topics on a namespace.") - @ApiResponses(value = { - @ApiResponse(code = 403, message = "Don't have admin or operate permission on the namespace"), - @ApiResponse(code = 404, message = "Namespace does not exist") }) - public void clearNamespaceBacklog(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateNamespaceName(property, cluster, namespace); - internalClearNamespaceBacklog(asyncResponse, authoritative); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{bundle}/clearBacklog") - @ApiOperation(hidden = true, value = "Clear backlog for all topics on a namespace bundle.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin or operate permission on the namespace"), - @ApiResponse(code = 404, message = "Namespace does not exist") }) - public void clearNamespaceBundleBacklog(@PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("bundle") String bundleRange, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateNamespaceName(property, cluster, namespace); - internalClearNamespaceBundleBacklog(bundleRange, authoritative); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/clearBacklog/{subscription}") - @ApiOperation(hidden = true, value = "Clear backlog for a given subscription on all topics on a namespace.") - @ApiResponses(value = { - @ApiResponse(code = 403, message = "Don't have admin or operate permission on the namespace"), - @ApiResponse(code = 404, message = "Namespace does not exist") }) - public void clearNamespaceBacklogForSubscription(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("subscription") String subscription, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateNamespaceName(property, cluster, namespace); - internalClearNamespaceBacklogForSubscription(asyncResponse, subscription, authoritative); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{bundle}/clearBacklog/{subscription}") - @ApiOperation(hidden = true, value = "Clear backlog for a given subscription on all topics on a namespace bundle.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin or operate permission on the namespace"), - @ApiResponse(code = 404, message = "Namespace does not exist") }) - public void clearNamespaceBundleBacklogForSubscription(@PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("subscription") String subscription, @PathParam("bundle") String bundleRange, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateNamespaceName(property, cluster, namespace); - internalClearNamespaceBundleBacklogForSubscription(subscription, bundleRange, authoritative); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/unsubscribe/{subscription}") - @ApiOperation(hidden = true, value = "Unsubscribes the given subscription on all topics on a namespace.") - @ApiResponses(value = { - @ApiResponse(code = 403, message = "Don't have admin or operate permission on the namespace"), - @ApiResponse(code = 404, message = "Namespace does not exist") }) - public void unsubscribeNamespace(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("subscription") String subscription, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateNamespaceName(property, cluster, namespace); - internalUnsubscribeNamespaceAsync(subscription, authoritative) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to unsubscribe {} on namespace {}", clientAppId(), - subscription, namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{bundle}/unsubscribe/{subscription}") - @ApiOperation(hidden = true, value = "Unsubscribes the given subscription on all topics on a namespace bundle.") - @ApiResponses(value = { - @ApiResponse(code = 403, message = "Don't have admin or operate permission on the namespace"), - @ApiResponse(code = 404, message = "Namespace does not exist") }) - public void unsubscribeNamespaceBundle(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("subscription") String subscription, - @PathParam("bundle") String bundleRange, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateNamespaceName(property, cluster, namespace); - internalUnsubscribeNamespaceBundleAsync(subscription, bundleRange, authoritative) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - log.error("[{}] Failed to unsubscribe {} on namespace bundle {}/{}", clientAppId(), - subscription, namespaceName, bundleRange, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/subscriptionAuthMode") - @ApiOperation(value = " Set a subscription auth mode for all the topics on a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification") }) - public void setSubscriptionAuthMode(@PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, SubscriptionAuthMode subscriptionAuthMode) { - validateNamespaceName(property, cluster, namespace); - internalSetSubscriptionAuthMode(subscriptionAuthMode); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/subscriptionAuthMode") - @ApiOperation(value = "Get subscription auth mode in a namespace") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist")}) - public void getSubscriptionAuthMode(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespacePolicyOperationAsync(namespaceName, PolicyName.SUBSCRIPTION_AUTH_MODE, PolicyOperation.READ) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(policies -> asyncResponse.resume(policies.subscription_auth_mode)) - .exceptionally(ex -> { - log.error("[{}] Failed to get subscription auth mode in a namespace {}", clientAppId(), - namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/encryptionRequired") - @ApiOperation(hidden = true, value = "Message encryption is required or not for all topics in a namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 409, message = "Concurrent modification"), }) - public void modifyEncryptionRequired(@PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, boolean encryptionRequired) { - validateNamespaceName(property, cluster, namespace); - internalModifyEncryptionRequired(encryptionRequired); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/encryptionRequired") - @ApiOperation(value = "Get message encryption required status in a namespace") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist")}) - public Boolean getEncryptionRequired(@PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateAdminAccessForTenant(property); - validateNamespaceName(property, cluster, namespace); - return internalGetEncryptionRequired(); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/maxProducersPerTopic") - @ApiOperation(value = "Get maxProducersPerTopic config on a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist") }) - public void getMaxProducersPerTopic( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespacePolicyOperationAsync(namespaceName, PolicyName.MAX_PRODUCERS, PolicyOperation.READ) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(policies -> asyncResponse.resume(policies.max_producers_per_topic)) - .exceptionally(ex -> { - log.error("[{}] Failed to get maxProducersPerTopic config on a namespace {}", clientAppId(), - namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/maxProducersPerTopic") - @ApiOperation(value = " Set maxProducersPerTopic configuration on a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification"), - @ApiResponse(code = 412, message = "maxProducersPerTopic value is not valid") }) - public void setMaxProducersPerTopic(@PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, int maxProducersPerTopic) { - validateNamespaceName(property, cluster, namespace); - internalSetMaxProducersPerTopic(maxProducersPerTopic); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/maxConsumersPerTopic") - @ApiOperation(value = "Get maxConsumersPerTopic config on a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist") }) - public void getMaxConsumersPerTopic( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespacePolicyOperationAsync(namespaceName, PolicyName.MAX_CONSUMERS, PolicyOperation.READ) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(policies -> asyncResponse.resume(policies.max_consumers_per_topic)) - .exceptionally(ex -> { - log.error("[{}] Failed to get maxConsumersPerTopic config on a namespace {}", clientAppId(), - namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/maxConsumersPerTopic") - @ApiOperation(value = " Set maxConsumersPerTopic configuration on a namespace.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification"), - @ApiResponse(code = 412, message = "maxConsumersPerTopic value is not valid") }) - public void setMaxConsumersPerTopic(@PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, int maxConsumersPerTopic) { - validateNamespaceName(property, cluster, namespace); - internalSetMaxConsumersPerTopic(maxConsumersPerTopic); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/maxConsumersPerSubscription") - @ApiOperation(value = "Get maxConsumersPerSubscription config on a namespace.") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist")}) - public void getMaxConsumersPerSubscription( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespacePolicyOperationAsync(namespaceName, PolicyName.MAX_CONSUMERS, PolicyOperation.READ) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(polices -> asyncResponse.resume(polices.max_consumers_per_subscription)) - .exceptionally(ex -> { - log.error("[{}] Failed to get maxConsumersPerSubscription config on namespace {}: {} ", - clientAppId(), namespaceName, ex.getCause().getMessage(), ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/maxConsumersPerSubscription") - @ApiOperation(value = " Set maxConsumersPerSubscription configuration on a namespace.") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist"), - @ApiResponse(code = 409, message = "Concurrent modification"), - @ApiResponse(code = 412, message = "maxConsumersPerSubscription value is not valid")}) - public void setMaxConsumersPerSubscription( - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, int maxConsumersPerSubscription) { - validateNamespaceName(property, cluster, namespace); - internalSetMaxConsumersPerSubscription(maxConsumersPerSubscription); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/maxConsumersPerSubscription") - @ApiOperation(value = "Remove maxConsumersPerSubscription configuration on a namespace.") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 409, message = "Concurrent modification")}) - public void removeMaxConsumersPerSubscription( - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalSetMaxConsumersPerSubscription(null); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/compactionThreshold") - @ApiOperation(value = "Maximum number of uncompacted bytes in topics before compaction is triggered.", - notes = "The backlog size is compared to the threshold periodically. " - + "A threshold of 0 disabled automatic compaction") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist") }) - public void getCompactionThreshold( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespacePolicyOperationAsync(namespaceName, PolicyName.COMPACTION, PolicyOperation.READ) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(policies -> asyncResponse.resume(policies.compaction_threshold)) - .exceptionally(ex -> { - log.error("[{}] Failed to get compaction threshold on namespace {}", clientAppId(), namespaceName, - ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @PUT - @Path("/{property}/{cluster}/{namespace}/compactionThreshold") - @ApiOperation(value = "Set maximum number of uncompacted bytes in a topic before compaction is triggered.", - notes = "The backlog size is compared to the threshold periodically. " - + "A threshold of 0 disabled automatic compaction") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist"), - @ApiResponse(code = 409, message = "Concurrent modification"), - @ApiResponse(code = 412, message = "compactionThreshold value is not valid") }) - public void setCompactionThreshold(@PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - long newThreshold) { - validateNamespaceName(property, cluster, namespace); - internalSetCompactionThreshold(newThreshold); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/offloadThreshold") - @ApiOperation(value = "Maximum number of bytes stored on the pulsar cluster for a topic," - + " before the broker will start offloading to longterm storage", - notes = "A negative value disables automatic offloading") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist") }) - public void getOffloadThreshold( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - validateNamespacePolicyOperationAsync(namespaceName, PolicyName.OFFLOAD, PolicyOperation.READ) - .thenCompose(__ -> getNamespacePoliciesAsync(namespaceName)) - .thenAccept(policies -> { - if (policies.offload_policies == null) { - asyncResponse.resume(policies.offload_threshold); - } else { - asyncResponse.resume(policies.offload_policies.getManagedLedgerOffloadThresholdInBytes()); - } - }) - .exceptionally(ex -> { - log.error("[{}] Failed to get offload threshold on namespace {}", clientAppId(), namespaceName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @PUT - @Path("/{property}/{cluster}/{namespace}/offloadThreshold") - @ApiOperation(value = "Set maximum number of bytes stored on the pulsar cluster for a topic," - + " before the broker will start offloading to longterm storage", - notes = "A negative value disables automatic offloading") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist"), - @ApiResponse(code = 409, message = "Concurrent modification"), - @ApiResponse(code = 412, message = "offloadThreshold value is not valid") }) - public void setOffloadThreshold(@PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - long newThreshold) { - validateNamespaceName(property, cluster, namespace); - internalSetOffloadThreshold(newThreshold); - } - - @GET - @Path("/{tenant}/{cluster}/{namespace}/schemaAutoUpdateCompatibilityStrategy") - @ApiOperation(value = "The strategy used to check the compatibility of new schemas," - + " provided by producers, before automatically updating the schema", - notes = "The value AutoUpdateDisabled prevents producers from updating the schema. " - + " If set to AutoUpdateDisabled, schemas must be updated through the REST api") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist"), - @ApiResponse(code = 409, message = "Concurrent modification") }) - public SchemaAutoUpdateCompatibilityStrategy getSchemaAutoUpdateCompatibilityStrategy( - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(tenant, cluster, namespace); - return internalGetSchemaAutoUpdateCompatibilityStrategy(); - } - - @PUT - @Path("/{tenant}/{cluster}/{namespace}/schemaAutoUpdateCompatibilityStrategy") - @ApiOperation(value = "Update the strategy used to check the compatibility of new schemas," - + " provided by producers, before automatically updating the schema", - notes = "The value AutoUpdateDisabled prevents producers from updating the schema. " - + " If set to AutoUpdateDisabled, schemas must be updated through the REST api") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist"), - @ApiResponse(code = 409, message = "Concurrent modification") }) - public void setSchemaAutoUpdateCompatibilityStrategy(@PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - SchemaAutoUpdateCompatibilityStrategy strategy) { - validateNamespaceName(tenant, cluster, namespace); - internalSetSchemaAutoUpdateCompatibilityStrategy(strategy); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/migration") - @ApiOperation(hidden = true, value = "Update migration for all topics in a namespace") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist") }) - public void enableMigration(@PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - boolean migrated) { - validateNamespaceName(property, cluster, namespace); - internalEnableMigration(migrated); - } - - @PUT - @Path("/{property}/{cluster}/{namespace}/policy") - @ApiOperation(value = "Creates a new namespace with the specified policies") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), - @ApiResponse(code = 409, message = "Namespace already exists"), - @ApiResponse(code = 412, message = "Namespace name is not valid") }) - public void createNamespace(@Suspended AsyncResponse response, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @ApiParam(value = "Policies for the namespace") Policies policies) { - validateNamespaceName(property, cluster, namespace); - CompletableFuture ret; - if (!namespaceName.isGlobal()) { - // If the namespace is non global, make sure property has the access on the cluster. For global namespace, - // same check is made at the time of setting replication. - ret = validateClusterForTenantAsync(namespaceName.getTenant(), namespaceName.getCluster()); - } else { - ret = CompletableFuture.completedFuture(null); - } - - ret.thenApply(__ -> getDefaultPolicesIfNull(policies)).thenCompose(this::internalCreateNamespace) - .thenAccept(__ -> response.resume(Response.noContent().build())) - .exceptionally(ex -> { - Throwable root = FutureUtil.unwrapCompletionException(ex); - if (root instanceof MetadataStoreException.AlreadyExistsException) { - response.resume(new RestException(Status.CONFLICT, "Namespace already exists")); - } else { - log.error("[{}] Failed to create namespace {}", clientAppId(), namespaceName, ex); - resumeAsyncResponseExceptionally(response, ex); - } - return null; - }); - } - - private static final Logger log = LoggerFactory.getLogger(Namespaces.class); -} diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/NonPersistentTopics.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/NonPersistentTopics.java deleted file mode 100644 index 1c1dd74719641..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/NonPersistentTopics.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.admin.v1; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.Encoded; -import javax.ws.rs.GET; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.container.AsyncResponse; -import javax.ws.rs.container.Suspended; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response.Status; -import org.apache.commons.lang3.StringUtils; -import org.apache.pulsar.broker.PulsarServerException; -import org.apache.pulsar.broker.service.Topic; -import org.apache.pulsar.broker.web.RestException; -import org.apache.pulsar.common.naming.Constants; -import org.apache.pulsar.common.naming.NamespaceBundle; -import org.apache.pulsar.common.naming.NamespaceName; -import org.apache.pulsar.common.naming.TopicName; -import org.apache.pulsar.common.policies.data.NamespaceOperation; -import org.apache.pulsar.common.policies.data.Policies; -import org.apache.pulsar.common.policies.data.TopicOperation; -import org.apache.pulsar.common.util.FutureUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - */ -@Path("/non-persistent") -@Produces(MediaType.APPLICATION_JSON) -@Api(value = "/non-persistent", - description = "Non-Persistent topic admin apis", tags = "non-persistent topic", hidden = true) -@SuppressWarnings("deprecation") -public class NonPersistentTopics extends PersistentTopics { - private static final Logger log = LoggerFactory.getLogger(NonPersistentTopics.class); - - @GET - @Path("/{property}/{cluster}/{namespace}/{topic}/partitions") - @ApiOperation(hidden = true, value = "Get partitioned topic metadata.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission")}) - public void getPartitionedMetadata( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @QueryParam("checkAllowAutoCreation") @DefaultValue("false") boolean checkAllowAutoCreation) { - super.getPartitionedMetadata(asyncResponse, property, cluster, namespace, encodedTopic, authoritative, - checkAllowAutoCreation); - } - - @GET - @Path("{property}/{cluster}/{namespace}/{topic}/internalStats") - @ApiOperation(hidden = true, value = "Get the internal stats for the topic.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Topic does not exist")}) - public void getInternalStats( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @QueryParam("metadata") @DefaultValue("false") boolean metadata) { - validateTopicName(property, cluster, namespace, encodedTopic); - validateTopicOwnershipAsync(topicName, authoritative) - .thenCompose(__ -> validateTopicOperationAsync(topicName, TopicOperation.GET_STATS)) - .thenCompose(__ -> { - Topic topic = getTopicReference(topicName); - boolean includeMetadata = metadata && hasSuperUserAccess(); - return topic.getInternalStats(includeMetadata); - }) - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to get internal stats for topic {}", clientAppId(), topicName, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @PUT - @Path("/{property}/{cluster}/{namespace}/{topic}/partitions") - @ApiOperation(hidden = true, 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 = 404, message = "Namespace doesn't exist"), - @ApiResponse(code = 406, message = "The number of partitions should be more than 0 and less than or equal" - + " to maxNumPartitionsPerPartitionedTopic"), - @ApiResponse(code = 409, message = "Partitioned topic already exist")}) - public void createPartitionedTopic( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - int numPartitions, - @QueryParam("createLocalTopicOnly") @DefaultValue("false") boolean createLocalTopicOnly) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalCreatePartitionedTopic(asyncResponse, numPartitions, createLocalTopicOnly); - } catch (Exception e) { - log.error("[{}] Failed to create partitioned topic {}", clientAppId(), topicName, e); - resumeAsyncResponseExceptionally(asyncResponse, e); - } - } - - @PUT - @Path("/{property}/{cluster}/{namespace}/{topic}/unload") - @ApiOperation(hidden = true, value = "Unload a topic") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist")}) - public void unloadTopic(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalUnloadTopic(asyncResponse, authoritative); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @GET - @Path("/{property}/{cluster}/{namespace}") - @ApiOperation(value = "Get the list of non-persistent topics under a namespace.", - response = String.class, responseContainer = "List") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist")}) - public void getList(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @QueryParam("bundle") String nsBundle) { - log.info("[{}] list of topics on namespace {}/{}/{}", clientAppId(), property, cluster, namespace); - - Policies policies = null; - NamespaceName nsName = null; - try { - validateNamespaceName(property, cluster, namespace); - validateNamespaceOperation(namespaceName, NamespaceOperation.GET_TOPICS); - policies = getNamespacePolicies(property, cluster, namespace); - nsName = NamespaceName.get(property, cluster, namespace); - - if (!cluster.equals(Constants.GLOBAL_CLUSTER)) { - validateClusterOwnership(cluster); - validateClusterForTenant(property, cluster); - } else { - // check cluster ownership for a given global namespace: redirect if peer-cluster owns it - validateGlobalNamespaceOwnership(nsName); - } - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - return; - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - return; - } - - final List>> futures = new ArrayList<>(); - final List boundaries = policies.bundles.getBoundaries(); - for (int i = 0; i < boundaries.size() - 1; i++) { - final String bundle = String.format("%s_%s", boundaries.get(i), boundaries.get(i + 1)); - if (StringUtils.isNotBlank(nsBundle) && !nsBundle.equals(bundle)) { - continue; - } - try { - futures.add(pulsar().getAdminClient().nonPersistentTopics().getListInBundleAsync(nsName.toString(), - bundle)); - } catch (PulsarServerException e) { - log.error("[{}] Failed to get list of topics under namespace {}/{}/{}/{}", clientAppId(), property, - cluster, namespace, bundle, e); - asyncResponse.resume(new RestException(e)); - return; - } - } - - FutureUtil.waitForAll(futures).whenComplete((result, ex) -> { - if (ex != null) { - resumeAsyncResponseExceptionally(asyncResponse, ex); - } else { - final List topics = new ArrayList<>(); - for (int i = 0; i < futures.size(); i++) { - List topicList = futures.get(i).join(); - if (topicList != null) { - topics.addAll(topicList); - } - } - asyncResponse.resume(topics); - } - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/{bundle}") - @ApiOperation(value = "Get the list of non-persistent topics under a namespace bundle.", - response = String.class, responseContainer = "List") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist")}) - public List getListFromBundle(@PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("bundle") String bundleRange) { - log.info("[{}] list of topics on namespace bundle {}/{}/{}/{}", clientAppId(), property, cluster, namespace, - bundleRange); - validateNamespaceName(property, cluster, namespace); - validateNamespaceOperation(namespaceName, NamespaceOperation.GET_BUNDLE); - Policies policies = getNamespacePolicies(property, cluster, namespace); - if (!cluster.equals(Constants.GLOBAL_CLUSTER)) { - validateClusterOwnership(cluster); - validateClusterForTenant(property, cluster); - } else { - // check cluster ownership for a given global namespace: redirect if peer-cluster owns it - validateGlobalNamespaceOwnership(NamespaceName.get(property, cluster, namespace)); - } - NamespaceName fqnn = NamespaceName.get(property, cluster, namespace); - try { - if (!isBundleOwnedByAnyBroker(fqnn, policies.bundles, bundleRange) - .get(pulsar().getConfig().getMetadataStoreOperationTimeoutSeconds(), TimeUnit.SECONDS)) { - log.info("[{}] Namespace bundle is not owned by any broker {}/{}/{}/{}", clientAppId(), property, - cluster, namespace, bundleRange); - return null; - } - NamespaceBundle nsBundle = validateNamespaceBundleOwnership(fqnn, policies.bundles, bundleRange, - true, true); - final List topicList = new ArrayList<>(); - pulsar().getBrokerService().forEachTopic(topic -> { - TopicName topicName = TopicName.get(topic.getName()); - if (nsBundle.includes(topicName)) { - topicList.add(topic.getName()); - } - }); - return topicList; - } catch (WebApplicationException wae) { - throw wae; - } catch (Exception e) { - log.error("[{}] Failed to unload namespace bundle {}/{}", clientAppId(), fqnn.toString(), bundleRange, e); - throw new RestException(e); - } - } - - private Topic getTopicReference(final TopicName topicName) { - try { - return pulsar().getBrokerService().getTopicIfExists(topicName.toString()) - .get(config().getMetadataStoreOperationTimeoutSeconds(), TimeUnit.SECONDS) - .orElseThrow(() -> new RestException(Status.NOT_FOUND, - String.format("Topic not found %s", topicName.toString()))); - } catch (ExecutionException e) { - throw new RuntimeException(e.getCause()); - } catch (InterruptedException | TimeoutException e) { - throw new RestException(e); - } - } -} diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/PersistentTopics.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/PersistentTopics.java deleted file mode 100644 index 3ebf8f81f6ed1..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/PersistentTopics.java +++ /dev/null @@ -1,1137 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.admin.v1; - -import static org.apache.pulsar.common.util.Codec.decode; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import java.util.Optional; -import java.util.Set; -import javax.ws.rs.DELETE; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.Encoded; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.container.AsyncResponse; -import javax.ws.rs.container.Suspended; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import org.apache.pulsar.broker.admin.AdminResource; -import org.apache.pulsar.broker.admin.impl.PersistentTopicsBase; -import org.apache.pulsar.broker.service.BrokerServiceException; -import org.apache.pulsar.broker.service.GetStatsOptions; -import org.apache.pulsar.broker.web.RestException; -import org.apache.pulsar.client.impl.MessageIdImpl; -import org.apache.pulsar.client.impl.ResetCursorData; -import org.apache.pulsar.common.policies.data.AuthAction; -import org.apache.pulsar.common.policies.data.PolicyName; -import org.apache.pulsar.common.policies.data.PolicyOperation; -import org.apache.pulsar.common.util.FutureUtil; -import org.apache.pulsar.metadata.api.MetadataStoreException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - */ -@Path("/persistent") -@Produces(MediaType.APPLICATION_JSON) -@Api(value = "/persistent", description = "Persistent topic admin apis", tags = "persistent topic", hidden = true) -@SuppressWarnings("deprecation") -public class PersistentTopics extends PersistentTopicsBase { - private static final Logger log = LoggerFactory.getLogger(PersistentTopics.class); - @GET - @Path("/{property}/{cluster}/{namespace}") - @ApiOperation(hidden = true, value = "Get the list of topics under a namespace.", - response = String.class, responseContainer = "List") - @ApiResponses(value = { - @ApiResponse(code = 403, message = "Don't have admin or operate permission on the namespace"), - @ApiResponse(code = 404, message = "Namespace doesn't exist")}) - public void getList(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @ApiParam(value = "Specify the bundle name", required = false) - @QueryParam("bundle") String bundle) { - validateNamespaceName(property, cluster, namespace); - internalGetListAsync(Optional.ofNullable(bundle), null) - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to get topic list {}", clientAppId(), namespaceName, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/partitioned") - @ApiOperation(hidden = true, value = "Get the list of partitioned topics under a namespace.", - response = String.class, responseContainer = "List") - @ApiResponses(value = { - @ApiResponse(code = 403, message = "Don't have admin or operate permission on the namespace"), - @ApiResponse(code = 404, message = "Namespace doesn't exist")}) - public void getPartitionedTopicList( - @Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace) { - validateNamespaceName(property, cluster, namespace); - internalGetPartitionedTopicListAsync() - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to get partitioned topic list {}", clientAppId(), namespaceName, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/{topic}/permissions") - @ApiOperation(hidden = true, value = "Get permissions on a topic.", - notes = "Retrieve the effective permissions for a topic." - + " These permissions are defined by the permissions set at the" - + "namespace level combined (union) with any eventual specific permission set on the topic.") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist")}) - public void getPermissionsOnTopic(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalGetPermissionsOnTopic().thenAccept(permissions -> asyncResponse.resume(permissions)) - .exceptionally(ex -> { - log.error("[{}] Failed to get permissions for topic {}", clientAppId(), topicName, ex); - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } catch (Exception e) { - log.error("[{}] Failed to validate topic name {}", clientAppId(), topicName, e); - resumeAsyncResponseExceptionally(asyncResponse, e); - } - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{topic}/permissions/{role}") - @ApiOperation(hidden = true, value = "Grant a new permission to a role on a single topic.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist"), - @ApiResponse(code = 409, message = "Concurrent modification") }) - public void grantPermissionsOnTopic(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, - @PathParam("role") String role, - Set actions) { - - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalGrantPermissionsOnTopic(asyncResponse, role, actions); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/{topic}/permissions/{role}") - @ApiOperation(hidden = true, value = "Revoke permissions on a topic.", - notes = "Revoke permissions to a role on a single topic. If the permission was not set at the topic" - + "level, but rather at the namespace level," - + " this operation will return an error (HTTP status code 412).") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist"), - @ApiResponse(code = 412, message = "Permissions are not set at the topic level")}) - public void revokePermissionsOnTopic(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, - @PathParam("role") String role) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalRevokePermissionsOnTopic(asyncResponse, role); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @PUT - @Path("/{property}/{cluster}/{namespace}/{topic}/partitions") - @ApiOperation(hidden = true, value = "Create a partitioned topic.", - notes = "It needs to be called before creating a producer on a partitioned topic.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist"), - @ApiResponse(code = 406, message = "The number of partitions should be " - + "more than 0 and less than or equal to maxNumPartitionsPerPartitionedTopic"), - @ApiResponse(code = 409, message = "Partitioned topic already exist")}) - public void createPartitionedTopic( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - int numPartitions, - @QueryParam("createLocalTopicOnly") @DefaultValue("false") boolean createLocalTopicOnly) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalCreatePartitionedTopic(asyncResponse, numPartitions, createLocalTopicOnly); - } catch (Exception e) { - log.error("[{}] Failed to create partitioned topic {}", clientAppId(), topicName, e); - resumeAsyncResponseExceptionally(asyncResponse, e); - } - } - - @PUT - @Path("/{tenant}/{cluster}/{namespace}/{topic}") - @ApiOperation(value = "Create a non-partitioned topic.", - notes = "This is the only REST endpoint from which non-partitioned topics could be created.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Don't have permission to administrate resources on this tenant"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace doesn't exist"), - @ApiResponse(code = 409, message = "Partitioned topic already exist"), - @ApiResponse(code = 412, - message = "Failed Reason : Name is invalid or Namespace does not have any clusters configured"), - @ApiResponse(code = 500, message = "Internal server error"), - @ApiResponse(code = 503, message = "Failed to validate global cluster configuration") - }) - public void createNonPartitionedTopic( - @Suspended final AsyncResponse asyncResponse, - @ApiParam(value = "Specify the tenant", required = true) - @PathParam("tenant") String tenant, - @ApiParam(value = "Specify the cluster", required = true) - @PathParam("cluster") String cluster, - @ApiParam(value = "Specify the namespace", required = true) - @PathParam("namespace") String namespace, - @ApiParam(value = "Specify topic name", required = true) - @PathParam("topic") @Encoded String encodedTopic, - @ApiParam(value = "Whether leader broker redirected this call to this broker. For internal use.") - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateNamespaceName(tenant, cluster, namespace); - validateTopicName(tenant, cluster, namespace, encodedTopic); - validateGlobalNamespaceOwnership(); - validateCreateTopic(topicName); - internalCreateNonPartitionedTopicAsync(authoritative, null) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to create non-partitioned topic {}", clientAppId(), topicName, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - /** - * It updates number of partitions of an existing partitioned topic. It requires partitioned-topic to be - * already exist and number of new partitions must be greater than existing number of partitions. Decrementing - * number of partitions requires deletion of topic which is not supported. - */ - @POST - @Path("/{property}/{cluster}/{namespace}/{topic}/partitions") - @ApiOperation(hidden = true, value = "Increment partitions of an existing partitioned topic.", - notes = "It increments partitions of existing partitioned-topic") - @ApiResponses(value = { - @ApiResponse(code = 204, message = "Update topic partition successful."), - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Unauthenticated"), - @ApiResponse(code = 403, message = "Forbidden/Unauthorized"), - @ApiResponse(code = 404, message = "Topic does not exist"), - @ApiResponse(code = 422, message = "The number of partitions should be more than 0 and" - + " less than or equal to maxNumPartitionsPerPartitionedTopic" - + " and number of new partitions must be greater than existing number of partitions"), - @ApiResponse(code = 412, message = "Partitioned topic name is invalid"), - @ApiResponse(code = 500, message = "Internal server error") - }) - public void updatePartitionedTopic( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("updateLocalTopicOnly") @DefaultValue("false") boolean updateLocalTopic, - @ApiParam(value = "Whether leader broker redirected this call to this broker. For internal use.") - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @QueryParam("force") @DefaultValue("false") boolean force, - int numPartitions) { - validateTopicName(property, cluster, namespace, encodedTopic); - validateTopicPolicyOperationAsync(topicName, PolicyName.PARTITION, PolicyOperation.WRITE) - .thenCompose(__ -> internalUpdatePartitionedTopicAsync(numPartitions, updateLocalTopic, force)) - .thenAccept(__ -> { - log.info("[{}][{}] Updated topic partition to {}.", clientAppId(), topicName, numPartitions); - asyncResponse.resume(Response.noContent().build()); - }) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}][{}] Failed to update partition to {}", - clientAppId(), topicName, numPartitions, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/{topic}/partitions") - @ApiOperation(hidden = true, value = "Get partitioned topic metadata.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist")}) - public void getPartitionedMetadata( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @QueryParam("checkAllowAutoCreation") @DefaultValue("false") boolean checkAllowAutoCreation) { - validateTopicName(property, cluster, namespace, encodedTopic); - internalGetPartitionedMetadataAsync(authoritative, checkAllowAutoCreation) - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - Throwable t = FutureUtil.unwrapCompletionException(ex); - if (!isRedirectException(t)) { - if (AdminResource.isNotFoundException(t)) { - log.error("[{}] Failed to get partitioned metadata topic {}: {}", - clientAppId(), topicName, ex.getMessage()); - } else { - log.error("[{}] Failed to get partitioned metadata topic {}", - clientAppId(), topicName, t); - } - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/{topic}/partitions") - @ApiOperation(hidden = true, value = "Delete a partitioned topic.", - notes = "It will also delete all the partitions of the topic if it exists.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or partitioned topic does not exist")}) - public void deletePartitionedTopic(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("force") @DefaultValue("false") boolean force, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalDeletePartitionedTopic(asyncResponse, authoritative, force); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @PUT - @Path("/{property}/{cluster}/{namespace}/{topic}/unload") - @ApiOperation(hidden = true, value = "Unload a topic") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist") }) - public void unloadTopic(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateTopicName(property, cluster, namespace, encodedTopic); - internalUnloadTopic(asyncResponse, authoritative); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/{topic}") - @ApiOperation(hidden = true, value = "Delete a topic.", - notes = "The topic cannot be deleted if delete is not forcefully and there's any active " - + "subscription or producer connected to the it. " - + "Force delete ignores connected clients and deletes topic by explicitly closing them.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist"), - @ApiResponse(code = 412, message = "Topic has active producers/subscriptions")}) - public void deleteTopic( - @Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("force") @DefaultValue("false") boolean force, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateTopicName(property, cluster, namespace, encodedTopic); - internalDeleteTopicAsync(authoritative, force) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - Throwable t = FutureUtil.unwrapCompletionException(ex); - if (!force && (t instanceof BrokerServiceException.TopicBusyException)) { - ex = new RestException(Response.Status.PRECONDITION_FAILED, - t.getMessage()); - } - if (isManagedLedgerNotFoundException(t)) { - ex = new RestException(Response.Status.NOT_FOUND, - getTopicNotFoundErrorMessage(topicName.toString())); - } else if (!isRedirectException(ex)) { - log.error("[{}] Failed to delete topic {}", clientAppId(), topicName, t); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/{topic}/subscriptions") - @ApiOperation(hidden = true, value = "Get the list of persistent subscriptions for a given topic.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist") }) - public void getSubscriptions(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalGetSubscriptions(asyncResponse, authoritative); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @GET - @Path("{property}/{cluster}/{namespace}/{topic}/stats") - @ApiOperation(hidden = true, value = "Get the stats for the topic.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist")}) - public void getStats( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @QueryParam("getPreciseBacklog") @DefaultValue("false") boolean getPreciseBacklog) { - validateTopicName(property, cluster, namespace, encodedTopic); - GetStatsOptions getStatsOptions = - new GetStatsOptions(getPreciseBacklog, false, false, false, false); - internalGetStatsAsync(authoritative, getStatsOptions) - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - // If the exception is not redirect exception we need to log it. - if (!isRedirectException(ex)) { - log.error("[{}] Failed to get stats for {}", clientAppId(), topicName, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("{property}/{cluster}/{namespace}/{topic}/internalStats") - @ApiOperation(hidden = true, value = "Get the internal stats for the topic.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist")}) - public void getInternalStats( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @QueryParam("metadata") @DefaultValue("false") boolean metadata) { - validateTopicName(property, cluster, namespace, encodedTopic); - internalGetInternalStatsAsync(authoritative, metadata) - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to get internal stats for topic {}", clientAppId(), topicName, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("{property}/{cluster}/{namespace}/{topic}/internal-info") - @ApiOperation(hidden = true, value = "Get the stored topic metadata.") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist")}) - public void getManagedLedgerInfo(@PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded - String encodedTopic, - @Suspended AsyncResponse asyncResponse, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateTopicName(property, cluster, namespace, encodedTopic); - internalGetManagedLedgerInfo(asyncResponse, authoritative); - } - - @GET - @Path("{property}/{cluster}/{namespace}/{topic}/partitioned-stats") - @ApiOperation(hidden = true, value = "Get the stats for the partitioned topic.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist")}) - public void getPartitionedStats(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("perPartition") @DefaultValue("true") boolean perPartition, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - GetStatsOptions getStatsOptions = new GetStatsOptions(false, false, false, false, false); - internalGetPartitionedStats(asyncResponse, authoritative, perPartition, getStatsOptions); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - - @GET - @Path("{property}/{cluster}/{namespace}/{topic}/partitioned-internalStats") - @ApiOperation(hidden = true, value = "Get the stats-internal for the partitioned topic.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist")}) - public void getPartitionedStatsInternal( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalGetPartitionedStatsInternal(asyncResponse, authoritative); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/{topic}/subscription/{subName}") - @ApiOperation(hidden = true, value = "Delete a subscription.", - notes = "The subscription cannot be deleted if delete is not forcefully" - + " and there are any active consumers attached to it. " - + "Force delete ignores connected consumers and deletes subscription by explicitly closing them.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic or subscription does not exist"), - @ApiResponse(code = 412, message = "Subscription has active consumers")}) - public void deleteSubscription(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, @PathParam("subName") String encodedSubName, - @QueryParam("force") @DefaultValue("false") boolean force, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateTopicName(property, cluster, namespace, encodedTopic); - String subName = decode(encodedSubName); - internalDeleteSubscriptionAsync(subName, authoritative, force) - .thenRun(() -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - Throwable cause = FutureUtil.unwrapCompletionException(ex); - - // If the exception is not redirect exception we need to log it. - if (!isRedirectException(cause)) { - log.error("[{}] Failed to delete subscription {} from topic {}", clientAppId(), subName, - topicName, cause); - } - - if (cause instanceof BrokerServiceException.SubscriptionBusyException) { - resumeAsyncResponseExceptionally(asyncResponse, - new RestException(Response.Status.PRECONDITION_FAILED, - "Subscription has active connected consumers")); - } else { - resumeAsyncResponseExceptionally(asyncResponse, cause); - } - - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{topic}/subscription/{subName}/skip_all") - @ApiOperation(hidden = true, value = "Skip all messages on a topic subscription.", - notes = "Completely clears the backlog on the subscription.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 405, message = "Operation not allowed on non-persistent topic"), - @ApiResponse(code = 404, message = "Namespace or topic or subscription does not exist")}) - public void skipAllMessages(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, @PathParam("subName") String encodedSubName, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalSkipAllMessages(asyncResponse, decode(encodedSubName), authoritative); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{topic}/subscription/{subName}/skip/{numMessages}") - @ApiOperation(hidden = true, value = "Skip messages on a topic subscription.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namesapce or topic or subscription does not exist") }) - public void skipMessages(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, @PathParam("subName") String encodedSubName, - @PathParam("numMessages") int numMessages, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalSkipMessages(asyncResponse, decode(encodedSubName), numMessages, authoritative); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{topic}/subscription/{subName}/expireMessages/{expireTimeInSeconds}") - @ApiOperation(hidden = true, value = "Expire messages on a topic subscription.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic or subscription does not exist") }) - public void expireTopicMessages(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, - @PathParam("subName") String encodedSubName, @PathParam("expireTimeInSeconds") int expireTimeInSeconds, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalExpireMessagesByTimestamp(asyncResponse, decode(encodedSubName), - expireTimeInSeconds, authoritative); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{topic}/subscription/{subName}/expireMessages") - @ApiOperation(value = "Expiry messages on a topic subscription.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Don't have permission to administrate resources on this tenant or" - + "subscriber is not authorized to access this operation"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic or subscription does not exist"), - @ApiResponse(code = 405, message = "Expiry messages on a non-persistent topic is not allowed"), - @ApiResponse(code = 500, message = "Internal server error"), - @ApiResponse(code = 503, message = "Failed to validate global cluster configuration")}) - public void expireTopicMessages( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @ApiParam(value = "Specify the namespace", required = true) - @PathParam("namespace") String namespace, - @ApiParam(value = "Specify topic name", required = true) - @PathParam("topic") @Encoded String encodedTopic, - @ApiParam(value = "Subscription to be Expiry messages on") - @PathParam("subName") String encodedSubName, - @ApiParam(value = "Whether leader broker redirected this call to this broker. For internal use.") - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @ApiParam(name = "messageId", value = "messageId to reset back to (ledgerId:entryId)") - ResetCursorData resetCursorData) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalExpireMessagesByPosition(asyncResponse, decode(encodedSubName), authoritative, - new MessageIdImpl(resetCursorData.getLedgerId(), - resetCursorData.getEntryId(), resetCursorData.getPartitionIndex()) - , resetCursorData.isExcluded(), resetCursorData.getBatchIndex()); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{topic}/all_subscription/expireMessages/{expireTimeInSeconds}") - @ApiOperation(hidden = true, value = "Expire messages on all subscriptions of topic.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic or subscription does not exist") }) - public void expireMessagesForAllSubscriptions(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, - @PathParam("expireTimeInSeconds") int expireTimeInSeconds, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalExpireMessagesForAllSubscriptions(asyncResponse, expireTimeInSeconds, authoritative); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{topic}/subscription/{subName}/resetcursor/{timestamp}") - @ApiOperation(hidden = true, - value = "Reset subscription to message position closest to absolute timestamp (in ms).", - notes = "It fence cursor and disconnects all active consumers before resetting cursor.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic or subscription does not exist")}) - public void resetCursor(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, @PathParam("subName") String encodedSubName, - @PathParam("timestamp") long timestamp, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateTopicName(property, cluster, namespace, encodedTopic); - internalResetCursorAsync(decode(encodedSubName), timestamp, authoritative) - .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) - .exceptionally(ex -> { - Throwable t = FutureUtil.unwrapCompletionException(ex); - if (!isRedirectException(t)) { - log.error("[{}][{}] Failed to reset cursor on subscription {} to time {}", - clientAppId(), topicName, encodedSubName, timestamp, t); - } - if (t instanceof BrokerServiceException.SubscriptionInvalidCursorPosition) { - t = new RestException(Response.Status.PRECONDITION_FAILED, - "Unable to find position for timestamp specified: " + t.getMessage()); - } else if (t instanceof BrokerServiceException.SubscriptionBusyException) { - t = new RestException(Response.Status.PRECONDITION_FAILED, - "Failed for Subscription Busy: " + t.getMessage()); - } - resumeAsyncResponseExceptionally(asyncResponse, t); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{topic}/subscription/{subName}/resetcursor") - @ApiOperation(hidden = true, value = "Reset subscription to message position closest to given position.", - notes = "It fence cursor and disconnects all active consumers before resetting cursor.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic or subscription does not exist"), - @ApiResponse(code = 405, message = "Not supported for partitioned topics")}) - public void resetCursorOnPosition(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded - String encodedTopic, - @PathParam("subName") String encodedSubName, - @QueryParam("authoritative") @DefaultValue("false") - boolean authoritative, ResetCursorData resetCursorData) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalResetCursorOnPosition(asyncResponse, decode(encodedSubName), authoritative, - new MessageIdImpl(resetCursorData.getLedgerId(), - resetCursorData.getEntryId(), resetCursorData.getPartitionIndex()) - , resetCursorData.isExcluded(), resetCursorData.getBatchIndex()); - } catch (Exception e) { - resumeAsyncResponseExceptionally(asyncResponse, e); - } - } - - @PUT - @Path("/{property}/{cluster}/{namespace}/{topic}/subscription/{subscriptionName}") - @ApiOperation(value = "Create a subscription on the topic.", - notes = "Creates a subscription on the topic at the specified message id") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 400, message = "Create subscription on non persistent topic is not supported"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic or subscription does not exist"), - @ApiResponse(code = 405, message = "Not supported for partitioned topics")}) - public void createSubscription(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String topic, @PathParam("subscriptionName") String encodedSubName, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, MessageIdImpl messageId, - @QueryParam("replicated") boolean replicated) { - try { - validateTopicName(property, cluster, namespace, topic); - if (!topicName.isPersistent()) { - throw new RestException(Response.Status.BAD_REQUEST, "Create subscription on non-persistent topic " - + "can only be done through client"); - } - internalCreateSubscription(asyncResponse, decode(encodedSubName), messageId, authoritative, replicated, - null); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @GET - @Path("/{property}/{cluster}/{namespace}/{topic}/subscription/{subName}/position/{messagePosition}") - @ApiOperation(hidden = true, value = "Peek nth message on a topic subscription.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic or subscription or the message position does not" - + " exist") }) - public void peekNthMessage( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, - @PathParam("subName") String encodedSubName, @PathParam("messagePosition") int messagePosition, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateTopicName(property, cluster, namespace, encodedTopic); - internalPeekNthMessageAsync(decode(encodedSubName), messagePosition, authoritative) - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to get peek nth message for topic {} subscription {}", clientAppId(), - topicName, decode(encodedSubName), ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("/{property}/{cluster}/{namespace}/{topic}/ledger/{ledgerId}/entry/{entryId}") - @ApiOperation(hidden = true, value = "Get message by its messageId.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't java admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic or subscription or the messageId does not exist") - }) - public void getMessageByID(@Suspended final AsyncResponse asyncResponse, @PathParam("property") String property, - @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, @PathParam("ledgerId") Long ledgerId, - @PathParam("entryId") Long entryId, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateTopicName(property, cluster, namespace, encodedTopic); - internalGetMessageById(ledgerId, entryId, authoritative) - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - // If the exception is not redirect exception we need to log it. - if (!isRedirectException(ex)) { - log.error("[{}] Failed to get message with ledgerId {} entryId {} from {}", - clientAppId(), ledgerId, entryId, topicName, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("{property}/{cluster}/{namespace}/{topic}/backlog") - @ApiOperation(hidden = true, value = "Get estimated backlog for offline topic.") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist")}) - public void getBacklog( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateTopicName(property, cluster, namespace, encodedTopic); - internalGetBacklogAsync(authoritative) - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - Throwable t = FutureUtil.unwrapCompletionException(ex); - if (t instanceof MetadataStoreException.NotFoundException) { - log.warn("[{}] Failed to get topic backlog {}: Namespace does not exist", clientAppId(), - namespaceName); - ex = new RestException(Response.Status.NOT_FOUND, "Namespace does not exist"); - } else if (!isRedirectException(ex)) { - log.error("[{}] Failed to get estimated backlog for topic {}", clientAppId(), encodedTopic, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{topic}/terminate") - @ApiOperation(hidden = true, value = "Terminate a topic. A topic that is terminated will not accept any more " - + "messages to be published and will let consumer to drain existing messages in backlog") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 405, message = "Operation not allowed on non-persistent topic"), - @ApiResponse(code = 406, message = "Need to provide a persistent topic name"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist") }) - public void terminate( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validatePersistentTopicName(property, cluster, namespace, encodedTopic); - internalTerminateAsync(authoritative) - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to terminated topic {}", clientAppId(), topicName, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{topic}/terminate/partitions") - @ApiOperation(hidden = true, - value = "Terminate all partitioned topic. A topic that is terminated will not accept any more " - + "messages to be published and will let consumer to drain existing messages in backlog") - @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 405, message = "Operation not allowed on non-persistent topic"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist")}) - public void terminatePartitionedTopic(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateTopicName(property, cluster, namespace, encodedTopic); - internalTerminatePartitionedTopic(asyncResponse, authoritative); - } - - @PUT - @Path("/{property}/{cluster}/{namespace}/{topic}/compaction") - @ApiOperation(value = "Trigger a compaction operation on a topic.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 405, message = "Operation not allowed on persistent topic"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist"), - @ApiResponse(code = 409, message = "Compaction already running")}) - public void compact(@Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateTopicName(property, cluster, namespace, encodedTopic); - internalTriggerCompaction(asyncResponse, authoritative); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @GET - @Path("/{property}/{cluster}/{namespace}/{topic}/compaction") - @ApiOperation(value = "Get the status of a compaction operation for a topic.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 405, message = "Operation not allowed on persistent topic"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist, or compaction hasn't run") }) - public void compactionStatus( - @Suspended final AsyncResponse asyncResponse, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateTopicName(property, cluster, namespace, encodedTopic); - internalCompactionStatusAsync(authoritative) - .thenAccept(asyncResponse::resume) - .exceptionally(ex -> { - if (!isRedirectException(ex)) { - log.error("[{}] Failed to get the status of a compaction operation for the topic {}", - clientAppId(), topicName, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @PUT - @Path("/{tenant}/{cluster}/{namespace}/{topic}/offload") - @ApiOperation(value = "Offload a prefix of a topic to long term storage") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 405, message = "Operation not allowed on persistent topic"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist"), - @ApiResponse(code = 409, message = "Offload already running")}) - public void triggerOffload(@Suspended final AsyncResponse asyncResponse, - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - MessageIdImpl messageId) { - try { - validateTopicName(tenant, cluster, namespace, encodedTopic); - internalTriggerOffload(asyncResponse, authoritative, messageId); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @GET - @Path("/{tenant}/{cluster}/{namespace}/{topic}/offload") - @ApiOperation(value = "Offload a prefix of a topic to long term storage") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 405, message = "Operation not allowed on persistent topic"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist")}) - public void offloadStatus(@Suspended final AsyncResponse asyncResponse, - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") @Encoded String encodedTopic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateTopicName(tenant, cluster, namespace, encodedTopic); - internalOffloadStatus(asyncResponse, authoritative); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @GET - @Path("/{tenant}/{cluster}/{namespace}/{topic}/lastMessageId") - @ApiOperation(value = "Return the last commit message id of topic") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Don't have permission to administrate resources on this tenant or" - + "subscriber is not authorized to access this operation"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist"), - @ApiResponse(code = 405, message = "Operation is not allowed on the persistent topic"), - @ApiResponse(code = 412, message = "Topic name is not valid"), - @ApiResponse(code = 500, message = "Internal server error"), - @ApiResponse(code = 503, message = "Failed to validate global cluster configuration")}) - public void getLastMessageId( - @Suspended final AsyncResponse asyncResponse, - @ApiParam(value = "Specify the tenant", required = true) - @PathParam("tenant") String tenant, - @ApiParam(value = "Specify the cluster", required = true) - @PathParam("cluster") String cluster, - @ApiParam(value = "Specify the namespace", required = true) - @PathParam("namespace") String namespace, - @ApiParam(value = "Specify topic name", required = true) - @PathParam("topic") @Encoded String encodedTopic, - @ApiParam(value = "Whether leader broker redirected this call to this broker. For internal use.") - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - try { - validateTopicName(tenant, cluster, namespace, encodedTopic); - internalGetLastMessageId(asyncResponse, authoritative); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @POST - @Path("/{tenant}/{cluster}/{namespace}/{topic}/subscription/{subName}/replicatedSubscriptionStatus") - @ApiOperation(value = "Enable or disable a replicated subscription on a topic.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Don't have permission to administrate resources on this tenant or " - + "subscriber is not authorized to access this operation"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic or subscription does not exist"), - @ApiResponse(code = 405, message = "Operation not allowed on this topic"), - @ApiResponse(code = 412, message = "Can't find owner for topic"), - @ApiResponse(code = 500, message = "Internal server error"), - @ApiResponse(code = 503, message = "Failed to validate global cluster configuration")}) - public void setReplicatedSubscriptionStatus( - @Suspended final AsyncResponse asyncResponse, - @ApiParam(value = "Specify the tenant", required = true) - @PathParam("tenant") String tenant, - @ApiParam(value = "Specify the cluster", required = true) - @PathParam("cluster") String cluster, - @ApiParam(value = "Specify the namespace", required = true) - @PathParam("namespace") String namespace, - @ApiParam(value = "Specify topic name", required = true) - @PathParam("topic") @Encoded String encodedTopic, - @ApiParam(value = "Name of subscription", required = true) - @PathParam("subName") String encodedSubName, - @ApiParam(value = "Whether leader broker redirected this call to this broker. For internal use.") - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @ApiParam(value = "Whether to enable replicated subscription", required = true) - boolean enabled) { - try { - validateTopicName(tenant, cluster, namespace, encodedTopic); - internalSetReplicatedSubscriptionStatus(asyncResponse, decode(encodedSubName), authoritative, enabled); - } catch (WebApplicationException wae) { - asyncResponse.resume(wae); - } catch (Exception e) { - asyncResponse.resume(new RestException(e)); - } - } - - @GET - @Path("/{tenant}/{cluster}/{namespace}/{topic}/subscription/{subName}/replicatedSubscriptionStatus") - @ApiOperation(value = "Get replicated subscription status on a topic.") - @ApiResponses(value = { - @ApiResponse(code = 401, message = "Don't have permission to administrate resources"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace or topic does not exist"), - @ApiResponse(code = 412, message = "Can't find owner for topic"), - @ApiResponse(code = 500, message = "Internal server error")}) - public void getReplicatedSubscriptionStatus( - @Suspended AsyncResponse asyncResponse, - @ApiParam(value = "Specify the tenant", required = true) - @PathParam("tenant") String tenant, - @ApiParam(value = "Specify the cluster", required = true) - @PathParam("cluster") String cluster, - @ApiParam(value = "Specify the namespace", required = true) - @PathParam("namespace") String namespace, - @ApiParam(value = "Specify topic name", required = true) - @PathParam("topic") @Encoded String encodedTopic, - @ApiParam(value = "Name of subscription", required = true) - @PathParam("subName") String encodedSubName, - @ApiParam(value = "Whether leader broker redirected this call to this broker. For internal use.") - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative) { - validateTopicName(tenant, cluster, namespace, encodedTopic); - internalGetReplicatedSubscriptionStatus(asyncResponse, decode(encodedSubName), authoritative); - } - -} diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Properties.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Properties.java deleted file mode 100644 index 66764d41ce467..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/Properties.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.admin.v1; - -import io.swagger.annotations.Api; -import javax.ws.rs.Consumes; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import org.apache.pulsar.broker.admin.impl.TenantsBase; - -@Path("/properties") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -@Api(value = "/properties", description = "TenantsBase admin apis", tags = "properties", hidden = true) -public class Properties extends TenantsBase { -} diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/ResourceQuotas.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/ResourceQuotas.java deleted file mode 100644 index 37244fea1cd6c..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/ResourceQuotas.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.admin.v1; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.container.AsyncResponse; -import javax.ws.rs.container.Suspended; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import lombok.extern.slf4j.Slf4j; -import org.apache.pulsar.broker.admin.impl.ResourceQuotasBase; -import org.apache.pulsar.common.policies.data.ResourceQuota; - -@Slf4j -@Path("/resource-quotas") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -@Api(value = "/resource-quotas", description = "Quota admin APIs", tags = "resource-quotas", hidden = true) -public class ResourceQuotas extends ResourceQuotasBase { - - @GET - @Path("/{property}/{cluster}/{namespace}/{bundle}") - @ApiOperation(hidden = true, value = "Get resource quota of a namespace bundle.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Namespace does not exist") }) - public void getNamespaceBundleResourceQuota( - @Suspended AsyncResponse response, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("bundle") String bundleRange) { - validateNamespaceName(property, cluster, namespace); - internalGetNamespaceBundleResourceQuota(bundleRange) - .thenAccept(response::resume) - .exceptionally(ex -> { - log.error("[{}] Failed to get namespace bundle resource quota {}", clientAppId(), - namespaceName, ex); - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @POST - @Path("/{property}/{cluster}/{namespace}/{bundle}") - @ApiOperation(hidden = true, value = "Set resource quota on a namespace.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 409, message = "Concurrent modification") }) - public void setNamespaceBundleResourceQuota( - @Suspended AsyncResponse response, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("bundle") String bundleRange, - ResourceQuota quota) { - validateNamespaceName(property, cluster, namespace); - internalSetNamespaceBundleResourceQuota(bundleRange, quota) - .thenAccept(__ -> { - log.info("[{}] Successfully set resource quota for namespace bundle {}", - clientAppId(), bundleRange); - response.resume(Response.noContent().build()); - }) - .exceptionally(ex -> { - log.error("[{}] Failed to set namespace resource quota for bundle {}", - clientAppId(), bundleRange, ex); - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @DELETE - @Path("/{property}/{cluster}/{namespace}/{bundle}") - @ApiOperation(hidden = true, value = "Remove resource quota for a namespace.") - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace"), - @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 409, message = "Concurrent modification") }) - public void removeNamespaceBundleResourceQuota( - @Suspended AsyncResponse response, - @PathParam("property") String property, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("bundle") String bundleRange) { - validateNamespaceName(property, cluster, namespace); - internalRemoveNamespaceBundleResourceQuota(bundleRange) - .thenAccept(__ -> { - log.info("[{}] Successfully remove namespace bundle resource quota {}", clientAppId(), bundleRange); - response.resume(Response.noContent().build()); - }) - .exceptionally(ex -> { - log.error("[{}] Failed to remove namespace bundle resource quota {}", - clientAppId(), bundleRange, ex); - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } -} diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/SchemasResource.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/SchemasResource.java deleted file mode 100644 index 0d6c3814bf863..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/SchemasResource.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.admin.v1; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.Example; -import io.swagger.annotations.ExampleProperty; -import javax.ws.rs.Consumes; -import javax.ws.rs.DELETE; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.Encoded; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.container.AsyncResponse; -import javax.ws.rs.container.Suspended; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import lombok.extern.slf4j.Slf4j; -import org.apache.pulsar.broker.admin.impl.SchemasResourceBase; -import org.apache.pulsar.broker.service.schema.exceptions.IncompatibleSchemaException; -import org.apache.pulsar.broker.service.schema.exceptions.InvalidSchemaDataException; -import org.apache.pulsar.common.policies.data.SchemaMetadata; -import org.apache.pulsar.common.protocol.schema.DeleteSchemaResponse; -import org.apache.pulsar.common.protocol.schema.GetAllVersionsSchemaResponse; -import org.apache.pulsar.common.protocol.schema.GetSchemaResponse; -import org.apache.pulsar.common.protocol.schema.IsCompatibilityResponse; -import org.apache.pulsar.common.protocol.schema.LongSchemaVersionResponse; -import org.apache.pulsar.common.protocol.schema.PostSchemaPayload; -import org.apache.pulsar.common.protocol.schema.PostSchemaResponse; -import org.apache.pulsar.common.schema.LongSchemaVersion; -import org.apache.pulsar.common.util.FutureUtil; - -@Path("/schemas") -@Api( - value = "/schemas", - description = "Schemas related admin APIs", - tags = "schemas" -) -@Slf4j -public class SchemasResource extends SchemasResourceBase { - - public SchemasResource() { - super(); - } - - @GET - @Path("/{tenant}/{cluster}/{namespace}/{topic}/schema") - @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Get the schema of a topic", response = GetSchemaResponse.class) - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Client is not authorized or Don't have admin permission"), - @ApiResponse(code = 403, message = "Client is not authenticated"), - @ApiResponse(code = 404, - message = "Tenant or Namespace or Topic doesn't exist; or Schema is not found for this topic"), - @ApiResponse(code = 412, message = "Failed to find the ownership for the topic"), - @ApiResponse(code = 500, message = "Internal Server Error"), - }) - public void getSchema( - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") String topic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @Suspended final AsyncResponse response - ) { - validateTopicName(tenant, cluster, namespace, topic); - getSchemaAsync(authoritative) - .thenApply(this::convertToSchemaResponse) - .thenApply(response::resume) - .exceptionally(ex -> { - if (shouldPrintErrorLog(ex)) { - log.error("[{}] Failed to get schema for topic {}", clientAppId(), topicName, ex); - } - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @GET - @Path("/{tenant}/{cluster}/{namespace}/{topic}/schema/{version}") - @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Get the schema of a topic at a given version", response = GetSchemaResponse.class) - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Client is not authorized or Don't have admin permission"), - @ApiResponse(code = 403, message = "Client is not authenticated"), - @ApiResponse(code = 404, - message = "Tenant or Namespace or Topic doesn't exist; or Schema is not found for this topic"), - @ApiResponse(code = 412, message = "Failed to find the ownership for the topic"), - @ApiResponse(code = 500, message = "Internal Server Error"), - }) - public void getSchema( - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") String topic, - @PathParam("version") @Encoded String version, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @Suspended final AsyncResponse response - ) { - validateTopicName(tenant, cluster, namespace, topic); - getSchemaAsync(authoritative, version) - .thenApply(this::convertToSchemaResponse) - .thenAccept(response::resume) - .exceptionally(ex -> { - if (shouldPrintErrorLog(ex)) { - log.error("[{}] Failed to get schema for topic {} with version {}", - clientAppId(), topicName, version, ex); - } - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @GET - @Path("/{tenant}/{cluster}/{namespace}/{topic}/schemas") - @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Get the all schemas of a topic", response = GetAllVersionsSchemaResponse.class) - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Client is not authorized or Don't have admin permission"), - @ApiResponse(code = 403, message = "Client is not authenticated"), - @ApiResponse(code = 404, - message = "Tenant or Namespace or Topic doesn't exist; or Schema is not found for this topic"), - @ApiResponse(code = 412, message = "Failed to find the ownership for the topic"), - @ApiResponse(code = 500, message = "Internal Server Error"), - }) - public void getAllSchemas( - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") String topic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @Suspended final AsyncResponse response - ) { - validateTopicName(tenant, cluster, namespace, topic); - getAllSchemasAsync(authoritative) - .thenApply(this::convertToAllVersionsSchemaResponse) - .thenAccept(response::resume) - .exceptionally(ex -> { - if (shouldPrintErrorLog(ex)) { - log.error("[{}] Failed to get all schemas for topic {}", clientAppId(), topicName, ex); - } - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @GET - @Path("/{tenant}/{cluster}/{namespace}/{topic}/metadata") - @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Get the schema metadata of a topic", response = SchemaMetadata.class) - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Client is not authorized or Don't have admin permission"), - @ApiResponse(code = 403, message = "Client is not authenticated"), - @ApiResponse(code = 404, - message = "Tenant or Namespace or Topic doesn't exist; or Schema is not found for this topic"), - @ApiResponse(code = 412, message = "Failed to find the ownership for the topic"), - @ApiResponse(code = 500, message = "Internal Server Error"), - }) - public void getSchemaMetadata( - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") String topic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @Suspended final AsyncResponse response - ) { - validateTopicName(tenant, cluster, namespace, topic); - getSchemaMetadataAsync(authoritative) - .thenAccept(response::resume) - .exceptionally(ex -> { - log.error("[{}] Failed to get schema metadata for topic {}", clientAppId(), topicName, ex); - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @DELETE - @Path("/{tenant}/{cluster}/{namespace}/{topic}/schema") - @Produces(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Delete the schema of a topic", response = DeleteSchemaResponse.class) - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Client is not authorized or Don't have admin permission"), - @ApiResponse(code = 403, message = "Client is not authenticated"), - @ApiResponse(code = 404, message = "Tenant or Namespace or Topic doesn't exist"), - @ApiResponse(code = 412, message = "Failed to find the ownership for the topic"), - @ApiResponse(code = 500, message = "Internal Server Error"), - }) - public void deleteSchema( - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") String topic, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @QueryParam("force") @DefaultValue("false") boolean force, - @Suspended final AsyncResponse response - ) { - validateTopicName(tenant, cluster, namespace, topic); - deleteSchemaAsync(authoritative, force) - .thenAccept(version -> { - response.resume(DeleteSchemaResponse.builder().version(getLongSchemaVersion(version)).build()); - }) - .exceptionally(ex -> { - if (shouldPrintErrorLog(ex)) { - log.error("[{}] Failed to delete schemas for topic {}", clientAppId(), topicName, ex); - } - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @POST - @Path("/{tenant}/{cluster}/{namespace}/{topic}/schema") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @ApiOperation(value = "Update the schema of a topic", response = PostSchemaResponse.class) - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Client is not authorized or Don't have admin permission"), - @ApiResponse(code = 403, message = "Client is not authenticated"), - @ApiResponse(code = 404, message = "Tenant or Namespace or Topic doesn't exist"), - @ApiResponse(code = 409, message = "Incompatible schema"), - @ApiResponse(code = 412, message = "Failed to find the ownership for the topic"), - @ApiResponse(code = 422, message = "Invalid schema data"), - @ApiResponse(code = 500, message = "Internal Server Error"), - }) - public void postSchema( - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") String topic, - @ApiParam( - value = "A JSON value presenting a schema playload. An example of the expected schema can be found down" - + " here.", - examples = @Example( - value = @ExampleProperty( - mediaType = MediaType.APPLICATION_JSON, - value = "{\"type\": \"STRING\", \"schema\": \"\", \"properties\": { \"key1\" : \"value1\" + } }" - ) - ) - ) - PostSchemaPayload payload, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @Suspended final AsyncResponse response - ) { - validateTopicName(tenant, cluster, namespace, topic); - postSchemaAsync(payload, authoritative) - .thenAccept(version -> response.resume(PostSchemaResponse.builder().version(version).build())) - .exceptionally(ex -> { - Throwable root = FutureUtil.unwrapCompletionException(ex); - if (root instanceof IncompatibleSchemaException) { - response.resume(Response - .status(Response.Status.CONFLICT.getStatusCode(), root.getMessage()) - .build()); - } else if (root instanceof InvalidSchemaDataException) { - response.resume(Response.status(422, /* Unprocessable Entity */ - root.getMessage()).build()); - } else { - if (shouldPrintErrorLog(ex)) { - log.error("[{}] Failed to post schemas for topic {}", clientAppId(), topicName, root); - } - resumeAsyncResponseExceptionally(response, ex); - } - return null; - }); - } - - @POST - @Path("/{tenant}/{cluster}/{namespace}/{topic}/compatibility") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @ApiOperation(value = "test the schema compatibility", response = IsCompatibilityResponse.class) - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Client is not authorized or Don't have admin permission"), - @ApiResponse(code = 403, message = "Client is not authenticated"), - @ApiResponse(code = 404, message = "Tenant or Namespace or Topic doesn't exist"), - @ApiResponse(code = 412, message = "Failed to find the ownership for the topic"), - @ApiResponse(code = 500, message = "Internal Server Error"), - }) - public void testCompatibility( - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") String topic, - @ApiParam( - value = "A JSON value presenting a schema playload." - + " An example of the expected schema can be found down here.", - examples = @Example( - value = @ExampleProperty( - mediaType = MediaType.APPLICATION_JSON, - value = "{\"type\": \"STRING\", \"schema\": \"\"," - + " \"properties\": { \"key1\" : \"value1\" + } }" - ) - ) - ) - PostSchemaPayload payload, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @Suspended final AsyncResponse response - ) { - validateTopicName(tenant, cluster, namespace, topic); - testCompatibilityAsync(payload, authoritative) - .thenAccept(pair -> response.resume(Response.accepted() - .entity(IsCompatibilityResponse.builder().isCompatibility(pair.getLeft()) - .schemaCompatibilityStrategy(pair.getRight().name()).build()) - .build())) - .exceptionally(ex -> { - if (shouldPrintErrorLog(ex)) { - log.error("[{}] Failed to test compatibility for topic {}", clientAppId(), topicName, ex); - } - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } - - @POST - @Path("/{tenant}/{cluster}/{namespace}/{topic}/version") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - @ApiOperation(value = "get the version of the schema", response = LongSchemaVersion.class) - @ApiResponses(value = { - @ApiResponse(code = 307, message = "Current broker doesn't serve the namespace of this topic"), - @ApiResponse(code = 401, message = "Client is not authorized or Don't have admin permission"), - @ApiResponse(code = 403, message = "Client is not authenticated"), - @ApiResponse(code = 404, message = "Tenant or Namespace or Topic doesn't exist"), - @ApiResponse(code = 412, message = "Failed to find the ownership for the topic"), - @ApiResponse(code = 422, message = "Invalid schema data"), - @ApiResponse(code = 500, message = "Internal Server Error"), - }) - public void getVersionBySchema( - @PathParam("tenant") String tenant, - @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, - @PathParam("topic") String topic, - @ApiParam( - value = "A JSON value presenting a schema playload." - + " An example of the expected schema can be found down here.", - examples = @Example( - value = @ExampleProperty( - mediaType = MediaType.APPLICATION_JSON, - value = "{\"type\": \"STRING\", \"schema\": \"\"," - + " \"properties\": { \"key1\" : \"value1\" + } }" - ) - ) - ) - PostSchemaPayload payload, - @QueryParam("authoritative") @DefaultValue("false") boolean authoritative, - @Suspended final AsyncResponse response - ) { - validateTopicName(tenant, cluster, namespace, topic); - getVersionBySchemaAsync(payload, authoritative) - .thenAccept(version -> response.resume(LongSchemaVersionResponse.builder().version(version).build())) - .exceptionally(ex -> { - if (shouldPrintErrorLog(ex)) { - log.error("[{}] Failed to get version by schema for topic {}", clientAppId(), topicName, ex); - } - resumeAsyncResponseExceptionally(response, ex); - return null; - }); - } -} diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/package-info.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/package-info.java deleted file mode 100644 index f6cffb50fb6e3..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v1/package-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.admin.v1; diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Namespaces.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Namespaces.java index 21466736af390..b770c078a2876 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Namespaces.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Namespaces.java @@ -364,21 +364,21 @@ public void revokePermissionsOnTopics(@Suspended final AsyncResponse asyncRespon } @POST - @Path("/{property}/{namespace}/permissions/subscription/{subscription}") + @Path("/{tenant}/{namespace}/permissions/subscription/{subscription}") @ApiOperation(hidden = true, value = "Grant a new permission to roles for a subscription." + "[Tenant admin is allowed to perform this operation]") @ApiResponses(value = { @ApiResponse(code = 204, message = "Operation successful"), @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist"), + @ApiResponse(code = 404, message = "Tenant or namespace doesn't exist"), @ApiResponse(code = 409, message = "Concurrent modification"), @ApiResponse(code = 501, message = "Authorization is not enabled") }) public void grantPermissionOnSubscription(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, + @PathParam("tenant") String tenant, @PathParam("namespace") String namespace, @PathParam("subscription") String subscription, @ApiParam(value = "List of roles for the specified subscription") Set roles) { - validateNamespaceName(property, namespace); + validateNamespaceName(tenant, namespace); internalGrantPermissionOnSubscriptionAsync(subscription, roles) .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) .exceptionally(ex -> { @@ -412,17 +412,17 @@ public void revokePermissionsOnNamespace(@Suspended AsyncResponse asyncResponse, } @DELETE - @Path("/{property}/{namespace}/permissions/{subscription}/{role}") + @Path("/{tenant}/{namespace}/permissions/{subscription}/{role}") @ApiOperation(hidden = true, value = "Revoke subscription admin-api access permission for a role.") @ApiResponses(value = { @ApiResponse(code = 204, message = "Operation successful"), @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Property or cluster or namespace doesn't exist") }) + @ApiResponse(code = 404, message = "Tenant or namespace doesn't exist") }) public void revokePermissionOnSubscription(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, + @PathParam("tenant") String tenant, @PathParam("namespace") String namespace, @PathParam("subscription") String subscription, @PathParam("role") String role) { - validateNamespaceName(property, namespace); + validateNamespaceName(tenant, namespace); internalRevokePermissionsOnSubscriptionAsync(subscription, role) .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) .exceptionally(ex -> { @@ -995,15 +995,15 @@ public void getTopicHashPositions( } @POST - @Path("/{property}/{namespace}/publishRate") + @Path("/{tenant}/{namespace}/publishRate") @ApiOperation(hidden = true, value = "Set publish-rate throttling for all topics of the namespace") @ApiResponses(value = { @ApiResponse(code = 204, message = "Operation successful"), @ApiResponse(code = 403, message = "Don't have admin permission") }) - public void setPublishRate(@Suspended AsyncResponse asyncResponse, @PathParam("property") String property, + public void setPublishRate(@Suspended AsyncResponse asyncResponse, @PathParam("tenant") String tenant, @PathParam("namespace") String namespace, @ApiParam(value = "Publish rate for all topics of the specified namespace") PublishRate publishRate) { - validateNamespaceName(property, namespace); + validateNamespaceName(tenant, namespace); internalSetPublishRateAsync(publishRate) .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) .exceptionally(ex -> { @@ -1013,14 +1013,14 @@ public void setPublishRate(@Suspended AsyncResponse asyncResponse, @PathParam("p } @DELETE - @Path("/{property}/{namespace}/publishRate") + @Path("/{tenant}/{namespace}/publishRate") @ApiOperation(hidden = true, value = "Set publish-rate throttling for all topics of the namespace") @ApiResponses(value = { @ApiResponse(code = 204, message = "Operation successful"), @ApiResponse(code = 403, message = "Don't have admin permission") }) - public void removePublishRate(@Suspended AsyncResponse asyncResponse, @PathParam("property") String property, + public void removePublishRate(@Suspended AsyncResponse asyncResponse, @PathParam("tenant") String tenant, @PathParam("namespace") String namespace) { - validateNamespaceName(property, namespace); + validateNamespaceName(tenant, namespace); internalRemovePublishRateAsync() .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) .exceptionally(ex -> { @@ -1032,7 +1032,7 @@ public void removePublishRate(@Suspended AsyncResponse asyncResponse, @PathParam } @GET - @Path("/{property}/{namespace}/publishRate") + @Path("/{tenant}/{namespace}/publishRate") @ApiOperation(hidden = true, value = "Get publish-rate configured for the namespace, null means publish-rate not configured, " + "-1 means msg-publish-rate or byte-publish-rate not configured in publish-rate yet", @@ -1040,9 +1040,9 @@ public void removePublishRate(@Suspended AsyncResponse asyncResponse, @PathParam @ApiResponses(value = {@ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Namespace does not exist")}) public void getPublishRate(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, + @PathParam("tenant") String tenant, @PathParam("namespace") String namespace) { - validateNamespaceName(property, namespace); + validateNamespaceName(tenant, namespace); internalGetPublishRateAsync() .thenAccept(asyncResponse::resume) .exceptionally(ex -> { @@ -1441,7 +1441,7 @@ public void setBookieAffinityGroup(@Suspended AsyncResponse asyncResponse, @Path } @GET - @Path("/{property}/{namespace}/persistence/bookieAffinity") + @Path("/{tenant}/{namespace}/persistence/bookieAffinity") @ApiOperation(value = "Get the bookie-affinity-group from namespace-local policy.", response = BookieAffinityGroupDataImpl.class) @ApiResponses(value = { @@ -1449,9 +1449,9 @@ public void setBookieAffinityGroup(@Suspended AsyncResponse asyncResponse, @Path @ApiResponse(code = 403, message = "Don't have admin permission"), @ApiResponse(code = 404, message = "Namespace does not exist"), @ApiResponse(code = 409, message = "Concurrent modification") }) - public void getBookieAffinityGroup(@Suspended AsyncResponse asyncResponse, @PathParam("property") String property, + public void getBookieAffinityGroup(@Suspended AsyncResponse asyncResponse, @PathParam("tenant") String tenant, @PathParam("namespace") String namespace) { - validateNamespaceName(property, namespace); + validateNamespaceName(tenant, namespace); internalGetBookieAffinityGroupAsync() .thenAccept(asyncResponse::resume) .exceptionally(ex -> { @@ -1463,7 +1463,7 @@ public void getBookieAffinityGroup(@Suspended AsyncResponse asyncResponse, @Path } @DELETE - @Path("/{property}/{namespace}/persistence/bookieAffinity") + @Path("/{tenant}/{namespace}/persistence/bookieAffinity") @ApiOperation(value = "Delete the bookie-affinity-group from namespace-local policy.") @ApiResponses(value = { @ApiResponse(code = 204, message = "Operation successful"), @@ -1471,9 +1471,9 @@ public void getBookieAffinityGroup(@Suspended AsyncResponse asyncResponse, @Path @ApiResponse(code = 404, message = "Namespace does not exist"), @ApiResponse(code = 409, message = "Concurrent modification") }) public void deleteBookieAffinityGroup(@Suspended AsyncResponse asyncResponse, - @PathParam("property") String property, + @PathParam("tenant") String tenant, @PathParam("namespace") String namespace) { - validateNamespaceName(property, namespace); + validateNamespaceName(tenant, namespace); internalDeleteBookieAffinityGroupAsync() .thenAccept(__ -> asyncResponse.resume(Response.noContent().build())) .exceptionally(ex -> { diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/extensions/channel/ServiceUnitStateChannelImpl.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/extensions/channel/ServiceUnitStateChannelImpl.java index 6ea75d11de0a9..4c613f3c2e17a 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/extensions/channel/ServiceUnitStateChannelImpl.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/extensions/channel/ServiceUnitStateChannelImpl.java @@ -93,7 +93,6 @@ import org.apache.pulsar.common.naming.NamespaceBundleFactory; import org.apache.pulsar.common.naming.NamespaceBundleSplitAlgorithm; import org.apache.pulsar.common.naming.NamespaceBundles; -import org.apache.pulsar.common.naming.TopicVersion; import org.apache.pulsar.common.stats.Metrics; import org.apache.pulsar.common.util.FutureUtil; import org.apache.pulsar.common.util.Reflections; @@ -1526,7 +1525,7 @@ private void doHealthCheckBrokerAsyncWithRetries(String brokerId, int retry, Com } try { var admin = getPulsarAdmin(); - admin.brokers().healthcheckAsync(TopicVersion.V2, Optional.of(brokerId)) + admin.brokers().healthcheckAsync(Optional.of(brokerId)) .whenComplete((__, e) -> { if (e == null) { log.info("Completed health-check broker :{}", brokerId, e); diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/extensions/channel/ServiceUnitStateTableViewBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/extensions/channel/ServiceUnitStateTableViewBase.java index a236de89f0ee0..587f5ca3ad99e 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/extensions/channel/ServiceUnitStateTableViewBase.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/extensions/channel/ServiceUnitStateTableViewBase.java @@ -50,17 +50,12 @@ protected void init(PulsarService pulsar) throws MetadataStoreException { // Add heartbeat and SLA monitor namespace bundle. NamespaceName heartbeatNamespace = NamespaceService.getHeartbeatNamespace(brokerId, pulsar.getConfiguration()); - NamespaceName heartbeatNamespaceV2 = NamespaceService - .getHeartbeatNamespaceV2(brokerId, pulsar.getConfiguration()); NamespaceName slaMonitorNamespace = NamespaceService .getSLAMonitorNamespace(brokerId, pulsar.getConfiguration()); try { pulsar.getNamespaceService().getNamespaceBundleFactory() .getFullBundleAsync(heartbeatNamespace) .thenAccept(fullBundle -> ownedServiceUnitsMap.put(fullBundle, true)) - .thenCompose(__ -> pulsar.getNamespaceService().getNamespaceBundleFactory() - .getFullBundleAsync(heartbeatNamespaceV2)) - .thenAccept(fullBundle -> ownedServiceUnitsMap.put(fullBundle, true)) .thenCompose(__ -> pulsar.getNamespaceService().getNamespaceBundleFactory() .getFullBundleAsync(slaMonitorNamespace)) .thenAccept(fullBundle -> ownedServiceUnitsMap.put(fullBundle, true)) diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/impl/LoadManagerShared.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/impl/LoadManagerShared.java index 591b061253d3b..f7c2e4aa6dfc1 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/impl/LoadManagerShared.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/loadbalance/impl/LoadManagerShared.java @@ -283,7 +283,7 @@ public static CompletableFuture> applyNamespacePoliciesAsync( // From a full bundle name, extract the bundle range. public static String getBundleRangeFromBundleName(String bundleName) { - // the bundle format is property/cluster/namespace/0x00000000_0xFFFFFFFF + // the bundle format is tenant/namespace/0x00000000_0xFFFFFFFF int pos = bundleName.lastIndexOf("/"); checkArgument(pos != -1, "Invalid bundle name format: %s", bundleName); return bundleName.substring(pos + 1); @@ -291,7 +291,7 @@ public static String getBundleRangeFromBundleName(String bundleName) { // From a full bundle name, extract the namespace name. public static String getNamespaceNameFromBundleName(String bundleName) { - // the bundle format is property/cluster/namespace/0x00000000_0xFFFFFFFF + // the bundle format is tenant/namespace/0x00000000_0xFFFFFFFF int pos = bundleName.lastIndexOf('/'); checkArgument(pos != -1, "Invalid bundle name format: %s", bundleName); return bundleName.substring(0, pos); diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/lookup/TopicLookupBase.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/lookup/TopicLookupBase.java index e89ae6bc99d62..4decdc50e9847 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/lookup/TopicLookupBase.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/lookup/TopicLookupBase.java @@ -55,8 +55,7 @@ public class TopicLookupBase extends PulsarWebResource { - private static final String LOOKUP_PATH_V1 = "/lookup/v2/destination/"; - private static final String LOOKUP_PATH_V2 = "/lookup/v2/topic/"; + private static final String LOOKUP_PATH = "/lookup/v2/topic/"; protected CompletableFuture internalLookupTopicAsync(final TopicName topicName, boolean authoritative, String listenerName) { @@ -64,8 +63,7 @@ protected CompletableFuture internalLookupTopicAsync(final TopicName log.warn("No broker was found available for topic {}", topicName); return FutureUtil.failedFuture(new WebApplicationException(Response.Status.SERVICE_UNAVAILABLE)); } - return validateClusterOwnershipAsync(topicName.getCluster()) - .thenCompose(__ -> validateGlobalNamespaceOwnershipAsync(topicName.getNamespaceObject())) + return validateGlobalNamespaceOwnershipAsync(topicName.getNamespaceObject()) .thenCompose(__ -> validateTopicOperationAsync(topicName, TopicOperation.LOOKUP, null)) .thenCompose(__ -> { // Case-1: Non-persistent topic. @@ -118,7 +116,7 @@ protected CompletableFuture internalLookupTopicAsync(final TopicName throw new RestException(Response.Status.PRECONDITION_FAILED, "Redirected cluster's service url is not configured."); } - String lookupPath = topicName.isV2() ? LOOKUP_PATH_V2 : LOOKUP_PATH_V1; + String lookupPath = LOOKUP_PATH; String path = String.format("%s%s%s?authoritative=%s", redirectUrl, lookupPath, topicName.getLookupName(), newAuthoritative); path = listenerName == null ? path : path + "&listenerName=" + listenerName; @@ -190,84 +188,65 @@ public static CompletableFuture lookupTopicAsync(PulsarService pulsarSe final CompletableFuture validationFuture = new CompletableFuture<>(); final CompletableFuture 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 - checkAuthorizationAsync(pulsarService, topicName, clientAppId, originalPrinciple, - authenticationData, originalAuthenticationData).thenRun(() -> { - // (3) validate global namespace - // It is necessary for system topic operations because system topics are used to store metadata - // and other vital information. Even after namespace starting deletion, - // we need to access the metadata of system topics to create readers and clean up topic data. - // If we don't do this, it can prevent namespace deletion due to inaccessible readers. - checkLocalOrGetPeerReplicationCluster(pulsarService, - topicName.getNamespaceObject(), SystemTopicNames.isSystemTopic(topicName)) - .thenAccept(peerClusterData -> { - if (peerClusterData == null) { - // (4) all validation passed: initiate lookup - validationFuture.complete(null); - return; - } - // if peer-cluster-data is present it means namespace is owned by that peer-cluster - // and request should be redirect to the peer-cluster - if (StringUtils.isBlank(peerClusterData.getBrokerServiceUrl()) - && StringUtils.isBlank(peerClusterData.getBrokerServiceUrlTls())) { - validationFuture.complete(newLookupErrorResponse(ServerError.MetadataError, - "Redirected cluster's brokerService url is not configured", - requestId)); - return; + // (1) authorize client + checkAuthorizationAsync(pulsarService, topicName, clientAppId, originalPrinciple, + authenticationData, originalAuthenticationData).thenRun(() -> { + // (2) validate global namespace + // It is necessary for system topic operations because system topics are used to store metadata + // and other vital information. Even after namespace starting deletion, + // we need to access the metadata of system topics to create readers and clean up topic data. + // If we don't do this, it can prevent namespace deletion due to inaccessible readers. + checkLocalOrGetPeerReplicationCluster(pulsarService, + topicName.getNamespaceObject(), SystemTopicNames.isSystemTopic(topicName)) + .thenAccept(peerClusterData -> { + if (peerClusterData == null) { + // (3) all validation passed: initiate lookup + validationFuture.complete(null); + return; + } + // if peer-cluster-data is present it means namespace is owned by that peer-cluster + // and request should be redirect to the peer-cluster + if (StringUtils.isBlank(peerClusterData.getBrokerServiceUrl()) + && StringUtils.isBlank(peerClusterData.getBrokerServiceUrlTls())) { + 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 -> { + Throwable throwable = FutureUtil.unwrapCompletionException(ex); + if (throwable instanceof RestException restException){ + if (restException.getResponse().getStatus() + == Response.Status.NOT_FOUND.getStatusCode()) { + validationFuture.complete( + newLookupErrorResponse(ServerError.TopicNotFound, + throwable.getMessage(), requestId)); + return null; } - validationFuture.complete(newLookupResponse(peerClusterData.getBrokerServiceUrl(), - peerClusterData.getBrokerServiceUrlTls(), true, - LookupType.Redirect, requestId, - false)); - }).exceptionally(ex -> { - Throwable throwable = FutureUtil.unwrapCompletionException(ex); - if (throwable instanceof RestException restException){ - if (restException.getResponse().getStatus() - == Response.Status.NOT_FOUND.getStatusCode()) { - validationFuture.complete( - newLookupErrorResponse(ServerError.TopicNotFound, - throwable.getMessage(), requestId)); - return null; } - } - validationFuture.complete( - newLookupErrorResponse(ServerError.MetadataError, - throwable.getMessage(), requestId)); - return null; - }); - }) - .exceptionally(e -> { - Throwable throwable = FutureUtil.unwrapCompletionException(e); - if (throwable instanceof RestException) { - log.warn("Failed to authorized {} on cluster {}", clientAppId, topicName); - validationFuture.complete(newLookupErrorResponse(ServerError.AuthorizationError, - throwable.getMessage(), requestId)); - } else { - log.warn("Unknown error while authorizing {} on cluster {}", clientAppId, topicName); - validationFuture.completeExceptionally(throwable); - } - return null; - }); - } - }).exceptionally(ex -> { - validationFuture.completeExceptionally(FutureUtil.unwrapCompletionException(ex)); - return null; - }); + validationFuture.complete( + newLookupErrorResponse(ServerError.MetadataError, + throwable.getMessage(), requestId)); + return null; + }); + }) + .exceptionally(e -> { + Throwable throwable = FutureUtil.unwrapCompletionException(e); + if (throwable instanceof RestException) { + log.warn("Failed to authorized {} on topic {}", clientAppId, topicName); + validationFuture.complete(newLookupErrorResponse(ServerError.AuthorizationError, + throwable.getMessage(), requestId)); + } else { + log.warn("Unknown error while authorizing {} on topic {}", clientAppId, topicName); + validationFuture.completeExceptionally(throwable); + } + return null; + }); // Initiate lookup once validation completes validationFuture.thenAccept(validationFailureResponse -> { @@ -363,12 +342,6 @@ private static void handleLookupError(CompletableFuture lookupFuture, S } } - protected TopicName getTopicName(String topicDomain, String tenant, String cluster, String namespace, - @Encoded String encodedTopic) { - String decodedName = Codec.decode(encodedTopic); - return TopicName.get(TopicDomain.getEnum(topicDomain).value(), tenant, cluster, namespace, decodedName); - } - protected TopicName getTopicName(String topicDomain, String tenant, String namespace, @Encoded String encodedTopic) { String decodedName = Codec.decode(encodedTopic); diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/lookup/v1/TopicLookup.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/lookup/v1/TopicLookup.java deleted file mode 100644 index ac471a1a819e6..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/lookup/v1/TopicLookup.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.lookup.v1; - -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.Encoded; -import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.container.AsyncResponse; -import javax.ws.rs.container.Suspended; -import javax.ws.rs.core.MediaType; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.apache.pulsar.broker.lookup.TopicLookupBase; -import org.apache.pulsar.broker.web.NoSwaggerDocumentation; -import org.apache.pulsar.common.naming.TopicName; - -/** - * The path for this handler is marked as "v2" even though it refers to Pulsar 1.x topic name format. - * - * The lookup API was already /v2/ in Pulsar 1.x. This was internally versioned at Yahoo to not clash with - * an earlier API. - * - * Since we're adding now the "Pulsar v2" we cannot rename this topic lookup into /v1. Rather the - * difference here would be : lookup/v2/destination/persistent/prop/cluster/ns/topic vs - * lookup/v2/topic/persistent/prop/ns/topic. - */ -@Path("/v2/destination/") -@NoSwaggerDocumentation -@Slf4j -public class TopicLookup extends TopicLookupBase { - - static final String LISTENERNAME_HEADER = "X-Pulsar-ListenerName"; - - @GET - @Path("{topic-domain}/{property}/{cluster}/{namespace}/{topic}") - @Produces(MediaType.APPLICATION_JSON) - @ApiResponses(value = { @ApiResponse(code = 307, - message = "Current broker doesn't serve the namespace of this topic") }) - public void lookupTopicAsync( - @Suspended AsyncResponse asyncResponse, - @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, - @QueryParam("listenerName") String listenerName, - @HeaderParam(LISTENERNAME_HEADER) String listenerNameHeader) { - TopicName topicName = getTopicName(topicDomain, property, cluster, namespace, encodedTopic); - if (StringUtils.isEmpty(listenerName) && StringUtils.isNotEmpty(listenerNameHeader)) { - listenerName = listenerNameHeader; - } - internalLookupTopicAsync(topicName, authoritative, listenerName) - .thenAccept(lookupData -> asyncResponse.resume(lookupData)) - .exceptionally(ex -> { - if (log.isDebugEnabled()) { - log.debug("Failed to check exist for topic {} when lookup", topicName, ex); - } - resumeAsyncResponseExceptionally(asyncResponse, ex); - return null; - }); - } - - @GET - @Path("{topic-domain}/{property}/{cluster}/{namespace}/{topic}/bundle") - @Produces(MediaType.APPLICATION_JSON) - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 405, message = "Invalid topic domain type") }) - public String getNamespaceBundle(@PathParam("topic-domain") String topicDomain, - @PathParam("property") String property, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic) { - TopicName topicName = getTopicName(topicDomain, property, cluster, namespace, encodedTopic); - return internalGetNamespaceBundle(topicName); - } -} diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/lookup/v1/package-info.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/lookup/v1/package-info.java deleted file mode 100644 index 81fe5cb610575..0000000000000 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/lookup/v1/package-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.lookup.v1; diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/namespace/NamespaceService.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/namespace/NamespaceService.java index 8fe0cd627c411..c16c9338bf994 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/namespace/NamespaceService.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/namespace/NamespaceService.java @@ -142,12 +142,10 @@ public class NamespaceService implements AutoCloseable { public static final int BUNDLE_SPLIT_RETRY_LIMIT = 7; public static final String SLA_NAMESPACE_PROPERTY = "sla-monitor"; - public static final Pattern HEARTBEAT_NAMESPACE_PATTERN = Pattern.compile("pulsar/[^/]+/([^:]+:\\d+)"); - public static final Pattern HEARTBEAT_NAMESPACE_PATTERN_V2 = Pattern.compile("pulsar/([^:]+:\\d+)"); - public static final Pattern SLA_NAMESPACE_PATTERN = Pattern.compile(SLA_NAMESPACE_PROPERTY + "/[^/]+/([^:]+:\\d+)"); - public static final String HEARTBEAT_NAMESPACE_FMT = "pulsar/%s/%s"; - public static final String HEARTBEAT_NAMESPACE_FMT_V2 = "pulsar/%s"; - public static final String SLA_NAMESPACE_FMT = SLA_NAMESPACE_PROPERTY + "/%s/%s"; + public static final Pattern HEARTBEAT_NAMESPACE_PATTERN = Pattern.compile("pulsar/([^:]+:\\d+)"); + public static final Pattern SLA_NAMESPACE_PATTERN = Pattern.compile(SLA_NAMESPACE_PROPERTY + "/([^:]+:\\d+)"); + public static final String HEARTBEAT_NAMESPACE_FMT = "pulsar/%s"; + public static final String SLA_NAMESPACE_FMT = SLA_NAMESPACE_PROPERTY + "/%s"; private final Map namespaceClients = new ConcurrentHashMap<>(); @@ -393,12 +391,6 @@ public void registerBootstrapNamespaces() throws PulsarServerException { getHeartbeatNamespace(brokerId, config)); } - // ensure that we own the heartbeat namespace - if (registerNamespace(getHeartbeatNamespaceV2(brokerId, config), true)) { - LOG.info("added heartbeat namespace name in local cache: ns={}", - getHeartbeatNamespaceV2(brokerId, config)); - } - // we may not need strict ownership checking for bootstrap names for now for (String namespace : config.getBootstrapNamespaces()) { if (registerNamespace(NamespaceName.get(namespace), false)) { @@ -551,10 +543,6 @@ public CompletableFuture getHeartbeatOrSLAMonitorBrokerId( if (candidateBroker != null) { return CompletableFuture.completedFuture(candidateBroker); } - candidateBroker = NamespaceService.checkHeartbeatNamespaceV2(serviceUnit); - if (candidateBroker != null) { - return CompletableFuture.completedFuture(candidateBroker); - } candidateBroker = NamespaceService.getSLAMonitorBrokerName(serviceUnit); if (candidateBroker != null) { // Check if the broker is available @@ -1770,15 +1758,11 @@ public void unloadSLANamespace() throws Exception { } public static NamespaceName getHeartbeatNamespace(String lookupBroker, ServiceConfiguration config) { - return NamespaceName.get(String.format(HEARTBEAT_NAMESPACE_FMT, config.getClusterName(), lookupBroker)); - } - - public static NamespaceName getHeartbeatNamespaceV2(String lookupBroker, ServiceConfiguration config) { - return NamespaceName.get(String.format(HEARTBEAT_NAMESPACE_FMT_V2, lookupBroker)); + return NamespaceName.get(String.format(HEARTBEAT_NAMESPACE_FMT, lookupBroker)); } public static NamespaceName getSLAMonitorNamespace(String lookupBroker, ServiceConfiguration config) { - return NamespaceName.get(String.format(SLA_NAMESPACE_FMT, config.getClusterName(), lookupBroker)); + return NamespaceName.get(String.format(SLA_NAMESPACE_FMT, lookupBroker)); } public static String checkHeartbeatNamespace(ServiceUnitId ns) { @@ -1791,16 +1775,6 @@ public static String checkHeartbeatNamespace(ServiceUnitId ns) { } } - public static String checkHeartbeatNamespaceV2(ServiceUnitId ns) { - Matcher m = HEARTBEAT_NAMESPACE_PATTERN_V2.matcher(ns.getNamespaceObject().toString()); - if (m.matches()) { - LOG.debug("Heartbeat namespace v2 matched the lookup namespace {}", ns.getNamespaceObject().toString()); - return m.group(1); - } else { - return null; - } - } - public static String getSLAMonitorBrokerName(ServiceUnitId ns) { Matcher m = SLA_NAMESPACE_PATTERN.matcher(ns.getNamespaceObject().toString()); if (m.matches()) { @@ -1813,8 +1787,7 @@ public static String getSLAMonitorBrokerName(ServiceUnitId ns) { public static boolean isSystemServiceNamespace(String namespace) { return SYSTEM_NAMESPACE.toString().equals(namespace) || SLA_NAMESPACE_PATTERN.matcher(namespace).matches() - || HEARTBEAT_NAMESPACE_PATTERN.matcher(namespace).matches() - || HEARTBEAT_NAMESPACE_PATTERN_V2.matcher(namespace).matches(); + || HEARTBEAT_NAMESPACE_PATTERN.matcher(namespace).matches(); } /** @@ -1824,14 +1797,12 @@ public static boolean isSystemServiceNamespace(String namespace) { */ public static boolean isSLAOrHeartbeatNamespace(String namespace) { return SLA_NAMESPACE_PATTERN.matcher(namespace).matches() - || HEARTBEAT_NAMESPACE_PATTERN.matcher(namespace).matches() - || HEARTBEAT_NAMESPACE_PATTERN_V2.matcher(namespace).matches(); + || HEARTBEAT_NAMESPACE_PATTERN.matcher(namespace).matches(); } public static boolean isHeartbeatNamespace(ServiceUnitId ns) { String namespace = ns.getNamespaceObject().toString(); - return HEARTBEAT_NAMESPACE_PATTERN.matcher(namespace).matches() - || HEARTBEAT_NAMESPACE_PATTERN_V2.matcher(namespace).matches(); + return HEARTBEAT_NAMESPACE_PATTERN.matcher(namespace).matches(); } public boolean registerSLANamespace() throws PulsarServerException { diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/namespace/ServiceUnitUtils.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/namespace/ServiceUnitUtils.java index 432aa29798ebd..478094de245e2 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/namespace/ServiceUnitUtils.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/namespace/ServiceUnitUtils.java @@ -47,15 +47,9 @@ public static NamespaceBundle suBundleFromPath(String path, NamespaceBundleFacto checkArgument(parts[1].equals("namespace")); checkArgument(parts.length > 4); - if (parts.length > 5) { - // this is a V1 path prop/cluster/namespace/hash - Range range = getHashRange(parts[5]); - return factory.getBundle(NamespaceName.get(parts[2], parts[3], parts[4]), range); - } else { - // this is a V2 path prop/namespace/hash - Range range = getHashRange(parts[4]); - return factory.getBundle(NamespaceName.get(parts[2], parts[3]), range); - } + // Path format: /namespace/tenant/namespace/hash + Range range = getHashRange(parts[4]); + return factory.getBundle(NamespaceName.get(parts[2], parts[3]), range); } private static Range getHashRange(String rangePathPart) { diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/AbstractReplicator.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/AbstractReplicator.java index 3477ab793f3f4..bb1d1e08f12a5 100644 --- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/AbstractReplicator.java +++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/AbstractReplicator.java @@ -487,7 +487,7 @@ public static String getReplicatorName(String replicatorPrefix, String cluster) * *
      * eg:
-     * if topic : persistent://prop/cluster/ns/my-topic is a partitioned topic with 2 partitions then
+     * if topic : persistent://prop/ns/my-topic is a partitioned topic with 2 partitions then
      * broker explicitly creates replicator producer for: "my-topic-partition-1" and "my-topic-partition-2".
      *
      * However, if broker tries to start producer with root topic "my-topic" then client-lib internally
diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/BrokerService.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/BrokerService.java
index f4df62879e5e4..513b16a5255f4 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/BrokerService.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/BrokerService.java
@@ -158,13 +158,11 @@
 import org.apache.pulsar.common.intercept.BrokerEntryMetadataInterceptor;
 import org.apache.pulsar.common.intercept.BrokerEntryMetadataUtils;
 import org.apache.pulsar.common.intercept.ManagedLedgerPayloadProcessor;
-import org.apache.pulsar.common.naming.Constants;
 import org.apache.pulsar.common.naming.NamespaceBundle;
 import org.apache.pulsar.common.naming.NamespaceName;
 import org.apache.pulsar.common.naming.SystemTopicNames;
 import org.apache.pulsar.common.naming.TopicDomain;
 import org.apache.pulsar.common.naming.TopicName;
-import org.apache.pulsar.common.naming.TopicVersion;
 import org.apache.pulsar.common.partition.PartitionedTopicMetadata;
 import org.apache.pulsar.common.policies.data.AutoSubscriptionCreationOverride;
 import org.apache.pulsar.common.policies.data.AutoTopicCreationOverride;
@@ -696,7 +694,7 @@ public CompletableFuture checkHealth() {
         if (!pulsar().isRunning()) {
             return CompletableFuture.completedFuture(null);
         }
-        return pulsar().runHealthCheck(TopicVersion.V2, null).thenAccept(__ -> {
+        return pulsar().runHealthCheck(null).thenAccept(__ -> {
             this.pulsarStats.getBrokerOperabilityMetrics().recordHealthCheckStatusSuccess();
         }).exceptionally(ex -> {
             this.pulsarStats.getBrokerOperabilityMetrics().recordHealthCheckStatusFail();
@@ -3689,13 +3687,6 @@ private CompletableFuture isAllowAutoTopicCreationAsync(final TopicName
             return CompletableFuture.completedFuture(true);
         }
 
-        //If 'allowAutoTopicCreation' is true, and the name of the topic contains 'cluster',
-        //the topic cannot be automatically created.
-        if (!pulsar.getConfiguration().isAllowAutoTopicCreationWithLegacyNamingScheme()
-                && StringUtils.isNotBlank(topicName.getCluster())) {
-            return CompletableFuture.completedFuture(false);
-        }
-
         final boolean allowed;
         AutoTopicCreationOverride autoTopicCreationOverride = getAutoTopicCreationOverride(topicName, policies);
         if (autoTopicCreationOverride != null) {
@@ -3940,10 +3931,6 @@ public void setPulsarChannelInitializerFactory(PulsarChannelInitializer.Factory
      * means the default replication clusters for the topics under the namespace.
      */
     public boolean isCurrentClusterAllowed(NamespaceName nsName, Policies nsPolicies) {
-        // Compatibility with v1 version namespace.
-        if (Constants.GLOBAL_CLUSTER.equalsIgnoreCase(nsName.getCluster())) {
-            return nsPolicies.replication_clusters.contains(pulsar.getConfig().getClusterName());
-        }
         // If allowed clusters has been set, only check allowed clusters.
         if (!nsPolicies.allowed_clusters.isEmpty()) {
             return nsPolicies.allowed_clusters.contains(pulsar.getConfig().getClusterName());
@@ -3953,10 +3940,6 @@ public boolean isCurrentClusterAllowed(NamespaceName nsName, Policies nsPolicies
     }
 
     public void setCurrentClusterAllowedIfNoClusterIsAllowed(NamespaceName nsName, Policies nsPolicies) {
-        // Compatibility with v1 version namespace.
-        if (!nsName.isV2()) {
-            return;
-        }
         if (nsPolicies.replication_clusters.contains(pulsar.getConfig().getClusterName())
                 || nsPolicies.allowed_clusters.contains(pulsar.getConfig().getClusterName())) {
             return;
diff --git a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/HealthChecker.java b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/HealthChecker.java
index 1df828e2c954d..087e38bdb07a7 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/HealthChecker.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/service/HealthChecker.java
@@ -47,7 +47,6 @@
 import org.apache.pulsar.client.api.Schema;
 import org.apache.pulsar.client.util.ScheduledExecutorProvider;
 import org.apache.pulsar.common.naming.NamespaceName;
-import org.apache.pulsar.common.naming.TopicVersion;
 import org.apache.pulsar.common.util.FutureUtil;
 import org.apache.pulsar.metadata.api.MetadataStoreException;
 
@@ -79,13 +78,9 @@ public class HealthChecker implements AutoCloseable{
      */
     private final PulsarService pulsar;
     /**
-     * Topic name for v1 heartbeat checks.
+     * Topic name for heartbeat checks.
      */
-    private final String heartbeatTopicV1;
-    /**
-     * Topic name for v2 heartbeat checks.
-     */
-    private final String heartbeatTopicV2;
+    private final String heartbeatTopic;
     /**
      * Pulsar client instance for health check operations.
      * A separate client is needed so that it can be shutdown before the webservice is closed.
@@ -116,8 +111,7 @@ public class HealthChecker implements AutoCloseable{
 
     public HealthChecker(PulsarService pulsar) throws PulsarServerException {
         this.pulsar = pulsar;
-        this.heartbeatTopicV1 = getHeartbeatTopicName(pulsar.getBrokerId(), pulsar.getConfiguration(), false);
-        this.heartbeatTopicV2 = getHeartbeatTopicName(pulsar.getBrokerId(), pulsar.getConfiguration(), true);
+        this.heartbeatTopic = getHeartbeatTopicName(pulsar.getBrokerId(), pulsar.getConfiguration());
         this.lookupExecutor =
                 new ScheduledExecutorProvider(1, "health-checker-client-lookup-executor");
         this.scheduledExecutorProvider =
@@ -134,10 +128,8 @@ public HealthChecker(PulsarService pulsar) throws PulsarServerException {
         }
     }
 
-    private static String getHeartbeatTopicName(String brokerId, ServiceConfiguration configuration, boolean isV2) {
-        NamespaceName namespaceName = isV2
-                ? NamespaceService.getHeartbeatNamespaceV2(brokerId, configuration)
-                : NamespaceService.getHeartbeatNamespace(brokerId, configuration);
+    private static String getHeartbeatTopicName(String brokerId, ServiceConfiguration configuration) {
+        NamespaceName namespaceName = NamespaceService.getHeartbeatNamespace(brokerId, configuration);
         return String.format("persistent://%s/%s", namespaceName, HEALTH_CHECK_TOPIC_SUFFIX);
     }
 
@@ -147,13 +139,12 @@ private static String getHeartbeatTopicName(String brokerId, ServiceConfiguratio
      * 1. Producing a test message
      * 2. Reading the message back to verify end-to-end functionality
      *
-     * @param topicVersion The version of the topic to use (V1 or V2)
      * @param clientAppId  The identifier of the client application requesting the health check
      * @return A CompletableFuture that completes when the health check is successful, or completes exceptionally if the
      * check fails
      */
-    public CompletableFuture checkHealth(TopicVersion topicVersion, String clientAppId) {
-        final String topicName = topicVersion == TopicVersion.V2 ? heartbeatTopicV2 : heartbeatTopicV1;
+    public CompletableFuture checkHealth(String clientAppId) {
+        final String topicName = heartbeatTopic;
         log.info("[{}] Running healthCheck with topic={}", clientAppId, topicName);
         final String messageStr = UUID.randomUUID().toString();
         final String subscriptionName = "healthCheck-" + messageStr;
@@ -307,8 +298,7 @@ private static CompletableFuture healthCheckRecursiveReadNext(Reader getClusterDataIfDifferentCluster
                                                                                      String clientAppId) {
         CompletableFuture clusterDataFuture = new CompletableFuture<>();
         if (isValidCluster(pulsar, cluster)
-                // this code should only happen with a v1 namespace format prop/cluster/namespaces
                 || pulsar.getConfiguration().getClusterName().equals(cluster)) {
             clusterDataFuture.complete(null);
             return clusterDataFuture;
@@ -558,11 +554,8 @@ protected static CompletableFuture getClusterDataIfDifferentCluster
         return clusterDataFuture;
     }
 
-    static boolean isValidCluster(PulsarService pulsarService, String cluster) {// If the cluster name is
-        // cluster == null or "global", don't validate the
-        // cluster ownership. Cluster will be null in v2 naming.
-        // The validation will be done by checking the namespace configuration
-        if (cluster == null || Constants.GLOBAL_CLUSTER.equals(cluster)) {
+    static boolean isValidCluster(PulsarService pulsarService, String cluster) {
+        if (cluster == null) {
             return true;
         }
 
@@ -570,21 +563,6 @@ static boolean isValidCluster(PulsarService pulsarService, String cluster) {// I
         return !pulsarService.getConfiguration().isAuthorizationEnabled();
     }
 
-    protected void validateBundleOwnership(String tenant, String cluster, String namespace, boolean authoritative,
-            boolean readOnly, NamespaceBundle bundle) {
-        NamespaceName fqnn = NamespaceName.get(tenant, cluster, namespace);
-
-        try {
-            validateBundleOwnership(bundle, authoritative, readOnly);
-        } catch (WebApplicationException wae) {
-            // propagate already wrapped-up WebApplicationExceptions
-            throw wae;
-        } catch (Exception oe) {
-            log.debug("Failed to find owner for namespace {}", fqnn, oe);
-            throw new RestException(oe);
-        }
-    }
-
     protected NamespaceBundle validateNamespaceBundleRange(NamespaceName fqnn, BundlesData bundles,
             String bundleRange) {
         try {
@@ -894,7 +872,7 @@ public static CompletableFuture checkLocalOrGetPeerReplicationC
     public static CompletableFuture checkLocalOrGetPeerReplicationCluster(PulsarService pulsarService,
                                                                                      NamespaceName namespace,
                                                                                      boolean allowDeletedNamespace) {
-        if (!namespace.isGlobal() || NamespaceService.isHeartbeatNamespace(namespace)) {
+        if (!namespace.isGlobal() || NamespaceService.isSLAOrHeartbeatNamespace(namespace.toString())) {
             return CompletableFuture.completedFuture(null);
         }
 
@@ -1110,6 +1088,42 @@ && pulsar().getBrokerService().isAuthorizationEnabled()) {
         return CompletableFuture.completedFuture(null);
     }
 
+    protected CompletableFuture canUpdateCluster(String tenant, Set oldClusters,
+            Set newClusters) {
+        // Check if any clusters are being removed
+        Set removedClusters = new java.util.HashSet<>(oldClusters);
+        removedClusters.removeAll(newClusters);
+        if (removedClusters.isEmpty()) {
+            return CompletableFuture.completedFuture(null);
+        }
+
+        // For each removed cluster, check if any namespace under this tenant references it
+        return tenantResources().getListOfNamespacesAsync(tenant)
+                .thenCompose(namespaces -> {
+                    java.util.List> checks = new java.util.ArrayList<>();
+                    for (String ns : namespaces) {
+                        NamespaceName namespaceName = NamespaceName.get(ns);
+                        CompletableFuture check = namespaceResources()
+                                .getPoliciesAsync(namespaceName)
+                                .thenAccept(policiesOpt -> {
+                                    if (policiesOpt.isPresent()) {
+                                        for (String cluster : removedClusters) {
+                                            if (policiesOpt.get().replication_clusters.contains(cluster)) {
+                                                throw new RestException(Status.PRECONDITION_FAILED,
+                                                        "Cannot remove cluster " + cluster
+                                                                + " from tenant " + tenant
+                                                                + ": namespace " + ns
+                                                                + " still has it as a replication cluster");
+                                            }
+                                        }
+                                    }
+                                });
+                        checks.add(check);
+                    }
+                    return FutureUtil.waitForAll(checks);
+                });
+    }
+
     protected PulsarResources getPulsarResources() {
         return pulsar().getPulsarResources();
     }
@@ -1191,31 +1205,6 @@ protected void validateClusterExists(String cluster) {
         }
     }
 
-    protected CompletableFuture canUpdateCluster(String tenant, Set oldClusters,
-            Set newClusters) {
-        List> activeNamespaceFuture = new ArrayList<>();
-        for (String cluster : oldClusters) {
-            if (Constants.GLOBAL_CLUSTER.equals(cluster) || newClusters.contains(cluster)) {
-                continue;
-            }
-            CompletableFuture checkNs = new CompletableFuture<>();
-            activeNamespaceFuture.add(checkNs);
-            tenantResources().getActiveNamespaces(tenant, cluster).whenComplete((activeNamespaces, ex) -> {
-                if (ex != null) {
-                    log.warn("Failed to get namespaces under {}-{}, {}", tenant, cluster, ex.getCause().getMessage());
-                    checkNs.completeExceptionally(ex.getCause());
-                    return;
-                }
-                if (activeNamespaces.size() > 0) {
-                    log.warn("{}/{} Active-namespaces {}", tenant, cluster, activeNamespaces);
-                    checkNs.completeExceptionally(new RestException(Status.PRECONDITION_FAILED, "Active namespaces"));
-                    return;
-                }
-                checkNs.complete(null);
-            });
-        }
-        return FutureUtil.waitForAll(activeNamespaceFuture);
-    }
 
     /**
      * Redirect the call to the specified broker.
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/SLAMonitoringTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/SLAMonitoringTest.java
index 941229fc3d96c..699dd1ddedf10 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/SLAMonitoringTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/SLAMonitoringTest.java
@@ -172,7 +172,7 @@ public void testOwnedNamespaces() {
 
                 Map nsMap = pulsarAdmins[i].brokers().getOwnedNamespaces("my-cluster",
                         list.get(0));
-                Assert.assertEquals(nsMap.size(), 3);
+                Assert.assertEquals(nsMap.size(), 2);
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -184,8 +184,8 @@ public void testOwnedNamespaces() {
     public void testOwnershipViaAdminAfterSetup() {
         for (int i = 0; i < BROKER_COUNT; i++) {
             try {
-                String topic = String.format("persistent://%s/%s/%s/%s",
-                        NamespaceService.SLA_NAMESPACE_PROPERTY, "my-cluster",
+                String topic = String.format("persistent://%s/%s/%s",
+                        NamespaceService.SLA_NAMESPACE_PROPERTY,
                         pulsarServices[i].getBrokerId(), "my-topic");
                 assertEquals(pulsarAdmins[0].lookups().lookupTopic(topic),
                         "pulsar://" + pulsarServices[i].getAdvertisedAddress() + ":" + brokerNativeBrokerPorts[i]);
@@ -210,8 +210,8 @@ public void testUnloadIfBrokerCrashes() {
             fail("Should be a able to close the broker index " + crashIndex + " Exception: " + e);
         }
 
-        String topic = String.format("persistent://%s/%s/%s/%s", NamespaceService.SLA_NAMESPACE_PROPERTY,
-                "my-cluster", pulsarServices[crashIndex].getBrokerId(),
+        String topic = String.format("persistent://%s/%s/%s", NamespaceService.SLA_NAMESPACE_PROPERTY,
+                pulsarServices[crashIndex].getBrokerId(),
                 "my-topic");
 
         log.info("Lookup for namespace {}", topic);
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApi2Test.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApi2Test.java
index 3578467bb4292..a2aa358cc0088 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApi2Test.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApi2Test.java
@@ -319,12 +319,7 @@ public Object[][] topicTypeProvider() {
 
     @DataProvider(name = "namespaceNames")
     public Object[][] namespaceNameProvider() {
-        return new Object[][] { { "ns1" }, { "global" } };
-    }
-
-    @DataProvider(name = "isV1")
-    public Object[][] isV1() {
-        return new Object[][] { { true }, { false } };
+        return new Object[][] { { "ns1" } };
     }
 
 
@@ -919,7 +914,7 @@ private void unloadTopic(String topicName) throws Exception {
     @Test(dataProvider = "namespaceNames", timeOut = 30000)
     public void testResetCursorOnPosition(String namespaceName) throws Exception {
         restartClusterAfterTest();
-        final String topicName = "persistent://" + defaultTenant + "/use/" + namespaceName + "/resetPosition";
+        final String topicName = "persistent://" + defaultTenant + "/" + namespaceName + "/resetPosition";
         final int totalProducedMessages = 50;
 
         // set retention
@@ -1136,20 +1131,19 @@ public void testReplicationPeerCluster() throws Exception {
                 ClusterData.builder().serviceUrl("http://broker.messaging.east1.example.com:8080").build());
         admin.clusters().createCluster("us-east2",
                 ClusterData.builder().serviceUrl("http://broker.messaging.east2.example.com:8080").build());
-        admin.clusters().createCluster("global", ClusterData.builder().build());
 
         List allClusters = admin.clusters().getClusters();
         Collections.sort(allClusters);
         assertEquals(allClusters,
                 List.of("test", "us-east1", "us-east2", "us-west1", "us-west2", "us-west3", "us-west4"));
 
-        final String property = newUniqueName("peer-prop");
-        Set allowedClusters = Set.of("us-west1", "us-west2", "us-west3", "us-west4", "us-east1",
-                "us-east2", "global");
+        final String tenant = newUniqueName("peer-prop");
+        Set allowedClusters = Set.of("test", "us-west1", "us-west2", "us-west3", "us-west4", "us-east1",
+                "us-east2");
         TenantInfoImpl propConfig = new TenantInfoImpl(Set.of("test"), allowedClusters);
-        admin.tenants().createTenant(property, propConfig);
+        admin.tenants().createTenant(tenant, propConfig);
 
-        final String namespace = property + "/global/conflictPeer";
+        final String namespace = tenant + "/conflictPeer";
         admin.namespaces().createNamespace(namespace);
 
         admin.clusters().updatePeerClusterNames("us-west1",
@@ -1525,7 +1519,7 @@ public void testTenantNameWithUnderscore() throws Exception {
 
         admin.namespaces().createNamespace("prop_xyz/my-namespace", Set.of("test"));
 
-        String topic = "persistent://prop_xyz/use/my-namespace/my-topic";
+        String topic = "persistent://prop_xyz/my-namespace/my-topic";
 
         @Cleanup
         Producer producer = pulsarClient.newProducer().topic(topic)
@@ -1701,8 +1695,8 @@ public void clustersList() throws PulsarAdminException {
         admin.clusters().createCluster("global", ClusterData.builder()
                 .serviceUrl("http://localhost:6650").build());
 
-        // Global cluster, if there, should be omitted from the results
-        assertEquals(admin.clusters().getClusters(), List.of(cluster));
+        // With V1 removal, "global" cluster is no longer filtered from the results
+        assertEquals(new HashSet<>(admin.clusters().getClusters()), Set.of(cluster, "global"));
     }
     /**
      * verifies cluster has been set before create topic.
@@ -2349,11 +2343,11 @@ public void testListOfNamespaceBundles() throws Exception {
         admin.tenants().createTenant(tenantName, tenantInfo);
         admin.namespaces().createNamespace(tenantName + "/ns1", 10);
         admin.namespaces().setNamespaceReplicationClusters(tenantName + "/ns1", Set.of("test"), false);
-        admin.namespaces().createNamespace(tenantName + "/test/ns2", 10);
+        admin.namespaces().createNamespace(tenantName + "/ns2", 10);
         assertEquals(admin.namespaces().getBundles(tenantName + "/ns1").getNumBundles(), 10);
-        assertEquals(admin.namespaces().getBundles(tenantName + "/test/ns2").getNumBundles(), 10);
+        assertEquals(admin.namespaces().getBundles(tenantName + "/ns2").getNumBundles(), 10);
 
-        admin.namespaces().deleteNamespace(tenantName + "/test/ns2");
+        admin.namespaces().deleteNamespace(tenantName + "/ns2");
     }
 
     @Test
@@ -3532,13 +3526,13 @@ public void testGetTopicsWithDifferentMode() throws Exception {
         producer2.close();
     }
 
-    @Test(dataProvider = "isV1")
-    public void testNonPartitionedTopic(boolean isV1) throws Exception {
+    @Test
+    public void testNonPartitionedTopic() throws Exception {
         restartClusterAfterTest();
         String tenant = defaultTenant;
         String cluster = "test";
-        String namespace = tenant + "/" + (isV1 ? cluster + "/" : "") + "n1" + isV1;
-        String topic = "persistent://" + namespace + "/t1" + isV1;
+        String namespace = tenant + "/n1";
+        String topic = "persistent://" + namespace + "/t1";
         admin.namespaces().createNamespace(namespace, Set.of(cluster));
         admin.topics().createNonPartitionedTopic(topic);
         assertTrue(admin.topics().getList(namespace).contains(topic));
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiHealthCheckTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiHealthCheckTest.java
index 5b274c211e68c..25c8f1e716771 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiHealthCheckTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiHealthCheckTest.java
@@ -45,7 +45,6 @@
 import org.apache.pulsar.client.impl.ProducerBuilderImpl;
 import org.apache.pulsar.client.impl.PulsarClientImpl;
 import org.apache.pulsar.common.naming.NamespaceName;
-import org.apache.pulsar.common.naming.TopicVersion;
 import org.apache.pulsar.common.policies.data.ClusterData;
 import org.apache.pulsar.common.policies.data.TenantInfoImpl;
 import org.apache.pulsar.compaction.Compactor;
@@ -54,7 +53,6 @@
 import org.springframework.util.CollectionUtils;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 @Test(groups = "broker-admin")
@@ -83,27 +81,14 @@ public void cleanup() throws Exception {
         super.internalCleanup();
     }
 
-    @DataProvider(name = "topicVersion")
-    public static Object[][] topicVersions() {
-        return new Object[][] {
-                { null },
-                { TopicVersion.V1 },
-                { TopicVersion.V2 },
-        };
-    }
-
-    @Test(dataProvider = "topicVersion")
-    public void testHealthCheckup(TopicVersion topicVersion) throws Exception {
+    @Test
+    public void testHealthCheckup() throws Exception {
         final int times = 30;
         CompletableFuture future = new CompletableFuture<>();
         pulsar.getExecutor().execute(() -> {
             try {
                 for (int i = 0; i < times; i++) {
-                    if (topicVersion == null) {
-                        admin.brokers().healthcheck();
-                    } else {
-                        admin.brokers().healthcheck(topicVersion);
-                    }
+                    admin.brokers().healthcheck();
                 }
                 future.complete(null);
             } catch (PulsarAdminException e) {
@@ -111,17 +96,12 @@ public void testHealthCheckup(TopicVersion topicVersion) throws Exception {
             }
         });
         for (int i = 0; i < times; i++) {
-            if (topicVersion == null) {
-                admin.brokers().healthcheck();
-            } else {
-                admin.brokers().healthcheck(topicVersion);
-            }
+            admin.brokers().healthcheck();
         }
         // To ensure we don't have any subscription
         String brokerId = pulsar.getBrokerId();
-        NamespaceName namespaceName = (topicVersion == TopicVersion.V2)
-                ? NamespaceService.getHeartbeatNamespaceV2(brokerId, pulsar.getConfiguration())
-                : NamespaceService.getHeartbeatNamespace(brokerId, pulsar.getConfiguration());
+        NamespaceName namespaceName =
+                NamespaceService.getHeartbeatNamespace(brokerId, pulsar.getConfiguration());
         final String testHealthCheckTopic = String.format("persistent://%s/%s",
                 namespaceName, HEALTH_CHECK_TOPIC_SUFFIX);
         Awaitility.await().untilAsserted(() -> {
@@ -168,7 +148,7 @@ public void testHealthCheckupDetectsDeadlock() throws Exception {
         Thread.sleep(5000L);
 
         try {
-            admin.brokers().healthcheck(TopicVersion.V2);
+            admin.brokers().healthcheck();
         } finally {
             // unlock the deadlock
             thread1.interrupt();
@@ -249,7 +229,7 @@ public void testHealthCheckTimeOut() throws Exception {
         timeoutField.set(healthChecker, Duration.ofSeconds(1));
 
         try {
-            admin.brokers().healthcheck(TopicVersion.V2);
+            admin.brokers().healthcheck();
             fail("Should not reach here");
         } catch (PulsarAdminException e) {
             log.info("Exception caught", e);
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiOffloadTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiOffloadTest.java
index 5c24b8b1c418b..cadfd759c15e7 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiOffloadTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiOffloadTest.java
@@ -204,8 +204,8 @@ public void testOffloadV2() throws Exception {
 
     @Test
     public void testOffloadV1() throws Exception {
-        String topicName = "persistent://prop-xyz/test/ns1/topic2";
-        String mlName = "prop-xyz/test/ns1/persistent/topic2";
+        String topicName = "persistent://prop-xyz/ns1/topic2";
+        String mlName = "prop-xyz/ns1/persistent/topic2";
         testOffload(topicName, mlName);
     }
 
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiSchemaAutoUpdateTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiSchemaAutoUpdateTest.java
index cabeb91753373..b0c2dc4827e06 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiSchemaAutoUpdateTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiSchemaAutoUpdateTest.java
@@ -48,9 +48,7 @@ public void setup() throws Exception {
         TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("test"));
         admin.tenants().createTenant("prop-xyz", tenantInfo);
         admin.namespaces().createNamespace("prop-xyz/ns1", Set.of("test"));
-        admin.namespaces().createNamespace("prop-xyz/test/ns1");
         admin.namespaces().createNamespace("prop-xyz/ns2", Set.of("test"));
-        admin.namespaces().createNamespace("prop-xyz/test/ns2");
     }
 
     @AfterMethod(alwaysRun = true)
@@ -257,25 +255,25 @@ public void testDisabledV2() throws Exception {
 
     @Test
     public void testBackwardV1() throws Exception {
-        testAutoUpdateBackward("prop-xyz/test/ns1", "persistent://prop-xyz/test/ns1/backward");
-        testAutoUpdateBackward("prop-xyz/test/ns2", "non-persistent://prop-xyz/test/ns2/backward-np");
+        testAutoUpdateBackward("prop-xyz/ns1", "persistent://prop-xyz/ns1/backward");
+        testAutoUpdateBackward("prop-xyz/ns2", "non-persistent://prop-xyz/ns2/backward-np");
     }
 
     @Test
     public void testForwardV1() throws Exception {
-        testAutoUpdateForward("prop-xyz/test/ns1", "persistent://prop-xyz/test/ns1/forward");
-        testAutoUpdateForward("prop-xyz/test/ns2", "non-persistent://prop-xyz/test/ns2/forward-np");
+        testAutoUpdateForward("prop-xyz/ns1", "persistent://prop-xyz/ns1/forward");
+        testAutoUpdateForward("prop-xyz/ns2", "non-persistent://prop-xyz/ns2/forward-np");
     }
 
     @Test
     public void testFullV1() throws Exception {
-        testAutoUpdateFull("prop-xyz/test/ns1", "persistent://prop-xyz/test/ns1/full");
-        testAutoUpdateFull("prop-xyz/test/ns2", "non-persistent://prop-xyz/test/ns2/full-np");
+        testAutoUpdateFull("prop-xyz/ns1", "persistent://prop-xyz/ns1/full");
+        testAutoUpdateFull("prop-xyz/ns2", "non-persistent://prop-xyz/ns2/full-np");
     }
 
     @Test
     public void testDisabledV1() throws Exception {
-        testAutoUpdateDisabled("prop-xyz/test/ns1", "persistent://prop-xyz/test/ns1/disabled");
-        testAutoUpdateDisabled("prop-xyz/test/ns2", "non-persistent://prop-xyz/test/ns2/disabled-np");
+        testAutoUpdateDisabled("prop-xyz/ns1", "persistent://prop-xyz/ns1/disabled");
+        testAutoUpdateDisabled("prop-xyz/ns2", "non-persistent://prop-xyz/ns2/disabled-np");
     }
 }
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiSchemaTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiSchemaTest.java
index 54c1be3e20439..034194bea0f8c 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiSchemaTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiSchemaTest.java
@@ -84,7 +84,6 @@ public void setup() throws Exception {
         TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("test"));
         admin.tenants().createTenant("schematest", tenantInfo);
         admin.namespaces().createNamespace("schematest/test", Set.of("test"));
-        admin.namespaces().createNamespace("schematest/" + cluster + "/test", Set.of("test"));
         admin.namespaces().createNamespace(schemaCompatibilityNamespace, Set.of("test"));
     }
 
@@ -95,7 +94,7 @@ public void cleanup() throws Exception {
     }
 
     enum ApiVersion{
-        V1, V2;
+        V2;
     }
 
     public static class Foo {
@@ -155,7 +154,7 @@ public Object[][] schemas() {
 
     @DataProvider(name = "version")
     public Object[][] versions() {
-        return new Object[][] { { ApiVersion.V1 }, { ApiVersion.V2 } };
+        return new Object[][] { { ApiVersion.V2 } };
     }
 
     @Test(dataProvider = "schemas")
@@ -190,7 +189,7 @@ private  void testSchemaInfoApi(Schema schema,
 
     @Test(dataProvider = "version")
     public void testPostSchemaCompatibilityStrategy(ApiVersion version) throws PulsarAdminException {
-        String namespace = format("%s%s%s", "schematest", (ApiVersion.V1.equals(version) ? "/" + cluster + "/" : "/"),
+        String namespace = format("%s%s%s", "schematest", "/",
                 "test");
         String topicName = "persistent://" + namespace + "/testStrategyChange";
         SchemaInfo fooSchemaInfo = Schema.AVRO(SchemaDefinition.builder()
@@ -248,7 +247,7 @@ private  void testSchemaInfoWithVersionApi(Schema schema,
 
     @Test(dataProvider = "version")
     public void createKeyValueSchema(ApiVersion version) throws Exception {
-        String namespace = format("%s%s%s", "schematest", (ApiVersion.V1.equals(version) ? "/" + cluster + "/" : "/"),
+        String namespace = format("%s%s%s", "schematest", "/",
                 "test");
         String topicName = "persistent://" + namespace + "/test-key-value-schema";
         Schema keyValueSchema = Schema.KeyValue(Schema.AVRO(Foo.class), Schema.AVRO(Foo.class));
@@ -270,7 +269,7 @@ public void createKeyValueSchema(ApiVersion version) throws Exception {
 
     @Test(dataProvider = "version")
     public void testInvalidSchemaDataException(ApiVersion version) {
-        String namespace = format("%s%s%s", "schematest", (ApiVersion.V1.equals(version) ? "/" + cluster + "/" : "/"),
+        String namespace = format("%s%s%s", "schematest", "/",
                 "test");
         String topicName = "persistent://" + namespace + "/test-invalid-schema-data-exception";
         SchemaInfo schemaInfo = SchemaInfo.builder()
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiTest.java
index 2930c552258e3..2b7b404e655b0 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminApiTest.java
@@ -541,7 +541,7 @@ public void brokers() throws Exception {
 
         Map nsMap = admin.brokers().getOwnedNamespaces("test", list.get(0));
         // since sla-monitor ns is not created nsMap.size() == 1 (for HeartBeat Namespace)
-        Assert.assertEquals(nsMap.size(), 2);
+        Assert.assertEquals(nsMap.size(), 1);
         for (String ns : nsMap.keySet()) {
             NamespaceOwnershipStatus nsStatus = nsMap.get(ns);
             if (ns.equals(
@@ -554,7 +554,7 @@ public void brokers() throws Exception {
         }
 
         Map nsMap2 = adminTls.brokers().getOwnedNamespaces("test", list.get(0));
-        Assert.assertEquals(nsMap2.size(), 2);
+        Assert.assertEquals(nsMap2.size(), 1);
 
         deleteNamespaceWithRetry("prop-xyz/ns1", false);
         admin.clusters().deleteCluster("test");
@@ -1492,7 +1492,7 @@ public void testDeleteNamespaceBundle(Integer numBundles) throws Exception {
         assertEquals(admin.namespaces().getTopics("prop-xyz/ns1-bundles"), new ArrayList<>());
 
         deleteNamespaceWithRetry("prop-xyz/ns1-bundles", false);
-        assertEquals(admin.namespaces().getNamespaces("prop-xyz", "test"), new ArrayList<>());
+        assertEquals(admin.namespaces().getNamespaces("prop-xyz"), new ArrayList<>());
     }
 
     @Test
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminTest.java
index b951549247a6f..88759522e6cb0 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminTest.java
@@ -57,14 +57,14 @@
 import org.apache.bookkeeper.conf.ClientConfiguration;
 import org.apache.bookkeeper.mledger.proto.PendingBookieOpsStats;
 import org.apache.pulsar.broker.ServiceConfiguration;
-import org.apache.pulsar.broker.admin.v1.BrokerStats;
-import org.apache.pulsar.broker.admin.v1.Brokers;
-import org.apache.pulsar.broker.admin.v1.Clusters;
-import org.apache.pulsar.broker.admin.v1.Namespaces;
-import org.apache.pulsar.broker.admin.v1.PersistentTopics;
-import org.apache.pulsar.broker.admin.v1.Properties;
-import org.apache.pulsar.broker.admin.v1.ResourceQuotas;
+import org.apache.pulsar.broker.admin.v2.BrokerStats;
+import org.apache.pulsar.broker.admin.v2.Brokers;
+import org.apache.pulsar.broker.admin.v2.Clusters;
+import org.apache.pulsar.broker.admin.v2.Namespaces;
+import org.apache.pulsar.broker.admin.v2.PersistentTopics;
+import org.apache.pulsar.broker.admin.v2.ResourceQuotas;
 import org.apache.pulsar.broker.admin.v2.SchemasResource;
+import org.apache.pulsar.broker.admin.v2.Tenants;
 import org.apache.pulsar.broker.auth.MockedPulsarServiceBaseTest;
 import org.apache.pulsar.broker.authentication.AuthenticationDataHttps;
 import org.apache.pulsar.broker.loadbalance.LeaderBroker;
@@ -78,7 +78,6 @@
 import org.apache.pulsar.common.policies.data.AutoFailoverPolicyData;
 import org.apache.pulsar.common.policies.data.AutoFailoverPolicyType;
 import org.apache.pulsar.common.policies.data.BrokerInfo;
-import org.apache.pulsar.common.policies.data.BundlesData;
 import org.apache.pulsar.common.policies.data.ClusterData;
 import org.apache.pulsar.common.policies.data.ClusterDataImpl;
 import org.apache.pulsar.common.policies.data.ErrorData;
@@ -108,7 +107,7 @@
 public class AdminTest extends MockedPulsarServiceBaseTest {
     private final String configClusterName = "use";
     private Clusters clusters;
-    private Properties properties;
+    private Tenants tenants;
     private Namespaces namespaces;
     private PersistentTopics persistentTopics;
     private Brokers brokers;
@@ -132,10 +131,10 @@ public void setup() throws Exception {
         doReturn("test").when(clusters).clientAppId();
         doNothing().when(clusters).validateSuperUserAccess();
 
-        properties = spy(Properties.class);
-        properties.setPulsar(pulsar);
-        doReturn("test").when(properties).clientAppId();
-        doNothing().when(properties).validateSuperUserAccess();
+        tenants = spy(Tenants.class);
+        tenants.setPulsar(pulsar);
+        doReturn("test").when(tenants).clientAppId();
+        doNothing().when(tenants).validateSuperUserAccess();
 
         namespaces = spy(Namespaces.class);
         namespaces.setServletContext(mock(ServletContext.class));
@@ -461,10 +460,10 @@ public void clusters() throws Exception {
     }
 
     @Test
-    public void properties() throws Throwable {
-        Object response = asyncRequests(ctx -> properties.getTenants(ctx));
+    public void tenants() throws Throwable {
+        Object response = asyncRequests(ctx -> tenants.getTenants(ctx));
         assertEquals(response, new ArrayList<>());
-        verify(properties, times(1)).validateSuperUserAccessAsync();
+        verify(tenants, times(1)).validateSuperUserAccessAsync();
 
         // create local cluster
         asyncRequests(ctx -> clusters.createCluster(ctx, configClusterName, ClusterDataImpl.builder().build()));
@@ -475,36 +474,36 @@ public void properties() throws Throwable {
                 .adminRoles(Set.of("role1", "role2"))
                 .allowedClusters(allowedClusters)
                 .build();
-        response = asyncRequests(ctx -> properties.createTenant(ctx, "test-property", tenantInfo));
-        verify(properties, times(2)).validateSuperUserAccessAsync();
+        response = asyncRequests(ctx -> tenants.createTenant(ctx, "test-property", tenantInfo));
+        verify(tenants, times(2)).validateSuperUserAccessAsync();
 
-        response = asyncRequests(ctx -> properties.getTenants(ctx));
+        response = asyncRequests(ctx -> tenants.getTenants(ctx));
         assertEquals(response, List.of("test-property"));
-        verify(properties, times(3)).validateSuperUserAccessAsync();
+        verify(tenants, times(3)).validateSuperUserAccessAsync();
 
-        response = asyncRequests(ctx -> properties.getTenantAdmin(ctx, "test-property"));
+        response = asyncRequests(ctx -> tenants.getTenantAdmin(ctx, "test-property"));
         assertEquals(response, tenantInfo);
-        verify(properties, times(4)).validateSuperUserAccessAsync();
+        verify(tenants, times(4)).validateSuperUserAccessAsync();
 
         final TenantInfoImpl newPropertyAdmin = TenantInfoImpl.builder()
                 .adminRoles(Set.of("role1", "other-role"))
                 .allowedClusters(allowedClusters)
                 .build();
-        response = asyncRequests(ctx -> properties.updateTenant(ctx, "test-property", newPropertyAdmin));
-        verify(properties, times(5)).validateSuperUserAccessAsync();
+        response = asyncRequests(ctx -> tenants.updateTenant(ctx, "test-property", newPropertyAdmin));
+        verify(tenants, times(5)).validateSuperUserAccessAsync();
 
         // Wait for updateTenant to take effect
         Thread.sleep(100);
 
-        response = asyncRequests(ctx -> properties.getTenantAdmin(ctx, "test-property"));
+        response = asyncRequests(ctx -> tenants.getTenantAdmin(ctx, "test-property"));
         assertEquals(response, newPropertyAdmin);
-        response = asyncRequests(ctx -> properties.getTenantAdmin(ctx, "test-property"));
+        response = asyncRequests(ctx -> tenants.getTenantAdmin(ctx, "test-property"));
         assertNotSame(response, tenantInfo);
-        verify(properties, times(7)).validateSuperUserAccessAsync();
+        verify(tenants, times(7)).validateSuperUserAccessAsync();
 
         // Check creating existing property
         try {
-            response = asyncRequests(ctx -> properties.createTenant(ctx, "test-property", tenantInfo));
+            response = asyncRequests(ctx -> tenants.createTenant(ctx, "test-property", tenantInfo));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.CONFLICT.getStatusCode());
@@ -512,14 +511,14 @@ public void properties() throws Throwable {
 
         // Check non-existing property
         try {
-            response = asyncRequests(ctx -> properties.getTenantAdmin(ctx, "non-existing"));
+            response = asyncRequests(ctx -> tenants.getTenantAdmin(ctx, "non-existing"));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
         }
 
         try {
-            response = asyncRequests(ctx -> properties.updateTenant(ctx, "xxx-non-existing", newPropertyAdmin));
+            response = asyncRequests(ctx -> tenants.updateTenant(ctx, "xxx-non-existing", newPropertyAdmin));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
@@ -527,7 +526,7 @@ public void properties() throws Throwable {
 
         // Check deleting non-existing property
         try {
-            response = asyncRequests(ctx -> properties.deleteTenant(ctx, "non-existing", false));
+            response = asyncRequests(ctx -> tenants.deleteTenant(ctx, "non-existing", false));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
@@ -544,7 +543,7 @@ public void properties() throws Throwable {
             return op == MockZooKeeper.Op.GET_CHILDREN && path.equals("/admin/policies");
         });
         try {
-            response = asyncRequests(ctx -> properties.getTenants(ctx));
+            response = asyncRequests(ctx -> tenants.getTenants(ctx));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
@@ -554,7 +553,7 @@ public void properties() throws Throwable {
             return op == MockZooKeeper.Op.GET && path.equals("/admin/policies/my-tenant");
         });
         try {
-            response = asyncRequests(ctx -> properties.getTenantAdmin(ctx, "my-tenant"));
+            response = asyncRequests(ctx -> tenants.getTenantAdmin(ctx, "my-tenant"));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
@@ -564,7 +563,7 @@ public void properties() throws Throwable {
             return op == MockZooKeeper.Op.GET && path.equals("/admin/policies/my-tenant");
         });
         try {
-            response = asyncRequests(ctx -> properties.updateTenant(ctx, "my-tenant", newPropertyAdmin));
+            response = asyncRequests(ctx -> tenants.updateTenant(ctx, "my-tenant", newPropertyAdmin));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
@@ -574,7 +573,7 @@ public void properties() throws Throwable {
             return op == MockZooKeeper.Op.CREATE && path.equals("/admin/policies/test");
         });
         try {
-            response = asyncRequests(ctx -> properties.createTenant(ctx, "test", tenantInfo));
+            response = asyncRequests(ctx -> tenants.createTenant(ctx, "test", tenantInfo));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
@@ -586,28 +585,28 @@ public void properties() throws Throwable {
         try {
             cache.invalidateAll();
             store.invalidateAll();
-            response = asyncRequests(ctx -> properties.deleteTenant(ctx, "test-property", false));
+            response = asyncRequests(ctx -> tenants.deleteTenant(ctx, "test-property", false));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
         }
 
-        response = asyncRequests(ctx -> properties.createTenant(ctx, "error-property", tenantInfo));
+        response = asyncRequests(ctx -> tenants.createTenant(ctx, "error-property", tenantInfo));
 
         mockZooKeeperGlobal.failConditional(Code.SESSIONEXPIRED, (op, path) -> {
             return op == MockZooKeeper.Op.DELETE && path.equals("/admin/policies/error-property");
         });
         try {
-            response = asyncRequests(ctx -> properties.deleteTenant(ctx, "error-property", false));
+            response = asyncRequests(ctx -> tenants.deleteTenant(ctx, "error-property", false));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.INTERNAL_SERVER_ERROR.getStatusCode());
         }
 
-        response = asyncRequests(ctx -> properties.deleteTenant(ctx, "test-property", false));
-        response = asyncRequests(ctx -> properties.deleteTenant(ctx, "error-property", false));
+        response = asyncRequests(ctx -> tenants.deleteTenant(ctx, "test-property", false));
+        response = asyncRequests(ctx -> tenants.deleteTenant(ctx, "error-property", false));
         response = new ArrayList<>();
-        response = asyncRequests(ctx -> properties.getTenants(ctx));
+        response = asyncRequests(ctx -> tenants.getTenants(ctx));
         assertEquals(response, new ArrayList<>());
 
         // Create a namespace to test deleting a non-empty property
@@ -615,13 +614,13 @@ public void properties() throws Throwable {
                 .adminRoles(Set.of("role1", "other-role"))
                 .allowedClusters(Set.of("use"))
                 .build();
-        response = asyncRequests(ctx -> properties.createTenant(ctx, "my-tenant", newPropertyAdmin2));
+        response = asyncRequests(ctx -> tenants.createTenant(ctx, "my-tenant", newPropertyAdmin2));
 
         response = asyncRequests(ctx -> namespaces.createNamespace(ctx, "my-tenant",
-                "use", "my-namespace", BundlesData.builder().build()));
+                "my-namespace", new Policies()));
 
         try {
-            response = asyncRequests(ctx -> properties.deleteTenant(ctx, "my-tenant", false));
+            response = asyncRequests(ctx -> tenants.deleteTenant(ctx, "my-tenant", false));
             fail("should have failed");
         } catch (RestException e) {
             // Ok
@@ -629,7 +628,7 @@ public void properties() throws Throwable {
 
         // Check name validation
         try {
-            response = asyncRequests(ctx -> properties.createTenant(ctx, "test&", tenantInfo));
+            response = asyncRequests(ctx -> tenants.createTenant(ctx, "test&", tenantInfo));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.PRECONDITION_FAILED.getStatusCode());
@@ -637,7 +636,7 @@ public void properties() throws Throwable {
 
         // Check tenantInfo is null
         try {
-            response = asyncRequests(ctx -> properties.createTenant(ctx, "tenant-config-is-null", null));
+            response = asyncRequests(ctx -> tenants.createTenant(ctx, "tenant-config-is-null", null));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.PRECONDITION_FAILED.getStatusCode());
@@ -651,7 +650,7 @@ public void properties() throws Throwable {
                 .allowedClusters(blankClusters)
                 .build();
         try {
-            response = asyncRequests(ctx -> properties.createTenant(ctx,
+            response = asyncRequests(ctx -> tenants.createTenant(ctx,
                     "tenant-config-is-empty", tenantWithEmptyCluster));
             fail("should have failed");
         } catch (RestException e) {
@@ -666,7 +665,7 @@ public void properties() throws Throwable {
                 .allowedClusters(containBlankClusters)
                 .build();
         try {
-            response = asyncRequests(ctx -> properties.createTenant(ctx,
+            response = asyncRequests(ctx -> tenants.createTenant(ctx,
                     "tenant-config-contain-empty", tenantContainEmptyCluster));
             fail("should have failed");
         } catch (RestException e) {
@@ -675,17 +674,17 @@ public void properties() throws Throwable {
 
         // Check max tenant count
         int maxTenants = pulsar.getConfiguration().getMaxTenants();
-        List tenants = pulsar.getPulsarResources().getTenantResources().listTenants();
+        List tenantsList = pulsar.getPulsarResources().getTenantResources().listTenants();
 
-        for (int tenantSize = tenants.size(); tenantSize < maxTenants; tenantSize++) {
+        for (int tenantSize = tenantsList.size(); tenantSize < maxTenants; tenantSize++) {
             final int tenantIndex = tenantSize;
             Response obj = (Response) asyncRequests(ctx ->
-                    properties.createTenant(ctx, "test-tenant-" + tenantIndex, tenantInfo));
+                    tenants.createTenant(ctx, "test-tenant-" + tenantIndex, tenantInfo));
             Assert.assertTrue(obj.getStatus() < 400 && obj.getStatus() >= 200);
         }
         try {
             Response obj = (Response) asyncRequests(ctx ->
-                    properties.createTenant(ctx, "test-tenant-" +  maxTenants, tenantInfo));
+                    tenants.createTenant(ctx, "test-tenant-" +  maxTenants, tenantInfo));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.PRECONDITION_FAILED.getStatusCode());
@@ -693,7 +692,7 @@ public void properties() throws Throwable {
 
         // Check creating existing property when tenant reach max count.
         try {
-            response = asyncRequests(ctx -> properties.createTenant(ctx,
+            response = asyncRequests(ctx -> tenants.createTenant(ctx,
                     "test-tenant-" +  (maxTenants - 1), tenantInfo));
             fail("should have failed");
         } catch (RestException e) {
@@ -701,11 +700,11 @@ public void properties() throws Throwable {
         }
 
         AsyncResponse response2 = mock(AsyncResponse.class);
-        namespaces.deleteNamespace(response2, "my-tenant", "use", "my-namespace", false, false);
+        namespaces.deleteNamespace(response2, "my-tenant", "my-namespace", false, false);
         ArgumentCaptor captor = ArgumentCaptor.forClass(Response.class);
         verify(response2, timeout(5000).times(1)).resume(captor.capture());
         assertEquals(captor.getValue().getStatus(), Status.NO_CONTENT.getStatusCode());
-        response = asyncRequests(ctx -> properties.deleteTenant(ctx, "my-tenant", false));
+        response = asyncRequests(ctx -> tenants.deleteTenant(ctx, "my-tenant", false));
     }
 
     @Test
@@ -752,40 +751,24 @@ public void resourceQuotas() throws Exception {
         Awaitility.await().untilAsserted(() ->
                 assertEquals(defaultBandwidth, resourceQuotas.getDefaultResourceQuota().getBandwidthOut()));
 
-        String property = "prop-xyz";
+        String tenant = "prop-xyz";
         String cluster = "use";
         String namespace = "ns";
         String bundleRange = "0x00000000_0xffffffff";
         Policies policies = new Policies();
         doReturn(policies).when(resourceQuotas).getNamespacePolicies(
-                NamespaceName.get(property, cluster, namespace));
+                NamespaceName.get(tenant, namespace));
         doReturn(CompletableFuture.completedFuture(policies)).when(resourceQuotas)
-                .getNamespacePoliciesAsync(NamespaceName.get(property, cluster, namespace));
+                .getNamespacePoliciesAsync(NamespaceName.get(tenant, namespace));
         doReturn("client-id").when(resourceQuotas).clientAppId();
 
-        try {
-            asyncRequests(ctx -> resourceQuotas.setNamespaceBundleResourceQuota(
-                    ctx, property, cluster, namespace, bundleRange, quota));
-            fail();
-        } catch (Exception e) {
-            // OK : should fail without creating policies
-        }
-
-        try {
-            asyncRequests(ctx -> resourceQuotas.removeNamespaceBundleResourceQuota(
-                    ctx, property, cluster, namespace, bundleRange));
-            fail();
-        } catch (Exception e) {
-            // OK : should fail without creating policies
-        }
-
         // create policies
         TenantInfoImpl admin = TenantInfoImpl.builder()
                 .allowedClusters(Collections.singleton(cluster))
                 .build();
         ClusterDataImpl clusterData = ClusterDataImpl.builder().serviceUrl("http://example.pulsar").build();
         asyncRequests(ctx -> clusters.createCluster(ctx, cluster, clusterData));
-        asyncRequests(ctx -> properties.createTenant(ctx, property, admin));
+        asyncRequests(ctx -> tenants.createTenant(ctx, tenant, admin));
 
         // customized bandwidth for this namespace
         double customizeBandwidth = 3000;
@@ -794,17 +777,17 @@ public void resourceQuotas() throws Exception {
 
         // set and get Resource Quota
         asyncRequests(ctx -> resourceQuotas.setNamespaceBundleResourceQuota(
-                ctx, property, cluster, namespace, bundleRange, quota));
+                ctx, tenant, namespace, bundleRange, quota));
         ResourceQuota bundleQuota = (ResourceQuota) asyncRequests(ctx -> resourceQuotas
-                .getNamespaceBundleResourceQuota(ctx, property, cluster, namespace,
+                .getNamespaceBundleResourceQuota(ctx, tenant, namespace,
                 bundleRange));
         assertEquals(quota, bundleQuota);
 
         // remove quota which sets to default quota
         asyncRequests(ctx -> resourceQuotas.removeNamespaceBundleResourceQuota(
-                ctx, property, cluster, namespace, bundleRange));
+                ctx, tenant, namespace, bundleRange));
         bundleQuota = (ResourceQuota) asyncRequests(ctx -> resourceQuotas
-                .getNamespaceBundleResourceQuota(ctx, property, cluster, namespace, bundleRange));
+                .getNamespaceBundleResourceQuota(ctx, tenant, namespace, bundleRange));
         assertEquals(defaultBandwidth, bundleQuota.getBandwidthIn());
         assertEquals(defaultBandwidth, bundleQuota.getBandwidthOut());
     }
@@ -826,7 +809,7 @@ public void brokerStats() throws Exception {
         StreamingOutput topic = brokerStats.getTopics2();
         assertNotNull(topic);
         try {
-            brokerStats.getBrokerResourceAvailability("prop", "use", "ns2");
+            brokerStats.getBrokerResourceAvailability("prop", "ns2");
             fail("should have failed as ModularLoadManager doesn't support it");
         } catch (RestException re) {
             // Ok
@@ -836,40 +819,42 @@ public void brokerStats() throws Exception {
     @Test
     public void persistentTopics() throws Exception {
 
-        final String property = "prop-xyz";
+        final String tenant = "prop-xyz";
         final String cluster = "use";
         final String namespace = "ns";
         final String topic = "ds1";
         Policies policies = new Policies();
-        doReturn(policies).when(resourceQuotas).getNamespacePolicies(NamespaceName.get(property, cluster, namespace));
+        doReturn(policies).when(resourceQuotas).getNamespacePolicies(NamespaceName.get(tenant, namespace));
         doReturn("client-id").when(resourceQuotas).clientAppId();
         // create policies
         TenantInfo admin = TenantInfo.builder()
                 .allowedClusters(Collections.singleton(cluster))
                 .build();
-        pulsar.getPulsarResources().getTenantResources().createTenant(property, admin);
+        pulsar.getPulsarResources().getTenantResources().createTenant(tenant, admin);
+        Policies nsPolicies = new Policies();
+        nsPolicies.replication_clusters = Sets.newHashSet(cluster);
         pulsar.getPulsarResources().getNamespaceResources()
-                .createPolicies(NamespaceName.get(property, cluster, namespace), new Policies());
+                .createPolicies(NamespaceName.get(tenant, namespace), nsPolicies);
 
         AsyncResponse response = mock(AsyncResponse.class);
-        persistentTopics.getList(response, property, cluster, namespace, null);
+        persistentTopics.getList(response, tenant, namespace, null, false, null);
         verify(response, timeout(5000).times(1)).resume(new ArrayList<>());
         // create topic
         response = mock(AsyncResponse.class);
-        persistentTopics.getPartitionedTopicList(response, property, cluster, namespace);
+        persistentTopics.getPartitionedTopicList(response, tenant, namespace, false);
         verify(response, timeout(5000).times(1)).resume(new ArrayList<>());
         response = mock(AsyncResponse.class);
         ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(Response.class);
-        persistentTopics.createPartitionedTopic(response, property, cluster, namespace, topic, 5, false);
+        persistentTopics.createPartitionedTopic(response, tenant, namespace, topic, 5, false);
         verify(response, timeout(5000).times(1)).resume(responseCaptor.capture());
         assertEquals(responseCaptor.getValue().getStatus(), Response.Status.NO_CONTENT.getStatusCode());
         response = mock(AsyncResponse.class);
-        persistentTopics.getPartitionedTopicList(response, property, cluster, namespace);
+        persistentTopics.getPartitionedTopicList(response, tenant, namespace, false);
         verify(response, timeout(5000).times(1))
                 .resume(Lists
-                        .newArrayList(String.format("persistent://%s/%s/%s/%s", property, cluster, namespace, topic)));
+                        .newArrayList(String.format("persistent://%s/%s/%s", tenant, namespace, topic)));
 
-        TopicName topicName = TopicName.get("persistent", property, cluster, namespace, topic);
+        TopicName topicName = TopicName.get("persistent", tenant, namespace, topic);
         assertEquals(persistentTopics.getPartitionedTopicMetadata(topicName, true, false).partitions, 5);
 
         // grant permission
@@ -877,19 +862,19 @@ public void persistentTopics() throws Exception {
         final String role = "test-role";
         response = mock(AsyncResponse.class);
         responseCaptor = ArgumentCaptor.forClass(Response.class);
-        persistentTopics.grantPermissionsOnTopic(response, property, cluster, namespace, topic, role, actions);
+        persistentTopics.grantPermissionsOnTopic(response, tenant, namespace, topic, role, actions);
         verify(response, timeout(5000).times(1)).resume(responseCaptor.capture());
         Assert.assertEquals(responseCaptor.getValue().getStatus(), Response.Status.NO_CONTENT.getStatusCode());
         // verify permission
         response = mock(AsyncResponse.class);
         ArgumentCaptor>> permissionsCaptor = ArgumentCaptor.forClass(Map.class);
-        persistentTopics.getPermissionsOnTopic(response, property, cluster, namespace, topic);
+        persistentTopics.getPermissionsOnTopic(response, tenant, namespace, topic);
         verify(response, timeout(5000).times(1)).resume(permissionsCaptor.capture());
         Map> permission = permissionsCaptor.getValue();
         assertEquals(permission.get(role), actions);
         // remove permission
         response = mock(AsyncResponse.class);
-        persistentTopics.revokePermissionsOnTopic(response, property, cluster, namespace, topic, role);
+        persistentTopics.revokePermissionsOnTopic(response, tenant, namespace, topic, role);
         responseCaptor = ArgumentCaptor.forClass(Response.class);
         verify(response, timeout(5000).times(1)).resume(responseCaptor.capture());
         Assert.assertEquals(responseCaptor.getValue().getStatus(), Response.Status.NO_CONTENT.getStatusCode());
@@ -897,7 +882,7 @@ public void persistentTopics() throws Exception {
         Awaitility.await().untilAsserted(() -> {
             AsyncResponse response1 = mock(AsyncResponse.class);
             ArgumentCaptor>> permissionsCaptor1 = ArgumentCaptor.forClass(Map.class);
-            persistentTopics.getPermissionsOnTopic(response1, property, cluster, namespace, topic);
+            persistentTopics.getPermissionsOnTopic(response1, tenant, namespace, topic);
             verify(response1, timeout(5000).times(1)).resume(permissionsCaptor1.capture());
             Map> p = permissionsCaptor1.getValue();
             assertTrue(p.isEmpty());
@@ -916,18 +901,26 @@ public void testRestExceptionMessage() {
     @Test
     public void testUpdatePartitionedTopicCoontainedInOldTopic() throws Exception {
 
-        final String property = "prop-xyz";
+        final String tenant = "prop-xyz";
         final String cluster = "use";
         final String namespace = "ns";
         final String partitionedTopicName = "old-special-topic";
         final String partitionedTopicName2 = "special-topic";
 
+        if (!pulsar.getPulsarResources().getTenantResources().tenantExists(tenant)) {
+            TenantInfo tenantInfo = TenantInfo.builder()
+                    .allowedClusters(Collections.singleton(cluster))
+                    .build();
+            pulsar.getPulsarResources().getTenantResources().createTenant(tenant, tenantInfo);
+        }
+        Policies nsPolicies = new Policies();
+        nsPolicies.replication_clusters = Sets.newHashSet(cluster);
         pulsar.getPulsarResources().getNamespaceResources()
-                .createPolicies(NamespaceName.get(property, cluster, namespace), new Policies());
+                .createPolicies(NamespaceName.get(tenant, namespace), nsPolicies);
 
         AsyncResponse response1 = mock(AsyncResponse.class);
         ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(Response.class);
-        persistentTopics.createPartitionedTopic(response1, property, cluster, namespace,
+        persistentTopics.createPartitionedTopic(response1, tenant, namespace,
                 partitionedTopicName, 5, false);
         verify(response1, timeout(5000).times(1)).resume(responseCaptor.capture());
         Assert.assertEquals(responseCaptor.getValue().getStatus(),
@@ -935,23 +928,38 @@ public void testUpdatePartitionedTopicCoontainedInOldTopic() throws Exception {
 
         AsyncResponse response2 = mock(AsyncResponse.class);
         responseCaptor = ArgumentCaptor.forClass(Response.class);
-        persistentTopics.createPartitionedTopic(response2, property, cluster, namespace,
+        persistentTopics.createPartitionedTopic(response2, tenant, namespace,
                 partitionedTopicName2, 2, false);
         verify(response2, timeout(5000).times(1)).resume(responseCaptor.capture());
         Assert.assertEquals(responseCaptor.getValue().getStatus(),
                 Response.Status.NO_CONTENT.getStatusCode());
 
-        persistentTopics.updatePartitionedTopic(response2, property, cluster, namespace,
+        persistentTopics.updatePartitionedTopic(response2, tenant, namespace,
                 partitionedTopicName2, false, false,
                 false, 10);
     }
 
     @Test
     public void test500Error() throws Exception {
-        final String property = "prop-xyz";
+        final String tenant = "prop-xyz";
         final String cluster = "use";
         final String namespace = "ns";
         final String partitionedTopicName = "error-500-topic";
+
+        if (!pulsar.getPulsarResources().getTenantResources().tenantExists(tenant)) {
+            TenantInfo tenantInfo = TenantInfo.builder()
+                    .allowedClusters(Collections.singleton(cluster))
+                    .build();
+            pulsar.getPulsarResources().getTenantResources().createTenant(tenant, tenantInfo);
+        }
+        if (!pulsar.getPulsarResources().getNamespaceResources()
+                .namespaceExists(NamespaceName.get(tenant, namespace))) {
+            Policies nsPolicies = new Policies();
+            nsPolicies.replication_clusters = Sets.newHashSet(cluster);
+            pulsar.getPulsarResources().getNamespaceResources()
+                    .createPolicies(NamespaceName.get(tenant, namespace), nsPolicies);
+        }
+
         AsyncResponse response1 = mock(AsyncResponse.class);
         ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(RestException.class);
         CompletableFuture> future = new CompletableFuture();
@@ -959,7 +967,7 @@ public void test500Error() throws Exception {
         NamespaceService namespaceService = pulsar.getNamespaceService();
 
         doReturn(future).when(namespaceService).checkTopicExists(any());
-        persistentTopics.createPartitionedTopic(response1, property, cluster, namespace,
+        persistentTopics.createPartitionedTopic(response1, tenant, namespace,
                 partitionedTopicName, 5, false);
 
         verify(response1, timeout(5000).times(1)).resume(responseCaptor.capture());
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminTopicApiTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminTopicApiTest.java
index b9a0849e01f89..22ba4e35a5832 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminTopicApiTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/AdminTopicApiTest.java
@@ -179,10 +179,6 @@ public void testPeekMessages() throws Exception {
     @DataProvider
     public Object[] getStatsDataProvider() {
         return new Object[]{
-                // v1 topic
-                TopicDomain.persistent + "://my-property/test/my-ns/" + UUID.randomUUID(),
-                TopicDomain.non_persistent + "://my-property/test/my-ns/" + UUID.randomUUID(),
-                //v2 topic
                 TopicDomain.persistent + "://my-property/my-ns/" + UUID.randomUUID(),
                 TopicDomain.non_persistent + "://my-property/my-ns/" + UUID.randomUUID(),
         };
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/BrokerEndpointsAuthorizationTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/BrokerEndpointsAuthorizationTest.java
index 7fd5fc1cc85d7..bc94fc85309e3 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/BrokerEndpointsAuthorizationTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/BrokerEndpointsAuthorizationTest.java
@@ -29,7 +29,6 @@
 import org.apache.pulsar.client.admin.PulsarAdmin;
 import org.apache.pulsar.client.admin.PulsarAdminException;
 import org.apache.pulsar.client.impl.auth.AuthenticationToken;
-import org.apache.pulsar.common.naming.TopicVersion;
 import org.apache.pulsar.common.policies.data.BrokerOperation;
 import org.apache.pulsar.security.MockedPulsarStandalone;
 import org.testng.Assert;
@@ -287,7 +286,7 @@ public void testBacklogQuotaCheck() throws PulsarAdminException {
     public void testHealthCheck() throws PulsarAdminException {
         final String clusterName = getPulsarService().getConfiguration().getClusterName();
         final String brokerId = getPulsarService().getBrokerId();
-        superUserAdmin.brokers().healthcheck(TopicVersion.V2);
+        superUserAdmin.brokers().healthcheck();
         // test allow broker operation
         verify(spyAuthorizationService)
                 .allowBrokerOperationAsync(eq(clusterName), eq(brokerId),
@@ -297,6 +296,6 @@ public void testHealthCheck() throws PulsarAdminException {
 
         // ---- test nobody
         Assert.assertThrows(PulsarAdminException.NotAuthorizedException.class,
-                () ->  nobodyAdmin.brokers().healthcheck(TopicVersion.V2));
+                () ->  nobodyAdmin.brokers().healthcheck());
     }
 }
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/IncrementPartitionsTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/IncrementPartitionsTest.java
index 091f4ae6c07df..31071131c4276 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/IncrementPartitionsTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/IncrementPartitionsTest.java
@@ -62,12 +62,11 @@ public void setup() throws Exception {
         mockPulsarSetup.setup();
 
         // Setup namespaces
-        admin.clusters().createCluster("use", ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build());
-        TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("use"));
+        admin.clusters().createCluster("test", ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build());
+        TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("test"));
         admin.tenants().createTenant("prop-xyz", tenantInfo);
-        admin.namespaces().createNamespace("prop-xyz/use/ns1");
+        admin.namespaces().createNamespace("prop-xyz/ns1");
 
-        // Setup v2 namespaces
         setupDefaultTenantAndNamespace();
     }
 
@@ -80,7 +79,7 @@ public void cleanup() throws Exception {
 
     @Test
     public void testIncrementPartitionsOfTopicOnUnusedTopic() throws Exception {
-        final String partitionedTopicName = "persistent://prop-xyz/use/ns1/test-topic";
+        final String partitionedTopicName = "persistent://prop-xyz/ns1/test-topic";
 
         admin.topics().createPartitionedTopic(partitionedTopicName, 10);
         assertEquals(admin.topics().getPartitionedTopicMetadata(partitionedTopicName).partitions, 10);
@@ -91,7 +90,7 @@ public void testIncrementPartitionsOfTopicOnUnusedTopic() throws Exception {
 
     @Test
     public void testIncrementPartitionsOfTopic() throws Exception {
-        final String partitionedTopicName = "persistent://prop-xyz/use/ns1/test-topic-2";
+        final String partitionedTopicName = "persistent://prop-xyz/ns1/test-topic-2";
 
         admin.topics().createPartitionedTopic(partitionedTopicName, 1);
         assertEquals(admin.topics().getPartitionedTopicMetadata(partitionedTopicName).partitions, 1);
@@ -153,7 +152,7 @@ public void testIncrementPartitionsOfTopicWithSubscriptionProperties() throws Ex
     @Test
     public void testIncrementPartitionsWithNoSubscriptions() throws Exception {
         final String partitionedTopicName =
-                BrokerTestUtil.newUniqueName("persistent://prop-xyz/use/ns1/test-topic");
+                BrokerTestUtil.newUniqueName("persistent://prop-xyz/ns1/test-topic");
 
         admin.topics().createPartitionedTopic(partitionedTopicName, 1);
         assertEquals(admin.topics().getPartitionedTopicMetadata(partitionedTopicName).partitions, 1);
@@ -180,7 +179,7 @@ public void testIncrementPartitionsWithNoSubscriptions() throws Exception {
     @Test
     public void testIncrementPartitionsWithReaders() throws Exception {
         TopicName partitionedTopicName = TopicName.get(
-                BrokerTestUtil.newUniqueName("persistent://prop-xyz/use/ns1/test-topic"));
+                BrokerTestUtil.newUniqueName("persistent://prop-xyz/ns1/test-topic"));
 
         admin.topics().createPartitionedTopic(partitionedTopicName.toString(), 1);
         assertEquals(admin.topics().getPartitionedTopicMetadata(partitionedTopicName.toString()).partitions, 1);
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/NamespacesTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/NamespacesTest.java
index 92e104e67a2eb..ca3f039fea41a 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/NamespacesTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/NamespacesTest.java
@@ -45,6 +45,7 @@
 import java.util.Collection;
 import java.util.EnumSet;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -73,8 +74,8 @@
 import org.apache.bookkeeper.util.ZkUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.pulsar.broker.BrokerTestUtil;
-import org.apache.pulsar.broker.admin.v1.Namespaces;
-import org.apache.pulsar.broker.admin.v1.PersistentTopics;
+import org.apache.pulsar.broker.admin.v2.Namespaces;
+import org.apache.pulsar.broker.admin.v2.PersistentTopics;
 import org.apache.pulsar.broker.auth.MockedPulsarServiceBaseTest;
 import org.apache.pulsar.broker.namespace.LookupOptions;
 import org.apache.pulsar.broker.namespace.NamespaceEphemeralData;
@@ -147,7 +148,6 @@ public class NamespacesTest extends MockedPulsarServiceBaseTest {
     private final String testTenant = "my-tenant";
     private final String testOtherTenant = "other-tenant";
     private final String testLocalCluster = "use";
-    private final String testOtherCluster = "usc";
 
     public static final long THREE_MINUTE_MILLIS = 180000;
 
@@ -165,12 +165,12 @@ public void setup() throws Exception {
         testLocalNamespaces = new ArrayList<>();
         testGlobalNamespaces = new ArrayList<>();
 
-        testLocalNamespaces.add(NamespaceName.get(this.testTenant, this.testLocalCluster, "test-namespace-1"));
-        testLocalNamespaces.add(NamespaceName.get(this.testTenant, this.testLocalCluster, "test-namespace-2"));
-        testLocalNamespaces.add(NamespaceName.get(this.testTenant, this.testOtherCluster, "test-other-namespace-1"));
-        testLocalNamespaces.add(NamespaceName.get(this.testOtherTenant, this.testLocalCluster, "test-namespace-1"));
+        testLocalNamespaces.add(NamespaceName.get(this.testTenant, "test-namespace-1"));
+        testLocalNamespaces.add(NamespaceName.get(this.testTenant, "test-namespace-2"));
+        testLocalNamespaces.add(NamespaceName.get(this.testTenant, "test-other-namespace-1"));
+        testLocalNamespaces.add(NamespaceName.get(this.testOtherTenant, "test-namespace-1"));
 
-        testGlobalNamespaces.add(NamespaceName.get(this.testTenant, "global", "test-global-ns1"));
+        testGlobalNamespaces.add(NamespaceName.get(this.testTenant, "test-global-ns1"));
 
         uriField = PulsarWebResource.class.getDeclaredField("uri");
         uriField.setAccessible(true);
@@ -218,11 +218,16 @@ private void initAndStartBroker() throws Exception {
         doReturn("test").when(namespaces).clientAppId();
         doReturn(null).when(namespaces).originalPrincipal();
         doReturn(null).when(namespaces).clientAuthData();
-        doReturn(Set.of("use", "usw", "usc", "global")).when(namespaces).clusters();
+        doReturn(Set.of("use", "usw", "usc")).when(namespaces).clusters();
 
         admin.clusters().createCluster("use", ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build());
         admin.clusters().createCluster("usw", ClusterData.builder().serviceUrl("http://127.0.0.2:8082").build());
         admin.clusters().createCluster("usc", ClusterData.builder().serviceUrl("http://127.0.0.3:8083").build());
+        // After V1 removal, all namespaces go through the peer-cluster redirect path
+        // (NamespaceName.isGlobal() always returns true), so peer clusters must be configured.
+        // Only "usc" is a peer because peer clusters cannot also be replication clusters.
+        admin.clusters().updatePeerClusterNames("use",
+                new LinkedHashSet<>(List.of("usc")));
         admin.tenants().createTenant(this.testTenant,
                 new TenantInfoImpl(Set.of("role1", "role2"), Set.of("use", "usc", "usw")));
         admin.tenants().createTenant(this.testOtherTenant,
@@ -236,19 +241,19 @@ private void initAndStartBroker() throws Exception {
                 .validateTenantOperation(this.testOtherTenant, null);
 
         doThrow(new RestException(Status.UNAUTHORIZED, "unauthorized")).when(namespaces)
-                .validateNamespacePolicyOperation(NamespaceName.get("other-tenant/use/test-namespace-1"),
+                .validateNamespacePolicyOperation(NamespaceName.get("other-tenant/test-namespace-1"),
                         PolicyName.PERSISTENCE, PolicyOperation.WRITE);
 
         doThrow(new RestException(Status.UNAUTHORIZED, "unauthorized")).when(namespaces)
-                .validateNamespacePolicyOperation(NamespaceName.get("other-tenant/use/test-namespace-1"),
+                .validateNamespacePolicyOperation(NamespaceName.get("other-tenant/test-namespace-1"),
                         PolicyName.RETENTION, PolicyOperation.WRITE);
 
         doReturn(FutureUtil.failedFuture(new RestException(Status.UNAUTHORIZED, "unauthorized"))).when(namespaces)
-                .validateNamespacePolicyOperationAsync(NamespaceName.get("other-tenant/use/test-namespace-1"),
+                .validateNamespacePolicyOperationAsync(NamespaceName.get("other-tenant/test-namespace-1"),
                         PolicyName.PERSISTENCE, PolicyOperation.WRITE);
 
         doReturn(FutureUtil.failedFuture(new RestException(Status.UNAUTHORIZED, "unauthorized"))).when(namespaces)
-                .validateNamespacePolicyOperationAsync(NamespaceName.get("other-tenant/use/test-namespace-1"),
+                .validateNamespacePolicyOperationAsync(NamespaceName.get("other-tenant/test-namespace-1"),
                         PolicyName.RETENTION, PolicyOperation.WRITE);
 
         nsSvc = pulsar.getNamespaceService();
@@ -257,23 +262,24 @@ private void initAndStartBroker() throws Exception {
     @Test
     public void testCreateNamespaces() throws Exception {
         try {
+            Policies policies = new Policies();
+            policies.replication_clusters = Set.of("other-colo");
             asyncRequests(response -> namespaces.createNamespace(response,
-                    this.testTenant, "other-colo", "my-namespace",
-                    BundlesData.builder().build()));
+                    this.testTenant, "my-namespace", policies));
             fail("should have failed");
         } catch (RestException e) {
             // Ok, cluster doesn't exist
         }
 
         List nsnames = new ArrayList<>();
-        nsnames.add(NamespaceName.get(this.testTenant, "use", "create-namespace-1"));
-        nsnames.add(NamespaceName.get(this.testTenant, "use", "create-namespace-2"));
-        nsnames.add(NamespaceName.get(this.testTenant, "usc", "create-other-namespace-1"));
+        nsnames.add(NamespaceName.get(this.testTenant, "create-namespace-1"));
+        nsnames.add(NamespaceName.get(this.testTenant, "create-namespace-2"));
+        nsnames.add(NamespaceName.get(this.testTenant, "create-other-namespace-1"));
         createTestNamespaces(nsnames, BundlesData.builder().build());
 
         try {
-            asyncRequests(response -> namespaces.createNamespace(response, this.testTenant, "use", "create-namespace-1",
-                    BundlesData.builder().build()));
+            asyncRequests(response -> namespaces.createNamespace(response, this.testTenant, "create-namespace-1",
+                    (Policies) null));
             fail("should have failed");
         } catch (RestException e) {
             // Ok, namespace already exists
@@ -281,16 +287,15 @@ public void testCreateNamespaces() throws Exception {
 
         try {
             asyncRequests(response -> namespaces.createNamespace(response, "non-existing-tenant",
-                    "use", "create-namespace-1",
-                    BundlesData.builder().build()));
+                    "create-namespace-1", (Policies) null));
             fail("should have failed");
         } catch (RestException e) {
             // Ok, tenant doesn't exist
         }
 
         try {
-            asyncRequests(response -> namespaces.createNamespace(response, this.testTenant, "use", "create-namespace-#",
-                    BundlesData.builder().build()));
+            asyncRequests(response -> namespaces.createNamespace(response, this.testTenant, "create-namespace-#",
+                    (Policies) null));
             fail("should have failed");
         } catch (RestException e) {
             // Ok, invalid namespace name
@@ -299,11 +304,11 @@ public void testCreateNamespaces() throws Exception {
 
         mockZooKeeperGlobal.failConditional(Code.SESSIONEXPIRED, (op, path) -> {
                 return op == MockZooKeeper.Op.CREATE
-                    && path.equals("/admin/policies/my-tenant/use/my-namespace-3");
+                    && path.equals("/admin/policies/my-tenant/my-namespace-3");
             });
         try {
             asyncRequests(response -> namespaces.createNamespace(response, this.testTenant,
-                    "use", "my-namespace-3", BundlesData.builder().build()));
+                    "my-namespace-3", (Policies) null));
             fail("should have failed");
         } catch (RestException e) {
             // Ok
@@ -312,11 +317,7 @@ public void testCreateNamespaces() throws Exception {
 
     @Test
     public void testGetNamespaces() throws Exception {
-        List expectedList = Arrays.asList(this.testLocalNamespaces.get(0).toString(),
-                this.testLocalNamespaces.get(1).toString());
-        expectedList.sort(null);
-        assertEquals(namespaces.getNamespacesForCluster(this.testTenant, this.testLocalCluster), expectedList);
-        expectedList = Arrays.asList(
+        List expectedList = Arrays.asList(
                 this.testLocalNamespaces.get(0).toString(),
                 this.testLocalNamespaces.get(1).toString(),
                 this.testLocalNamespaces.get(2).toString(),
@@ -346,13 +347,6 @@ public void testGetNamespaces() throws Exception {
             // Ok, does not exist
         }
 
-        try {
-            namespaces.getNamespacesForCluster(this.testTenant, "other-cluster");
-            fail("should have failed");
-        } catch (RestException e) {
-            // Ok, does not exist
-        }
-
         // ZK Errors
         mockZooKeeperGlobal.failConditional(Code.SESSIONEXPIRED, (op, path) -> {
                 return op == MockZooKeeper.Op.GET_CHILDREN
@@ -371,60 +365,49 @@ public void testGetNamespaces() throws Exception {
             // Ok
         }
 
-        mockZooKeeperGlobal.failConditional(Code.SESSIONEXPIRED, (op, path) -> {
-                return op == MockZooKeeper.Op.GET_CHILDREN
-                    && path.equals("/admin/policies/my-tenant/use");
-            });
-        try {
-            namespaces.getNamespacesForCluster(this.testTenant, this.testLocalCluster);
-            fail("should have failed");
-        } catch (RestException e) {
-            // Ok
-        }
-
     }
 
     @Test(enabled = false)
     public void testGrantAndRevokePermissions() throws Exception {
         Policies expectedPolicies = new Policies();
-        assertEquals(asyncRequests(ctx -> namespaces.getPolicies(ctx, this.testTenant, this.testLocalCluster,
+        assertEquals(asyncRequests(ctx -> namespaces.getPolicies(ctx, this.testTenant,
                 this.testLocalNamespaces.get(0).getLocalName())), expectedPolicies);
-        assertEquals(asyncRequests(ctx -> namespaces.getPermissions(ctx, this.testTenant, this.testLocalCluster,
+        assertEquals(asyncRequests(ctx -> namespaces.getPermissions(ctx, this.testTenant,
                 this.testLocalNamespaces.get(0).getLocalName())),
                 expectedPolicies.auth_policies.getNamespaceAuthentication());
 
-        asyncRequests(ctx -> namespaces.grantPermissionOnNamespace(ctx, this.testTenant, this.testLocalCluster,
+        asyncRequests(ctx -> namespaces.grantPermissionOnNamespace(ctx, this.testTenant,
                 this.testLocalNamespaces.get(0).getLocalName(), "my-role", EnumSet.of(AuthAction.produce)));
 
         expectedPolicies.auth_policies.getNamespaceAuthentication().put("my-role", EnumSet.of(AuthAction.produce));
-        assertEquals(asyncRequests(ctx -> namespaces.getPolicies(ctx, this.testTenant, this.testLocalCluster,
+        assertEquals(asyncRequests(ctx -> namespaces.getPolicies(ctx, this.testTenant,
                 this.testLocalNamespaces.get(0).getLocalName())), expectedPolicies);
-        assertEquals(asyncRequests(ctx -> namespaces.getPermissions(ctx, this.testTenant, this.testLocalCluster,
+        assertEquals(asyncRequests(ctx -> namespaces.getPermissions(ctx, this.testTenant,
                 this.testLocalNamespaces.get(0).getLocalName())),
                 expectedPolicies.auth_policies.getNamespaceAuthentication());
 
-        asyncRequests(ctx -> namespaces.grantPermissionOnNamespace(ctx, this.testTenant, this.testLocalCluster,
+        asyncRequests(ctx -> namespaces.grantPermissionOnNamespace(ctx, this.testTenant,
                 this.testLocalNamespaces.get(0).getLocalName(), "other-role", EnumSet.of(AuthAction.consume)));
         expectedPolicies.auth_policies.getNamespaceAuthentication().put("other-role", EnumSet.of(AuthAction.consume));
-        assertEquals(asyncRequests(ctx -> namespaces.getPolicies(ctx, this.testTenant, this.testLocalCluster,
+        assertEquals(asyncRequests(ctx -> namespaces.getPolicies(ctx, this.testTenant,
                 this.testLocalNamespaces.get(0).getLocalName())), expectedPolicies);
-        assertEquals(asyncRequests(ctx -> namespaces.getPermissions(ctx, this.testTenant, this.testLocalCluster,
+        assertEquals(asyncRequests(ctx -> namespaces.getPermissions(ctx, this.testTenant,
                 this.testLocalNamespaces.get(0).getLocalName())),
                 expectedPolicies.auth_policies.getNamespaceAuthentication());
 
-        asyncRequests(ctx -> namespaces.revokePermissionsOnNamespace(ctx, this.testTenant, this.testLocalCluster,
+        asyncRequests(ctx -> namespaces.revokePermissionsOnNamespace(ctx, this.testTenant,
                 this.testLocalNamespaces.get(0).getLocalName(), "my-role"));
         expectedPolicies.auth_policies.getNamespaceAuthentication().remove("my-role");
-        assertEquals(asyncRequests(ctx -> namespaces.getPolicies(ctx, this.testTenant, this.testLocalCluster,
+        assertEquals(asyncRequests(ctx -> namespaces.getPolicies(ctx, this.testTenant,
                 this.testLocalNamespaces.get(0).getLocalName())), expectedPolicies);
-        assertEquals(asyncRequests(ctx -> namespaces.getPermissions(ctx, this.testTenant, this.testLocalCluster,
+        assertEquals(asyncRequests(ctx -> namespaces.getPermissions(ctx, this.testTenant,
                 this.testLocalNamespaces.get(0).getLocalName())),
                 expectedPolicies.auth_policies.getNamespaceAuthentication());
 
         // Non-existing namespaces
         try {
             asyncRequests(ctx -> namespaces.getPolicies(ctx, this.testTenant,
-                    this.testLocalCluster, "non-existing-namespace-1"));
+                    "non-existing-namespace-1"));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
@@ -432,14 +415,14 @@ public void testGrantAndRevokePermissions() throws Exception {
 
         try {
             asyncRequests(ctx -> namespaces.getPermissions(ctx, this.testTenant,
-                    this.testLocalCluster, "non-existing-namespace-1"));
+                    "non-existing-namespace-1"));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
         }
 
         try {
-            asyncRequests(ctx -> namespaces.grantPermissionOnNamespace(ctx, this.testTenant, this.testLocalCluster,
+            asyncRequests(ctx -> namespaces.grantPermissionOnNamespace(ctx, this.testTenant,
                     "non-existing-namespace-1",
                     "my-role", EnumSet.of(AuthAction.produce)));
             fail("should have failed");
@@ -448,7 +431,7 @@ public void testGrantAndRevokePermissions() throws Exception {
         }
 
         try {
-            asyncRequests(ctx -> namespaces.revokePermissionsOnNamespace(ctx, this.testTenant, this.testLocalCluster,
+            asyncRequests(ctx -> namespaces.revokePermissionsOnNamespace(ctx, this.testTenant,
                     "non-existing-namespace-1", "my-role"));
             fail("should have failed");
         } catch (RestException e) {
@@ -467,7 +450,7 @@ public void testGrantAndRevokePermissions() throws Exception {
 
         try {
             asyncRequests(ctx -> namespaces.getPolicies(ctx, testNs.getTenant(),
-                    testNs.getCluster(), testNs.getLocalName()));
+                    testNs.getLocalName()));
             fail("should have failed");
         } catch (RestException e) {
             // Ok
@@ -482,7 +465,7 @@ public void testGrantAndRevokePermissions() throws Exception {
             });
         try {
             asyncRequests(ctx -> namespaces.getPermissions(ctx, testNs.getTenant(),
-                    testNs.getCluster(), testNs.getLocalName()));
+                    testNs.getLocalName()));
             fail("should have failed");
         } catch (RestException e) {
             // Ok
@@ -496,7 +479,7 @@ public void testGrantAndRevokePermissions() throws Exception {
                 return true;
             });
         try {
-            asyncRequests(ctx -> namespaces.grantPermissionOnNamespace(ctx, testNs.getTenant(), testNs.getCluster(),
+            asyncRequests(ctx -> namespaces.grantPermissionOnNamespace(ctx, testNs.getTenant(),
                     testNs.getLocalName(),
                     "other-role", EnumSet.of(AuthAction.consume)));
             fail("should have failed");
@@ -512,7 +495,7 @@ public void testGrantAndRevokePermissions() throws Exception {
                 return true;
             });
         try {
-            asyncRequests(ctx -> namespaces.grantPermissionOnNamespace(ctx, testNs.getTenant(), testNs.getCluster(),
+            asyncRequests(ctx -> namespaces.grantPermissionOnNamespace(ctx, testNs.getTenant(),
                     testNs.getLocalName(),
                     "other-role", EnumSet.of(AuthAction.consume)));
             fail("should have failed");
@@ -528,7 +511,7 @@ public void testGrantAndRevokePermissions() throws Exception {
                 return true;
             });
         try {
-            asyncRequests(ctx -> namespaces.revokePermissionsOnNamespace(ctx, testNs.getTenant(), testNs.getCluster(),
+            asyncRequests(ctx -> namespaces.revokePermissionsOnNamespace(ctx, testNs.getTenant(),
                     testNs.getLocalName(),
                     "other-role"));
             fail("should have failed");
@@ -544,7 +527,7 @@ public void testGrantAndRevokePermissions() throws Exception {
                 return true;
             });
         try {
-            asyncRequests(ctx -> namespaces.revokePermissionsOnNamespace(ctx, testNs.getTenant(), testNs.getCluster(),
+            asyncRequests(ctx -> namespaces.revokePermissionsOnNamespace(ctx, testNs.getTenant(),
                     testNs.getLocalName(),
                     "other-role"));
             fail("should have failed");
@@ -557,23 +540,23 @@ public void testGrantAndRevokePermissions() throws Exception {
     public void testGlobalNamespaceReplicationConfiguration() throws Exception {
 
         Set repCluster = (Set) asyncRequests(rsp -> namespaces.getNamespaceReplicationClusters(rsp,
-                this.testGlobalNamespaces.get(0).getTenant(), this.testGlobalNamespaces.get(0).getCluster(),
+                this.testGlobalNamespaces.get(0).getTenant(),
                 this.testGlobalNamespaces.get(0).getLocalName()));
-        assertEquals(repCluster, new HashSet<>());
+        assertEquals(repCluster, Set.of("use"));
 
         asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp,
-                this.testGlobalNamespaces.get(0).getTenant(), this.testGlobalNamespaces.get(0).getCluster(),
+                this.testGlobalNamespaces.get(0).getTenant(),
                 this.testGlobalNamespaces.get(0).getLocalName(),
                 List.of("use", "usw"), false));
 
         repCluster = (Set) asyncRequests(rsp -> namespaces.getNamespaceReplicationClusters(rsp,
-                this.testGlobalNamespaces.get(0).getTenant(), this.testGlobalNamespaces.get(0).getCluster(),
+                this.testGlobalNamespaces.get(0).getTenant(),
                 this.testGlobalNamespaces.get(0).getLocalName()));
         assertEquals(repCluster, List.of("use", "usw"));
 
         try {
             asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp,
-                    this.testGlobalNamespaces.get(0).getTenant(), this.testGlobalNamespaces.get(0).getCluster(),
+                    this.testGlobalNamespaces.get(0).getTenant(),
                     this.testGlobalNamespaces.get(0).getLocalName(),
                     List.of("use", "invalid-cluster"), false));
             fail("should have failed");
@@ -582,18 +565,7 @@ public void testGlobalNamespaceReplicationConfiguration() throws Exception {
         }
 
         try {
-            asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp,
-                    this.testGlobalNamespaces.get(0).getTenant(), this.testGlobalNamespaces.get(0).getCluster(),
-                    this.testGlobalNamespaces.get(0).getLocalName(),
-                    List.of("use", "global"), false));
-            fail("should have failed");
-        } catch (RestException e) {
-            // Ok, global should not be allowed in the list of replication clusters
-            assertEquals(e.getResponse().getStatus(), Status.PRECONDITION_FAILED.getStatusCode());
-        }
-
-        try {
-            asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp, this.testTenant, "global",
+            asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp, this.testTenant,
                     this.testGlobalNamespaces.get(0).getLocalName(),
                     List.of("use", "invalid-cluster"),  false));
             fail("should have failed");
@@ -602,11 +574,17 @@ public void testGlobalNamespaceReplicationConfiguration() throws Exception {
             assertEquals(e.getResponse().getStatus(), Status.FORBIDDEN.getStatusCode());
         }
 
+        // First remove usw from namespace replication clusters before removing from tenant
+        asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp,
+                this.testGlobalNamespaces.get(0).getTenant(),
+                this.testGlobalNamespaces.get(0).getLocalName(),
+                List.of("use"), false));
+
         admin.tenants().updateTenant(testTenant,
                 new TenantInfoImpl(Set.of("role1", "role2"), Set.of("use", "usc")));
 
         try {
-            asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp, this.testTenant, "global",
+            asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp, this.testTenant,
                     this.testGlobalNamespaces.get(0).getLocalName(), List.of("use", "usw"), false));
             fail("should have failed");
         } catch (RestException e) {
@@ -619,7 +597,7 @@ public void testGlobalNamespaceReplicationConfiguration() throws Exception {
         mockZooKeeperGlobal.setAlwaysFail(Code.SESSIONEXPIRED);
 
         try {
-            asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp, this.testTenant, "global",
+            asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp, this.testTenant,
                     this.testGlobalNamespaces.get(0).getLocalName(), List.of("use"), false));
             fail("should have failed");
         } catch (RestException e) {
@@ -635,13 +613,13 @@ public void testGlobalNamespaceReplicationConfiguration() throws Exception {
 
         mockZooKeeperGlobal.failConditional(Code.SESSIONEXPIRED, (op, path) -> {
                 return op == MockZooKeeper.Op.SET
-                    && path.equals("/admin/policies/my-tenant/global/test-global-ns1");
+                    && path.equals("/admin/policies/my-tenant/test-global-ns1");
             });
 
         policiesCache.invalidateAll();
         store.invalidateAll();
         try {
-            asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp, this.testTenant, "global",
+            asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp, this.testTenant,
                     this.testGlobalNamespaces.get(0).getLocalName(), List.of("use"), false));
             fail("should have failed");
         } catch (RestException e) {
@@ -650,7 +628,7 @@ public void testGlobalNamespaceReplicationConfiguration() throws Exception {
 
         try {
             asyncRequests(rsp -> namespaces.getNamespaceReplicationClusters(rsp, this.testTenant,
-                                                                     "global", "non-existing-ns"));
+                    "non-existing-ns"));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
@@ -658,7 +636,7 @@ public void testGlobalNamespaceReplicationConfiguration() throws Exception {
 
         try {
             asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp, this.testTenant,
-                    "global", "non-existing-ns", List.of("use"), false));
+                    "non-existing-ns", List.of("use"), false));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
@@ -666,7 +644,7 @@ public void testGlobalNamespaceReplicationConfiguration() throws Exception {
 
         mockZooKeeperGlobal.failConditional(Code.SESSIONEXPIRED, (op, path) -> {
                 return op == MockZooKeeper.Op.GET
-                    && path.equals("/admin/policies/my-tenant/global/test-global-ns1");
+                    && path.equals("/admin/policies/my-tenant/test-global-ns1");
             });
 
         policiesCache.invalidateAll();
@@ -674,23 +652,15 @@ public void testGlobalNamespaceReplicationConfiguration() throws Exception {
         // ensure the ZooKeeper read happens, bypassing the cache
         try {
             asyncRequests(rsp -> namespaces.getNamespaceReplicationClusters(rsp,
-                    this.testGlobalNamespaces.get(0).getTenant(), this.testGlobalNamespaces.get(0).getCluster(),
+                    this.testGlobalNamespaces.get(0).getTenant(),
                     this.testGlobalNamespaces.get(0).getLocalName()));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), 500);
         }
 
-        try {
-            asyncRequests(rsp -> namespaces.getNamespaceReplicationClusters(rsp, this.testTenant,
-                    this.testLocalCluster, this.testLocalNamespaces.get(0).getLocalName()));
-            fail("should have failed");
-        } catch (RestException e) {
-            assertEquals(e.getResponse().getStatus(), Status.PRECONDITION_FAILED.getStatusCode());
-        }
-
         // setting the replication clusters for a local namespace to the local cluster should succeed
-        asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp, this.testTenant, this.testLocalCluster,
+        asyncRequests(rsp -> namespaces.setNamespaceReplicationClusters(rsp, this.testTenant,
                 this.testLocalNamespaces.get(0).getLocalName(), List.of(this.testLocalCluster), false));
 
         // cleanup
@@ -704,8 +674,8 @@ public void testGetBundles() throws Exception {
                 .boundaries(boundaries)
                 .numBundles(boundaries.size() - 1)
                 .build();
-        createBundledTestNamespaces(this.testTenant, this.testLocalCluster, "test-bundled-namespace-1", bundle);
-        assertEquals(asyncRequests(ctx -> namespaces.getBundlesData(ctx, testTenant, this.testLocalCluster,
+        createBundledTestNamespaces(this.testTenant, "test-bundled-namespace-1", bundle);
+        assertEquals(asyncRequests(ctx -> namespaces.getBundlesData(ctx, testTenant,
                 "test-bundled-namespace-1")), bundle);
     }
 
@@ -719,24 +689,29 @@ public void testNamespacesApiRedirects() throws Exception {
                 + this.testLocalNamespaces.get(2).toString());
         doReturn(uri).when(uriInfo).getRequestUri();
 
+        // Set the replication cluster to "usc" so that the delete redirects to that cluster
+        admin.namespaces().setNamespaceReplicationClusters(
+                this.testLocalNamespaces.get(2).toString(), Set.of("usc"), false);
+
         // Trick to force redirection
         conf.setAuthorizationEnabled(true);
 
         AsyncResponse response = mock(AsyncResponse.class);
-        namespaces.deleteNamespace(response, this.testTenant, this.testOtherCluster,
+        namespaces.deleteNamespace(response, this.testTenant,
                 this.testLocalNamespaces.get(2).getLocalName(), false, false);
         ArgumentCaptor captor = ArgumentCaptor.forClass(WebApplicationException.class);
         verify(response, timeout(5000).times(1)).resume(captor.capture());
         assertEquals(captor.getValue().getResponse().getStatus(), Status.TEMPORARY_REDIRECT.getStatusCode());
         assertEquals(captor.getValue().getResponse().getLocation().toString(),
-                UriBuilder.fromUri(uri).host("127.0.0.3").port(8083).toString());
+                UriBuilder.fromUri(uri).host("127.0.0.3").port(8083)
+                        .replaceQueryParam("authoritative", false).toString());
 
         uri = URI.create(pulsar.getWebServiceAddress() + "/admin/namespace/"
                 + this.testLocalNamespaces.get(2).toString() + "/unload");
         doReturn(uri).when(uriInfo).getRequestUri();
 
         response = mock(AsyncResponse.class);
-        namespaces.unloadNamespaceBundle(response, this.testTenant, this.testOtherCluster,
+        namespaces.unloadNamespaceBundle(response, this.testTenant,
                 this.testLocalNamespaces.get(2).getLocalName(), "0x00000000_0xffffffff", false, null);
         captor = ArgumentCaptor.forClass(WebApplicationException.class);
         verify(response, timeout(5000).atLeast(1)).resume(captor.capture());
@@ -746,7 +721,7 @@ public void testNamespacesApiRedirects() throws Exception {
 
         // check the bundle should not unload to an inactive destination broker
         response = mock(AsyncResponse.class);
-        namespaces.unloadNamespaceBundle(response, this.testTenant, this.testOtherCluster,
+        namespaces.unloadNamespaceBundle(response, this.testTenant,
                 this.testLocalNamespaces.get(2).getLocalName(), "0x00000000_0xffffffff",
                 false, "inactive_destination:8080");
         captor = ArgumentCaptor.forClass(WebApplicationException.class);
@@ -776,7 +751,7 @@ public boolean matches(NamespaceName nsname) {
 
         response = mock(AsyncResponse.class);
         namespaces.deleteNamespace(response, this.testLocalNamespaces.get(2).getTenant(),
-                this.testLocalNamespaces.get(2).getCluster(), this.testLocalNamespaces.get(2).getLocalName(),
+                this.testLocalNamespaces.get(2).getLocalName(),
                 false, false);
         captor = ArgumentCaptor.forClass(WebApplicationException.class);
         verify(response, timeout(5000).times(1)).resume(captor.capture());
@@ -791,7 +766,7 @@ public boolean matches(NamespaceName nsname) {
     @Test
     public void testDeleteNamespaces() throws Exception {
         AsyncResponse response = mock(AsyncResponse.class);
-        namespaces.deleteNamespace(response, this.testTenant, this.testLocalCluster,
+        namespaces.deleteNamespace(response, this.testTenant,
                 "non-existing-namespace-1", false, false);
         ArgumentCaptor errorCaptor = ArgumentCaptor.forClass(RestException.class);
         verify(response, timeout(5000).times(1)).resume(errorCaptor.capture());
@@ -810,7 +785,7 @@ public void testDeleteNamespaces() throws Exception {
         doReturn(true).when(nsSvc).isServiceUnitOwned(testNs);
 
         response = mock(AsyncResponse.class);
-        namespaces.deleteNamespace(response, testNs.getTenant(), testNs.getCluster(),
+        namespaces.deleteNamespace(response, testNs.getTenant(),
                 testNs.getLocalName(), false, false);
         errorCaptor = ArgumentCaptor.forClass(RestException.class);
         // Ok, namespace not empty
@@ -825,7 +800,7 @@ public void testDeleteNamespaces() throws Exception {
                 new byte[0], null, null);
 
         response = mock(AsyncResponse.class);
-        namespaces.deleteNamespace(response, testNs.getTenant(), testNs.getCluster(),
+        namespaces.deleteNamespace(response, testNs.getTenant(),
                 testNs.getLocalName(), false, false);
         errorCaptor = ArgumentCaptor.forClass(RestException.class);
         // Ok, namespace not empty
@@ -839,7 +814,7 @@ public void testDeleteNamespaces() throws Exception {
         doReturn(Optional.of(localWebServiceUrl)).when(nsSvc).getWebServiceUrl(testNs, options);
         doReturn(true).when(nsSvc).isServiceUnitOwned(testNs);
         response = mock(AsyncResponse.class);
-        namespaces.deleteNamespace(response, testNs.getTenant(), testNs.getCluster(),
+        namespaces.deleteNamespace(response, testNs.getTenant(),
                 testNs.getLocalName(), false, false);
         ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(Response.class);
         verify(response, timeout(5000).times(1)).resume(responseCaptor.capture());
@@ -850,7 +825,7 @@ public void testDeleteNamespaces() throws Exception {
         doReturn(Optional.of(localWebServiceUrl)).when(nsSvc).getWebServiceUrl(testNs, options);
         doReturn(true).when(nsSvc).isServiceUnitOwned(testNs);
         response = mock(AsyncResponse.class);
-        namespaces.deleteNamespace(response, testNs.getTenant(), testNs.getCluster(),
+        namespaces.deleteNamespace(response, testNs.getTenant(),
                 testNs.getLocalName(), false, false);
         responseCaptor = ArgumentCaptor.forClass(Response.class);
         verify(response, timeout(5000).times(1)).resume(responseCaptor.capture());
@@ -867,7 +842,7 @@ public void testDeleteNamespaces() throws Exception {
         doReturn(Optional.of(localWebServiceUrl)).when(nsSvc).getWebServiceUrl(testNs, options);
         doReturn(true).when(nsSvc).isServiceUnitOwned(testNs);
         response = mock(AsyncResponse.class);
-        namespaces.deleteNamespace(response, testNs.getTenant(), testNs.getCluster(),
+        namespaces.deleteNamespace(response, testNs.getTenant(),
                 testNs.getLocalName(), false, false);
         responseCaptor = ArgumentCaptor.forClass(Response.class);
         verify(response, timeout(5000).times(1)).resume(responseCaptor.capture());
@@ -889,8 +864,8 @@ public void testDeleteNamespaceWithBundles() throws Exception {
                 .boundaries(boundaries)
                 .numBundles(boundaries.size() - 1)
                 .build();
-        createBundledTestNamespaces(this.testTenant, this.testLocalCluster, bundledNsLocal, bundleData);
-        final NamespaceName testNs = NamespaceName.get(this.testTenant, this.testLocalCluster, bundledNsLocal);
+        createBundledTestNamespaces(this.testTenant, bundledNsLocal, bundleData);
+        final NamespaceName testNs = NamespaceName.get(this.testTenant, bundledNsLocal);
 
         org.apache.pulsar.client.admin.Namespaces namespacesAdmin = mock(
                 org.apache.pulsar.client.admin.Namespaces.class);
@@ -915,7 +890,7 @@ public void testDeleteNamespaceWithBundles() throws Exception {
 
         AsyncResponse response = mock(AsyncResponse.class);
         ArgumentCaptor captor = ArgumentCaptor.forClass(WebApplicationException.class);
-        namespaces.deleteNamespaceBundle(response, testTenant, testLocalCluster, bundledNsLocal,
+        namespaces.deleteNamespaceBundle(response, testTenant, bundledNsLocal,
                 "0x00000000_0x80000000", false, false);
         verify(response, timeout(5000).times(1)).resume(captor.capture());
         assertEquals(captor.getValue().getResponse().getStatus(), Status.TEMPORARY_REDIRECT.getStatusCode());
@@ -923,7 +898,7 @@ public void testDeleteNamespaceWithBundles() throws Exception {
         doReturn(CompletableFuture.completedFuture(Optional.empty())).when(nsSvc)
                 .getWebServiceUrlAsync(any(NamespaceBundle.class), any(LookupOptions.class));
         response = mock(AsyncResponse.class);
-        namespaces.deleteNamespace(response, testTenant, testLocalCluster, bundledNsLocal, false, false);
+        namespaces.deleteNamespace(response, testTenant, bundledNsLocal, false, false);
         verify(response, timeout(5000).times(1)).resume(captor.capture());
         assertEquals(captor.getValue().getResponse().getStatus(), Status.PRECONDITION_FAILED.getStatusCode());
         // make one bundle owned
@@ -934,10 +909,10 @@ public void testDeleteNamespaceWithBundles() throws Exception {
         doReturn(CompletableFuture.completedFuture(true)).when(nsSvc)
                 .isServiceUnitOwnedAsync(nsBundles.getBundles().get(0));
         doReturn(CompletableFuture.completedFuture(null)).when(namespacesAdmin).deleteNamespaceBundleAsync(
-                testTenant + "/" + testLocalCluster + "/" + bundledNsLocal, "0x00000000_0x80000000",
+                testTenant + "/" + bundledNsLocal, "0x00000000_0x80000000",
                 false);
         response = mock(AsyncResponse.class);
-        namespaces.deleteNamespaceBundle(response, testTenant, testLocalCluster, bundledNsLocal,
+        namespaces.deleteNamespaceBundle(response, testTenant, bundledNsLocal,
                 "0x80000000_0xffffffff",  false, false);
         verify(response, timeout(5000).times(1)).resume(captor.capture());
         assertEquals(captor.getValue().getResponse().getStatus(), Status.PRECONDITION_FAILED.getStatusCode());
@@ -947,7 +922,7 @@ public void testDeleteNamespaceWithBundles() throws Exception {
         for (NamespaceBundle bundle : nsBundles.getBundles()) {
             doReturn(CompletableFuture.completedFuture(true)).when(nsSvc).isServiceUnitOwnedAsync(bundle);
         }
-        namespaces.deleteNamespace(response, testTenant, testLocalCluster, bundledNsLocal, false, false);
+        namespaces.deleteNamespace(response, testTenant, bundledNsLocal, false, false);
         ArgumentCaptor captor2 = ArgumentCaptor.forClass(Response.class);
         verify(response, timeout(5000).times(1)).resume(captor2.capture());
         assertEquals(captor2.getValue().getStatus(), Status.NO_CONTENT.getStatusCode());
@@ -969,7 +944,7 @@ public void testUnloadNamespaces() throws Exception {
 
         // The namespace unload should succeed on all the bundles
         AsyncResponse response = mock(AsyncResponse.class);
-        namespaces.unloadNamespace(response, testNs.getTenant(), testNs.getCluster(), testNs.getLocalName());
+        namespaces.unloadNamespace(response, testNs.getTenant(), testNs.getLocalName());
         ArgumentCaptor captor = ArgumentCaptor.forClass(Response.class);
         verify(response, timeout(5000).times(1)).resume(captor.capture());
         assertEquals(captor.getValue().getStatus(), Status.NO_CONTENT.getStatusCode());
@@ -987,8 +962,8 @@ public void testSplitBundles() throws Exception {
                 .boundaries(boundaries)
                 .numBundles(boundaries.size() - 1)
                 .build();
-        createBundledTestNamespaces(this.testTenant, this.testLocalCluster, bundledNsLocal, bundleData);
-        final NamespaceName testNs = NamespaceName.get(this.testTenant, this.testLocalCluster, bundledNsLocal);
+        createBundledTestNamespaces(this.testTenant, bundledNsLocal, bundleData);
+        final NamespaceName testNs = NamespaceName.get(this.testTenant, bundledNsLocal);
 
         OwnershipCache mockOwnershipCache = spy(pulsar.getNamespaceService().getOwnershipCache());
         doReturn(CompletableFuture.completedFuture(null)).when(mockOwnershipCache)
@@ -1001,14 +976,14 @@ public void testSplitBundles() throws Exception {
         // split bundles
         try {
             AsyncResponse response = mock(AsyncResponse.class);
-            namespaces.splitNamespaceBundle(response, testTenant, testLocalCluster, bundledNsLocal,
+            namespaces.splitNamespaceBundle(response, testTenant, bundledNsLocal,
                     "0x00000000_0xffffffff",
                     false, true, null, null);
             ArgumentCaptor captor = ArgumentCaptor.forClass(Response.class);
             verify(response, timeout(5000).times(1)).resume(captor.capture());
             // verify split bundles
             BundlesData bundlesData = (BundlesData) asyncRequests(ctx -> namespaces.getBundlesData(ctx, testTenant,
-                    testLocalCluster, bundledNsLocal));
+                    bundledNsLocal));
             assertNotNull(bundlesData);
             assertEquals(bundlesData.getBoundaries().size(), 3);
             assertEquals(bundlesData.getBoundaries().get(0), "0x00000000");
@@ -1031,8 +1006,8 @@ public void testSplitBundleWithUnDividedRange() throws Exception {
                 .boundaries(boundaries)
                 .numBundles(boundaries.size() - 1)
                 .build();
-        createBundledTestNamespaces(this.testTenant, this.testLocalCluster, bundledNsLocal, bundleData);
-        final NamespaceName testNs = NamespaceName.get(this.testTenant, this.testLocalCluster, bundledNsLocal);
+        createBundledTestNamespaces(this.testTenant, bundledNsLocal, bundleData);
+        final NamespaceName testNs = NamespaceName.get(this.testTenant, bundledNsLocal);
 
         OwnershipCache mockOwnershipCache = spy(pulsar.getNamespaceService().getOwnershipCache());
         doReturn(CompletableFuture.completedFuture(null)).when(mockOwnershipCache)
@@ -1044,7 +1019,7 @@ public void testSplitBundleWithUnDividedRange() throws Exception {
 
         // split bundles
         AsyncResponse response = mock(AsyncResponse.class);
-        namespaces.splitNamespaceBundle(response, testTenant, testLocalCluster, bundledNsLocal,
+        namespaces.splitNamespaceBundle(response, testTenant, bundledNsLocal,
                 "0x08375b1a_0x08375b1b", false, false, null, null);
         ArgumentCaptor captor = ArgumentCaptor.forClass(Response.class);
         verify(response, timeout(5000).times(1)).resume(any(RestException.class));
@@ -1062,8 +1037,8 @@ public void testUnloadNamespaceWithBundles() throws Exception {
                 .boundaries(boundaries)
                 .numBundles(boundaries.size() - 1)
                 .build();
-        createBundledTestNamespaces(this.testTenant, this.testLocalCluster, bundledNsLocal, bundleData);
-        final NamespaceName testNs = NamespaceName.get(this.testTenant, this.testLocalCluster, bundledNsLocal);
+        createBundledTestNamespaces(this.testTenant, bundledNsLocal, bundleData);
+        final NamespaceName testNs = NamespaceName.get(this.testTenant, bundledNsLocal);
 
         doReturn(CompletableFuture.completedFuture(Optional.of(localWebServiceUrl))).when(nsSvc)
                 .getWebServiceUrlAsync(Mockito.argThat(bundle -> bundle.getNamespaceObject().equals(testNs)),
@@ -1081,7 +1056,7 @@ public void testUnloadNamespaceWithBundles() throws Exception {
         doReturn(true).when(nsSvc).isServiceUnitOwned(testBundle);
         doReturn(CompletableFuture.completedFuture(null)).when(nsSvc).unloadNamespaceBundle(testBundle);
         AsyncResponse response = mock(AsyncResponse.class);
-        namespaces.unloadNamespaceBundle(response, testTenant, testLocalCluster, bundledNsLocal,
+        namespaces.unloadNamespaceBundle(response, testTenant, bundledNsLocal,
                 "0x00000000_0x80000000",
                 false, null);
         verify(response, timeout(5000).times(1)).resume(any(RestException.class));
@@ -1090,19 +1065,25 @@ public void testUnloadNamespaceWithBundles() throws Exception {
         resetBroker();
     }
 
-    private void createBundledTestNamespaces(String property, String cluster, String namespace, BundlesData bundle)
+    private void createBundledTestNamespaces(String tenant, String namespace, BundlesData bundle)
             throws Exception {
-        asyncRequests(ctx -> namespaces.createNamespace(ctx, property, cluster, namespace, bundle));
+        Policies policies = new Policies();
+        policies.bundles = bundle;
+        asyncRequests(ctx -> namespaces.createNamespace(ctx, tenant, namespace, policies));
     }
 
-    private void createGlobalTestNamespaces(String property, String namespace, BundlesData bundle) throws Exception {
-        asyncRequests(ctx -> namespaces.createNamespace(ctx, property, "global", namespace, bundle));
+    private void createGlobalTestNamespaces(String tenant, String namespace, BundlesData bundle) throws Exception {
+        Policies policies = new Policies();
+        policies.bundles = bundle;
+        asyncRequests(ctx -> namespaces.createNamespace(ctx, tenant, namespace, policies));
     }
 
     private void createTestNamespaces(List nsnames, BundlesData bundle) throws Exception {
         for (NamespaceName nsName : nsnames) {
+            Policies policies = new Policies();
+            policies.bundles = bundle;
             asyncRequests(ctx -> namespaces.createNamespace(ctx, nsName.getTenant(),
-                    nsName.getCluster(), nsName.getLocalName(), bundle));
+                    nsName.getLocalName(), policies));
         }
     }
 
@@ -1132,8 +1113,8 @@ public void testRetention() throws Exception {
                     .boundaries(boundaries)
                     .numBundles(boundaries.size() - 1)
                     .build();
-            createBundledTestNamespaces(this.testTenant, this.testLocalCluster, bundledNsLocal, bundleData);
-            final NamespaceName testNs = NamespaceName.get(this.testTenant, this.testLocalCluster, bundledNsLocal);
+            createBundledTestNamespaces(this.testTenant, bundledNsLocal, bundleData);
+            final NamespaceName testNs = NamespaceName.get(this.testTenant, bundledNsLocal);
             mockWebUrl(localWebServiceUrl, testNs);
 
             OwnershipCache mockOwnershipCache = spy(pulsar.getNamespaceService().getOwnershipCache());
@@ -1143,9 +1124,9 @@ public void testRetention() throws Exception {
             ownership.setAccessible(true);
             ownership.set(pulsar.getNamespaceService(), mockOwnershipCache);
             RetentionPolicies retention = new RetentionPolicies(10, 10);
-            namespaces.setRetention(this.testTenant, this.testLocalCluster, bundledNsLocal, retention);
+            namespaces.setRetention(this.testTenant, bundledNsLocal, retention);
             AsyncResponse response = mock(AsyncResponse.class);
-            namespaces.getRetention(response, this.testTenant, this.testLocalCluster, bundledNsLocal);
+            namespaces.getRetention(response, this.testTenant, bundledNsLocal);
             ArgumentCaptor captor = ArgumentCaptor.forClass(RetentionPolicies.class);
             verify(response, timeout(5000).times(1)).resume(captor.capture());
             RetentionPolicies retention2 = captor.getValue();
@@ -1163,7 +1144,7 @@ public void testRetentionUnauthorized() throws Exception {
         try {
             NamespaceName testNs = this.testLocalNamespaces.get(3);
             RetentionPolicies retention = new RetentionPolicies(10, 10);
-            namespaces.setRetention(testNs.getTenant(), testNs.getCluster(), testNs.getLocalName(), retention);
+            namespaces.setRetention(testNs.getTenant(), testNs.getLocalName(), retention);
             fail("Should fail");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.UNAUTHORIZED.getStatusCode());
@@ -1175,13 +1156,13 @@ public void testPersistence() throws Exception {
         NamespaceName testNs = this.testLocalNamespaces.get(0);
         PersistencePolicies persistence1 = new PersistencePolicies(3, 2, 1, 0.0);
         AsyncResponse response = mock(AsyncResponse.class);
-        namespaces.setPersistence(response, testNs.getTenant(), testNs.getCluster(),
+        namespaces.setPersistence(response, testNs.getTenant(),
                 testNs.getLocalName(), persistence1);
         ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(Response.class);
         verify(response, timeout(5000).times(1)).resume(responseCaptor.capture());
         assertEquals(responseCaptor.getValue().getStatus(), Response.Status.NO_CONTENT.getStatusCode());
         response = mock(AsyncResponse.class);
-        namespaces.getPersistence(response, testNs.getTenant(), testNs.getCluster(), testNs.getLocalName());
+        namespaces.getPersistence(response, testNs.getTenant(), testNs.getLocalName());
         ArgumentCaptor captor = ArgumentCaptor.forClass(PersistencePolicies.class);
         verify(response, timeout(5000).times(1)).resume(captor.capture());
         PersistencePolicies persistence2 =  captor.getValue();
@@ -1193,7 +1174,7 @@ public void testSetIncorrectPersistentPolicies(int ensembleSize, int writeQuorum
         NamespaceName testNs = this.testLocalNamespaces.get(0);
         PersistencePolicies persistence1 = new PersistencePolicies(ensembleSize, writeQuorum, ackQuorum, 0.0);
         AsyncResponse response = mock(AsyncResponse.class);
-        namespaces.setPersistence(response, testNs.getTenant(), testNs.getCluster(),
+        namespaces.setPersistence(response, testNs.getTenant(),
                 testNs.getLocalName(), persistence1);
         ArgumentCaptor responseCaptor = ArgumentCaptor.forClass(RestException.class);
         verify(response, timeout(5000).times(1)).resume(responseCaptor.capture());
@@ -1205,7 +1186,7 @@ public void testPersistenceUnauthorized() throws Exception {
         NamespaceName testNs = this.testLocalNamespaces.get(3);
         PersistencePolicies persistence = new PersistencePolicies(3, 2, 1, 0.0);
         AsyncResponse response = mock(AsyncResponse.class);
-        namespaces.setPersistence(response, testNs.getTenant(), testNs.getCluster(),
+        namespaces.setPersistence(response, testNs.getTenant(),
                 testNs.getLocalName(), persistence);
         ArgumentCaptor errorCaptor = ArgumentCaptor.forClass(RestException.class);
         verify(response, timeout(5000).times(1)).resume(errorCaptor.capture());
@@ -1221,8 +1202,8 @@ public void testValidateTopicOwnership() throws Exception {
                 .boundaries(boundaries)
                 .numBundles(boundaries.size() - 1)
                 .build();
-        createBundledTestNamespaces(this.testTenant, this.testLocalCluster, bundledNsLocal, bundleData);
-        final NamespaceName testNs = NamespaceName.get(this.testTenant, this.testLocalCluster, bundledNsLocal);
+        createBundledTestNamespaces(this.testTenant, bundledNsLocal, bundleData);
+        final NamespaceName testNs = NamespaceName.get(this.testTenant, bundledNsLocal);
         OwnershipCache mockOwnershipCache = spy(pulsar.getNamespaceService().getOwnershipCache());
         doReturn(CompletableFuture.completedFuture(null)).when(mockOwnershipCache)
                 .disableOwnership(any(NamespaceBundle.class));
@@ -1240,7 +1221,7 @@ public void testValidateTopicOwnership() throws Exception {
         mockWebUrl(localWebServiceUrl, testNs);
         doReturn("persistent").when(topics).domain();
 
-        topics.validateTopicName(topicName.getTenant(), topicName.getCluster(),
+        topics.validateTopicName(topicName.getTenant(),
                 topicName.getNamespacePortion(), topicName.getEncodedLocalName());
         topics.validateAdminOperationOnTopic(false);
 
@@ -1261,7 +1242,7 @@ public void testIsLeader() throws Exception {
     @Test
     public void testDeleteNamespace() throws Exception {
 
-        final String namespace = this.testTenant + "/use/deleteNs";
+        final String namespace = this.testTenant + "/deleteNs";
         admin.namespaces().createNamespace(namespace, 100);
         assertEquals(admin.namespaces().getPolicies(namespace).bundles.getNumBundles(), 100);
 
@@ -1491,26 +1472,26 @@ public void testOperationNamespaceMessageTTL() throws Exception {
         resetBroker();
         String namespace = "ttlnamespace";
 
-        asyncRequests(response -> namespaces.createNamespace(response, this.testTenant, this.testLocalCluster,
-                namespace, BundlesData.builder().build()));
+        asyncRequests(response -> namespaces.createNamespace(response, this.testTenant,
+                namespace, (Policies) null));
 
-        asyncRequests(response -> namespaces.setNamespaceMessageTTL(response, this.testTenant, this.testLocalCluster,
+        asyncRequests(response -> namespaces.setNamespaceMessageTTL(response, this.testTenant,
                 namespace, 100));
 
         int namespaceMessageTTL = (Integer) asyncRequests(response -> namespaces
-                .getNamespaceMessageTTL(response, this.testTenant, this.testLocalCluster,
+                .getNamespaceMessageTTL(response, this.testTenant,
                 namespace));
         assertEquals(100, namespaceMessageTTL);
 
         asyncRequests(response -> namespaces.removeNamespaceMessageTTL(response,
-                this.testTenant, this.testLocalCluster, namespace));
+                this.testTenant, namespace));
         assertNull(asyncRequests(response -> namespaces.getNamespaceMessageTTL(response,
-                this.testTenant, this.testLocalCluster,
+                this.testTenant,
                 namespace)));
 
         try {
             asyncRequests(response -> namespaces.setNamespaceMessageTTL(response,
-                    this.testTenant, this.testLocalCluster,
+                    this.testTenant,
                     namespace, -1));
             fail("should have failed");
         } catch (RestException e) {
@@ -1866,23 +1847,23 @@ public void testOptionsAutoTopicCreation() throws Exception {
                 AutoTopicCreationOverride.builder().allowAutoTopicCreation(true).topicType("partitioned")
                         .defaultNumPartitions(4).build();
         try {
-            asyncRequests(response -> namespaces.setAutoTopicCreation(response, this.testTenant, this.testLocalCluster,
+            asyncRequests(response -> namespaces.setAutoTopicCreation(response, this.testTenant,
                     namespace, autoTopicCreationOverride));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
         }
 
-        asyncRequests(response -> namespaces.createNamespace(response, this.testTenant, this.testLocalCluster,
-                namespace, BundlesData.builder().build()));
+        asyncRequests(response -> namespaces.createNamespace(response, this.testTenant,
+                namespace, (Policies) null));
 
         // 1. set auto topic creation
-        asyncRequests(response -> namespaces.setAutoTopicCreation(response, this.testTenant, this.testLocalCluster,
+        asyncRequests(response -> namespaces.setAutoTopicCreation(response, this.testTenant,
                 namespace, autoTopicCreationOverride));
 
         // 2. assert get auto topic creation
         AutoTopicCreationOverride autoTopicCreationOverrideRsp = (AutoTopicCreationOverride) asyncRequests(
-                response -> namespaces.getAutoTopicCreation(response, this.testTenant, this.testLocalCluster,
+                response -> namespaces.getAutoTopicCreation(response, this.testTenant,
                         namespace));
         assertEquals(autoTopicCreationOverride.getTopicType(), autoTopicCreationOverrideRsp.getTopicType());
         assertEquals(autoTopicCreationOverride.getDefaultNumPartitions(),
@@ -1891,9 +1872,9 @@ public void testOptionsAutoTopicCreation() throws Exception {
                                           autoTopicCreationOverrideRsp.isAllowAutoTopicCreation());
         // 2. remove auto topic creation and assert get null
         asyncRequests(response -> namespaces.removeAutoTopicCreation(response, this.testTenant,
-                this.testLocalCluster, namespace));
+                namespace));
         assertNull(asyncRequests(
-                response -> namespaces.getAutoTopicCreation(response, this.testTenant, this.testLocalCluster,
+                response -> namespaces.getAutoTopicCreation(response, this.testTenant,
                         namespace)));
     }
 
@@ -2093,32 +2074,32 @@ public void testOperationSubscriptionDispatchRate() throws Exception {
         String namespace = "sub-dispatchrate-namespace";
 
         // 0. create subscription dispatch rate test namespace
-        asyncRequests(response -> namespaces.createNamespace(response, this.testTenant, this.testLocalCluster,
-                namespace, BundlesData.builder().build()));
+        asyncRequests(response -> namespaces.createNamespace(response, this.testTenant,
+                namespace, (Policies) null));
 
         // 1. set subscription dispatch
         asyncRequests(response -> namespaces.setSubscriptionDispatchRate(response,
-                this.testTenant, this.testLocalCluster,
+                this.testTenant,
                 namespace, DispatchRateImpl.builder().build()));
 
         // 2. check subscription dispatch
         DispatchRate dispatchRate = (DispatchRate) asyncRequests(
                 response -> namespaces.getSubscriptionDispatchRate(response,
-                        this.testTenant, this.testLocalCluster, namespace));
+                        this.testTenant, namespace));
         assertNotNull(dispatchRate);
         assertEquals(-1, dispatchRate.getDispatchThrottlingRateInMsg());
 
         // 3. delete & check subscription dispatch
         asyncRequests(response -> namespaces.deleteSubscriptionDispatchRate(response,
-                this.testTenant, this.testLocalCluster, namespace));
+                this.testTenant, namespace));
         assertNull(asyncRequests(response -> namespaces.getSubscriptionDispatchRate(response,
-                this.testTenant, this.testLocalCluster,
+                this.testTenant,
                 namespace)));
 
         // 4. exception check
         try {
             asyncRequests(response -> namespaces.setSubscriptionDispatchRate(response,
-                    this.testTenant, this.testLocalCluster, "testNamespace", null));
+                    this.testTenant, "testNamespace", null));
             fail("should have failed");
         } catch (RestException e) {
             assertEquals(e.getResponse().getStatus(), Status.NOT_FOUND.getStatusCode());
@@ -2240,9 +2221,10 @@ public void testDeleteTopicPolicyWhenDeleteSystemTopic() throws Exception {
     @Test
     public void testCreateNamespacesWithPolicy() throws Exception {
         try {
+            Policies policies = new Policies();
+            policies.replication_clusters = Set.of("other-colo");
             asyncRequests(response -> namespaces.createNamespace(response, this.testTenant,
-                    "other-colo", "my-namespace",
-                    new Policies()));
+                    "my-namespace", policies));
             fail("should have failed");
         } catch (RestException e) {
             // Ok, cluster doesn't exist
@@ -2250,13 +2232,13 @@ public void testCreateNamespacesWithPolicy() throws Exception {
         }
 
         List nsnames = new ArrayList<>();
-        nsnames.add(NamespaceName.get(this.testTenant, "use", "create-namespace-1"));
-        nsnames.add(NamespaceName.get(this.testTenant, "use", "create-namespace-2"));
-        nsnames.add(NamespaceName.get(this.testTenant, "usc", "create-other-namespace-1"));
-        createTestNamespaces(nsnames, BundlesData.builder().build());
+        nsnames.add(NamespaceName.get(this.testTenant, "create-namespace-1"));
+        nsnames.add(NamespaceName.get(this.testTenant, "create-namespace-2"));
+        nsnames.add(NamespaceName.get(this.testTenant, "create-other-namespace-1"));
+        createTestNamespacesWithPolicies(nsnames, new Policies());
 
         try {
-            asyncRequests(response -> namespaces.createNamespace(response, this.testTenant, "use", "create-namespace-1",
+            asyncRequests(response -> namespaces.createNamespace(response, this.testTenant, "create-namespace-1",
                     new Policies()));
             fail("should have failed");
         } catch (RestException e) {
@@ -2267,7 +2249,7 @@ public void testCreateNamespacesWithPolicy() throws Exception {
 
         try {
             asyncRequests(response -> namespaces.createNamespace(response, "non-existing-tenant",
-                    "use", "create-namespace-1",
+                    "create-namespace-1",
                     new Policies()));
             fail("should have failed");
         } catch (RestException e) {
@@ -2276,7 +2258,7 @@ public void testCreateNamespacesWithPolicy() throws Exception {
         }
 
         try {
-            asyncRequests(response -> namespaces.createNamespace(response, this.testTenant, "use", "create-namespace-#",
+            asyncRequests(response -> namespaces.createNamespace(response, this.testTenant, "create-namespace-#",
                     new Policies()));
             fail("should have failed");
         } catch (RestException e) {
@@ -2286,11 +2268,11 @@ public void testCreateNamespacesWithPolicy() throws Exception {
 
         mockZooKeeperGlobal.failConditional(Code.SESSIONEXPIRED, (op, path) -> {
             return op == MockZooKeeper.Op.CREATE
-                    && path.equals("/admin/policies/my-tenant/use/my-namespace-3");
+                    && path.equals("/admin/policies/my-tenant/my-namespace-3");
         });
         try {
             asyncRequests(response -> namespaces.createNamespace(response, this.testTenant,
-                    "use", "my-namespace-3", new Policies()));
+                    "my-namespace-3", new Policies()));
             fail("should have failed");
         } catch (RestException e) {
             // Ok
@@ -2298,10 +2280,10 @@ public void testCreateNamespacesWithPolicy() throws Exception {
         }
     }
 
-    private void createTestNamespaces(List nsnames, Policies policies) throws Exception {
+    private void createTestNamespacesWithPolicies(List nsnames, Policies policies) throws Exception {
         for (NamespaceName nsName : nsnames) {
             asyncRequests(ctx -> namespaces.createNamespace(ctx, nsName.getTenant(),
-                    nsName.getCluster(), nsName.getLocalName(), policies));
+                    nsName.getLocalName(), policies));
         }
     }
 
@@ -2470,7 +2452,7 @@ public void testSetAndDeleteBookieAffinityGroup() throws Exception {
         // 1. create namespace with empty policies
         String setBookieAffinityGroupNs = "test-set-bookie-affinity-group-ns";
         asyncRequests(
-                response -> namespaces.createNamespace(response, testTenant, testLocalCluster, setBookieAffinityGroupNs,
+                response -> namespaces.createNamespace(response, testTenant, setBookieAffinityGroupNs,
                         (Policies) null));
 
         // 2.set bookie affinity group
@@ -2479,22 +2461,22 @@ public void testSetAndDeleteBookieAffinityGroup() throws Exception {
         BookieAffinityGroupData bookieAffinityGroupDataReq =
                 BookieAffinityGroupData.builder().bookkeeperAffinityGroupPrimary(primaryAffinityGroup)
                         .bookkeeperAffinityGroupSecondary(secondaryAffinityGroup).build();
-        asyncRequests(response -> namespaces.setBookieAffinityGroup(response, testTenant, testLocalCluster,
+        asyncRequests(response -> namespaces.setBookieAffinityGroup(response, testTenant,
                 setBookieAffinityGroupNs, bookieAffinityGroupDataReq));
 
         // 3.assert namespace bookie affinity group
         BookieAffinityGroupData bookieAffinityGroupDataResp = (BookieAffinityGroupData) asyncRequests(
-                response -> namespaces.getBookieAffinityGroup(response, testTenant, testLocalCluster,
+                response -> namespaces.getBookieAffinityGroup(response, testTenant,
                         setBookieAffinityGroupNs));
         assertEquals(bookieAffinityGroupDataResp, bookieAffinityGroupDataReq);
 
         // 4.delete bookie affinity group
-        asyncRequests(response -> namespaces.deleteBookieAffinityGroup(response, testTenant, testLocalCluster,
+        asyncRequests(response -> namespaces.deleteBookieAffinityGroup(response, testTenant,
                 setBookieAffinityGroupNs));
 
         // 5.assert namespace bookie affinity group
         bookieAffinityGroupDataResp = (BookieAffinityGroupData) asyncRequests(
-                response -> namespaces.getBookieAffinityGroup(response, testTenant, testLocalCluster,
+                response -> namespaces.getBookieAffinityGroup(response, testTenant,
                         setBookieAffinityGroupNs));
         assertNull(bookieAffinityGroupDataResp);
     }
@@ -2503,31 +2485,31 @@ public void testSetAndDeleteBookieAffinityGroup() throws Exception {
     public void testSetAndDeleteNamespaceAntiAffinityGroup() throws Exception {
         // 1. create namespace with empty policies, namespace anti affinity group should be null
         String setNamespaceAntiAffinityGroupNs = "test-set-namespace-anti-affinity-group-ns";
-        asyncRequests(response -> namespaces.createNamespace(response, testTenant, testLocalCluster,
+        asyncRequests(response -> namespaces.createNamespace(response, testTenant,
                 setNamespaceAntiAffinityGroupNs, (Policies) null));
         String namespaceAntiAffinityGroupResp = (String) asyncRequests(
-                response -> namespaces.getNamespaceAntiAffinityGroup(response, testTenant, testLocalCluster,
+                response -> namespaces.getNamespaceAntiAffinityGroup(response, testTenant,
                         setNamespaceAntiAffinityGroupNs));
         assertNull(namespaceAntiAffinityGroupResp);
 
         // 2.set namespace anti affinity group
         String namespaceAntiAffinityGroupReq = "namespace-anti-affinity-group";
-        asyncRequests(response -> namespaces.setNamespaceAntiAffinityGroup(response, testTenant, testLocalCluster,
+        asyncRequests(response -> namespaces.setNamespaceAntiAffinityGroup(response, testTenant,
                 setNamespaceAntiAffinityGroupNs, namespaceAntiAffinityGroupReq));
 
         // 3.assert namespace anti affinity group
         namespaceAntiAffinityGroupResp = (String) asyncRequests(
-                response -> namespaces.getNamespaceAntiAffinityGroup(response, testTenant, testLocalCluster,
+                response -> namespaces.getNamespaceAntiAffinityGroup(response, testTenant,
                         setNamespaceAntiAffinityGroupNs));
         assertEquals(namespaceAntiAffinityGroupResp, namespaceAntiAffinityGroupReq);
 
         // 4.delete namespace anti affinity group
-        asyncRequests(response -> namespaces.removeNamespaceAntiAffinityGroup(response, testTenant, testLocalCluster,
+        asyncRequests(response -> namespaces.removeNamespaceAntiAffinityGroup(response, testTenant,
                 setNamespaceAntiAffinityGroupNs));
 
         // 5.assert namespace anti affinity group
         namespaceAntiAffinityGroupResp = (String) asyncRequests(
-                response -> namespaces.getNamespaceAntiAffinityGroup(response, testTenant, testLocalCluster,
+                response -> namespaces.getNamespaceAntiAffinityGroup(response, testTenant,
                         setNamespaceAntiAffinityGroupNs));
         assertNull(namespaceAntiAffinityGroupResp);
     }
@@ -2547,7 +2529,7 @@ public void testGetClusterAntiAffinityNamespaces() throws Exception {
                 List.of(namespaceWithAntiAffinity1, namespaceWithAntiAffinity2, namespaceWithAntiAffinity3,
                         namespaceWithoutAntiAffinity1, namespaceWithoutAntiAffinity2);
         for (String namespace : allNamespaces) {
-            asyncRequests(response -> namespaces.createNamespace(response, testTenant, testLocalCluster, namespace,
+            asyncRequests(response -> namespaces.createNamespace(response, testTenant, namespace,
                     (Policies) null));
         }
 
@@ -2556,14 +2538,14 @@ public void testGetClusterAntiAffinityNamespaces() throws Exception {
         List namespacesWithAntiAffinityGroup =
                 List.of(namespaceWithAntiAffinity1, namespaceWithAntiAffinity2, namespaceWithAntiAffinity3);
         for (String namespace : namespacesWithAntiAffinityGroup) {
-            asyncRequests(response -> namespaces.setNamespaceAntiAffinityGroup(response, testTenant, testLocalCluster,
+            asyncRequests(response -> namespaces.setNamespaceAntiAffinityGroup(response, testTenant,
                     namespace, namespaceAntiAffinityGroupReq));
         }
 
         // assert namespace anti affinity group
         for (String namespace : namespacesWithAntiAffinityGroup) {
             String namespaceAntiAffinityGroupResp = (String) asyncRequests(
-                    response -> namespaces.getNamespaceAntiAffinityGroup(response, testTenant, testLocalCluster,
+                    response -> namespaces.getNamespaceAntiAffinityGroup(response, testTenant,
                             namespace));
             assertEquals(namespaceAntiAffinityGroupResp, namespaceAntiAffinityGroupReq);
         }
@@ -2573,7 +2555,7 @@ public void testGetClusterAntiAffinityNamespaces() throws Exception {
                 response -> namespaces.getAntiAffinityNamespaces(response, testLocalCluster,
                         namespaceAntiAffinityGroupReq, testTenant));
         List namespacesWithFullPath =
-                namespacesWithAntiAffinityGroup.stream().map(ns -> NamespaceName.get(testTenant, testLocalCluster, ns))
+                namespacesWithAntiAffinityGroup.stream().map(ns -> NamespaceName.get(testTenant, ns))
                         .map(NamespaceName::toString).toList();
         assertEquals(namespacesResp, namespacesWithFullPath);
     }
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/NamespacesV2Test.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/NamespacesV2Test.java
index fcd603434111c..70f8ad90d44e2 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/NamespacesV2Test.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/NamespacesV2Test.java
@@ -82,7 +82,7 @@ public NamespacesV2Test() {
     @BeforeClass
     public void initNamespace() throws Exception {
         testLocalNamespaces = new ArrayList<>();
-        testLocalNamespaces.add(NamespaceName.get(this.testTenant, this.testLocalCluster, this.testNamespace));
+        testLocalNamespaces.add(NamespaceName.get(this.testTenant, this.testNamespace));
 
         uriField = PulsarWebResource.class.getDeclaredField("uri");
         uriField.setAccessible(true);
@@ -113,11 +113,11 @@ public void setup() throws Exception {
         createTestNamespaces(this.testLocalNamespaces);
 
         doThrow(new RestException(Response.Status.UNAUTHORIZED, "unauthorized")).when(namespaces)
-                .validateNamespacePolicyOperation(NamespaceName.get("other-tenant/use/test-namespace-1"),
+                .validateNamespacePolicyOperation(NamespaceName.get("other-tenant/test-namespace-1"),
                         PolicyName.PERSISTENCE, PolicyOperation.WRITE);
 
         doThrow(new RestException(Response.Status.UNAUTHORIZED, "unauthorized")).when(namespaces)
-                .validateNamespacePolicyOperation(NamespaceName.get("other-tenant/use/test-namespace-1"),
+                .validateNamespacePolicyOperation(NamespaceName.get("other-tenant/test-namespace-1"),
                         PolicyName.RETENTION, PolicyOperation.WRITE);
 
         nsSvc = pulsar.getNamespaceService();
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/PersistentTopicsTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/PersistentTopicsTest.java
index 090e34deecd44..7ed059390455e 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/PersistentTopicsTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/PersistentTopicsTest.java
@@ -718,7 +718,7 @@ public void testUpdatePartitionedTopicHavingNonPartitionTopicWithPartitionSuffix
                 .open(TopicName.get(nonPartitionTopicName2).getPersistenceNamingEncoding());
         doAnswer(invocation -> {
             persistentTopics.namespaceName = NamespaceName.get("tenant", "namespace");
-            persistentTopics.topicName = TopicName.get("persistent", "tenant", "cluster", "namespace", "topicname");
+            persistentTopics.topicName = TopicName.get("persistent", "tenant", "namespace", "topicname");
             return null;
         }).when(persistentTopics).validatePartitionedTopicName(any(), any(), any());
 
@@ -1870,7 +1870,7 @@ public void testInternalGetReplicatedSubscriptionStatusFromLocal() throws Except
 
     @Test
     public void testNamespaceResources() throws Exception {
-        String ns1V1 = "test/" + testNamespace + "v1";
+        String ns1V1 = testNamespace + "v1";
         String ns1V2 = testNamespace + "v2";
         admin.namespaces().createNamespace(testTenant + "/" + ns1V1);
         admin.namespaces().createNamespace(testTenant + "/" + ns1V2);
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/TopicMessageTTLTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/TopicMessageTTLTest.java
index c191cc3633ec8..8ecd37a931d0f 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/TopicMessageTTLTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/TopicMessageTTLTest.java
@@ -32,7 +32,6 @@
 import org.testng.Assert;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 @Slf4j
@@ -69,11 +68,6 @@ public void cleanup() throws Exception {
         super.internalCleanup();
     }
 
-    @DataProvider(name = "isV1")
-    public Object[][] isV1() {
-        return new Object[][] { { true }, { false } };
-    }
-
     @Test
     public void testSetThenRemoveMessageTTL() throws Exception {
         admin.topics().setMessageTTL(testTopic, 100);
@@ -176,9 +170,9 @@ public void testDifferentLevelPolicyPriority() throws Exception {
                 (int) persistentTopic.getHierarchyTopicPolicies().getMessageTTLInSeconds().get(), 3600));
     }
 
-    @Test(dataProvider = "isV1")
-    public void testNamespaceTTL(boolean isV1) throws Exception {
-        String myNamespace = testTenant + "/" + (isV1 ? testCluster + "/" : "") + "n1" + isV1;
+    @Test
+    public void testNamespaceTTL() throws Exception {
+        String myNamespace = testTenant + "/" + "n1";
         admin.namespaces().createNamespace(myNamespace, Set.of(testCluster));
 
         admin.namespaces().setNamespaceMessageTTL(myNamespace, 10);
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/TopicPoliciesTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/TopicPoliciesTest.java
index 37edc600b478b..47b0d63aba635 100644
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/TopicPoliciesTest.java
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/TopicPoliciesTest.java
@@ -134,7 +134,7 @@ public class TopicPoliciesTest extends MockedPulsarServiceBaseTest {
 
     private final String myNamespace = testTenant + "/" + testNamespace;
 
-    private final String myNamespaceV1 = testTenant + "/test/" + testNamespace;
+    private final String myNamespaceV1 = testTenant + "/" + testNamespace + "-v1";
 
     private final String testTopic = "persistent://" + myNamespace + "/test-set-backlog-quota";
 
@@ -3605,7 +3605,6 @@ public void testDoNotCreateSystemTopicForHeartbeatNamespace() {
         pulsar.getBrokerService().getTopics().forEach((k, v) -> {
             TopicName topicName = TopicName.get(k);
             assertNull(NamespaceService.checkHeartbeatNamespace(topicName.getNamespaceObject()));
-            assertNull(NamespaceService.checkHeartbeatNamespaceV2(topicName.getNamespaceObject()));
         });
     }
 
diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/v1/V1AdminApi2Test.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/v1/V1AdminApi2Test.java
deleted file mode 100644
index 056a2e7cbbeee..0000000000000
--- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/v1/V1AdminApi2Test.java
+++ /dev/null
@@ -1,829 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.pulsar.broker.admin.v1;
-
-import static org.apache.commons.lang3.StringUtils.isBlank;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-import com.google.common.collect.Sets;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import lombok.Cleanup;
-import org.apache.bookkeeper.mledger.impl.ManagedCursorImpl;
-import org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl;
-import org.apache.pulsar.broker.admin.v1.V1AdminApiTest.MockedPulsarService;
-import org.apache.pulsar.broker.auth.MockedPulsarServiceBaseTest;
-import org.apache.pulsar.broker.loadbalance.impl.ModularLoadManagerImpl;
-import org.apache.pulsar.broker.loadbalance.impl.SimpleLoadManagerImpl;
-import org.apache.pulsar.broker.service.Topic;
-import org.apache.pulsar.broker.service.persistent.PersistentTopic;
-import org.apache.pulsar.client.admin.PulsarAdmin;
-import org.apache.pulsar.client.admin.PulsarAdminException;
-import org.apache.pulsar.client.admin.PulsarAdminException.PreconditionFailedException;
-import org.apache.pulsar.client.api.Consumer;
-import org.apache.pulsar.client.api.Message;
-import org.apache.pulsar.client.api.MessageRoutingMode;
-import org.apache.pulsar.client.api.Producer;
-import org.apache.pulsar.client.api.PulsarClient;
-import org.apache.pulsar.client.api.SubscriptionType;
-import org.apache.pulsar.client.impl.MessageIdImpl;
-import org.apache.pulsar.common.naming.TopicDomain;
-import org.apache.pulsar.common.naming.TopicName;
-import org.apache.pulsar.common.policies.data.ClusterData;
-import org.apache.pulsar.common.policies.data.ConsumerStats;
-import org.apache.pulsar.common.policies.data.FailureDomain;
-import org.apache.pulsar.common.policies.data.NonPersistentTopicStats;
-import org.apache.pulsar.common.policies.data.PartitionedTopicStats;
-import org.apache.pulsar.common.policies.data.PersistencePolicies;
-import org.apache.pulsar.common.policies.data.PersistentTopicInternalStats;
-import org.apache.pulsar.common.policies.data.RetentionPolicies;
-import org.apache.pulsar.common.policies.data.SubscriptionStats;
-import org.apache.pulsar.common.policies.data.TenantInfoImpl;
-import org.apache.pulsar.common.policies.data.TopicStats;
-import org.awaitility.Awaitility;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-@Test(groups = "broker-admin")
-public class V1AdminApi2Test extends MockedPulsarServiceBaseTest {
-
-    private MockedPulsarService mockPulsarSetup;
-
-    @BeforeMethod
-    @Override
-    public void setup() throws Exception {
-        conf.setTopicLevelPoliciesEnabled(false);
-        conf.setSystemTopicEnabled(false);
-        conf.setLoadBalancerEnabled(true);
-        super.internalSetup();
-
-        // create other broker to test redirect on calls that need
-        // namespace ownership
-        mockPulsarSetup = new MockedPulsarService(this.conf);
-        mockPulsarSetup.setup();
-
-        // Setup namespaces
-        admin.clusters().createCluster("use", ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build());
-        TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("use"));
-        admin.tenants().createTenant("prop-xyz", tenantInfo);
-        admin.namespaces().createNamespace("prop-xyz/use/ns1");
-    }
-
-    @AfterMethod(alwaysRun = true)
-    @Override
-    public void cleanup() throws Exception {
-        super.internalCleanup();
-        mockPulsarSetup.cleanup();
-    }
-
-    @DataProvider(name = "topicType")
-    public Object[][] topicTypeProvider() {
-        return new Object[][] { { TopicDomain.persistent.value() }, { TopicDomain.non_persistent.value() } };
-    }
-
-    @DataProvider(name = "namespaceNames")
-    public Object[][] namespaceNameProvider() {
-        return new Object[][] { { "ns1" }, { "global" } };
-    }
-
-    /**
-     * 
-     * It verifies increasing partitions for partitioned-topic.
-     * 1. create a partitioned-topic
-     * 2. update partitions with larger number of partitions
-     * 3. verify: getPartitionedMetadata and check number of partitions
-     * 4. verify: this api creates existing subscription to new partitioned-topics
-     *            so, message will not be lost in new partitions
-     *  a. start producer and produce messages
-     *  b. check existing subscription for new topics and it should have backlog msgs
-     *
-     * 
- * - * @throws Exception - */ - @Test - public void testIncrementPartitionsOfTopic() throws Exception { - final String topicName = "increment-partitionedTopic"; - final String subName1 = topicName + "-my-sub-1"; - final String subName2 = topicName + "-my-sub-2"; - final int startPartitions = 4; - final int newPartitions = 8; - final String partitionedTopicName = "persistent://prop-xyz/use/ns1/" + topicName; - - URL pulsarUrl = new URL(pulsar.getWebServiceAddress()); - - admin.topics().createPartitionedTopic(partitionedTopicName, startPartitions); - // validate partition topic is created - assertEquals(admin.topics().getPartitionedTopicMetadata(partitionedTopicName).partitions, - startPartitions); - - // create consumer and subscriptions : check subscriptions - @Cleanup - PulsarClient client = PulsarClient.builder().serviceUrl(pulsarUrl.toString()).build(); - Consumer consumer1 = client.newConsumer().topic(partitionedTopicName).subscriptionName(subName1) - .subscriptionType(SubscriptionType.Shared).subscribe(); - assertEquals(admin.topics().getSubscriptions(partitionedTopicName), List.of(subName1)); - Consumer consumer2 = client.newConsumer().topic(partitionedTopicName).subscriptionName(subName2) - .subscriptionType(SubscriptionType.Shared).subscribe(); - assertEquals(new HashSet<>(admin.topics().getSubscriptions(partitionedTopicName)), - Set.of(subName1, subName2)); - - // (1) update partitions - admin.topics().updatePartitionedTopic(partitionedTopicName, newPartitions); - // verify new partitions have been created - assertEquals(admin.topics().getPartitionedTopicMetadata(partitionedTopicName).partitions, - newPartitions); - // (2) No Msg loss: verify new partitions have the same existing subscription names - final String newPartitionTopicName = TopicName.get(partitionedTopicName).getPartition(startPartitions + 1) - .toString(); - - // (3) produce messages to all partitions including newly created partitions (RoundRobin) - Producer producer = client.newProducer().topic(partitionedTopicName) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.RoundRobinPartition) - .create(); - final int totalMessages = newPartitions * 2; - for (int i = 0; i < totalMessages; i++) { - String message = "message-" + i; - producer.send(message.getBytes()); - } - - // (4) verify existing subscription has not lost any message: create new consumer with sub-2: it will load all - // newly created partition topics - consumer2.close(); - consumer2 = client.newConsumer().topic(partitionedTopicName).subscriptionName(subName2) - .subscriptionType(SubscriptionType.Shared).subscribe(); - assertEquals(new HashSet<>(admin.topics().getSubscriptions(newPartitionTopicName)), - Set.of(subName1, subName2)); - - assertEquals(new HashSet<>(admin.topics().getList("prop-xyz/use/ns1")).size(), newPartitions); - - // test cumulative stats for partitioned topic - PartitionedTopicStats topicStats = admin.topics().getPartitionedStats(partitionedTopicName, false); - assertEquals(topicStats.getSubscriptions().keySet(), Set.of(subName1, subName2)); - assertEquals(topicStats.getSubscriptions().get(subName2).getConsumers().size(), 1); - assertEquals(topicStats.getSubscriptions().get(subName2).getMsgBacklog(), totalMessages); - assertEquals(topicStats.getPublishers().size(), 1); - assertEquals(topicStats.getPartitions(), new HashMap<>()); - - // (5) verify: each partition should have backlog - topicStats = admin.topics().getPartitionedStats(partitionedTopicName, true); - assertEquals(topicStats.getMetadata().partitions, newPartitions); - Set partitionSet = new HashSet<>(); - for (int i = 0; i < newPartitions; i++) { - partitionSet.add(partitionedTopicName + "-partition-" + i); - } - assertEquals(topicStats.getPartitions().keySet(), partitionSet); - for (int i = 0; i < newPartitions; i++) { - TopicStats partitionStats = topicStats.getPartitions() - .get(TopicName.get(partitionedTopicName).getPartition(i).toString()); - assertEquals(partitionStats.getPublishers().size(), 1); - assertEquals(partitionStats.getSubscriptions().get(subName2).getConsumers().size(), 1); - assertEquals(partitionStats.getSubscriptions().get(subName2).getMsgBacklog(), 2, 1); - } - - producer.close(); - consumer1.close(); - consumer2.close(); - consumer2.close(); - } - - /** - * verifies admin api command for non-persistent topic. It verifies: partitioned-topic, stats - * - * @throws Exception - */ - @Test - public void nonPersistentTopics() throws Exception { - final String topicName = "nonPersistentTopic"; - - final String persistentTopicName = "non-persistent://prop-xyz/use/ns1/" + topicName; - // Force to create a topic - publishMessagesOnTopic("non-persistent://prop-xyz/use/ns1/" + topicName, 0, 0); - - // create consumer and subscription - @Cleanup - PulsarClient client = PulsarClient.builder() - .serviceUrl(pulsar.getWebServiceAddress()) - .statsInterval(0, TimeUnit.SECONDS) - .build(); - Consumer consumer = client.newConsumer().topic(persistentTopicName).subscriptionName("my-sub") - .subscribe(); - - publishMessagesOnTopic("non-persistent://prop-xyz/use/ns1/" + topicName, 10, 0); - - NonPersistentTopicStats topicStats = admin.nonPersistentTopics().getStats(persistentTopicName); - assertEquals(topicStats.getSubscriptions().keySet(), Set.of("my-sub")); - assertEquals(topicStats.getSubscriptions().get("my-sub").getConsumers().size(), 1); - assertEquals(topicStats.getPublishers().size(), 0); - - PersistentTopicInternalStats internalStats = admin.nonPersistentTopics().getInternalStats(persistentTopicName); - assertEquals(internalStats.cursors.keySet(), Set.of("my-sub")); - - consumer.close(); - client.close(); - - topicStats = admin.nonPersistentTopics().getStats(persistentTopicName); - assertFalse(topicStats.getSubscriptions().keySet().contains("my-sub")); - assertEquals(topicStats.getPublishers().size(), 0); - - // test partitioned-topic - final String partitionedTopicName = "non-persistent://prop-xyz/use/ns1/paritioned"; - try { - admin.nonPersistentTopics().getPartitionedTopicMetadata(partitionedTopicName); - fail("Should have failed"); - } catch (Exception ex) { - assertTrue(ex instanceof PulsarAdminException.NotFoundException); - } - admin.nonPersistentTopics().createPartitionedTopic(partitionedTopicName, 5); - assertEquals(admin.nonPersistentTopics().getPartitionedTopicMetadata(partitionedTopicName).partitions, 5); - } - - private void publishMessagesOnTopic(String topicName, int messages, int startIdx) throws Exception { - Producer producer = pulsarClient.newProducer() - .topic(topicName) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - - for (int i = startIdx; i < (messages + startIdx); i++) { - String message = "message-" + i; - producer.send(message.getBytes()); - } - - producer.close(); - } - - /** - * verifies validation on persistent-policies. - * - * @throws Exception - */ - @Test - public void testSetPersistencepolicies() throws Exception { - - final String namespace = "prop-xyz/use/ns2"; - admin.namespaces().createNamespace(namespace); - - assertEquals(admin.namespaces().getPersistence(namespace), null); - admin.namespaces().setPersistence(namespace, new PersistencePolicies(3, 3, 3, 10.0)); - assertEquals(admin.namespaces().getPersistence(namespace), new PersistencePolicies(3, 3, 3, 10.0)); - - try { - admin.namespaces().setPersistence(namespace, new PersistencePolicies(3, 4, 3, 10.0)); - fail("should have failed"); - } catch (PulsarAdminException e) { - assertEquals(e.getStatusCode(), 400); - } - try { - admin.namespaces().setPersistence(namespace, new PersistencePolicies(3, 3, 4, 10.0)); - fail("should have failed"); - } catch (PulsarAdminException e) { - assertEquals(e.getStatusCode(), 400); - } - try { - admin.namespaces().setPersistence(namespace, new PersistencePolicies(6, 3, 1, 10.0)); - fail("should have failed"); - } catch (PulsarAdminException e) { - assertEquals(e.getStatusCode(), 400); - } - - // make sure policies has not been changed - assertEquals(admin.namespaces().getPersistence(namespace), new PersistencePolicies(3, 3, 3, 10.0)); - } - - /** - * validates update of persistent-policies reflects on managed-ledger and managed-cursor. - * - * @throws Exception - */ - @Test - public void testUpdatePersistencePolicyUpdateManagedCursor() throws Exception { - - final String namespace = "prop-xyz/use/ns2"; - final String topicName = "persistent://" + namespace + "/topic1"; - admin.namespaces().createNamespace(namespace); - - admin.namespaces().setPersistence(namespace, new PersistencePolicies(3, 3, 3, 50.0)); - assertEquals(admin.namespaces().getPersistence(namespace), new PersistencePolicies(3, 3, 3, 50.0)); - - Producer producer = pulsarClient.newProducer() - .topic(topicName) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - Consumer consumer = pulsarClient.newConsumer().topic(topicName).subscriptionName("my-sub").subscribe(); - - PersistentTopic topic = (PersistentTopic) pulsar.getBrokerService().getOrCreateTopic(topicName).get(); - ManagedLedgerImpl managedLedger = (ManagedLedgerImpl) topic.getManagedLedger(); - ManagedCursorImpl cursor = (ManagedCursorImpl) managedLedger.getCursors().iterator().next(); - - final double newThrottleRate = 100; - final int newEnsembleSize = 5; - admin.namespaces().setPersistence(namespace, new PersistencePolicies(newEnsembleSize, 3, 3, newThrottleRate)); - - retryStrategically((test) -> managedLedger.getConfig().getEnsembleSize() == newEnsembleSize - && cursor.getThrottleMarkDelete() != newThrottleRate, 5, 200); - - // (1) verify cursor.markDelete has been updated - assertEquals(cursor.getThrottleMarkDelete(), newThrottleRate); - - // (2) verify new ledger creation takes new config - - producer.close(); - consumer.close(); - - } - - /** - * Verify unloading topic. - * - * @throws Exception - */ - @Test(dataProvider = "topicType") - public void testUnloadTopic(final String topicType) throws Exception { - - final String namespace = "prop-xyz/use/ns2"; - final String topicName = topicType + "://" + namespace + "/topic1"; - admin.namespaces().createNamespace(namespace); - - // create a topic by creating a producer - Producer producer = pulsarClient.newProducer().topic(topicName).create(); - producer.close(); - - Topic topic = pulsar.getBrokerService().getTopicIfExists(topicName).join().get(); - final boolean isPersistentTopic = topic instanceof PersistentTopic; - - // (1) unload the topic - unloadTopic(topicName, isPersistentTopic); - - // topic must be removed from map - assertFalse(pulsar.getBrokerService().getTopicReference(topicName).isPresent()); - - // recreation of producer will load the topic again - producer = pulsarClient.newProducer().topic(topicName).create(); - topic = pulsar.getBrokerService().getTopicReference(topicName).get(); - assertNotNull(topic); - // unload the topic - unloadTopic(topicName, isPersistentTopic); - // producer will retry and recreate the topic - Awaitility.await().until(() -> pulsar.getBrokerService().getTopicReference(topicName).isPresent()); - // topic should be loaded by this time - topic = pulsar.getBrokerService().getTopicReference(topicName).get(); - assertNotNull(topic); - } - - private void unloadTopic(String topicName, boolean isPersistentTopic) throws Exception { - if (isPersistentTopic) { - admin.topics().unload(topicName); - } else { - admin.nonPersistentTopics().unload(topicName); - } - } - - /** - * Verifies reset-cursor at specific position using admin-api. - * - *
-     * 1. Publish 50 messages
-     * 2. Consume 20 messages
-     * 3. reset cursor position on 10th message
-     * 4. consume 40 messages from reset position
-     * 
- * - * @param namespaceName - * @throws Exception - */ - @Test(dataProvider = "namespaceNames", timeOut = 10000) - public void testResetCursorOnPosition(String namespaceName) throws Exception { - final String topicName = "persistent://prop-xyz/use/" + namespaceName + "/resetPosition"; - final int totalProducedMessages = 50; - - // set retention - admin.namespaces().setRetention("prop-xyz/use/ns1", new RetentionPolicies(10, 10)); - - // create consumer and subscription - Consumer consumer = pulsarClient.newConsumer().topic(topicName).subscriptionName("my-sub") - .subscriptionType(SubscriptionType.Shared).subscribe(); - - assertEquals(admin.topics().getSubscriptions(topicName), List.of("my-sub")); - - publishMessagesOnPersistentTopic(topicName, totalProducedMessages, 0); - - List> messages = admin.topics().peekMessages(topicName, "my-sub", 10); - assertEquals(messages.size(), 10); - - Message message = null; - MessageIdImpl resetMessageId = null; - int resetPositionId = 10; - for (int i = 0; i < 20; i++) { - message = consumer.receive(1, TimeUnit.SECONDS); - consumer.acknowledge(message); - if (i == resetPositionId) { - resetMessageId = (MessageIdImpl) message.getMessageId(); - } - } - - // close consumer which will clean up internal-receive-queue - consumer.close(); - - // messages should still be available due to retention - MessageIdImpl messageId = new MessageIdImpl(resetMessageId.getLedgerId(), resetMessageId.getEntryId(), -1); - // reset position at resetMessageId - admin.topics().resetCursor(topicName, "my-sub", messageId); - - consumer = pulsarClient.newConsumer().topic(topicName).subscriptionName("my-sub") - .subscriptionType(SubscriptionType.Shared).subscribe(); - MessageIdImpl msgId2 = (MessageIdImpl) consumer.receive(1, TimeUnit.SECONDS).getMessageId(); - assertEquals(resetMessageId, msgId2); - - int receivedAfterReset = 1; // start with 1 because we have already received 1 msg - - for (int i = 0; i < totalProducedMessages; i++) { - message = consumer.receive(500, TimeUnit.MILLISECONDS); - if (message == null) { - break; - } - consumer.acknowledge(message); - ++receivedAfterReset; - } - assertEquals(receivedAfterReset, totalProducedMessages - resetPositionId); - - // invalid topic name - try { - admin.topics().resetCursor(topicName + "invalid", "my-sub", messageId); - fail("It should have failed due to invalid topic name"); - } catch (PulsarAdminException.NotFoundException e) { - // Ok - } - - // invalid cursor name - try { - admin.topics().resetCursor(topicName, "invalid-sub", messageId); - fail("It should have failed due to invalid subscription name"); - } catch (PulsarAdminException.NotFoundException e) { - // Ok - } - - // invalid position - try { - messageId = new MessageIdImpl(0, 0, -1); - admin.topics().resetCursor(topicName, "my-sub", messageId); - } catch (PulsarAdminException.PreconditionFailedException e) { - fail("It shouldn't fail for a invalid position"); - } - - consumer.close(); - } - - private void publishMessagesOnPersistentTopic(String topicName, int messages, int startIdx) throws Exception { - Producer producer = pulsarClient.newProducer() - .topic(topicName) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - - for (int i = startIdx; i < (messages + startIdx); i++) { - String message = "message-" + i; - producer.send(message.getBytes()); - } - - producer.close(); - } - - /** - * It verifies that pulsar with different load-manager generates different load-report and returned by admin-api. - * - * @throws Exception - */ - @Test - public void testLoadReportApi() throws Exception { - - this.conf.setLoadManagerClassName(SimpleLoadManagerImpl.class.getName()); - MockedPulsarService mockPulsarSetup1 = new MockedPulsarService(this.conf); - mockPulsarSetup1.setup(); - PulsarAdmin simpleLoadManagerAdmin = mockPulsarSetup1.getAdmin(); - assertNotNull(simpleLoadManagerAdmin.brokerStats().getLoadReport()); - - this.conf.setLoadManagerClassName(ModularLoadManagerImpl.class.getName()); - MockedPulsarService mockPulsarSetup2 = new MockedPulsarService(this.conf); - mockPulsarSetup2.setup(); - PulsarAdmin modularLoadManagerAdmin = mockPulsarSetup2.getAdmin(); - assertNotNull(modularLoadManagerAdmin.brokerStats().getLoadReport()); - - mockPulsarSetup1.cleanup(); - mockPulsarSetup2.cleanup(); - } - - @Test - public void testPeerCluster() throws Exception { - admin.clusters().createCluster("us-west1", - ClusterData.builder().serviceUrl("http://broker.messaging.west1.example.com:8080").build()); - admin.clusters().createCluster("us-west2", - ClusterData.builder().serviceUrl("http://broker.messaging.west2.example.com:8080").build()); - admin.clusters().createCluster("us-east1", - ClusterData.builder().serviceUrl("http://broker.messaging.east1.example.com:8080").build()); - admin.clusters().createCluster("us-east2", - ClusterData.builder().serviceUrl("http://broker.messaging.east2.example.com:8080").build()); - - admin.clusters().updatePeerClusterNames("us-west1", Sets.newLinkedHashSet(List.of("us-west2"))); - assertEquals(admin.clusters().getCluster("us-west1").getPeerClusterNames(), List.of("us-west2")); - assertNull(admin.clusters().getCluster("us-west2").getPeerClusterNames()); - // update cluster with duplicate peer-clusters in the list - admin.clusters().updatePeerClusterNames("us-west1", Sets.newLinkedHashSet( - List.of("us-west2", "us-east1", "us-west2", "us-east1", "us-west2", "us-east1"))); - assertEquals(admin.clusters().getCluster("us-west1").getPeerClusterNames(), - List.of("us-west2", "us-east1")); - admin.clusters().updatePeerClusterNames("us-west1", null); - assertNull(admin.clusters().getCluster("us-west1").getPeerClusterNames()); - - // Check name validation - try { - admin.clusters().updatePeerClusterNames("us-west1", - Sets.newLinkedHashSet(List.of("invalid-cluster"))); - fail("should have failed"); - } catch (PulsarAdminException e) { - assertTrue(e instanceof PreconditionFailedException); - } - - // Cluster itselft can't be part of peer-list - try { - admin.clusters().updatePeerClusterNames("us-west1", Sets.newLinkedHashSet(List.of("us-west1"))); - fail("should have failed"); - } catch (PulsarAdminException e) { - assertTrue(e instanceof PreconditionFailedException); - } - } - - /** - * It validates that peer-cluster can't coexist in replication-cluster list. - * - * @throws Exception - */ - @Test - public void testReplicationPeerCluster() throws Exception { - admin.clusters().createCluster("us-west1", - ClusterData.builder().serviceUrl("http://broker.messaging.west1.example.com:8080").build()); - admin.clusters().createCluster("us-west2", - ClusterData.builder().serviceUrl("http://broker.messaging.west2.example.com:8080").build()); - admin.clusters().createCluster("us-west3", - ClusterData.builder().serviceUrl("http://broker.messaging.west2.example.com:8080").build()); - admin.clusters().createCluster("us-west4", - ClusterData.builder().serviceUrl("http://broker.messaging.west2.example.com:8080").build()); - admin.clusters().createCluster("us-east1", - ClusterData.builder().serviceUrl("http://broker.messaging.east1.example.com:8080").build()); - admin.clusters().createCluster("us-east2", - ClusterData.builder().serviceUrl("http://broker.messaging.east2.example.com:8080").build()); - admin.clusters().createCluster("global", ClusterData.builder().build()); - - final String property = "peer-prop"; - Set allowedClusters = Set.of("us-west1", "us-west2", "us-west3", "us-west4", "us-east1", - "us-east2"); - TenantInfoImpl propConfig = new TenantInfoImpl(Set.of("test"), allowedClusters); - admin.tenants().createTenant(property, propConfig); - - final String namespace = property + "/global/conflictPeer"; - admin.namespaces().createNamespace(namespace); - - admin.clusters().updatePeerClusterNames("us-west1", - Sets.newLinkedHashSet(List.of("us-west2", "us-west3"))); - assertEquals(admin.clusters().getCluster("us-west1").getPeerClusterNames(), - List.of("us-west2", "us-west3")); - - // (1) no conflicting peer - Set clusterIds = Set.of("us-east1", "us-east2"); - admin.namespaces().setNamespaceReplicationClusters(namespace, clusterIds, false); - - // (2) conflicting peer - clusterIds = Set.of("us-west2", "us-west3", "us-west1"); - try { - admin.namespaces().setNamespaceReplicationClusters(namespace, clusterIds, false); - fail("Peer-cluster can't coexist in replication cluster list"); - } catch (PulsarAdminException.ConflictException e) { - // Ok - } - - clusterIds = Set.of("us-west2", "us-west3"); - // no peer coexist in replication clusters - admin.namespaces().setNamespaceReplicationClusters(namespace, clusterIds, false); - - clusterIds = Set.of("us-west1", "us-west4"); - // no peer coexist in replication clusters - admin.namespaces().setNamespaceReplicationClusters(namespace, clusterIds, false); - } - - @Test - public void clusterFailureDomain() throws PulsarAdminException { - - final String cluster = pulsar.getConfiguration().getClusterName(); - admin.clusters().createCluster(cluster, - ClusterData.builder() - .serviceUrl(pulsar.getSafeWebServiceAddress()) - .serviceUrlTls(pulsar.getWebServiceAddressTls()) - .build()); - // create - FailureDomain domain = FailureDomain.builder() - .brokers(Set.of("b1", "b2", "b3")) - .build(); - admin.clusters().createFailureDomain(cluster, "domain-1", domain); - admin.clusters().updateFailureDomain(cluster, "domain-1", domain); - - assertEquals(admin.clusters().getFailureDomain(cluster, "domain-1"), domain); - - Map domains = admin.clusters().getFailureDomains(cluster); - assertEquals(domains.size(), 1); - assertTrue(domains.containsKey("domain-1")); - - try { - // try to create domain with already registered brokers - admin.clusters().createFailureDomain(cluster, "domain-2", domain); - fail("should have failed because of brokers are already registered"); - } catch (PulsarAdminException.ConflictException e) { - // Ok - } - - admin.clusters().deleteFailureDomain(cluster, "domain-1"); - assertTrue(admin.clusters().getFailureDomains(cluster).isEmpty()); - - admin.clusters().createFailureDomain(cluster, "domain-2", domain); - domains = admin.clusters().getFailureDomains(cluster); - assertEquals(domains.size(), 1); - assertTrue(domains.containsKey("domain-2")); - } - - @Test - public void namespaceAntiAffinity() throws PulsarAdminException { - final String namespace = "prop-xyz/use/ns1"; - final String antiAffinityGroup = "group"; - assertTrue(isBlank(admin.namespaces().getNamespaceAntiAffinityGroup(namespace))); - admin.namespaces().setNamespaceAntiAffinityGroup(namespace, antiAffinityGroup); - assertEquals(admin.namespaces().getNamespaceAntiAffinityGroup(namespace), antiAffinityGroup); - admin.namespaces().deleteNamespaceAntiAffinityGroup(namespace); - assertTrue(isBlank(admin.namespaces().getNamespaceAntiAffinityGroup(namespace))); - - final String ns1 = "prop-xyz/use/antiAG1"; - final String ns2 = "prop-xyz/use/antiAG2"; - final String ns3 = "prop-xyz/use/antiAG3"; - admin.namespaces().createNamespace(ns1); - admin.namespaces().createNamespace(ns2); - admin.namespaces().createNamespace(ns3); - admin.namespaces().setNamespaceAntiAffinityGroup(ns1, antiAffinityGroup); - admin.namespaces().setNamespaceAntiAffinityGroup(ns2, antiAffinityGroup); - admin.namespaces().setNamespaceAntiAffinityGroup(ns3, antiAffinityGroup); - - Set namespaces = new HashSet<>( - admin.namespaces().getAntiAffinityNamespaces("prop-xyz", "use", antiAffinityGroup)); - assertEquals(namespaces.size(), 3); - assertTrue(namespaces.contains(ns1)); - assertTrue(namespaces.contains(ns2)); - assertTrue(namespaces.contains(ns3)); - - List namespaces2 = admin.namespaces().getAntiAffinityNamespaces("prop-xyz", "use", "invalid-group"); - assertEquals(namespaces2.size(), 0); - } - - @Test - public void testNonPersistentTopics() throws Exception { - final String namespace = "prop-xyz/use/ns2"; - final String topicName = "non-persistent://" + namespace + "/topic"; - admin.namespaces().createNamespace(namespace, 20); - int totalTopics = 100; - - Set topicNames = new HashSet<>(); - for (int i = 0; i < totalTopics; i++) { - topicNames.add(topicName + i); - Producer producer = pulsarClient.newProducer() - .topic(topicName + i) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - producer.close(); - } - - for (int i = 0; i < totalTopics; i++) { - Topic topic = pulsar.getBrokerService().getTopicReference(topicName + i).get(); - assertNotNull(topic); - } - - Set topicsInNs = Sets.newHashSet(admin.nonPersistentTopics().getList(namespace)); - assertEquals(topicsInNs.size(), totalTopics); - topicsInNs.removeAll(topicNames); - assertEquals(topicsInNs.size(), 0); - } - - @Test - public void testPublishConsumerStats() throws Exception { - final String topicName = "statTopic"; - final String subscriberName = topicName + "-my-sub-1"; - final String topic = "persistent://prop-xyz/use/ns1/" + topicName; - final String producerName = "myProducer"; - - @Cleanup - PulsarClient client = PulsarClient.builder().serviceUrl(pulsar.getWebServiceAddress()).build(); - Consumer consumer = client.newConsumer().topic(topic).subscriptionName(subscriberName) - .subscriptionType(SubscriptionType.Shared).subscribe(); - Producer producer = client.newProducer() - .topic(topic) - .producerName(producerName) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - - retryStrategically((test) -> { - TopicStats stats; - try { - stats = admin.topics().getStats(topic); - return stats.getPublishers().size() > 0 && stats.getSubscriptions().get(subscriberName) != null - && stats.getSubscriptions().get(subscriberName).getConsumers().size() > 0; - } catch (PulsarAdminException e) { - return false; - } - }, 5, 200); - - TopicStats topicStats = admin.topics().getStats(topic); - assertEquals(topicStats.getPublishers().size(), 1); - assertNotNull(topicStats.getPublishers().get(0).getAddress()); - assertNotNull(topicStats.getPublishers().get(0).getClientVersion()); - assertNotNull(topicStats.getPublishers().get(0).getConnectedSince()); - assertNotNull(topicStats.getPublishers().get(0).getProducerName()); - assertEquals(topicStats.getPublishers().get(0).getProducerName(), producerName); - - SubscriptionStats subscriber = topicStats.getSubscriptions().get(subscriberName); - assertNotNull(subscriber); - assertEquals(subscriber.getConsumers().size(), 1); - ConsumerStats consumerStats = subscriber.getConsumers().get(0); - assertNotNull(consumerStats.getAddress()); - assertNotNull(consumerStats.getClientVersion()); - assertNotNull(consumerStats.getConnectedSince()); - - producer.close(); - consumer.close(); - } - - @Test - public void testTenantNameWithUnderscore() throws Exception { - TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("use")); - admin.tenants().createTenant("prop_xyz", tenantInfo); - - admin.namespaces().createNamespace("prop_xyz/use/my-namespace"); - - String topic = "persistent://prop_xyz/use/my-namespace/my-topic"; - - Producer producer = pulsarClient.newProducer() - .topic(topic) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - - TopicStats stats = admin.topics().getStats(topic); - assertEquals(stats.getPublishers().size(), 1); - producer.close(); - } - - @Test - public void testTenantNameWithInvalidCharacters() throws Exception { - TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("use")); - - // If we try to create property with invalid characters, it should fail immediately - try { - admin.tenants().createTenant("prop xyz", tenantInfo); - fail("Should have failed"); - } catch (PulsarAdminException e) { - // Expected - } - - try { - admin.tenants().createTenant("prop&xyz", tenantInfo); - fail("Should have failed"); - } catch (PulsarAdminException e) { - // Expected - } - } -} diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/v1/V1AdminApiTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/v1/V1AdminApiTest.java deleted file mode 100644 index 2d1a0acab843f..0000000000000 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/v1/V1AdminApiTest.java +++ /dev/null @@ -1,2140 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.broker.admin.v1; - -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; -import com.google.common.collect.BoundType; -import com.google.common.collect.Lists; -import com.google.common.collect.Range; -import com.google.common.hash.Hashing; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import javax.ws.rs.client.InvocationCallback; -import javax.ws.rs.client.WebTarget; -import lombok.Builder; -import lombok.Cleanup; -import lombok.Value; -import lombok.extern.slf4j.Slf4j; -import org.apache.pulsar.broker.PulsarService; -import org.apache.pulsar.broker.ServiceConfiguration; -import org.apache.pulsar.broker.auth.MockedPulsarServiceBaseTest; -import org.apache.pulsar.broker.namespace.NamespaceEphemeralData; -import org.apache.pulsar.broker.namespace.NamespaceService; -import org.apache.pulsar.broker.testcontext.PulsarTestContext; -import org.apache.pulsar.broker.testcontext.SpyConfig; -import org.apache.pulsar.client.admin.LongRunningProcessStatus; -import org.apache.pulsar.client.admin.PulsarAdmin; -import org.apache.pulsar.client.admin.PulsarAdminException; -import org.apache.pulsar.client.admin.PulsarAdminException.ConflictException; -import org.apache.pulsar.client.admin.PulsarAdminException.NotAuthorizedException; -import org.apache.pulsar.client.admin.PulsarAdminException.NotFoundException; -import org.apache.pulsar.client.admin.PulsarAdminException.PreconditionFailedException; -import org.apache.pulsar.client.admin.internal.LookupImpl; -import org.apache.pulsar.client.admin.internal.TenantsImpl; -import org.apache.pulsar.client.admin.internal.TopicsImpl; -import org.apache.pulsar.client.api.Consumer; -import org.apache.pulsar.client.api.ConsumerBuilder; -import org.apache.pulsar.client.api.Message; -import org.apache.pulsar.client.api.MessageRoutingMode; -import org.apache.pulsar.client.api.Producer; -import org.apache.pulsar.client.api.PulsarClient; -import org.apache.pulsar.client.api.Schema; -import org.apache.pulsar.client.api.SubscriptionType; -import org.apache.pulsar.common.lookup.data.LookupData; -import org.apache.pulsar.common.naming.NamespaceBundle; -import org.apache.pulsar.common.naming.NamespaceBundleFactory; -import org.apache.pulsar.common.naming.NamespaceBundles; -import org.apache.pulsar.common.naming.NamespaceName; -import org.apache.pulsar.common.naming.TopicDomain; -import org.apache.pulsar.common.naming.TopicName; -import org.apache.pulsar.common.partition.PartitionedTopicMetadata; -import org.apache.pulsar.common.policies.data.AuthAction; -import org.apache.pulsar.common.policies.data.AutoFailoverPolicyData; -import org.apache.pulsar.common.policies.data.AutoFailoverPolicyType; -import org.apache.pulsar.common.policies.data.BacklogQuota; -import org.apache.pulsar.common.policies.data.BacklogQuota.BacklogQuotaType; -import org.apache.pulsar.common.policies.data.BacklogQuota.RetentionPolicy; -import org.apache.pulsar.common.policies.data.BrokerAssignment; -import org.apache.pulsar.common.policies.data.BrokerNamespaceIsolationData; -import org.apache.pulsar.common.policies.data.ClusterData; -import org.apache.pulsar.common.policies.data.NamespaceIsolationData; -import org.apache.pulsar.common.policies.data.NamespaceIsolationDataImpl; -import org.apache.pulsar.common.policies.data.NamespaceOwnershipStatus; -import org.apache.pulsar.common.policies.data.PartitionedTopicStats; -import org.apache.pulsar.common.policies.data.PersistencePolicies; -import org.apache.pulsar.common.policies.data.PersistentTopicInternalStats; -import org.apache.pulsar.common.policies.data.Policies; -import org.apache.pulsar.common.policies.data.PoliciesUtil; -import org.apache.pulsar.common.policies.data.RetentionPolicies; -import org.apache.pulsar.common.policies.data.TenantInfo; -import org.apache.pulsar.common.policies.data.TenantInfoImpl; -import org.apache.pulsar.common.policies.data.TopicStats; -import org.apache.pulsar.common.util.Codec; -import org.apache.pulsar.common.util.ObjectMapperFactory; -import org.apache.pulsar.compaction.Compactor; -import org.apache.pulsar.compaction.PulsarCompactionServiceFactory; -import org.apache.pulsar.metadata.cache.impl.MetadataCacheImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -@Slf4j -@Test(groups = "broker-admin") -public class V1AdminApiTest extends MockedPulsarServiceBaseTest { - - private static final Logger LOG = LoggerFactory.getLogger(V1AdminApiTest.class); - - private MockedPulsarService mockPulsarSetup; - - private PulsarService otherPulsar; - - private PulsarAdmin adminTls; - private PulsarAdmin otheradmin; - - private NamespaceBundleFactory bundleFactory; - - @BeforeClass - @Override - public void setup() throws Exception { - conf.setTopicLevelPoliciesEnabled(false); - conf.setSystemTopicEnabled(false); - conf.setLoadBalancerEnabled(true); - conf.setBrokerServicePortTls(Optional.of(0)); - conf.setWebServicePortTls(Optional.of(0)); - conf.setTlsCertificateFilePath(BROKER_CERT_FILE_PATH); - conf.setTlsKeyFilePath(BROKER_KEY_FILE_PATH); - conf.setNumExecutorThreadPoolSize(5); - - super.internalSetup(); - - bundleFactory = new NamespaceBundleFactory(pulsar, Hashing.crc32()); - - adminTls = spy(PulsarAdmin.builder().tlsTrustCertsFilePath(CA_CERT_FILE_PATH) - .serviceHttpUrl(brokerUrlTls.toString()).build()); - - // create otherbroker to test redirect on calls that need - // namespace ownership - mockPulsarSetup = new MockedPulsarService(this.conf); - mockPulsarSetup.setup(); - otherPulsar = mockPulsarSetup.getPulsar(); - otheradmin = mockPulsarSetup.getAdmin(); - - // Setup namespaces - admin.clusters().createCluster("use", ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); - TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("use")); - admin.tenants().createTenant("prop-xyz", tenantInfo); - admin.namespaces().createNamespace("prop-xyz/use/ns1"); - } - - @AfterClass(alwaysRun = true) - @Override - public void cleanup() throws Exception { - pulsar.getConfiguration().setBrokerShutdownTimeoutMs(0); - adminTls.close(); - otheradmin.close(); - super.internalCleanup(); - mockPulsarSetup.cleanup(); - } - - @Override - protected void customizeMainPulsarTestContextBuilder(PulsarTestContext.Builder pulsarTestContextBuilder) { - pulsarTestContextBuilder.spyConfigCustomizer( - // verify(compactor) is used in this test class - builder -> builder.compactor(SpyConfig.SpyType.SPY_ALSO_INVOCATIONS)); - } - - @AfterMethod(alwaysRun = true) - public void reset() throws Exception { - pulsar.getConfiguration().setForceDeleteNamespaceAllowed(true); - for (String tenant : admin.tenants().getTenants()) { - for (String namespace : admin.namespaces().getNamespaces(tenant)) { - deleteNamespaceWithRetry(namespace, true, admin); - } - } - pulsar.getConfiguration().setForceDeleteNamespaceAllowed(false); - - resetConfig(); - - if (!admin.clusters().getClusters().contains("use")) { - admin.clusters().createCluster("use", - ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); - } - - if (!admin.tenants().getTenants().contains("prop-xyz")) { - TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("use")); - admin.tenants().createTenant("prop-xyz", tenantInfo); - } - admin.namespaces().createNamespace("prop-xyz/use/ns1"); - } - - @DataProvider(name = "numBundles") - public static Object[][] numBundles() { - return new Object[][] { { 1 }, { 4 } }; - } - - @DataProvider(name = "bundling") - public static Object[][] bundling() { - return new Object[][] { { 0 }, { 4 } }; - } - - @DataProvider(name = "topicName") - public Object[][] topicNamesProvider() { - return new Object[][] { { "topic_+&*%{}() \\/$@#^%" }, { "simple-topicName" } }; - } - - @DataProvider(name = "topicType") - public Object[][] topicTypeProvider() { - return new Object[][] { { TopicDomain.persistent.value() }, { TopicDomain.non_persistent.value() } }; - } - - @Test - public void clusters() throws Exception { - admin.clusters().createCluster("usw", - ClusterData.builder().serviceUrl("http://broker.messaging.use.example.com:8080").build()); - // "test" cluster is part of config-default cluster and it's znode gets created when PulsarService creates - // failure-domain znode of this default cluster - assertEquals(admin.clusters().getClusters(), List.of("use", "usw")); - - assertEquals(admin.clusters().getCluster("use"), - ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); - - admin.clusters().updateCluster("usw", - ClusterData.builder().serviceUrl("http://new-broker.messaging.use.example.com:8080").build()); - assertEquals(admin.clusters().getClusters(), List.of("use", "usw")); - assertEquals(admin.clusters().getCluster("usw"), - ClusterData.builder().serviceUrl("http://new-broker.messaging.use.example.com:8080").build()); - - admin.clusters().updateCluster("usw", - ClusterData.builder() - .serviceUrl("http://new-broker.messaging.usw.example.com:8080") - .serviceUrlTls("https://new-broker.messaging.usw.example.com:4443") - .build()); - assertEquals(admin.clusters().getClusters(), List.of("use", "usw")); - assertEquals(admin.clusters().getCluster("usw"), - ClusterData.builder() - .serviceUrl("http://new-broker.messaging.usw.example.com:8080") - .serviceUrlTls("https://new-broker.messaging.usw.example.com:4443") - .build()); - - admin.clusters().deleteCluster("usw"); - Thread.sleep(300); - - assertEquals(admin.clusters().getClusters(), List.of("use")); - - admin.namespaces().deleteNamespace("prop-xyz/use/ns1"); - admin.clusters().deleteCluster("use"); - assertEquals(admin.clusters().getClusters(), new ArrayList<>()); - - // Check name validation - try { - admin.clusters().createCluster("bf!", ClusterData.builder() - .serviceUrl("http://dummy.messaging.example.com").build()); - fail("should have failed"); - } catch (PulsarAdminException e) { - assertTrue(e instanceof PreconditionFailedException); - } - } - - @Test - public void clusterNamespaceIsolationPolicies() throws PulsarAdminException { - try { - // create - String policyName1 = "policy-1"; - Map parameters1 = new HashMap<>(); - parameters1.put("min_limit", "1"); - parameters1.put("usage_threshold", "100"); - - NamespaceIsolationData nsPolicyData1 = NamespaceIsolationData.builder() - .namespaces(Lists.newArrayList("other/use/other.*")) - // below match all broker. make it easy to verify `getBrokersWithNamespaceIsolationPolicy` later - .primary(Lists.newArrayList(".*")) - .secondary(Lists.newArrayList("prod1-broker.*.messaging.use.example.com")) - .autoFailoverPolicy(AutoFailoverPolicyData.builder() - .policyType(AutoFailoverPolicyType.min_available) - .parameters(parameters1) - .build()) - .build(); - - admin.clusters().createNamespaceIsolationPolicy("use", policyName1, nsPolicyData1); - - String policyName2 = "policy-2"; - Map parameters2 = new HashMap<>(); - parameters2.put("min_limit", "1"); - parameters2.put("usage_threshold", "100"); - - NamespaceIsolationData nsPolicyData2 = NamespaceIsolationData.builder() - .namespaces(Lists.newArrayList("other/use/other.*")) - .primary(Lists.newArrayList("prod1-broker[4-6].messaging.use.example.com")) - .secondary(Lists.newArrayList("prod1-broker.*.messaging.use.example.com")) - .autoFailoverPolicy(AutoFailoverPolicyData.builder() - .policyType(AutoFailoverPolicyType.min_available) - .parameters(parameters1) - .build()) - .build(); - admin.clusters().createNamespaceIsolationPolicy("use", policyName2, nsPolicyData2); - - // verify create indirectly with get - Map policiesMap = admin.clusters() - .getNamespaceIsolationPolicies("use"); - assertEquals(policiesMap.get(policyName1), nsPolicyData1); - assertEquals(policiesMap.get(policyName2), nsPolicyData2); - - // verify local broker get matched. - List isoList = admin.clusters().getBrokersWithNamespaceIsolationPolicy("use"); - assertEquals(isoList.size(), 1); - assertTrue(isoList.get(0).isPrimary()); - assertEquals(isoList.get(0).getPolicyName(), policyName1); - - // verify update of primary - nsPolicyData1.getPrimary().remove(0); - nsPolicyData1.getPrimary().add("prod1-broker[1-2].messaging.use.example.com"); - admin.clusters().updateNamespaceIsolationPolicy("use", policyName1, nsPolicyData1); - - // verify primary change - policiesMap = admin.clusters().getNamespaceIsolationPolicies("use"); - assertEquals(policiesMap.get(policyName1), nsPolicyData1); - - // verify update of secondary - nsPolicyData1.getSecondary().remove(0); - nsPolicyData1.getSecondary().add("prod1-broker[3-4].messaging.use.example.com"); - admin.clusters().updateNamespaceIsolationPolicy("use", policyName1, nsPolicyData1); - - // verify secondary change - policiesMap = admin.clusters().getNamespaceIsolationPolicies("use"); - assertEquals(policiesMap.get(policyName1), nsPolicyData1); - - // verify update of failover policy limit - nsPolicyData1.getAutoFailoverPolicy().getParameters().put("min_limit", "10"); - admin.clusters().updateNamespaceIsolationPolicy("use", policyName1, nsPolicyData1); - - // verify min_limit change - policiesMap = admin.clusters().getNamespaceIsolationPolicies("use"); - assertEquals(policiesMap.get(policyName1), nsPolicyData1); - - // verify update of failover usage_threshold limit - nsPolicyData1.getAutoFailoverPolicy().getParameters().put("usage_threshold", "80"); - admin.clusters().updateNamespaceIsolationPolicy("use", policyName1, nsPolicyData1); - - // verify usage_threshold change - policiesMap = admin.clusters().getNamespaceIsolationPolicies("use"); - assertEquals(policiesMap.get(policyName1), nsPolicyData1); - - // verify single get - NamespaceIsolationDataImpl policy1Data = - (NamespaceIsolationDataImpl) admin.clusters().getNamespaceIsolationPolicy("use", policyName1); - assertEquals(policy1Data, nsPolicyData1); - - // verify creation of more than one policy - admin.clusters().createNamespaceIsolationPolicy("use", policyName2, nsPolicyData1); - - try { - admin.clusters().getNamespaceIsolationPolicy("use", "no-such-policy"); - fail("should have raised exception"); - } catch (PulsarAdminException e) { - assertTrue(e instanceof NotFoundException); - } - - // verify delete cluster failed - try { - admin.clusters().deleteCluster("use"); - fail("should have raised exception"); - } catch (PulsarAdminException e) { - assertTrue(e instanceof PreconditionFailedException); - } - - // verify delete - admin.clusters().deleteNamespaceIsolationPolicy("use", policyName1); - admin.clusters().deleteNamespaceIsolationPolicy("use", policyName2); - - try { - admin.clusters().getNamespaceIsolationPolicy("use", policyName1); - fail("should have raised exception"); - } catch (PulsarAdminException e) { - assertTrue(e instanceof NotFoundException); - } - - try { - admin.clusters().getNamespaceIsolationPolicy("use", policyName2); - fail("should have raised exception"); - } catch (PulsarAdminException e) { - assertTrue(e instanceof NotFoundException); - } - - try { - admin.clusters().getNamespaceIsolationPolicies("usc"); - fail("should have raised exception"); - } catch (PulsarAdminException e) { - assertTrue(e instanceof NotFoundException); - } - - try { - admin.clusters().getNamespaceIsolationPolicy("usc", "no-such-cluster"); - fail("should have raised exception"); - } catch (PulsarAdminException e) { - assertTrue(e instanceof PreconditionFailedException); - } - - try { - admin.clusters().createNamespaceIsolationPolicy("usc", "no-such-cluster", nsPolicyData1); - fail("should have raised exception"); - } catch (PulsarAdminException e) { - assertTrue(e instanceof PreconditionFailedException); - } - - try { - admin.clusters().updateNamespaceIsolationPolicy("usc", "no-such-cluster", policy1Data); - fail("should have raised exception"); - } catch (PulsarAdminException e) { - assertTrue(e instanceof PreconditionFailedException); - } - - } catch (PulsarAdminException e) { - LOG.warn("TEST FAILED [{}]", e.getMessage()); - throw e; - } - } - - @Test - public void brokers() throws Exception { - List list = admin.brokers().getActiveBrokers("use"); - Assert.assertNotNull(list); - Assert.assertEquals(list.size(), 1); - - List list2 = otheradmin.brokers().getActiveBrokers("test"); - Assert.assertNotNull(list2); - Assert.assertEquals(list2.size(), 1); - - Map nsMap = admin.brokers().getOwnedNamespaces("use", list.get(0)); - // since sla-monitor ns is not created nsMap.size() == 1 (for HeartBeat Namespace) - Assert.assertEquals(nsMap.size(), 2); - for (String ns : nsMap.keySet()) { - NamespaceOwnershipStatus nsStatus = nsMap.get(ns); - if (ns.equals( - NamespaceService.getHeartbeatNamespace(pulsar.getBrokerId(), pulsar.getConfiguration()) - + "/0x00000000_0xffffffff")) { - assertEquals(nsStatus.broker_assignment, BrokerAssignment.shared); - assertFalse(nsStatus.is_controlled); - assertTrue(nsStatus.is_active); - } - } - - Map nsMap2 = adminTls.brokers().getOwnedNamespaces("use", list.get(0)); - Assert.assertEquals(nsMap2.size(), 2); - - admin.namespaces().deleteNamespace("prop-xyz/use/ns1"); - admin.clusters().deleteCluster("use"); - assertEquals(admin.clusters().getClusters(), new ArrayList<>()); - } - - /** - *
-     * Verifies: zk-update configuration updates service-config
-     * 1. create znode for dynamic-config
-     * 2. start pulsar service so, pulsar can set the watch on that znode
-     * 3. update the configuration with new value
-     * 4. wait and verify that new value has been updated
-     * 
- * - * @throws Exception - */ - @Test - public void testUpdateDynamicConfigurationWithZkWatch() throws Exception { - final int initValue = 30000; - long defaultValue = pulsar.getConfiguration().getBrokerShutdownTimeoutMs(); - pulsar.getConfiguration().setBrokerShutdownTimeoutMs(initValue); - // (1) try to update dynamic field - final long shutdownTime = 10; - // update configuration - admin.brokers().updateDynamicConfiguration("brokerShutdownTimeoutMs", Long.toString(shutdownTime)); - // sleep incrementally as zk-watch notification is async and may take some time - for (int i = 0; i < 5; i++) { - if (pulsar.getConfiguration().getBrokerShutdownTimeoutMs() != initValue) { - Thread.sleep(50 + (i * 10)); - } - } - // wait config to be updated - for (int i = 0; i < 5; i++) { - if (pulsar.getConfiguration().getBrokerShutdownTimeoutMs() != shutdownTime) { - Thread.sleep(100 + (i * 10)); - } else { - break; - } - } - // verify value is updated - assertEquals(pulsar.getConfiguration().getBrokerShutdownTimeoutMs(), shutdownTime); - - // (2) try to update non-dynamic field - try { - admin.brokers().updateDynamicConfiguration("metadataStoreUrl", "zk:test-zk:1234"); - } catch (Exception e) { - assertTrue(e instanceof PreconditionFailedException); - } - - // (3) try to update non-existent field - try { - admin.brokers().updateDynamicConfiguration("test", Long.toString(shutdownTime)); - } catch (Exception e) { - assertTrue(e instanceof PreconditionFailedException); - } - pulsar.getConfiguration().setBrokerShutdownTimeoutMs(defaultValue); - } - - /** - * Verifies broker sets watch on dynamic-configuration map even with invalid init json data - * - *
-     * 1. Set invalid json at dynamic-config znode
-     * 2. Broker fails to deserialize znode content but sets the watch on znode
-     * 3. Update znode with valid json map
-     * 4. Broker should get watch and update the dynamic-config map
-     * 
- * - * @throws Exception - */ - @Test - public void testInvalidDynamicConfigContentInZK() throws Exception { - final int newValue = 10; - - // set invalid data into dynamic-config znode so, broker startup fail to deserialize data - pulsar.getLocalMetadataStore().put("/admin/configuration", "$".getBytes(), - Optional.empty()).join(); - stopBroker(); - - // start broker: it should have set watch even if with failure of deserialization - startBroker(); - Assert.assertNotEquals(pulsar.getConfiguration().getBrokerShutdownTimeoutMs(), newValue); - // update zk with config-value which should fire watch and broker should update the config value - Map configMap = new HashMap<>(); - configMap.put("brokerShutdownTimeoutMs", Integer.toString(newValue)); - pulsar.getLocalMetadataStore().put("/admin/configuration", - ObjectMapperFactory.getMapper().writer().writeValueAsBytes(configMap), - Optional.empty()).join(); - // wait config to be updated - for (int i = 0; i < 5; i++) { - if (pulsar.getConfiguration().getBrokerShutdownTimeoutMs() != newValue) { - Thread.sleep(100 + (i * 10)); - } else { - break; - } - } - // verify value is updated - assertEquals(pulsar.getConfiguration().getBrokerShutdownTimeoutMs(), newValue); - - cleanup(); - setup(); - } - - /** - *
-     * verifies: that registerListener updates pulsar.config value with newly updated zk-dynamic config
-     * 1.start pulsar
-     * 2.update zk-config with admin api
-     * 3. trigger watch and listener
-     * 4. verify that config is updated
-     * 
- * - * @throws Exception - */ - @Test - public void testUpdateDynamicLocalConfiguration() throws Exception { - // (1) try to update dynamic field - final long initValue = 30000; - final long shutdownTime = 10; - long defaultValue = pulsar.getConfiguration().getBrokerShutdownTimeoutMs(); - pulsar.getConfiguration().setBrokerShutdownTimeoutMs(initValue); - // update configuration - admin.brokers().updateDynamicConfiguration("brokerShutdownTimeoutMs", Long.toString(shutdownTime)); - // sleep incrementally as zk-watch notification is async and may take some time - for (int i = 0; i < 5; i++) { - if (pulsar.getConfiguration().getBrokerShutdownTimeoutMs() == initValue) { - Thread.sleep(50 + (i * 10)); - } - } - - // verify value is updated - assertEquals(pulsar.getConfiguration().getBrokerShutdownTimeoutMs(), shutdownTime); - - pulsar.getConfiguration().setBrokerShutdownTimeoutMs(defaultValue); - } - - @Test - public void testUpdatableConfigurationName() throws Exception { - // (1) try to update dynamic field - final String configName = "brokerShutdownTimeoutMs"; - assertTrue(admin.brokers().getDynamicConfigurationNames().contains(configName)); - } - - @Test - public void testGetDynamicLocalConfiguration() throws Exception { - // (1) try to update dynamic field - final String configName = "brokerShutdownTimeoutMs"; - final long shutdownTime = 10; - long defaultValue = pulsar.getConfiguration().getBrokerShutdownTimeoutMs(); - pulsar.getConfiguration().setBrokerShutdownTimeoutMs(30000); - Map configs = admin.brokers().getAllDynamicConfigurations(); - assertTrue(configs.isEmpty()); - assertNotEquals(pulsar.getConfiguration().getBrokerShutdownTimeoutMs(), shutdownTime); - // update configuration - admin.brokers().updateDynamicConfiguration(configName, Long.toString(shutdownTime)); - // Now, znode is created: updateConfigurationAndregisterListeners and check if configuration updated - assertEquals(Long.parseLong(admin.brokers().getAllDynamicConfigurations().get(configName)), shutdownTime); - - pulsar.getConfiguration().setBrokerShutdownTimeoutMs(defaultValue); - } - - @Test - public void testTenant() throws Exception { - Set allowedClusters = Set.of("use"); - TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), allowedClusters); - admin.tenants().createTenant("prop-xyz2", tenantInfo); - admin.namespaces().createNamespace("prop-xyz2/use/ns1"); - - assertEquals(admin.tenants().getTenants(), List.of("prop-xyz", "prop-xyz2")); - - assertEquals(admin.tenants().getTenantInfo("prop-xyz2"), tenantInfo); - - TenantInfoImpl newPropertyAdmin = new TenantInfoImpl(Set.of("role3", "role4"), allowedClusters); - admin.tenants().updateTenant("prop-xyz2", newPropertyAdmin); - - assertEquals(admin.tenants().getTenantInfo("prop-xyz2"), newPropertyAdmin); - - admin.namespaces().deleteNamespace("prop-xyz2/use/ns1"); - admin.tenants().deleteTenant("prop-xyz2"); - assertEquals(admin.tenants().getTenants(), List.of("prop-xyz")); - - // Check name validation - try { - admin.tenants().createTenant("prop-xyz&", tenantInfo); - fail("should have failed"); - } catch (PulsarAdminException e) { - assertTrue(e instanceof PreconditionFailedException); - } - } - - @Test - public void namespaces() throws Exception { - admin.clusters().createCluster("usw", ClusterData.builder().build()); - TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), - Set.of("use", "usw")); - admin.tenants().updateTenant("prop-xyz", tenantInfo); - - assertEquals(admin.namespaces().getPolicies("prop-xyz/use/ns1").bundles, PoliciesUtil.defaultBundle()); - - admin.namespaces().createNamespace("prop-xyz/use/ns2"); - - admin.namespaces().createNamespace("prop-xyz/use/ns3", 4); - assertEquals(admin.namespaces().getPolicies("prop-xyz/use/ns3").bundles.getNumBundles(), 4); - assertEquals(admin.namespaces().getPolicies("prop-xyz/use/ns3").bundles.getBoundaries().size(), 5); - - admin.namespaces().deleteNamespace("prop-xyz/use/ns3"); - - try { - admin.namespaces().createNamespace("non-existing/usw/ns1"); - fail("Should not have passed"); - } catch (NotFoundException e) { - // Ok - } - - assertEquals(admin.namespaces().getNamespaces("prop-xyz"), - List.of("prop-xyz/use/ns1", "prop-xyz/use/ns2")); - assertEquals(admin.namespaces().getNamespaces("prop-xyz", "use"), - List.of("prop-xyz/use/ns1", "prop-xyz/use/ns2")); - - try { - admin.namespaces().createNamespace("prop-xyz/usc/ns1"); - fail("Should not have passed"); - } catch (NotAuthorizedException e) { - // Ok, got the non authorized exception since usc cluster is not in the allowed clusters list. - } - - // no need to clear cache once authorization-provide also start using metadata-store - clearCache(); - admin.namespaces().grantPermissionOnNamespace("prop-xyz/use/ns1", "my-role", EnumSet.allOf(AuthAction.class)); - - Policies policies = new Policies(); - policies.bundles = PoliciesUtil.defaultBundle(); - policies.auth_policies.getNamespaceAuthentication().put("my-role", EnumSet.allOf(AuthAction.class)); - policies.is_allow_auto_update_schema = conf.isAllowAutoUpdateSchemaEnabled(); - - assertEquals(admin.namespaces().getPolicies("prop-xyz/use/ns1"), policies); - assertEquals(admin.namespaces().getPermissions("prop-xyz/use/ns1"), - policies.auth_policies.getNamespaceAuthentication()); - - assertEquals(admin.namespaces().getTopics("prop-xyz/use/ns1"), new ArrayList<>()); - - admin.namespaces().revokePermissionsOnNamespace("prop-xyz/use/ns1", "my-role"); - policies.auth_policies.getNamespaceAuthentication().remove("my-role"); - policies.is_allow_auto_update_schema = conf.isAllowAutoUpdateSchemaEnabled(); - assertEquals(admin.namespaces().getPolicies("prop-xyz/use/ns1"), policies); - - assertNull(admin.namespaces().getPersistence("prop-xyz/use/ns1")); - admin.namespaces().setPersistence("prop-xyz/use/ns1", new PersistencePolicies(3, 2, 1, 10.0)); - assertEquals(admin.namespaces().getPersistence("prop-xyz/use/ns1"), new PersistencePolicies(3, 2, 1, 10.0)); - - // Force topic creation and namespace being loaded - Producer producer = pulsarClient.newProducer(Schema.BYTES).topic( - "persistent://prop-xyz/use/ns1/my-topic").create(); - producer.close(); - admin.topics().delete("persistent://prop-xyz/use/ns1/my-topic"); - - admin.namespaces().unloadNamespaceBundle("prop-xyz/use/ns1", "0x00000000_0xffffffff"); - NamespaceName ns = NamespaceName.get("prop-xyz/use/ns1"); - // Now, w/ bundle policies, we will use default bundle - NamespaceBundle defaultBundle = bundleFactory.getFullBundle(ns); - int i = 0; - for (; i < 10; i++) { - Optional data1 = pulsar.getNamespaceService().getOwnershipCache() - .getOwnerAsync(defaultBundle).get(); - if (!data1.isPresent()) { - // Already unloaded - break; - } - LOG.info("Waiting for unload namespace {} to complete. Current service unit isDisabled: {}", defaultBundle, - data1.get().isDisabled()); - Thread.sleep(1000); - } - assertTrue(i < 10); - - admin.namespaces().deleteNamespace("prop-xyz/use/ns1"); - assertEquals(admin.namespaces().getNamespaces("prop-xyz", "use"), List.of("prop-xyz/use/ns2")); - - try { - admin.namespaces().unload("prop-xyz/use/ns1"); - fail("should have raised exception"); - } catch (Exception e) { - // OK excepted - } - - // Force topic creation and namespace being loaded - producer = pulsarClient.newProducer(Schema.BYTES).topic("persistent://prop-xyz/use/ns2/my-topic").create(); - producer.close(); - admin.topics().delete("persistent://prop-xyz/use/ns2/my-topic"); - - // both unload and delete should succeed for ns2 on other broker with a redirect - // otheradmin.namespaces().unload("prop-xyz/use/ns2"); - tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("use")); - admin.tenants().updateTenant("prop-xyz", tenantInfo); - } - - @Test(dataProvider = "topicName") - public void persistentTopics(String topicName) throws Exception { - assertEquals(admin.topics().getList("prop-xyz/use/ns1"), new ArrayList<>()); - - final String persistentTopicName = "persistent://prop-xyz/use/ns1/" + topicName; - // Force to create a topic - publishMessagesOnPersistentTopic("persistent://prop-xyz/use/ns1/" + topicName, 0); - assertEquals(admin.topics().getList("prop-xyz/use/ns1"), - List.of("persistent://prop-xyz/use/ns1/" + topicName)); - - // create consumer and subscription - @Cleanup - PulsarClient client = PulsarClient.builder() - .serviceUrl(pulsar.getWebServiceAddress()) - .statsInterval(0, TimeUnit.SECONDS) - .build(); - Consumer consumer = client.newConsumer().topic(persistentTopicName).subscriptionName("my-sub") - .subscriptionType(SubscriptionType.Exclusive).subscribe(); - - assertEquals(admin.topics().getSubscriptions(persistentTopicName), List.of("my-sub")); - - publishMessagesOnPersistentTopic("persistent://prop-xyz/use/ns1/" + topicName, 10); - - TopicStats topicStats = admin.topics().getStats(persistentTopicName); - assertEquals(topicStats.getSubscriptions().keySet(), new TreeSet<>(List.of("my-sub"))); - assertEquals(topicStats.getSubscriptions().get("my-sub").getConsumers().size(), 1); - assertEquals(topicStats.getSubscriptions().get("my-sub").getMsgBacklog(), 10); - assertEquals(topicStats.getPublishers().size(), 0); - - PersistentTopicInternalStats internalStats = admin.topics().getInternalStats(persistentTopicName, false); - assertEquals(internalStats.cursors.keySet(), new TreeSet<>(List.of("my-sub"))); - - List> messages = admin.topics().peekMessages(persistentTopicName, "my-sub", 3); - assertEquals(messages.size(), 3); - for (int i = 0; i < 3; i++) { - String expectedMessage = "message-" + i; - assertEquals(messages.get(i).getData(), expectedMessage.getBytes()); - } - - messages = admin.topics().peekMessages(persistentTopicName, "my-sub", 15); - assertEquals(messages.size(), 10); - for (int i = 0; i < 10; i++) { - String expectedMessage = "message-" + i; - assertEquals(messages.get(i).getData(), expectedMessage.getBytes()); - } - - admin.topics().skipMessages(persistentTopicName, "my-sub", 5); - topicStats = admin.topics().getStats(persistentTopicName); - assertEquals(topicStats.getSubscriptions().get("my-sub").getMsgBacklog(), 5); - - admin.topics().skipAllMessages(persistentTopicName, "my-sub"); - topicStats = admin.topics().getStats(persistentTopicName); - assertEquals(topicStats.getSubscriptions().get("my-sub").getMsgBacklog(), 0); - - consumer.close(); - client.close(); - - admin.topics().deleteSubscription(persistentTopicName, "my-sub"); - - assertEquals(admin.topics().getSubscriptions(persistentTopicName), new ArrayList<>()); - topicStats = admin.topics().getStats(persistentTopicName); - assertEquals(topicStats.getSubscriptions().keySet(), new TreeSet<>()); - assertEquals(topicStats.getPublishers().size(), 0); - - try { - admin.topics().skipAllMessages(persistentTopicName, "my-sub"); - } catch (NotFoundException e) { - } - - admin.topics().delete(persistentTopicName); - - try { - admin.topics().delete(persistentTopicName); - fail("Should have received 404"); - } catch (NotFoundException e) { - } - - assertEquals(admin.topics().getList("prop-xyz/use/ns1"), new ArrayList<>()); - } - - @Test(dataProvider = "topicName") - public void partitionedTopics(String topicName) throws Exception { - assertEquals(admin.topics().getPartitionedTopicList("prop-xyz/use/ns1"), new ArrayList<>()); - final String partitionedTopicName = "persistent://prop-xyz/use/ns1/" + topicName; - admin.topics().createPartitionedTopic(partitionedTopicName, 4); - assertEquals(admin.topics().getPartitionedTopicList("prop-xyz/use/ns1"), - List.of(partitionedTopicName)); - - assertEquals(admin.topics().getPartitionedTopicMetadata(partitionedTopicName).partitions, 4); - - List topics = admin.topics().getList("prop-xyz/use/ns1"); - assertEquals(topics.size(), 4); - - try { - admin.topics().getPartitionedTopicMetadata("persistent://prop-xyz/use/ns1/ds2"); - fail("getPartitionedTopicMetadata of persistent://prop-xyz/use/ns1/ds2 should not succeed"); - } catch (NotFoundException expected) { - } - - // create consumer and subscription - @Cleanup - PulsarClient client = PulsarClient.builder() - .serviceUrl(pulsar.getWebServiceAddress()) - .statsInterval(0, TimeUnit.SECONDS) - .build(); - Consumer consumer = client.newConsumer().topic(partitionedTopicName).subscriptionName("my-sub") - .subscriptionType(SubscriptionType.Exclusive).subscribe(); - - assertEquals(admin.topics().getSubscriptions(partitionedTopicName), List.of("my-sub")); - - try { - admin.topics().deleteSubscription(partitionedTopicName, "my-sub"); - fail("should have failed"); - } catch (PulsarAdminException.PreconditionFailedException e) { - // ok - } catch (Exception e) { - fail(e.getMessage()); - } - - List subscriptions = admin.topics().getSubscriptions(partitionedTopicName); - assertEquals(subscriptions.size(), 1); - - Consumer consumer1 = client.newConsumer().topic(partitionedTopicName).subscriptionName("my-sub-1") - .subscribe(); - - assertEquals(new HashSet<>(admin.topics().getSubscriptions(partitionedTopicName)), - Set.of("my-sub", "my-sub-1")); - - consumer1.close(); - admin.topics().deleteSubscription(partitionedTopicName, "my-sub-1"); - assertEquals(admin.topics().getSubscriptions(partitionedTopicName), List.of("my-sub")); - - Producer producer = client.newProducer(Schema.BYTES) - .topic(partitionedTopicName) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.RoundRobinPartition) - .create(); - - for (int i = 0; i < 10; i++) { - String message = "message-" + i; - producer.send(message.getBytes()); - } - - assertEquals(new HashSet<>(admin.topics().getList("prop-xyz/use/ns1")), - Set.of(partitionedTopicName + "-partition-0", partitionedTopicName + "-partition-1", - partitionedTopicName + "-partition-2", partitionedTopicName + "-partition-3")); - - // test cumulative stats for partitioned topic - PartitionedTopicStats topicStats = admin.topics().getPartitionedStats(partitionedTopicName, false); - assertEquals(topicStats.getSubscriptions().keySet(), new TreeSet<>(List.of("my-sub"))); - assertEquals(topicStats.getSubscriptions().get("my-sub").getConsumers().size(), 1); - assertEquals(topicStats.getSubscriptions().get("my-sub").getMsgBacklog(), 10); - assertEquals(topicStats.getPublishers().size(), 1); - assertEquals(topicStats.getPartitions(), new HashMap<>()); - - // test per partition stats for partitioned topic - topicStats = admin.topics().getPartitionedStats(partitionedTopicName, true); - assertEquals(topicStats.getMetadata().partitions, 4); - assertEquals(topicStats.getPartitions().keySet(), - Set.of(partitionedTopicName + "-partition-0", partitionedTopicName + "-partition-1", - partitionedTopicName + "-partition-2", partitionedTopicName + "-partition-3")); - TopicStats partitionStats = topicStats.getPartitions().get(partitionedTopicName + "-partition-0"); - assertEquals(partitionStats.getPublishers().size(), 1); - assertEquals(partitionStats.getSubscriptions().get("my-sub").getConsumers().size(), 1); - assertEquals(partitionStats.getSubscriptions().get("my-sub").getMsgBacklog(), 3, 1); - - try { - admin.topics().skipMessages(partitionedTopicName, "my-sub", 5); - fail("skip messages for partitioned topics should fail"); - } catch (Exception e) { - // ok - } - - admin.topics().skipAllMessages(partitionedTopicName, "my-sub"); - topicStats = admin.topics().getPartitionedStats(partitionedTopicName, false); - assertEquals(topicStats.getSubscriptions().get("my-sub").getMsgBacklog(), 0); - - producer.close(); - consumer.close(); - - admin.topics().deleteSubscription(partitionedTopicName, "my-sub"); - - assertEquals(admin.topics().getSubscriptions(partitionedTopicName), new ArrayList<>()); - - try { - admin.topics().createPartitionedTopic(partitionedTopicName, 32); - fail("Should have failed as the partitioned topic exists with its partition created"); - } catch (ConflictException ignore) { - } - - producer = client.newProducer(Schema.BYTES) - .topic(partitionedTopicName) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - - topics = admin.topics().getList("prop-xyz/use/ns1"); - assertEquals(topics.size(), 4); - - try { - admin.topics().deletePartitionedTopic(partitionedTopicName); - fail("The topic is busy"); - } catch (PreconditionFailedException pfe) { - // ok - } - - producer.close(); - client.close(); - - admin.topics().deletePartitionedTopic(partitionedTopicName); - - try { - admin.topics().getPartitionedTopicMetadata(partitionedTopicName); - fail("getPartitionedTopicMetadata of " + partitionedTopicName + " should not succeed"); - } catch (NotFoundException expected) { - } - - admin.topics().createPartitionedTopic(partitionedTopicName, 32); - - assertEquals(admin.topics().getPartitionedTopicMetadata(partitionedTopicName).partitions, 32); - - try { - admin.topics().deletePartitionedTopic("persistent://prop-xyz/use/ns1/ds2"); - fail("Should have failed as the partitioned topic was not created"); - } catch (NotFoundException nfe) { - } - - admin.topics().deletePartitionedTopic(partitionedTopicName); - - // delete a partitioned topic in a global namespace - admin.topics().createPartitionedTopic(partitionedTopicName, 4); - admin.topics().deletePartitionedTopic(partitionedTopicName); - } - - @Test(dataProvider = "numBundles") - public void testDeleteNamespaceBundle(Integer numBundles) throws Exception { - admin.namespaces().deleteNamespace("prop-xyz/use/ns1"); - admin.namespaces().createNamespace("prop-xyz/use/ns1-bundles", numBundles); - - // since we have 2 brokers running, we try to let both of them acquire bundle ownership - admin.lookups().lookupTopic("persistent://prop-xyz/use/ns1-bundles/ds1"); - admin.lookups().lookupTopic("persistent://prop-xyz/use/ns1-bundles/ds2"); - admin.lookups().lookupTopic("persistent://prop-xyz/use/ns1-bundles/ds3"); - admin.lookups().lookupTopic("persistent://prop-xyz/use/ns1-bundles/ds4"); - - assertEquals(admin.namespaces().getTopics("prop-xyz/use/ns1-bundles"), new ArrayList<>()); - - admin.namespaces().deleteNamespace("prop-xyz/use/ns1-bundles"); - assertEquals(admin.namespaces().getNamespaces("prop-xyz", "use"), new ArrayList<>()); - } - - @Test - public void testNamespaceSplitBundle() throws Exception { - // Force to create a topic - final String namespace = "prop-xyz/use/ns1"; - final String topicName = "persistent://" + namespace + "/ds2"; - Producer producer = pulsarClient.newProducer(Schema.BYTES) - .topic(topicName) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - producer.send("message".getBytes()); - publishMessagesOnPersistentTopic(topicName, 0); - assertEquals(admin.topics().getList(namespace), List.of(topicName)); - - try { - admin.namespaces().splitNamespaceBundle(namespace, "0x00000000_0xffffffff", true, null); - } catch (Exception e) { - fail("split bundle shouldn't have thrown exception"); - } - - // bundle-factory cache must have updated split bundles - NamespaceBundles bundles = bundleFactory.getBundles(NamespaceName.get(namespace)); - String[] splitRange = { namespace + "/0x00000000_0x7fffffff", namespace + "/0x7fffffff_0xffffffff" }; - for (int i = 0; i < bundles.getBundles().size(); i++) { - assertEquals(bundles.getBundles().get(i).toString(), splitRange[i]); - } - - producer.close(); - } - - @Test - public void testNamespaceSplitBundleConcurrent() throws Exception { - // Force to create a topic - final String namespace = "prop-xyz/use/ns1"; - final String topicName = "persistent://" + namespace + "/ds2"; - Producer producer = pulsarClient.newProducer(Schema.BYTES) - .topic(topicName) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - producer.send("message".getBytes()); - publishMessagesOnPersistentTopic(topicName, 0); - assertEquals(admin.topics().getList(namespace), List.of(topicName)); - - try { - admin.namespaces().splitNamespaceBundle(namespace, "0x00000000_0xffffffff", false, null); - } catch (Exception e) { - fail("split bundle shouldn't have thrown exception"); - } - - // bundle-factory cache must have updated split bundles - NamespaceBundles bundles = bundleFactory.getBundles(NamespaceName.get(namespace)); - String[] splitRange = {namespace + "/0x00000000_0x7fffffff", namespace + "/0x7fffffff_0xffffffff"}; - for (int i = 0; i < bundles.getBundles().size(); i++) { - assertEquals(bundles.getBundles().get(i).toString(), splitRange[i]); - } - - @Cleanup("shutdownNow") - ExecutorService executorService = Executors.newCachedThreadPool(); - - - try { - executorService.invokeAll( - Arrays.asList( - () -> { - log.info("split 2 bundles at the same time. spilt: 0x00000000_0x7fffffff "); - admin.namespaces().splitNamespaceBundle(namespace, "0x00000000_0x7fffffff", false, null); - return null; - }, - () -> { - log.info("split 2 bundles at the same time. spilt: 0x7fffffff_0xffffffff "); - admin.namespaces().splitNamespaceBundle(namespace, "0x7fffffff_0xffffffff", false, null); - return null; - } - ) - ); - } catch (Exception e) { - fail("split bundle shouldn't have thrown exception"); - } - - String[] splitRange4 = { - namespace + "/0x00000000_0x3fffffff", - namespace + "/0x3fffffff_0x7fffffff", - namespace + "/0x7fffffff_0xbfffffff", - namespace + "/0xbfffffff_0xffffffff"}; - bundles = bundleFactory.getBundles(NamespaceName.get(namespace)); - assertEquals(bundles.getBundles().size(), 4); - for (int i = 0; i < bundles.getBundles().size(); i++) { - assertEquals(bundles.getBundles().get(i).toString(), splitRange4[i]); - } - - try { - executorService.invokeAll( - Arrays.asList( - () -> { - log.info("split 4 bundles at the same time. spilt: 0x00000000_0x3fffffff "); - admin.namespaces().splitNamespaceBundle(namespace, "0x00000000_0x3fffffff", false, null); - return null; - }, - () -> { - log.info("split 4 bundles at the same time. spilt: 0x3fffffff_0x7fffffff "); - admin.namespaces().splitNamespaceBundle(namespace, "0x3fffffff_0x7fffffff", false, null); - return null; - }, - () -> { - log.info("split 4 bundles at the same time. spilt: 0x7fffffff_0xbfffffff "); - admin.namespaces().splitNamespaceBundle(namespace, "0x7fffffff_0xbfffffff", false, null); - return null; - }, - () -> { - log.info("split 4 bundles at the same time. spilt: 0xbfffffff_0xffffffff "); - admin.namespaces().splitNamespaceBundle(namespace, "0xbfffffff_0xffffffff", false, null); - return null; - } - ) - ); - } catch (Exception e) { - fail("split bundle shouldn't have thrown exception"); - } - - String[] splitRange8 = { - namespace + "/0x00000000_0x1fffffff", - namespace + "/0x1fffffff_0x3fffffff", - namespace + "/0x3fffffff_0x5fffffff", - namespace + "/0x5fffffff_0x7fffffff", - namespace + "/0x7fffffff_0x9fffffff", - namespace + "/0x9fffffff_0xbfffffff", - namespace + "/0xbfffffff_0xdfffffff", - namespace + "/0xdfffffff_0xffffffff"}; - bundles = bundleFactory.getBundles(NamespaceName.get(namespace)); - assertEquals(bundles.getBundles().size(), 8); - for (int i = 0; i < bundles.getBundles().size(); i++) { - assertEquals(bundles.getBundles().get(i).toString(), splitRange8[i]); - } - - producer.close(); - } - - @Test - public void testNamespaceUnloadBundle() throws Exception { - assertEquals(admin.topics().getList("prop-xyz/use/ns1"), new ArrayList<>()); - - // Force to create a topic - publishMessagesOnPersistentTopic("persistent://prop-xyz/use/ns1/ds2", 0); - assertEquals(admin.topics().getList("prop-xyz/use/ns1"), - List.of("persistent://prop-xyz/use/ns1/ds2")); - - // create consumer and subscription - Consumer consumer = pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns1/ds2") - .subscriptionName("my-sub").subscribe(); - assertEquals(admin.topics().getSubscriptions("persistent://prop-xyz/use/ns1/ds2"), - List.of("my-sub")); - - // Create producer - Producer producer = pulsarClient.newProducer(Schema.BYTES) - .topic("persistent://prop-xyz/use/ns1/ds2") - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - for (int i = 0; i < 10; i++) { - String message = "message-" + i; - producer.send(message.getBytes()); - } - - consumer.close(); - producer.close(); - - try { - admin.namespaces().unloadNamespaceBundle("prop-xyz/use/ns1", "0x00000000_0xffffffff"); - } catch (Exception e) { - fail("Unload shouldn't have throw exception"); - } - - // check that no one owns the namespace - NamespaceBundle bundle = bundleFactory.getBundle(NamespaceName.get("prop-xyz/use/ns1"), - Range.range(0L, BoundType.CLOSED, 0xffffffffL, BoundType.CLOSED)); - assertFalse(pulsar.getNamespaceService().isServiceUnitOwned(bundle)); - assertFalse(otherPulsar.getNamespaceService().isServiceUnitOwned(bundle)); - pulsarClient.shutdown(); - - LOG.info("--- RELOAD ---"); - - // Force reload of namespace and wait for topic to be ready - for (int i = 0; i < 30; i++) { - try { - admin.topics().getStats("persistent://prop-xyz/use/ns1/ds2"); - break; - } catch (PulsarAdminException e) { - LOG.warn("Failed to get topic stats.. {}", e.getMessage()); - Thread.sleep(1000); - } - } - - admin.topics().deleteSubscription("persistent://prop-xyz/use/ns1/ds2", "my-sub"); - admin.topics().delete("persistent://prop-xyz/use/ns1/ds2"); - } - - @Test(dataProvider = "numBundles") - public void testNamespaceBundleUnload(Integer numBundles) throws Exception { - admin.namespaces().createNamespace("prop-xyz/use/ns1-bundles", numBundles); - - assertEquals(admin.topics().getList("prop-xyz/use/ns1-bundles"), new ArrayList<>()); - - // Force to create a topic - publishMessagesOnPersistentTopic("persistent://prop-xyz/use/ns1-bundles/ds2", 0); - assertEquals(admin.topics().getList("prop-xyz/use/ns1-bundles"), - List.of("persistent://prop-xyz/use/ns1-bundles/ds2")); - - // create consumer and subscription - Consumer consumer = pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns1-bundles/ds2") - .subscriptionName("my-sub").subscribe(); - assertEquals(admin.topics().getSubscriptions("persistent://prop-xyz/use/ns1-bundles/ds2"), - List.of("my-sub")); - - // Create producer - Producer producer = pulsarClient.newProducer(Schema.BYTES) - .topic("persistent://prop-xyz/use/ns1-bundles/ds2") - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - for (int i = 0; i < 10; i++) { - String message = "message-" + i; - producer.send(message.getBytes()); - } - - NamespaceBundle bundle = pulsar.getNamespaceService() - .getBundle(TopicName.get("persistent://prop-xyz/use/ns1-bundles/ds2")); - - consumer.close(); - producer.close(); - - admin.namespaces().unloadNamespaceBundle("prop-xyz/use/ns1-bundles", bundle.getBundleRange()); - - // check that no one owns the namespace bundle - assertFalse(pulsar.getNamespaceService().isServiceUnitOwned(bundle)); - assertFalse(otherPulsar.getNamespaceService().isServiceUnitOwned(bundle)); - - LOG.info("--- RELOAD ---"); - - // Force reload of namespace and wait for topic to be ready - for (int i = 0; i < 30; i++) { - try { - admin.topics().getStats("persistent://prop-xyz/use/ns1-bundles/ds2"); - break; - } catch (PulsarAdminException e) { - LOG.warn("Failed to get topic stats.. {}", e.getMessage()); - Thread.sleep(1000); - } - } - - admin.topics().deleteSubscription("persistent://prop-xyz/use/ns1-bundles/ds2", "my-sub"); - admin.topics().delete("persistent://prop-xyz/use/ns1-bundles/ds2"); - } - - @Test(dataProvider = "bundling") - public void testClearBacklogOnNamespace(Integer numBundles) throws Exception { - admin.namespaces().createNamespace("prop-xyz/use/ns1-bundles", numBundles); - - // create consumer and subscription - @Cleanup - Consumer subscribe = - pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns1-bundles/ds2").subscriptionName("my-sub") - .subscribe(); - @Cleanup - Consumer subscribe1 = pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns1-bundles/ds2") - .subscriptionName("my-sub-1") - .subscribe(); - @Cleanup - Consumer subscribe2 = pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns1-bundles/ds2") - .subscriptionName("my-sub-2") - .subscribe(); - @Cleanup - Consumer subscribe3 = - pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns1-bundles/ds1").subscriptionName("my-sub") - .subscribe(); - @Cleanup - Consumer subscribe4 = pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns1-bundles/ds1") - .subscriptionName("my-sub-1") - .subscribe(); - - // Create producer - Producer producer = pulsarClient.newProducer(Schema.BYTES) - .topic("persistent://prop-xyz/use/ns1-bundles/ds2") - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - for (int i = 0; i < 10; i++) { - String message = "message-" + i; - producer.send(message.getBytes()); - } - - producer.close(); - - // Create producer - Producer producer1 = pulsarClient.newProducer(Schema.BYTES) - .topic("persistent://prop-xyz/use/ns1-bundles/ds1") - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - for (int i = 0; i < 10; i++) { - String message = "message-" + i; - producer1.send(message.getBytes()); - } - - producer1.close(); - - admin.namespaces().clearNamespaceBacklogForSubscription("prop-xyz/use/ns1-bundles", "my-sub"); - - long backlog = admin.topics().getStats("persistent://prop-xyz/use/ns1-bundles/ds2").getSubscriptions() - .get("my-sub").getMsgBacklog(); - assertEquals(backlog, 0); - backlog = admin.topics().getStats("persistent://prop-xyz/use/ns1-bundles/ds1").getSubscriptions() - .get("my-sub").getMsgBacklog(); - assertEquals(backlog, 0); - backlog = admin.topics().getStats("persistent://prop-xyz/use/ns1-bundles/ds1").getSubscriptions() - .get("my-sub-1").getMsgBacklog(); - assertEquals(backlog, 10); - - admin.namespaces().clearNamespaceBacklog("prop-xyz/use/ns1-bundles"); - - backlog = admin.topics().getStats("persistent://prop-xyz/use/ns1-bundles/ds1").getSubscriptions() - .get("my-sub-1").getMsgBacklog(); - assertEquals(backlog, 0); - backlog = admin.topics().getStats("persistent://prop-xyz/use/ns1-bundles/ds2").getSubscriptions() - .get("my-sub-1").getMsgBacklog(); - assertEquals(backlog, 0); - backlog = admin.topics().getStats("persistent://prop-xyz/use/ns1-bundles/ds2").getSubscriptions() - .get("my-sub-2").getMsgBacklog(); - assertEquals(backlog, 0); - } - - @Test(dataProvider = "bundling") - public void testUnsubscribeOnNamespace(Integer numBundles) throws Exception { - admin.namespaces().createNamespace("prop-xyz/use/ns1-bundles", numBundles); - - // create consumer and subscription - Consumer consumer1 = pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns1-bundles/ds2") - .subscriptionName("my-sub").subscribe(); - Consumer consumer2 = pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns1-bundles/ds2") - .subscriptionName("my-sub-1").subscribe(); - /* Consumer consumer3 = */ pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns1-bundles/ds2") - .subscriptionName("my-sub-2").subscribe().close(); - Consumer consumer4 = pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns1-bundles/ds1") - .subscriptionName("my-sub").subscribe(); - Consumer consumer5 = pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns1-bundles/ds1") - .subscriptionName("my-sub-1").subscribe(); - - try { - admin.namespaces().unsubscribeNamespace("prop-xyz/use/ns1-bundles", "my-sub"); - fail("should have failed"); - } catch (PulsarAdminException.PreconditionFailedException e) { - // ok - } - - consumer1.close(); - - try { - admin.namespaces().unsubscribeNamespace("prop-xyz/use/ns1-bundles", "my-sub"); - fail("should have failed"); - } catch (PulsarAdminException.PreconditionFailedException e) { - // ok - } - - consumer4.close(); - - admin.namespaces().unsubscribeNamespace("prop-xyz/use/ns1-bundles", "my-sub"); - - assertEquals(admin.topics().getSubscriptions("persistent://prop-xyz/use/ns1-bundles/ds2").stream() - .sorted().toList(), List.of("my-sub-1", "my-sub-2")); - assertEquals(admin.topics().getSubscriptions("persistent://prop-xyz/use/ns1-bundles/ds1"), - List.of("my-sub-1")); - - consumer2.close(); - consumer5.close(); - - admin.namespaces().unsubscribeNamespace("prop-xyz/use/ns1-bundles", "my-sub-1"); - - assertEquals(admin.topics().getSubscriptions("persistent://prop-xyz/use/ns1-bundles/ds2"), - List.of("my-sub-2")); - assertEquals(admin.topics().getSubscriptions("persistent://prop-xyz/use/ns1-bundles/ds1"), - new ArrayList<>()); - } - - private void publishMessagesOnPersistentTopic(String topicName, int messages) throws Exception { - publishMessagesOnPersistentTopic(topicName, messages, 0); - } - - private void publishMessagesOnPersistentTopic(String topicName, int messages, int startIdx) throws Exception { - Producer producer = pulsarClient.newProducer(Schema.BYTES) - .topic(topicName) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - - for (int i = startIdx; i < (messages + startIdx); i++) { - String message = "message-" + i; - producer.send(message.getBytes()); - } - - producer.close(); - } - - @Test - public void backlogQuotas() throws Exception { - assertEquals(admin.namespaces().getBacklogQuotaMap("prop-xyz/use/ns1"), - new HashMap<>()); - - Map quotaMap = admin.namespaces().getBacklogQuotaMap("prop-xyz/use/ns1"); - assertEquals(quotaMap.size(), 0); - assertNull(quotaMap.get(BacklogQuotaType.destination_storage)); - - admin.namespaces().setBacklogQuota("prop-xyz/use/ns1", - BacklogQuota.builder() - .limitSize(1 * 1024 * 1024) - .retentionPolicy(RetentionPolicy.producer_exception) - .build()); - quotaMap = admin.namespaces().getBacklogQuotaMap("prop-xyz/use/ns1"); - assertEquals(quotaMap.size(), 1); - assertEquals(quotaMap.get(BacklogQuotaType.destination_storage), BacklogQuota.builder() - .limitSize(1 * 1024 * 1024) - .retentionPolicy(RetentionPolicy.producer_exception) - .build()); - - admin.namespaces().removeBacklogQuota("prop-xyz/use/ns1"); - - quotaMap = admin.namespaces().getBacklogQuotaMap("prop-xyz/use/ns1"); - assertEquals(quotaMap.size(), 0); - assertNull(quotaMap.get(BacklogQuotaType.destination_storage)); - } - - @Test - public void statsOnNonExistingTopics() throws Exception { - try { - admin.topics().getStats("persistent://prop-xyz/use/ns1/ghostTopic"); - fail("The topic doesn't exist"); - } catch (NotFoundException e) { - // OK - } - } - - @Test - public void testDeleteFailedReturnCode() throws Exception { - String topicName = "persistent://prop-xyz/use/ns1/my-topic"; - Producer producer = pulsarClient.newProducer(Schema.BYTES) - .topic(topicName) - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.SinglePartition) - .create(); - - try { - admin.topics().delete(topicName); - fail("The topic is busy"); - } catch (PreconditionFailedException e) { - // OK - } - - producer.close(); - - Consumer consumer = pulsarClient.newConsumer().topic(topicName).subscriptionName("sub").subscribe(); - - try { - admin.topics().delete(topicName); - fail("The topic is busy"); - } catch (PreconditionFailedException e) { - // OK - } - - try { - admin.topics().deleteSubscription(topicName, "sub"); - fail("The topic is busy"); - } catch (PreconditionFailedException e) { - // Ok - } - - consumer.close(); - - // Now should succeed - admin.topics().delete(topicName); - } - - private static class IncompatiblePropertyAdmin { - public Set allowedClusters; - public int someNewIntField; - public String someNewString; - } - - @Test - public void testJacksonWithTypeDifferencies() throws Exception { - String expectedJson = "{\"adminRoles\":[\"role1\",\"role2\"],\"allowedClusters\":[\"usw\",\"use\"]}"; - IncompatiblePropertyAdmin r1 = ObjectMapperFactory.getMapper().reader().forType(IncompatiblePropertyAdmin.class) - .readValue(expectedJson); - assertEquals(r1.allowedClusters, Set.of("use", "usw")); - assertEquals(r1.someNewIntField, 0); - assertNull(r1.someNewString); - } - - @Test - public void testBackwardCompatiblity() throws Exception { - Set allowedClusters = Set.of("use"); - TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), allowedClusters); - admin.tenants().createTenant("prop-xyz2", tenantInfo); - admin.namespaces().createNamespace("prop-xyz2/use/ns1"); - - assertEquals(admin.tenants().getTenants(), List.of("prop-xyz", "prop-xyz2")); - assertEquals(admin.tenants().getTenantInfo("prop-xyz2").getAdminRoles(), - List.of("role1", "role2")); - assertEquals(admin.tenants().getTenantInfo("prop-xyz2").getAllowedClusters(), Set.of("use")); - - // Try to deserialize property JSON with IncompatiblePropertyAdmin format - // it should succeed ignoring missing fields - TenantsImpl properties = (TenantsImpl) admin.tenants(); - IncompatiblePropertyAdmin result = properties.request(properties.getWebTarget().path("prop-xyz2")) - .get(IncompatiblePropertyAdmin.class); - - assertEquals(result.allowedClusters, Set.of("use")); - assertEquals(result.someNewIntField, 0); - assertNull(result.someNewString); - - admin.namespaces().deleteNamespace("prop-xyz2/use/ns1"); - admin.tenants().deleteTenant("prop-xyz2"); - assertEquals(admin.tenants().getTenants(), Set.of("prop-xyz")); - } - - @Test(dataProvider = "topicName") - public void persistentTopicsCursorReset(String topicName) throws Exception { - admin.namespaces().setRetention("prop-xyz/use/ns1", new RetentionPolicies(10, 10)); - - assertEquals(admin.topics().getList("prop-xyz/use/ns1"), new ArrayList<>()); - - topicName = "persistent://prop-xyz/use/ns1/" + topicName; - - // create consumer and subscription - Consumer consumer = pulsarClient.newConsumer().topic(topicName) - .subscriptionName("my-sub").startMessageIdInclusive() - .subscriptionType(SubscriptionType.Exclusive) - .acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); - - assertEquals(admin.topics().getSubscriptions(topicName), List.of("my-sub")); - - publishMessagesOnPersistentTopic(topicName, 5, 0); - - // Allow at least 1ms for messages to have different timestamps - Thread.sleep(1); - long messageTimestamp = System.currentTimeMillis(); - - publishMessagesOnPersistentTopic(topicName, 5, 5); - - List> messages = admin.topics().peekMessages(topicName, "my-sub", 10); - assertEquals(messages.size(), 10); - - for (int i = 0; i < 10; i++) { - Message message = consumer.receive(); - consumer.acknowledge(message); - } - // messages should still be available due to retention - - admin.topics().resetCursor(topicName, "my-sub", messageTimestamp); - - int receivedAfterReset = 0; - - for (int i = 5; i < 10; i++) { - Message message = consumer.receive(); - consumer.acknowledge(message); - ++receivedAfterReset; - String expected = "message-" + i; - assertEquals(message.getData(), expected.getBytes()); - } - assertEquals(receivedAfterReset, 5); - - consumer.close(); - - admin.topics().deleteSubscription(topicName, "my-sub"); - - assertEquals(admin.topics().getSubscriptions(topicName), new ArrayList<>()); - admin.topics().delete(topicName); - } - - @Test(dataProvider = "topicName") - public void persistentTopicsCursorResetAfterReset(String topicName) throws Exception { - admin.namespaces().setRetention("prop-xyz/use/ns1", new RetentionPolicies(10, 10)); - assertEquals(admin.topics().getList("prop-xyz/use/ns1"), new ArrayList<>()); - - topicName = "persistent://prop-xyz/use/ns1/" + topicName; - - // create consumer and subscription - Consumer consumer = pulsarClient.newConsumer().topic(topicName) - .subscriptionName("my-sub").startMessageIdInclusive() - .subscriptionType(SubscriptionType.Exclusive) - .acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); - - assertEquals(admin.topics().getSubscriptions(topicName), List.of("my-sub")); - - publishMessagesOnPersistentTopic(topicName, 5, 0); - - // Allow at least 1ms for messages to have different timestamps - Thread.sleep(1); - long firstTimestamp = System.currentTimeMillis(); - publishMessagesOnPersistentTopic(topicName, 3, 5); - - Thread.sleep(1); - long secondTimestamp = System.currentTimeMillis(); - - publishMessagesOnPersistentTopic(topicName, 2, 8); - - List> messages = admin.topics().peekMessages(topicName, "my-sub", 10); - assertEquals(messages.size(), 10); - messages.forEach(message -> { - LOG.info("Peeked message: {}", new String(message.getData())); - }); - - for (int i = 0; i < 10; i++) { - Message message = consumer.receive(); - consumer.acknowledge(message); - } - - admin.topics().resetCursor(topicName, "my-sub", firstTimestamp); - - int receivedAfterReset = 0; - - // Should received messages from 5-9 - for (int i = 5; i < 10; i++) { - Message message = consumer.receive(); - consumer.acknowledge(message); - ++receivedAfterReset; - String expected = "message-" + i; - assertEquals(new String(message.getData()), expected); - } - assertEquals(receivedAfterReset, 5); - - // Reset at 2nd timestamp - receivedAfterReset = 0; - admin.topics().resetCursor(topicName, "my-sub", secondTimestamp); - - // Should received messages from 8-9 - for (int i = 8; i < 10; i++) { - Message message = consumer.receive(); - consumer.acknowledge(message); - ++receivedAfterReset; - String expected = "message-" + i; - assertEquals(new String(message.getData()), expected); - } - assertEquals(receivedAfterReset, 2); - - consumer.close(); - admin.topics().deleteSubscription(topicName, "my-sub"); - - assertEquals(admin.topics().getSubscriptions(topicName), new ArrayList<>()); - admin.topics().delete(topicName); - } - - @Test(dataProvider = "topicName") - public void partitionedTopicsCursorReset(String topicName) throws Exception { - admin.namespaces().setRetention("prop-xyz/use/ns1", new RetentionPolicies(10, 10)); - topicName = "persistent://prop-xyz/use/ns1/" + topicName; - - admin.topics().createPartitionedTopic(topicName, 4); - - // create consumer and subscription - Consumer consumer = pulsarClient.newConsumer().topic(topicName) - .subscriptionName("my-sub").startMessageIdInclusive() - .subscriptionType(SubscriptionType.Exclusive) - .acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); - - List topics = admin.topics().getList("prop-xyz/use/ns1"); - assertEquals(topics.size(), 4); - - assertEquals(admin.topics().getSubscriptions(topicName), List.of("my-sub")); - - publishMessagesOnPersistentTopic(topicName, 5, 0); - Thread.sleep(1); - - long timestamp = System.currentTimeMillis(); - publishMessagesOnPersistentTopic(topicName, 5, 5); - - for (int i = 0; i < 10; i++) { - Message message = consumer.receive(); - consumer.acknowledge(message); - } - // messages should still be available due to retention - - admin.topics().resetCursor(topicName, "my-sub", timestamp); - - Set expectedMessages = new HashSet<>(); - Set receivedMessages = new HashSet<>(); - for (int i = 5; i < 10; i++) { - Message message = consumer.receive(); - consumer.acknowledge(message); - expectedMessages.add("message-" + i); - receivedMessages.add(new String(message.getData())); - } - - receivedMessages.removeAll(expectedMessages); - assertEquals(receivedMessages.size(), 0); - - consumer.close(); - admin.topics().deleteSubscription(topicName, "my-sub"); - admin.topics().deletePartitionedTopic(topicName); - } - - @Test - public void persistentTopicsInvalidCursorReset() throws Exception { - admin.namespaces().setRetention("prop-xyz/use/ns1", new RetentionPolicies(10, 10)); - - assertEquals(admin.topics().getList("prop-xyz/use/ns1"), new ArrayList<>()); - - String topicName = "persistent://prop-xyz/use/ns1/invalidcursorreset"; - // Force to create a topic - publishMessagesOnPersistentTopic(topicName, 0); - assertEquals(admin.topics().getList("prop-xyz/use/ns1"), List.of(topicName)); - - // create consumer and subscription - @Cleanup - PulsarClient client = PulsarClient.builder() - .serviceUrl(pulsar.getWebServiceAddress()) - .statsInterval(0, TimeUnit.SECONDS) - .build(); - Consumer consumer = client.newConsumer().topic(topicName).subscriptionName("my-sub") - .subscriptionType(SubscriptionType.Exclusive).subscribe(); - - assertEquals(admin.topics().getSubscriptions(topicName), List.of("my-sub")); - - publishMessagesOnPersistentTopic(topicName, 10); - - List> messages = admin.topics().peekMessages(topicName, "my-sub", 10); - assertEquals(messages.size(), 10); - - for (int i = 0; i < 10; i++) { - Message message = consumer.receive(); - consumer.acknowledge(message); - } - // use invalid timestamp - try { - admin.topics().resetCursor(topicName, "my-sub", System.currentTimeMillis() - 190000); - } catch (Exception e) { - // fail the test - throw e; - } - - admin.topics().resetCursor(topicName, "my-sub", System.currentTimeMillis() + 90000); - consumer = client.newConsumer().topic(topicName).subscriptionName("my-sub").subscribe(); - consumer.close(); - client.close(); - - admin.topics().deleteSubscription(topicName, "my-sub"); - - assertEquals(admin.topics().getSubscriptions(topicName), new ArrayList<>()); - admin.topics().delete(topicName); - } - - @Value - @Builder - static class CustomTenantAdmin implements TenantInfo { - private final int newTenant; - private final Set adminRoles; - private final Set allowedClusters; - } - - @Test - public void testObjectWithUnknownProperties() { - TenantInfo pa = TenantInfo.builder() - .adminRoles(Set.of("test_appid1", "test_appid2")) - .allowedClusters(Set.of("use")) - .build(); - CustomTenantAdmin cpa = CustomTenantAdmin.builder() - .adminRoles(pa.getAdminRoles()) - .allowedClusters(pa.getAllowedClusters()) - .newTenant(100) - .build(); - - try { - admin.tenants().createTenant("test-property", cpa); - } catch (Exception e) { - fail("Should not happen : ", e); - } - } - - /** - *
-     * Verify: PersistentTopicsBase.expireMessages()/expireMessagesForAllSubscriptions()
-     * 1. Created multiple shared subscriptions and publisher on topic
-     * 2. Publish messages on the topic
-     * 3. expire message on sub-1 : backlog for sub-1 must be 0
-     * 4. expire message on all subscriptions: backlog for all subscription must be 0
-     * 
- * - * @throws Exception - */ - @Test - public void testPersistentTopicsExpireMessages() throws Exception { - cleanup(); - setup(); - - // Force to create a topic - publishMessagesOnPersistentTopic("persistent://prop-xyz/use/ns1/ds2", 0); - assertEquals(admin.topics().getList("prop-xyz/use/ns1"), - List.of("persistent://prop-xyz/use/ns1/ds2")); - - // create consumer and subscription - @Cleanup - PulsarClient client = PulsarClient.builder() - .serviceUrl(pulsar.getWebServiceAddress()) - .statsInterval(0, TimeUnit.SECONDS) - .build(); - ConsumerBuilder consumerBuilder = client.newConsumer().topic("persistent://prop-xyz/use/ns1/ds2") - .subscriptionType(SubscriptionType.Shared); - Consumer consumer1 = consumerBuilder.clone().subscriptionName("my-sub1").subscribe(); - Consumer consumer2 = consumerBuilder.clone().subscriptionName("my-sub2").subscribe(); - Consumer consumer3 = consumerBuilder.clone().subscriptionName("my-sub3").subscribe(); - - assertEquals(admin.topics().getSubscriptions("persistent://prop-xyz/use/ns1/ds2").size(), 3); - - publishMessagesOnPersistentTopic("persistent://prop-xyz/use/ns1/ds2", 10); - - TopicStats topicStats = admin.topics().getStats("persistent://prop-xyz/use/ns1/ds2"); - assertEquals(topicStats.getSubscriptions().get("my-sub1").getMsgBacklog(), 10); - assertEquals(topicStats.getSubscriptions().get("my-sub2").getMsgBacklog(), 10); - assertEquals(topicStats.getSubscriptions().get("my-sub3").getMsgBacklog(), 10); - - Thread.sleep(1000); // wait for 1 seconds to expire message - admin.topics().expireMessages("persistent://prop-xyz/use/ns1/ds2", "my-sub1", 1); - Thread.sleep(1000); // wait for 1 seconds to execute expire message as it is async - - topicStats = admin.topics().getStats("persistent://prop-xyz/use/ns1/ds2"); - assertEquals(topicStats.getSubscriptions().get("my-sub1").getMsgBacklog(), 0); - assertEquals(topicStats.getSubscriptions().get("my-sub2").getMsgBacklog(), 10); - assertEquals(topicStats.getSubscriptions().get("my-sub3").getMsgBacklog(), 10); - - try { - admin.topics().expireMessagesForAllSubscriptions("persistent://prop-xyz/use/ns1/ds2", 1); - } catch (Exception e) { - // my-sub1 has no msg backlog, so expire message won't be issued on that subscription - assertTrue(e.getMessage().startsWith("Expire message by timestamp not issued on topic")); - } - Thread.sleep(1000); // wait for 1 seconds to execute expire message as it is async - - topicStats = admin.topics().getStats("persistent://prop-xyz/use/ns1/ds2"); - assertEquals(topicStats.getSubscriptions().get("my-sub1").getMsgBacklog(), 0); - assertEquals(topicStats.getSubscriptions().get("my-sub2").getMsgBacklog(), 0); - assertEquals(topicStats.getSubscriptions().get("my-sub3").getMsgBacklog(), 0); - - consumer1.close(); - consumer2.close(); - consumer3.close(); - - } - - /** - * Verify: PersistentTopicsBase.expireMessages()/expireMessagesForAllSubscriptions() for PartitionTopic. - * - * @throws Exception - */ - @Test - public void testPersistentTopicExpireMessageOnPartitionTopic() throws Exception { - - admin.topics().createPartitionedTopic("persistent://prop-xyz/use/ns1/ds1", 4); - - // create consumer and subscription - @Cleanup - PulsarClient client = PulsarClient.builder() - .serviceUrl(pulsar.getWebServiceAddress()) - .statsInterval(0, TimeUnit.SECONDS) - .build(); - Consumer consumer = client.newConsumer().topic("persistent://prop-xyz/use/ns1/ds1") - .subscriptionName("my-sub").subscribe(); - - Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://prop-xyz/use/ns1/ds1") - .enableBatching(false) - .messageRoutingMode(MessageRoutingMode.RoundRobinPartition) - .create(); - for (int i = 0; i < 10; i++) { - String message = "message-" + i; - producer.send(message.getBytes()); - } - - PartitionedTopicStats topicStats = admin.topics() - .getPartitionedStats("persistent://prop-xyz/use/ns1/ds1", true); - assertEquals(topicStats.getSubscriptions().get("my-sub").getMsgBacklog(), 10); - - TopicStats partitionStatsPartition0 = topicStats.getPartitions() - .get("persistent://prop-xyz/use/ns1/ds1-partition-0"); - TopicStats partitionStatsPartition1 = topicStats.getPartitions() - .get("persistent://prop-xyz/use/ns1/ds1-partition-1"); - assertEquals(partitionStatsPartition0.getSubscriptions().get("my-sub").getMsgBacklog(), 3, 1); - assertEquals(partitionStatsPartition1.getSubscriptions().get("my-sub").getMsgBacklog(), 3, 1); - - Thread.sleep(1000); - admin.topics().expireMessagesForAllSubscriptions("persistent://prop-xyz/use/ns1/ds1", 1); - Thread.sleep(1000); - - topicStats = admin.topics().getPartitionedStats("persistent://prop-xyz/use/ns1/ds1", true); - partitionStatsPartition0 = topicStats.getPartitions().get("persistent://prop-xyz/use/ns1/ds1-partition-0"); - partitionStatsPartition1 = topicStats.getPartitions().get("persistent://prop-xyz/use/ns1/ds1-partition-1"); - assertEquals(partitionStatsPartition0.getSubscriptions().get("my-sub").getMsgBacklog(), 0); - assertEquals(partitionStatsPartition1.getSubscriptions().get("my-sub").getMsgBacklog(), 0); - - producer.close(); - consumer.close(); - } - - /** - * This test-case verifies that broker should support both url/uri encoding for topic-name. It calls below api with - * url-encoded and also uri-encoded topic-name in http request: a. PartitionedMetadataLookup b. TopicLookupBase - * c. Topic - * Stats - * - * @param topicName - * @throws Exception - */ - @Test(dataProvider = "topicName") - public void testPulsarAdminForUriAndUrlEncoding(String topicName) throws Exception { - final String ns1 = "prop-xyz/use/ns1"; - final String topic1 = "persistent://" + ns1 + "/" + topicName; - final String urlEncodedTopic = Codec.encode(topicName); - final String uriEncodedTopic = urlEncodedTopic.replaceAll("\\+", "%20"); - final int numOfPartitions = 4; - admin.topics().createPartitionedTopic(topic1, numOfPartitions); - // Create a consumer to get stats on this topic - pulsarClient.newConsumer().topic(topic1).subscriptionName("my-subscriber-name").subscribe().close(); - - TopicsImpl persistent = (TopicsImpl) admin.topics(); - Field field = TopicsImpl.class.getDeclaredField("adminTopics"); - field.setAccessible(true); - WebTarget persistentTopics = ((WebTarget) field.get(persistent)).path("persistent"); - - // (1) Get PartitionedMetadata : with Url and Uri encoding - final CompletableFuture urlEncodedPartitionedMetadata = new CompletableFuture<>(); - // (a) Url encoding - persistent.asyncGetRequest(persistentTopics.path(ns1).path(urlEncodedTopic).path("partitions"), - new InvocationCallback() { - @Override - public void completed(PartitionedTopicMetadata response) { - urlEncodedPartitionedMetadata.complete(response); - } - - @Override - public void failed(Throwable e) { - urlEncodedPartitionedMetadata.completeExceptionally(e); - } - }); - final CompletableFuture uriEncodedPartitionedMetadata = new CompletableFuture<>(); - // (b) Uri encoding - persistent.asyncGetRequest(persistentTopics.path(ns1).path(uriEncodedTopic).path("partitions"), - new InvocationCallback() { - @Override - public void completed(PartitionedTopicMetadata response) { - uriEncodedPartitionedMetadata.complete(response); - } - - @Override - public void failed(Throwable e) { - uriEncodedPartitionedMetadata.completeExceptionally(e); - } - }); - assertEquals(urlEncodedPartitionedMetadata.get().partitions, numOfPartitions); - assertEquals(urlEncodedPartitionedMetadata.get().partitions, (uriEncodedPartitionedMetadata.get().partitions)); - - // (2) Get Topic Lookup - LookupImpl lookup = (LookupImpl) admin.lookups(); - Field field2 = LookupImpl.class.getDeclaredField("v2lookup"); - field2.setAccessible(true); - WebTarget target2 = (WebTarget) field2.get(lookup); - // (a) Url encoding - LookupData urlEncodedLookupData = lookup - .request(target2.path("/destination/persistent").path(ns1 + "/" + urlEncodedTopic)) - .get(LookupData.class); - // (b) Uri encoding - LookupData uriEncodedLookupData = lookup - .request(target2.path("/destination/persistent").path(ns1 + "/" + uriEncodedTopic)) - .get(LookupData.class); - Assert.assertNotNull(urlEncodedLookupData.getBrokerUrl()); - assertEquals(urlEncodedLookupData.getBrokerUrl(), uriEncodedLookupData.getBrokerUrl()); - - // (3) Get Topic Stats - final CompletableFuture urlStats = new CompletableFuture<>(); - // (a) Url encoding - persistent.asyncGetRequest(persistentTopics.path(ns1).path(urlEncodedTopic + "-partition-1").path("stats"), - new InvocationCallback() { - @Override - public void completed(TopicStats response) { - urlStats.complete(response); - } - - @Override - public void failed(Throwable e) { - urlStats.completeExceptionally(e); - } - }); - // (b) Uri encoding - final CompletableFuture uriStats = new CompletableFuture<>(); - persistent.asyncGetRequest(persistentTopics.path(ns1).path(uriEncodedTopic + "-partition-1").path("stats"), - new InvocationCallback() { - @Override - public void completed(TopicStats response) { - uriStats.complete(response); - } - - @Override - public void failed(Throwable e) { - uriStats.completeExceptionally(e); - } - }); - assertEquals(urlStats.get().getSubscriptions().size(), 1); - assertEquals(uriStats.get().getSubscriptions().size(), 1); - } - - static class MockedPulsarService extends MockedPulsarServiceBaseTest { - - private final ServiceConfiguration conf; - - public MockedPulsarService(ServiceConfiguration conf) { - super(); - this.conf = conf; - } - - @Override - protected void setup() throws Exception { - super.conf.setLoadManagerClassName(conf.getLoadManagerClassName()); - super.internalSetup(); - } - - @Override - protected void cleanup() throws Exception { - super.internalCleanup(); - } - - public PulsarService getPulsar() { - return pulsar; - } - - public PulsarAdmin getAdmin() { - return admin; - } - } - - @Test - public void testTopicBundleRangeLookup() throws Exception { - admin.clusters().createCluster("usw", ClusterData.builder().build()); - TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), - Set.of("use", "usw")); - admin.tenants().updateTenant("prop-xyz", tenantInfo); - admin.namespaces().createNamespace("prop-xyz/use/getBundleNs", 100); - assertEquals(admin.namespaces().getPolicies("prop-xyz/use/getBundleNs").bundles.getNumBundles(), 100); - - // (1) create a topic - final String topicName = "persistent://prop-xyz/use/getBundleNs/topic1"; - String bundleRange = admin.lookups().getBundleRange(topicName); - assertEquals(bundleRange, pulsar.getNamespaceService().getBundle(TopicName.get(topicName)).getBundleRange()); - - admin.tenants().updateTenant("prop-xyz", new TenantInfoImpl(Set.of("role1", "role2"), - Set.of("use"))); - } - - @Test - public void testTriggerCompaction() throws Exception { - String topicName = "persistent://prop-xyz/use/ns1/topic1"; - - // create a topic by creating a producer - pulsarClient.newProducer(Schema.BYTES).topic(topicName).create().close(); - assertNotNull(pulsar.getBrokerService().getTopicReference(topicName)); - - // mock actual compaction, we don't need to really run it - CompletableFuture promise = new CompletableFuture<>(); - Compactor compactor = ((PulsarCompactionServiceFactory) pulsar.getCompactionServiceFactory()).getCompactor(); - doReturn(promise).when(compactor).compact(topicName); - admin.topics().triggerCompaction(topicName); - - // verify compact called once - verify(compactor).compact(topicName); - try { - admin.topics().triggerCompaction(topicName); - - fail("Shouldn't be able to run while already running"); - } catch (ConflictException e) { - // expected - } - // compact shouldn't have been called again - verify(compactor).compact(topicName); - - // complete first compaction, and trigger again - promise.complete(1L); - admin.topics().triggerCompaction(topicName); - - // verify compact was called again - verify(compactor, times(2)).compact(topicName); - } - - @Test - public void testCompactionStatus() throws Exception { - String topicName = "persistent://prop-xyz/use/ns1/topic1"; - - // create a topic by creating a producer - pulsarClient.newProducer(Schema.BYTES).topic(topicName).create().close(); - assertNotNull(pulsar.getBrokerService().getTopicReference(topicName)); - - assertEquals(admin.topics().compactionStatus(topicName).status, - LongRunningProcessStatus.Status.NOT_RUN); - - // mock actual compaction, we don't need to really run it - CompletableFuture promise = new CompletableFuture<>(); - Compactor compactor = ((PulsarCompactionServiceFactory) pulsar.getCompactionServiceFactory()).getCompactor(); - doReturn(promise).when(compactor).compact(topicName); - admin.topics().triggerCompaction(topicName); - - assertEquals(admin.topics().compactionStatus(topicName).status, - LongRunningProcessStatus.Status.RUNNING); - - promise.complete(1L); - - assertEquals(admin.topics().compactionStatus(topicName).status, - LongRunningProcessStatus.Status.SUCCESS); - - CompletableFuture errorPromise = new CompletableFuture<>(); - doReturn(errorPromise).when(compactor).compact(topicName); - admin.topics().triggerCompaction(topicName); - errorPromise.completeExceptionally(new Exception("Failed at something")); - - assertEquals(admin.topics().compactionStatus(topicName).status, - LongRunningProcessStatus.Status.ERROR); - assertTrue(admin.topics().compactionStatus(topicName) - .lastError.contains("Failed at something")); - } - - private void clearCache() { - ((MetadataCacheImpl) pulsar.getPulsarResources().getNamespaceResources().getCache()).invalidateAll(); - } -} diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/auth/AuthorizationTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/auth/AuthorizationTest.java index 0f2058b3d16b6..e299c0a577e30 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/auth/AuthorizationTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/auth/AuthorizationTest.java @@ -91,161 +91,161 @@ public void cleanup() throws Exception { public void simple() throws Exception { AuthorizationService auth = pulsar.getBrokerService().getAuthorizationService(); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null)); admin.clusters().createCluster("c1", ClusterData.builder().build()); admin.tenants().createTenant("p1", new TenantInfoImpl(Sets.newHashSet("role1"), Sets.newHashSet("c1"))); waitForChange(); - admin.namespaces().createNamespace("p1/c1/ns1"); + admin.namespaces().createNamespace("p1/ns1"); waitForChange(); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null)); - admin.namespaces().grantPermissionOnNamespace("p1/c1/ns1", "my-role", EnumSet.of(AuthAction.produce)); + admin.namespaces().grantPermissionOnNamespace("p1/ns1", "my-role", EnumSet.of(AuthAction.produce)); waitForChange(); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null)); - assertTrue(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null)); + assertTrue(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null)); - String topic = "persistent://p1/c1/ns1/ds2"; + String topic = "persistent://p1/ns1/ds2"; admin.topics().createNonPartitionedTopic(topic); admin.topics().grantPermission(topic, "other-role", EnumSet.of(AuthAction.consume)); waitForChange(); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds2"), "other-role", null)); - assertTrue(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null)); - assertFalse(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds2"), "other-role", null)); - assertTrue(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds2"), "other-role", null, null)); - assertFalse(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds2"), "no-access-role", null, null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds2"), "other-role", null)); + assertTrue(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null)); + assertFalse(auth.canProduce(TopicName.get("persistent://p1/ns1/ds2"), "other-role", null)); + assertTrue(auth.canConsume(TopicName.get("persistent://p1/ns1/ds2"), "other-role", null, null)); + assertFalse(auth.canConsume(TopicName.get("persistent://p1/ns1/ds2"), "no-access-role", null, null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "no-access-role", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "no-access-role", null)); - admin.namespaces().grantPermissionOnNamespace("p1/c1/ns1", "my-role", EnumSet.allOf(AuthAction.class)); + admin.namespaces().grantPermissionOnNamespace("p1/ns1", "my-role", EnumSet.allOf(AuthAction.class)); waitForChange(); - assertTrue(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null)); - assertTrue(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null, null)); + assertTrue(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null)); + assertTrue(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null, null)); // test for wildcard // namespace prefix match - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.1", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.2", null)); - assertFalse(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.1", null)); - assertFalse(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.1", null, null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "other.role.1", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "other.role.2", null)); - - admin.namespaces().grantPermissionOnNamespace("p1/c1/ns1", "my.role.*", EnumSet.of(AuthAction.produce)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my.role.1", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my.role.2", null)); + assertFalse(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "my.role.1", null)); + assertFalse(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "my.role.1", null, null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "other.role.1", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "other.role.2", null)); + + admin.namespaces().grantPermissionOnNamespace("p1/ns1", "my.role.*", EnumSet.of(AuthAction.produce)); waitForChange(); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.1", null)); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.2", null)); - assertTrue(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.1", null)); - assertFalse(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.1", null, null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "other.role.1", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "other.role.2", null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my.role.1", null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my.role.2", null)); + assertTrue(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "my.role.1", null)); + assertFalse(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "my.role.1", null, null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "other.role.1", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "other.role.2", null)); // namespace suffix match - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "1.role.my", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "2.role.my", null)); - assertFalse(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "1.role.my", null)); - assertFalse(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "1.role.my", null, null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "2.role.other", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "2.role.other", null)); - - admin.namespaces().grantPermissionOnNamespace("p1/c1/ns1", "*.role.my", EnumSet.of(AuthAction.consume)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "1.role.my", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "2.role.my", null)); + assertFalse(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "1.role.my", null)); + assertFalse(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "1.role.my", null, null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "2.role.other", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "2.role.other", null)); + + admin.namespaces().grantPermissionOnNamespace("p1/ns1", "*.role.my", EnumSet.of(AuthAction.consume)); waitForChange(); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "1.role.my", null)); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "2.role.my", null)); - assertFalse(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "1.role.my", null)); - assertTrue(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "1.role.my", null, null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "2.role.other", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "2.role.other", null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "1.role.my", null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "2.role.my", null)); + assertFalse(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "1.role.my", null)); + assertTrue(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "1.role.my", null, null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "2.role.other", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "2.role.other", null)); // revoke for next test - admin.namespaces().revokePermissionsOnNamespace("p1/c1/ns1", "my.role.*"); - admin.namespaces().revokePermissionsOnNamespace("p1/c1/ns1", "*.role.my"); + admin.namespaces().revokePermissionsOnNamespace("p1/ns1", "my.role.*"); + admin.namespaces().revokePermissionsOnNamespace("p1/ns1", "*.role.my"); waitForChange(); // topic prefix match - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.1", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.2", null)); - assertFalse(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.1", null)); - assertFalse(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.1", null, null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "other.role.1", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "other.role.2", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds2"), "my.role.1", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds2"), "my.role.2", null)); - - String topic1 = "persistent://p1/c1/ns1/ds1"; + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my.role.1", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my.role.2", null)); + assertFalse(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "my.role.1", null)); + assertFalse(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "my.role.1", null, null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "other.role.1", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "other.role.2", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds2"), "my.role.1", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds2"), "my.role.2", null)); + + String topic1 = "persistent://p1/ns1/ds1"; admin.topics().createNonPartitionedTopic(topic1); admin.topics().grantPermission(topic1, "my.*", EnumSet.of(AuthAction.produce)); waitForChange(); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.1", null)); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.2", null)); - assertTrue(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.1", null)); - assertFalse(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "my.role.1", null, null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "other.role.1", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "other.role.2", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds2"), "my.role.1", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds2"), "my.role.2", null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my.role.1", null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my.role.2", null)); + assertTrue(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "my.role.1", null)); + assertFalse(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "my.role.1", null, null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "other.role.1", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "other.role.2", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds2"), "my.role.1", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds2"), "my.role.2", null)); // topic suffix match - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "1.role.my", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "2.role.my", null)); - assertFalse(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "1.role.my", null)); - assertFalse(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "1.role.my", null, null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "2.role.other", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "2.role.other", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds2"), "1.role.my", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds2"), "2.role.my", null)); - - admin.topics().grantPermission("persistent://p1/c1/ns1/ds1", "*.my", + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "1.role.my", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "2.role.my", null)); + assertFalse(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "1.role.my", null)); + assertFalse(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "1.role.my", null, null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "2.role.other", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "2.role.other", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds2"), "1.role.my", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds2"), "2.role.my", null)); + + admin.topics().grantPermission("persistent://p1/ns1/ds1", "*.my", EnumSet.of(AuthAction.consume)); waitForChange(); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "1.role.my", null)); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "2.role.my", null)); - assertFalse(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "1.role.my", null)); - assertTrue(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "1.role.my", null, null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "2.role.other", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "2.role.other", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds2"), "1.role.my", null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds2"), "2.role.my", null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "1.role.my", null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "2.role.my", null)); + assertFalse(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "1.role.my", null)); + assertTrue(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "1.role.my", null, null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "2.role.other", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "2.role.other", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds2"), "1.role.my", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds2"), "2.role.my", null)); - admin.topics().revokePermissions("persistent://p1/c1/ns1/ds1", "my.*"); - admin.topics().revokePermissions("persistent://p1/c1/ns1/ds1", "*.my"); + admin.topics().revokePermissions("persistent://p1/ns1/ds1", "my.*"); + admin.topics().revokePermissions("persistent://p1/ns1/ds1", "*.my"); // tests for subscription auth mode - admin.namespaces().grantPermissionOnNamespace("p1/c1/ns1", "*", EnumSet.of(AuthAction.consume)); - admin.namespaces().setSubscriptionAuthMode("p1/c1/ns1", SubscriptionAuthMode.None); - Assert.assertEquals(admin.namespaces().getSubscriptionAuthMode("p1/c1/ns1"), + admin.namespaces().grantPermissionOnNamespace("p1/ns1", "*", EnumSet.of(AuthAction.consume)); + admin.namespaces().setSubscriptionAuthMode("p1/ns1", SubscriptionAuthMode.None); + Assert.assertEquals(admin.namespaces().getSubscriptionAuthMode("p1/ns1"), SubscriptionAuthMode.None); - admin.namespaces().setSubscriptionAuthMode("p1/c1/ns1", SubscriptionAuthMode.Prefix); - Assert.assertEquals(admin.namespaces().getSubscriptionAuthMode("p1/c1/ns1"), + admin.namespaces().setSubscriptionAuthMode("p1/ns1", SubscriptionAuthMode.Prefix); + Assert.assertEquals(admin.namespaces().getSubscriptionAuthMode("p1/ns1"), SubscriptionAuthMode.Prefix); waitForChange(); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "role1", null)); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "role2", null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "role1", null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "role2", null)); try { - assertFalse(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "role1", null, "sub1")); + assertFalse(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "role1", null, "sub1")); fail(); } catch (Exception ignored) {} try { - assertFalse(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "role2", null, "sub2")); + assertFalse(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "role2", null, "sub2")); fail(); } catch (Exception ignored) {} - assertTrue(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "role1", null, "role1-sub1")); - assertTrue(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "role2", null, "role2-sub2")); - assertTrue(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "pulsar.super_user", + assertTrue(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "role1", null, "role1-sub1")); + assertTrue(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "role2", null, "role2-sub2")); + assertTrue(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "pulsar.super_user", null, "role3-sub1")); - admin.namespaces().deleteNamespace("p1/c1/ns1", true); + admin.namespaces().deleteNamespace("p1/ns1", true); admin.tenants().deleteTenant("p1"); admin.clusters().deleteCluster("c1"); @@ -256,14 +256,14 @@ public void testDeleteV1Tenant() throws Exception { admin.clusters().createCluster("c1", ClusterData.builder().build()); admin.tenants().createTenant("p1", new TenantInfoImpl(Sets.newHashSet("role1"), Sets.newHashSet("c1"))); waitForChange(); - admin.namespaces().createNamespace("p1/c1/ns1"); + admin.namespaces().createNamespace("p1/ns1"); waitForChange(); - String topic = "persistent://p1/c1/ns1/ds2"; + String topic = "persistent://p1/ns1/ds2"; admin.topics().createNonPartitionedTopic(topic); - admin.namespaces().deleteNamespace("p1/c1/ns1", true); + admin.namespaces().deleteNamespace("p1/ns1", true); admin.tenants().deleteTenant("p1", true); admin.clusters().deleteCluster("c1"); } @@ -308,22 +308,22 @@ public void testOriginalRoleValidation() throws Exception { @Test public void testGetListWithGetBundleOp() throws Exception { String tenant = "p1"; - String namespaceV1 = "p1/global/ns1"; - String namespaceV2 = "p1/ns2"; + String namespace1 = "p1/ns1"; + String namespace2 = "p1/ns2"; admin.clusters().createCluster("c1", ClusterData.builder().build()); admin.tenants().createTenant(tenant, new TenantInfoImpl(Sets.newHashSet("role1"), Sets.newHashSet("c1"))); - admin.namespaces().createNamespace(namespaceV1, Sets.newHashSet("c1")); - admin.namespaces().grantPermissionOnNamespace(namespaceV1, "pass.pass2", EnumSet.of(AuthAction.produce)); - admin.namespaces().createNamespace(namespaceV2, Sets.newHashSet("c1")); - admin.namespaces().grantPermissionOnNamespace(namespaceV2, "pass.pass2", EnumSet.of(AuthAction.produce)); + admin.namespaces().createNamespace(namespace1, Sets.newHashSet("c1")); + admin.namespaces().grantPermissionOnNamespace(namespace1, "pass.pass2", EnumSet.of(AuthAction.produce)); + admin.namespaces().createNamespace(namespace2, Sets.newHashSet("c1")); + admin.namespaces().grantPermissionOnNamespace(namespace2, "pass.pass2", EnumSet.of(AuthAction.produce)); @Cleanup PulsarAdmin admin2 = PulsarAdmin.builder().serviceHttpUrl(brokerUrl != null ? brokerUrl.toString() : brokerUrlTls.toString()) .authentication(new MockAuthentication("pass.pass2")) .build(); - Assert.assertEquals(admin2.topics().getList(namespaceV1, TopicDomain.non_persistent).size(), 0); - Assert.assertEquals(admin2.topics().getList(namespaceV2, TopicDomain.non_persistent).size(), 0); + Assert.assertEquals(admin2.topics().getList(namespace1, TopicDomain.non_persistent).size(), 0); + Assert.assertEquals(admin2.topics().getList(namespace2, TopicDomain.non_persistent).size(), 0); } private static void waitForChange() { diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/cache/BundlesQuotasTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/cache/BundlesQuotasTest.java index 079ce25318a6a..ae9e6cef5e16a 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/cache/BundlesQuotasTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/cache/BundlesQuotasTest.java @@ -88,7 +88,7 @@ public void testGetSetDefaultQuota() throws Exception { @Test public void testGetSetBundleQuota() throws Exception { BundlesQuotas bundlesQuotas = new BundlesQuotas(pulsar); - NamespaceBundle testBundle = new NamespaceBundle(NamespaceName.get("pulsar/test/ns-2"), + NamespaceBundle testBundle = new NamespaceBundle(NamespaceName.get("pulsar/ns-2"), Range.closedOpen(0L, (long) Integer.MAX_VALUE), bundleFactory); ResourceQuota quota2 = new ResourceQuota(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/AntiAffinityNamespaceGroupTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/AntiAffinityNamespaceGroupTest.java index 1431f3450dab7..26cad55f82400 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/AntiAffinityNamespaceGroupTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/AntiAffinityNamespaceGroupTest.java @@ -206,7 +206,7 @@ public void testClusterDomain() { @Test public void testAntiAffinityNamespaceFilteringWithDomain() throws Exception { - final String namespace = "my-tenant/test/my-ns"; + final String namespace = "my-tenant/my-ns"; final int totalNamespaces = 5; final String namespaceAntiAffinityGroup = "my-antiaffinity"; final String bundle = "/0x00000000_0xffffffff"; @@ -302,7 +302,7 @@ public void testAntiAffinityNamespaceFilteringWithDomain() throws Exception { @Test public void testAntiAffinityNamespaceFilteringWithoutDomain() throws Exception { - final String namespace = "my-tenant/test/my-ns-wo-domain"; + final String namespace = "my-tenant/my-ns-wo-domain"; final int totalNamespaces = 5; final String namespaceAntiAffinityGroup = "my-antiaffinity-wo-domain"; final String bundle = "/0x00000000_0xffffffff"; @@ -394,8 +394,8 @@ public void testBrokerSelectionForAntiAffinityGroup() throws Exception { final String broker2 = secondaryHost; final String cluster = pulsar1.getConfiguration().getClusterName(); final String tenant = "tenant-" + UUID.randomUUID(); - final String namespace1 = tenant + "/" + cluster + "/ns1"; - final String namespace2 = tenant + "/" + cluster + "/ns2"; + final String namespace1 = tenant + "/ns1"; + final String namespace2 = tenant + "/ns2"; final String namespaceAntiAffinityGroup = "group"; FailureDomain domain1 = FailureDomain.builder() @@ -421,10 +421,10 @@ public void testBrokerSelectionForAntiAffinityGroup() throws Exception { assertTrue(isLoadManagerUpdatedDomainCache(secondaryLoadManager)); }); - ServiceUnitId serviceUnit1 = makeBundle(tenant, cluster, "ns1"); + ServiceUnitId serviceUnit1 = makeBundle(tenant, "ns1"); String selectedBroker1 = selectBroker(serviceUnit1, primaryLoadManager); - ServiceUnitId serviceUnit2 = makeBundle(tenant, cluster, "ns2"); + ServiceUnitId serviceUnit2 = makeBundle(tenant, "ns2"); String selectedBroker2 = selectBroker(serviceUnit2, primaryLoadManager); assertNotEquals(selectedBroker1, selectedBroker2); @@ -450,7 +450,7 @@ protected String selectBroker(ServiceUnitId serviceUnit, Object loadManager) { @Test public void testLoadSheddingUtilWithAntiAffinityNamespace() throws Exception { - final String namespace = "my-tenant/test/my-ns-load-shedding-util"; + final String namespace = "my-tenant/my-ns-load-shedding-util"; final int totalNamespaces = 5; final String namespaceAntiAffinityGroup = "my-antiaffinity-load-shedding-util"; final String bundle = "/0x00000000_0xffffffff"; @@ -500,7 +500,7 @@ public void testLoadSheddingUtilWithAntiAffinityNamespace() throws Exception { @Test public void testLoadSheddingWithAntiAffinityNamespace() throws Exception { - final String namespace = "my-tenant/test/my-ns-load-shedding"; + final String namespace = "my-tenant/my-ns-load-shedding"; final int totalNamespaces = 5; final String namespaceAntiAffinityGroup = "my-antiaffinity-load-shedding"; final String bundle = "0x00000000_0xffffffff"; @@ -535,8 +535,8 @@ protected boolean isLoadManagerUpdatedDomainCache(Object loadManager) throws Exc return !brokerToFailureDomainMap.isEmpty(); } - private NamespaceBundle makeBundle(final String property, final String cluster, final String namespace) { - return nsFactory.getBundle(NamespaceName.get(property, cluster, namespace), + private NamespaceBundle makeBundle(final String tenant, final String namespace) { + return nsFactory.getBundle(NamespaceName.get(tenant, namespace), Range.range(NamespaceBundles.FULL_LOWER_BOUND, BoundType.CLOSED, NamespaceBundles.FULL_UPPER_BOUND, BoundType.CLOSED)); } diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/LoadBalancerTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/LoadBalancerTest.java index d164b6c9186eb..aa66c20e77129 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/LoadBalancerTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/LoadBalancerTest.java @@ -228,7 +228,7 @@ public void testLoadReportsWrittenOnMetadataStore() throws Exception { brokerCount += entry.getValue().size(); } assertEquals(brokerCount, BROKER_COUNT); - TopicName topicName = TopicName.get("persistent://pulsar/use/primary-ns/test-topic"); + TopicName topicName = TopicName.get("persistent://pulsar/primary-ns/test-topic"); ResourceUnit found = pulsarServices[i].getLoadManager().get() .getLeastLoaded(pulsarServices[i].getNamespaceService().getBundle(topicName)).get(); assertNotNull(found); @@ -263,7 +263,7 @@ public void testUpdateLoadReportAndCheckUpdatedRanking() throws Exception { int totalNamespaces = 200; Map namespaceOwner = new HashMap<>(); for (int i = 0; i < totalNamespaces; i++) { - TopicName topicName = TopicName.get("persistent://pulsar/use/primary-ns-" + i + "/test-topic"); + TopicName topicName = TopicName.get("persistent://pulsar/primary-ns-" + i + "/test-topic"); ResourceUnit found = pulsarServices[0].getLoadManager().get() .getLeastLoaded(pulsarServices[0].getNamespaceService().getBundle(topicName)).get(); if (namespaceOwner.containsKey(found.getResourceId())) { @@ -386,7 +386,7 @@ public void testTopicAssignmentWithExistingBundles() throws Exception { Map bundleStats = new HashMap(); for (int j = 0; j < (i + 1) * 5; j++) { - String bundleName = String.format("pulsar/use/primary-ns-%d-%d/0x00000000_0xffffffff", i, j); + String bundleName = String.format("pulsar/primary-ns-%d-%d/0x00000000_0xffffffff", i, j); NamespaceBundleStats stats = new NamespaceBundleStats(); bundleStats.put(bundleName, stats); } @@ -412,7 +412,7 @@ public void testTopicAssignmentWithExistingBundles() throws Exception { int[] expectedAssignments = new int[] { 17, 34, 51, 68, 85 }; Map namespaceOwner = new HashMap<>(); for (int i = 0; i < totalNamespaces; i++) { - TopicName topicName = TopicName.get("persistent://pulsar/use/primary-ns-" + i + "/test-topic"); + TopicName topicName = TopicName.get("persistent://pulsar/primary-ns-" + i + "/test-topic"); ResourceUnit found = pulsarServices[0].getLoadManager().get() .getLeastLoaded(pulsarServices[0].getNamespaceService().getBundle(topicName)).get(); if (namespaceOwner.containsKey(found.getResourceId())) { @@ -470,7 +470,7 @@ private void writeLoadReportsForDynamicQuota(long timestamp) throws Exception { Map bundleStats = new HashMap<>(); for (int j = 0; j < 5; j++) { - String bundleName = String.format("pulsar/use/primary-ns-%d-%d/0x00000000_0xffffffff", i, j); + String bundleName = String.format("pulsar/primary-ns-%d-%d/0x00000000_0xffffffff", i, j); NamespaceBundleStats stats = new NamespaceBundleStats(); stats.msgRateIn = 5 * (i + j); stats.msgRateOut = 15 * (i + j); @@ -523,11 +523,11 @@ public void testDynamicNamespaceBundleQuota() throws Exception { for (int i = 0; i < BROKER_COUNT; i++) { Map quotas = getRealtimeResourceQuota(pulsarServices[i]).get(); printResourceQuotas(quotas); - verifyBundleResourceQuota(quotas.get("pulsar/use/primary-ns-0-0/0x00000000_0xffffffff"), 19.0, 58.0, + verifyBundleResourceQuota(quotas.get("pulsar/primary-ns-0-0/0x00000000_0xffffffff"), 19.0, 58.0, 19791.0, 58958.0, 74.0); - verifyBundleResourceQuota(quotas.get("pulsar/use/primary-ns-2-2/0x00000000_0xffffffff"), 20.0, 60.0, + verifyBundleResourceQuota(quotas.get("pulsar/primary-ns-2-2/0x00000000_0xffffffff"), 20.0, 60.0, 20000.0, 60000.0, 100.0); - verifyBundleResourceQuota(quotas.get("pulsar/use/primary-ns-4-4/0x00000000_0xffffffff"), 40.0, 120.0, + verifyBundleResourceQuota(quotas.get("pulsar/primary-ns-4-4/0x00000000_0xffffffff"), 40.0, 120.0, 40000.0, 120000.0, 150.0); } @@ -539,11 +539,11 @@ public void testDynamicNamespaceBundleQuota() throws Exception { for (int i = 0; i < BROKER_COUNT; i++) { Map quotas = getRealtimeResourceQuota(pulsarServices[i]).get(); printResourceQuotas(quotas); - verifyBundleResourceQuota(quotas.get("pulsar/use/primary-ns-0-0/0x00000000_0xffffffff"), 5.0, 6.0, 10203.0, + verifyBundleResourceQuota(quotas.get("pulsar/primary-ns-0-0/0x00000000_0xffffffff"), 5.0, 6.0, 10203.0, 11019.0, 50.0); - verifyBundleResourceQuota(quotas.get("pulsar/use/primary-ns-2-2/0x00000000_0xffffffff"), 20.0, 60.0, + verifyBundleResourceQuota(quotas.get("pulsar/primary-ns-2-2/0x00000000_0xffffffff"), 20.0, 60.0, 20000.0, 60000.0, 100.0); - verifyBundleResourceQuota(quotas.get("pulsar/use/primary-ns-4-4/0x00000000_0xffffffff"), 40.0, 120.0, + verifyBundleResourceQuota(quotas.get("pulsar/primary-ns-4-4/0x00000000_0xffffffff"), 40.0, 120.0, 40000.0, 120000.0, 150.0); } } @@ -604,7 +604,7 @@ public void testNamespaceBundleAutoSplit() throws Exception { // create namespaces for (int i = 1; i <= 10; i++) { int numBundles = (i == 10) ? maxBundles : 2; - createNamespace(pulsarServices[0], String.format("pulsar/use/primary-ns-%02d", i), numBundles); + createNamespace(pulsarServices[0], String.format("pulsar/primary-ns-%02d", i), numBundles); } // fake Namespaces Admin @@ -623,26 +623,26 @@ public void testNamespaceBundleAutoSplit() throws Exception { lr.setSystemResourceUsage(new SystemResourceUsage()); Map bundleStats = new HashMap(); - bundleStats.put("pulsar/use/primary-ns-01/0x00000000_0x80000000", + bundleStats.put("pulsar/primary-ns-01/0x00000000_0x80000000", newBundleStats(maxTopics + 1, 0, 0, 0, 0, 0, 0)); - bundleStats.put("pulsar/use/primary-ns-02/0x00000000_0x80000000", + bundleStats.put("pulsar/primary-ns-02/0x00000000_0x80000000", newBundleStats(2, maxSessions + 1, 0, 0, 0, 0, 0)); - bundleStats.put("pulsar/use/primary-ns-03/0x00000000_0x80000000", + bundleStats.put("pulsar/primary-ns-03/0x00000000_0x80000000", newBundleStats(2, 0, maxSessions + 1, 0, 0, 0, 0)); - bundleStats.put("pulsar/use/primary-ns-04/0x00000000_0x80000000", + bundleStats.put("pulsar/primary-ns-04/0x00000000_0x80000000", newBundleStats(2, 0, 0, maxMsgRate + 1, 0, 0, 0)); - bundleStats.put("pulsar/use/primary-ns-05/0x00000000_0x80000000", + bundleStats.put("pulsar/primary-ns-05/0x00000000_0x80000000", newBundleStats(2, 0, 0, 0, maxMsgRate + 1, 0, 0)); - bundleStats.put("pulsar/use/primary-ns-06/0x00000000_0x80000000", + bundleStats.put("pulsar/primary-ns-06/0x00000000_0x80000000", newBundleStats(2, 0, 0, 0, 0, maxBandwidth + 1, 0)); - bundleStats.put("pulsar/use/primary-ns-07/0x00000000_0x80000000", + bundleStats.put("pulsar/primary-ns-07/0x00000000_0x80000000", newBundleStats(2, 0, 0, 0, 0, 0, maxBandwidth + 1)); - bundleStats.put("pulsar/use/primary-ns-08/0x00000000_0x80000000", + bundleStats.put("pulsar/primary-ns-08/0x00000000_0x80000000", newBundleStats(maxTopics - 1, maxSessions - 1, 1, maxMsgRate - 1, 1, maxBandwidth - 1, 1)); - bundleStats.put("pulsar/use/primary-ns-09/0x00000000_0x80000000", + bundleStats.put("pulsar/primary-ns-09/0x00000000_0x80000000", newBundleStats(1, 0, 0, 0, 0, 0, maxBandwidth + 1)); - bundleStats.put("pulsar/use/primary-ns-10/0x00000000_0x02000000", + bundleStats.put("pulsar/primary-ns-10/0x00000000_0x02000000", newBundleStats(maxTopics + 1, 0, 0, 0, 0, 0, 0)); lr.setBundleStats(bundleStats); @@ -656,30 +656,30 @@ public void testNamespaceBundleAutoSplit() throws Exception { boolean isAutoUnooadSplitBundleEnabled = pulsarServices[0].getConfiguration() .isLoadBalancerAutoUnloadSplitBundlesEnabled(); // verify bundles are split - verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/use/primary-ns-01", "0x00000000_0x80000000", + verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/primary-ns-01", "0x00000000_0x80000000", isAutoUnooadSplitBundleEnabled, null); - verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/use/primary-ns-02", "0x00000000_0x80000000", + verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/primary-ns-02", "0x00000000_0x80000000", isAutoUnooadSplitBundleEnabled, null); - verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/use/primary-ns-03", "0x00000000_0x80000000", + verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/primary-ns-03", "0x00000000_0x80000000", isAutoUnooadSplitBundleEnabled, null); - verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/use/primary-ns-04", "0x00000000_0x80000000", + verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/primary-ns-04", "0x00000000_0x80000000", isAutoUnooadSplitBundleEnabled, null); - verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/use/primary-ns-05", "0x00000000_0x80000000", + verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/primary-ns-05", "0x00000000_0x80000000", isAutoUnooadSplitBundleEnabled, null); - verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/use/primary-ns-06", "0x00000000_0x80000000", + verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/primary-ns-06", "0x00000000_0x80000000", isAutoUnooadSplitBundleEnabled, null); - verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/use/primary-ns-07", "0x00000000_0x80000000", + verify(namespaceAdmin, times(1)).splitNamespaceBundle("pulsar/primary-ns-07", "0x00000000_0x80000000", isAutoUnooadSplitBundleEnabled, null); - verify(namespaceAdmin, never()).splitNamespaceBundle("pulsar/use/primary-ns-08", "0x00000000_0x80000000", + verify(namespaceAdmin, never()).splitNamespaceBundle("pulsar/primary-ns-08", "0x00000000_0x80000000", isAutoUnooadSplitBundleEnabled, null); - verify(namespaceAdmin, never()).splitNamespaceBundle("pulsar/use/primary-ns-09", "0x00000000_0x80000000", + verify(namespaceAdmin, never()).splitNamespaceBundle("pulsar/primary-ns-09", "0x00000000_0x80000000", isAutoUnooadSplitBundleEnabled, null); - verify(namespaceAdmin, never()).splitNamespaceBundle("pulsar/use/primary-ns-10", "0x00000000_0x02000000", + verify(namespaceAdmin, never()).splitNamespaceBundle("pulsar/primary-ns-10", "0x00000000_0x02000000", isAutoUnooadSplitBundleEnabled, null); // disable max session - bundleStats.put("pulsar/use/primary-ns-03/0x00000000_0x80000000", + bundleStats.put("pulsar/primary-ns-03/0x00000000_0x80000000", newBundleStats(2, -1, 0, 0, 0, 0, 0)); - verify(namespaceAdmin, times(0)).splitNamespaceBundle("pulsar/use/primary-ns-12", "0x00000000_0x80000000", + verify(namespaceAdmin, times(0)).splitNamespaceBundle("pulsar/primary-ns-12", "0x00000000_0x80000000", isAutoUnooadSplitBundleEnabled, null); } @@ -738,7 +738,7 @@ private void createNamespacePolicies(PulsarService pulsar) throws Exception { } NamespaceIsolationData policyData = NamespaceIsolationData.builder() - .namespaces(Collections.singletonList("pulsar/use/primary-ns.*")) + .namespaces(Collections.singletonList("pulsar/primary-ns.*")) .primary(allBrokers) .secondary(Collections.emptyList()) .autoFailoverPolicy(AutoFailoverPolicyData.builder() @@ -755,7 +755,7 @@ private void createNamespacePolicies(PulsarService pulsar) throws Exception { // set up policy that use this broker as secondary policyData = NamespaceIsolationData.builder() - .namespaces(Collections.singletonList("pulsar/use/secondary-ns.*")) + .namespaces(Collections.singletonList("pulsar/secondary-ns.*")) .primary(Collections.singletonList(pulsarServices[0].getAdvertisedAddress())) .secondary(allExceptFirstBroker) .autoFailoverPolicy(AutoFailoverPolicyData.builder() @@ -767,7 +767,7 @@ private void createNamespacePolicies(PulsarService pulsar) throws Exception { // set up policy that do not use this broker (neither primary nor secondary) policyData = NamespaceIsolationData.builder() - .namespaces(Collections.singletonList("pulsar/use/shared-ns.*")) + .namespaces(Collections.singletonList("pulsar/shared-ns.*")) .primary(Collections.singletonList(pulsarServices[0].getAdvertisedAddress())) .secondary(allExceptFirstBroker) .autoFailoverPolicy(AutoFailoverPolicyData.builder() diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/LoadBalancerTestingUtils.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/LoadBalancerTestingUtils.java index 8052e94145bca..c4a4b3cc891fe 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/LoadBalancerTestingUtils.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/LoadBalancerTestingUtils.java @@ -26,10 +26,10 @@ import org.apache.pulsar.common.naming.NamespaceName; public class LoadBalancerTestingUtils { - public static NamespaceBundle[] makeBundles(final NamespaceBundleFactory nsFactory, final String property, - final String cluster, final String namespace, final int numBundles) { + public static NamespaceBundle[] makeBundles(final NamespaceBundleFactory nsFactory, final String tenant, + final String namespace, final int numBundles) { final NamespaceBundle[] result = new NamespaceBundle[numBundles]; - final NamespaceName namespaceName = NamespaceName.get(property, cluster, namespace); + final NamespaceName namespaceName = NamespaceName.get(tenant, namespace); for (int i = 0; i < numBundles - 1; ++i) { final long lower = NamespaceBundles.FULL_UPPER_BOUND * i / numBundles; final long upper = NamespaceBundles.FULL_UPPER_BOUND * (i + 1) / numBundles; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/SimpleLoadManagerImplTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/SimpleLoadManagerImplTest.java index 3f10553902a5c..d5ae598e527b6 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/SimpleLoadManagerImplTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/SimpleLoadManagerImplTest.java @@ -129,7 +129,7 @@ void setup() throws Exception { // Start broker 1 ServiceConfiguration config1 = new ServiceConfiguration(); - config1.setClusterName("use"); + config1.setClusterName("test"); config1.setWebServicePort(Optional.of(0)); config1.setWebServicePortTls(Optional.of(0)); config1.setMetadataStoreUrl("zk:127.0.0.1:" + bkEnsemble.getZookeeperPort()); @@ -153,7 +153,7 @@ void setup() throws Exception { // Start broker 2 ServiceConfiguration config2 = new ServiceConfiguration(); - config2.setClusterName("use"); + config2.setClusterName("test"); config2.setWebServicePort(Optional.of(0)); config2.setWebServicePortTls(Optional.of(0)); config2.setMetadataStoreUrl("zk:127.0.0.1:" + bkEnsemble.getZookeeperPort()); @@ -219,7 +219,7 @@ private void createNamespacePolicies(PulsarService pulsar) throws Exception { NamespaceIsolationPolicies policies = new NamespaceIsolationPolicies(); // set up policy that use this broker as primary NamespaceIsolationData policyData = NamespaceIsolationData.builder() - .namespaces(Collections.singletonList("pulsar/use/primary-ns.*")) + .namespaces(Collections.singletonList("pulsar/primary-ns.*")) .primary(Collections.singletonList(pulsar1.getAdvertisedAddress() + "*")) .secondary(Collections.singletonList("prod2-broker([78]).messaging.usw.example.co.*")) .autoFailoverPolicy(AutoFailoverPolicyData.builder() @@ -230,11 +230,11 @@ private void createNamespacePolicies(PulsarService pulsar) throws Exception { policies.setPolicy("primaryBrokerPolicy", policyData); try { - pulsar.getPulsarResources().getNamespaceResources().getIsolationPolicies().createIsolationData("use", + pulsar.getPulsarResources().getNamespaceResources().getIsolationPolicies().createIsolationData("test", policies.getPolicies()); } catch (BadVersionException e) { // isolation policy already exist - pulsar.getPulsarResources().getNamespaceResources().getIsolationPolicies().setIsolationData("use", + pulsar.getPulsarResources().getNamespaceResources().getIsolationPolicies().setIsolationData("test", data -> policies.getPolicies()); } } @@ -261,7 +261,7 @@ public void testBasicBrokerSelection() throws Exception { sortedRankings.set(loadManager, sortedRankingsInstance); Optional res = loadManager - .getLeastLoaded(NamespaceName.get("pulsar/use/primary-ns.10")); + .getLeastLoaded(NamespaceName.get("pulsar/primary-ns.10")); // broker is not active so found should be null assertEquals(res, Optional.empty(), "found a broker when expected none to be found"); @@ -308,7 +308,7 @@ public void testPrimary() throws Exception { sortedRankingsInstance.get().put(lr.getRank(rd), rus); setObjectField(SimpleLoadManagerImpl.class, loadManager, "sortedRankings", sortedRankingsInstance); - ResourceUnit found = loadManager.getLeastLoaded(NamespaceName.get("pulsar/use/primary-ns.10")).get(); + ResourceUnit found = loadManager.getLeastLoaded(NamespaceName.get("pulsar/primary-ns.10")).get(); // TODO: this test doesn't make sense. This was the original assertion. assertNotEquals(found, null, "did not find a broker when expected one to be found"); } @@ -337,7 +337,7 @@ public void testPrimarySecondary() throws Exception { sortedRankings.set(loadManager, sortedRankingsInstance); ResourceUnit found = loadManager - .getLeastLoaded(NamespaceName.get("pulsar/use/primary-ns.10")).get(); + .getLeastLoaded(NamespaceName.get("pulsar/primary-ns.10")).get(); assertEquals(found.getResourceId(), ru1.getResourceId()); } @@ -418,8 +418,8 @@ public void testDoLoadShedding() throws Exception { nsb1.msgRateOut = 10000; NamespaceBundleStats nsb2 = new NamespaceBundleStats(); nsb2.msgRateOut = 10000; - stats.put("property/cluster/namespace1/0x00000000_0xFFFFFFFF", nsb1); - stats.put("property/cluster/namespace2/0x00000000_0xFFFFFFFF", nsb2); + stats.put("property/namespace1/0x00000000_0xFFFFFFFF", nsb1); + stats.put("property/namespace2/0x00000000_0xFFFFFFFF", nsb2); Map loadReports = new HashMap<>(); org.apache.pulsar.policies.data.loadbalancer.LoadReport loadReport1 = @@ -442,7 +442,7 @@ public void testDoLoadShedding() throws Exception { @Test public void testEvenBundleDistribution() throws Exception { final NamespaceBundle[] bundles = LoadBalancerTestingUtils - .makeBundles(pulsar1.getNamespaceService().getNamespaceBundleFactory(), "pulsar", "use", "test", 16); + .makeBundles(pulsar1.getNamespaceService().getNamespaceBundleFactory(), "pulsar", "test", 16); final ResourceQuota quota = new ResourceQuota(); // Create high message rate quota for the first bundle to make it unlikely to be a coincidence of even // distribution. @@ -570,13 +570,13 @@ public void testRedirectOwner() throws PulsarAdminException { } private void setupClusters() throws PulsarAdminException { - admin1.clusters().createCluster("use", ClusterData.builder().serviceUrl(pulsar1.getWebServiceAddress()) + admin1.clusters().createCluster("test", ClusterData.builder().serviceUrl(pulsar1.getWebServiceAddress()) .brokerServiceUrl(pulsar1.getBrokerServiceUrl()).build()); - TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("use")); + TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("test")); defaultTenant = "prop-xyz"; admin1.tenants().createTenant(defaultTenant, tenantInfo); defaultNamespace = defaultTenant + "/ns1"; - admin1.namespaces().createNamespace(defaultNamespace, Set.of("use")); + admin1.namespaces().createNamespace(defaultNamespace, Set.of("test")); } } diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/extensions/AntiAffinityNamespaceGroupExtensionTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/extensions/AntiAffinityNamespaceGroupExtensionTest.java index 74807a03ab50a..7b4e3328f9a02 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/extensions/AntiAffinityNamespaceGroupExtensionTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/extensions/AntiAffinityNamespaceGroupExtensionTest.java @@ -104,7 +104,7 @@ public void testAntiAffinityGroupPolicyFilter() throws IllegalAccessException, ExecutionException, InterruptedException, TimeoutException, PulsarAdminException, PulsarClientException { - final String namespace = "my-tenant/test/my-ns-filter"; + final String namespace = "my-tenant/my-ns-filter"; final String namespaceAntiAffinityGroup = "my-antiaffinity-filter"; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/extensions/ExtensibleLoadManagerImplTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/extensions/ExtensibleLoadManagerImplTest.java index 6db6175649240..c179db9622789 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/extensions/ExtensibleLoadManagerImplTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/extensions/ExtensibleLoadManagerImplTest.java @@ -37,7 +37,6 @@ import static org.apache.pulsar.broker.loadbalance.extensions.models.UnloadDecision.Reason.Underloaded; import static org.apache.pulsar.broker.loadbalance.extensions.models.UnloadDecision.Reason.Unknown; import static org.apache.pulsar.broker.namespace.NamespaceService.getHeartbeatNamespace; -import static org.apache.pulsar.broker.namespace.NamespaceService.getHeartbeatNamespaceV2; import static org.apache.pulsar.broker.namespace.NamespaceService.getSLAMonitorNamespace; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; @@ -110,7 +109,6 @@ import org.apache.pulsar.broker.namespace.NamespaceBundleOwnershipListener; import org.apache.pulsar.broker.namespace.NamespaceBundleSplitListener; import org.apache.pulsar.broker.namespace.NamespaceEphemeralData; -import org.apache.pulsar.broker.namespace.NamespaceService; import org.apache.pulsar.broker.service.BrokerServiceException; import org.apache.pulsar.broker.service.nonpersistent.NonPersistentSystemTopic; import org.apache.pulsar.client.admin.PulsarAdmin; @@ -129,7 +127,6 @@ import org.apache.pulsar.common.naming.ServiceUnitId; import org.apache.pulsar.common.naming.TopicDomain; import org.apache.pulsar.common.naming.TopicName; -import org.apache.pulsar.common.naming.TopicVersion; import org.apache.pulsar.common.policies.data.BrokerAssignment; import org.apache.pulsar.common.policies.data.BundlesData; import org.apache.pulsar.common.policies.data.NamespaceOwnershipStatus; @@ -1518,17 +1515,11 @@ public void testLoadBalancerServiceUnitTableViewSyncer() throws Exception { private void assertLookupHeartbeatOwner(PulsarService pulsar, String brokerId, String expectedBrokerServiceUrl) throws Exception { - NamespaceName heartbeatNamespaceV1 = + NamespaceName heartbeatNamespace = getHeartbeatNamespace(brokerId, pulsar.getConfiguration()); - String heartbeatV1Topic = heartbeatNamespaceV1.getPersistentTopicName("test"); - assertEquals(pulsar.getAdminClient().lookups().lookupTopic(heartbeatV1Topic), expectedBrokerServiceUrl); - - NamespaceName heartbeatNamespaceV2 = - getHeartbeatNamespaceV2(brokerId, pulsar.getConfiguration()); - - String heartbeatV2Topic = heartbeatNamespaceV2.getPersistentTopicName("test"); - assertEquals(pulsar.getAdminClient().lookups().lookupTopic(heartbeatV2Topic), expectedBrokerServiceUrl); + String heartbeatTopic = heartbeatNamespace.getPersistentTopicName("test"); + assertEquals(pulsar.getAdminClient().lookups().lookupTopic(heartbeatTopic), expectedBrokerServiceUrl); } private void assertLookupSLANamespaceOwner(PulsarService pulsar, @@ -2107,15 +2098,11 @@ public void testListTopic() throws Exception { @Test(timeOut = 30 * 1000, priority = -1) public void testGetOwnedServiceUnitsAndGetOwnedNamespaceStatus() throws Exception { - NamespaceName heartbeatNamespacePulsar1V1 = + NamespaceName heartbeatNamespacePulsar1 = getHeartbeatNamespace(pulsar1.getBrokerId(), pulsar1.getConfiguration()); - NamespaceName heartbeatNamespacePulsar1V2 = - NamespaceService.getHeartbeatNamespaceV2(pulsar1.getBrokerId(), pulsar1.getConfiguration()); - NamespaceName heartbeatNamespacePulsar2V1 = + NamespaceName heartbeatNamespacePulsar2 = getHeartbeatNamespace(pulsar2.getBrokerId(), pulsar2.getConfiguration()); - NamespaceName heartbeatNamespacePulsar2V2 = - NamespaceService.getHeartbeatNamespaceV2(pulsar2.getBrokerId(), pulsar2.getConfiguration()); NamespaceName slaMonitorNamespacePulsar1 = getSLAMonitorNamespace(pulsar1.getBrokerId(), pulsar1.getConfiguration()); @@ -2124,14 +2111,10 @@ public void testGetOwnedServiceUnitsAndGetOwnedNamespaceStatus() throws Exceptio getSLAMonitorNamespace(pulsar2.getBrokerId(), pulsar2.getConfiguration()); NamespaceBundle bundle1 = pulsar1.getNamespaceService().getNamespaceBundleFactory() - .getFullBundle(heartbeatNamespacePulsar1V1); - NamespaceBundle bundle2 = pulsar1.getNamespaceService().getNamespaceBundleFactory() - .getFullBundle(heartbeatNamespacePulsar1V2); + .getFullBundle(heartbeatNamespacePulsar1); - NamespaceBundle bundle3 = pulsar2.getNamespaceService().getNamespaceBundleFactory() - .getFullBundle(heartbeatNamespacePulsar2V1); - NamespaceBundle bundle4 = pulsar2.getNamespaceService().getNamespaceBundleFactory() - .getFullBundle(heartbeatNamespacePulsar2V2); + NamespaceBundle bundle2 = pulsar2.getNamespaceService().getNamespaceBundleFactory() + .getFullBundle(heartbeatNamespacePulsar2); NamespaceBundle slaBundle1 = pulsar1.getNamespaceService().getNamespaceBundleFactory() .getFullBundle(slaMonitorNamespacePulsar1); @@ -2143,23 +2126,19 @@ public void testGetOwnedServiceUnitsAndGetOwnedNamespaceStatus() throws Exceptio log.info("Owned service units: {}", ownedServiceUnitsByPulsar1); // heartbeat namespace bundle will own by pulsar1 assertTrue(ownedServiceUnitsByPulsar1.contains(bundle1)); - assertTrue(ownedServiceUnitsByPulsar1.contains(bundle2)); assertTrue(ownedServiceUnitsByPulsar1.contains(slaBundle1)); Set ownedServiceUnitsByPulsar2 = secondaryLoadManager.getOwnedServiceUnits(); log.info("Owned service units: {}", ownedServiceUnitsByPulsar2); - assertTrue(ownedServiceUnitsByPulsar2.contains(bundle3)); - assertTrue(ownedServiceUnitsByPulsar2.contains(bundle4)); + assertTrue(ownedServiceUnitsByPulsar2.contains(bundle2)); assertTrue(ownedServiceUnitsByPulsar2.contains(slaBundle2)); Map ownedNamespacesByPulsar1 = admin.brokers().getOwnedNamespaces(conf.getClusterName(), pulsar1.getBrokerId()); Map ownedNamespacesByPulsar2 = admin.brokers().getOwnedNamespaces(conf.getClusterName(), pulsar2.getBrokerId()); assertTrue(ownedNamespacesByPulsar1.containsKey(bundle1.toString())); - assertTrue(ownedNamespacesByPulsar1.containsKey(bundle2.toString())); assertTrue(ownedNamespacesByPulsar1.containsKey(slaBundle1.toString())); - assertTrue(ownedNamespacesByPulsar2.containsKey(bundle3.toString())); - assertTrue(ownedNamespacesByPulsar2.containsKey(bundle4.toString())); + assertTrue(ownedNamespacesByPulsar2.containsKey(bundle2.toString())); assertTrue(ownedNamespacesByPulsar2.containsKey(slaBundle2.toString())); String topic = "persistent://" + defaultTestNamespace + "/test-get-owned-service-units"; @@ -2221,7 +2200,7 @@ public void testTryAcquiringOwnership() @Test(timeOut = 30 * 1000) public void testHealthcheck() throws PulsarAdminException { - admin.brokers().healthcheck(TopicVersion.V2); + admin.brokers().healthcheck(); } @Test(timeOut = 30 * 1000) diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/extensions/channel/ServiceUnitStateChannelTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/extensions/channel/ServiceUnitStateChannelTest.java index 5baf91f2d5d24..55756980b7364 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/extensions/channel/ServiceUnitStateChannelTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/extensions/channel/ServiceUnitStateChannelTest.java @@ -221,7 +221,7 @@ protected void setup() throws Exception { brokers = mock(Brokers.class); doReturn(CompletableFuture.failedFuture(new RuntimeException("failed"))).when(brokers) - .healthcheckAsync(any(), any()); + .healthcheckAsync(any()); } @BeforeMethod diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/impl/ModularLoadManagerImplTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/impl/ModularLoadManagerImplTest.java index f03bd6ed1f948..da12c84e19791 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/impl/ModularLoadManagerImplTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/loadbalance/impl/ModularLoadManagerImplTest.java @@ -108,7 +108,6 @@ import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; -import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @Slf4j @@ -282,18 +281,18 @@ void shutdown() throws Exception { } } - private NamespaceBundle makeBundle(final String property, final String cluster, final String namespace) { - return nsFactory.getBundle(NamespaceName.get(property, cluster, namespace), + private NamespaceBundle makeBundle(final String tenant, final String namespace) { + return nsFactory.getBundle(NamespaceName.get(tenant, namespace), Range.range(NamespaceBundles.FULL_LOWER_BOUND, BoundType.CLOSED, NamespaceBundles.FULL_UPPER_BOUND, BoundType.CLOSED)); } private NamespaceBundle makeBundle(final String all) { - return makeBundle(all, all, all); + return makeBundle(all, all); } private String mockBundleName(final int i) { - return String.format("%d/%d/%d/0x00000000_0xffffffff", i, i, i); + return String.format("%d/%d/0x00000000_0xffffffff", i, i); } // Test disabled since it's depending on CPU usage in the machine @@ -335,7 +334,7 @@ public void testCandidateConsistency() throws Exception { // Test disabled since it's depending on CPU usage in the machine @Test(enabled = false) public void testEvenBundleDistribution() throws Exception { - final NamespaceBundle[] bundles = LoadBalancerTestingUtils.makeBundles(nsFactory, "test", "test", "test", 16); + final NamespaceBundle[] bundles = LoadBalancerTestingUtils.makeBundles(nsFactory, "test", "test", 16); int numAssignedToPrimary = 0; int numAssignedToSecondary = 0; final BundleData bundleData = new BundleData(10, 1000); @@ -370,8 +369,8 @@ public void testBrokerAffinity() throws Exception { pulsar3.start(); final String tenant = "test"; - final String cluster = "test"; - String namespace = tenant + "/" + cluster + "/" + "test"; + final String cluster = "use"; + String namespace = tenant + "/" + "test"; String topic = "persistent://" + namespace + "/my-topic1"; admin1.clusters().createCluster(cluster, ClusterData.builder() .serviceUrl(pulsar1.getWebServiceAddress()).build()); @@ -430,7 +429,7 @@ public void testBrokerAffinity() throws Exception { public void testMaxTopicDistributionToBroker() throws Exception { final int totalBundles = 50; - final NamespaceBundle[] bundles = LoadBalancerTestingUtils.makeBundles(nsFactory, "test", "test", "test", + final NamespaceBundle[] bundles = LoadBalancerTestingUtils.makeBundles(nsFactory, "test", "test", totalBundles); final BundleData bundleData = new BundleData(10, 1000); // it sets max topics under this bundle so, owner of this broker reaches max-topic threshold @@ -470,7 +469,7 @@ public void testFilterBundlesWhileWritingToMetadataStore() throws Exception { // create and configure bundle-data final int totalBundles = 5; final NamespaceBundle[] bundles = LoadBalancerTestingUtils.makeBundles( - nsFactory, "test", "test", "test", totalBundles); + nsFactory, "test", "test", totalBundles); LoadData loadData = (LoadData) getField(loadManager, "loadData"); for (int i = 0; i < totalBundles; i++) { final BundleData bundleData = new BundleData(10, 1000); @@ -774,13 +773,13 @@ public void testNamespaceIsolationPoliciesForPrimaryAndSecondaryBrokers() throws .serviceUrl(pulsar1.getWebServiceAddress()).build()); admin1.tenants().createTenant(tenant, new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet(cluster))); - admin1.namespaces().createNamespace(tenant + "/" + cluster + "/" + namespace); + admin1.namespaces().createNamespace(tenant + "/" + namespace); // set a new policy - String newPolicyJsonTemplate = "{\"namespaces\":[\"%s/%s/%s.*\"],\"primary\":[\"%s\"]," + String newPolicyJsonTemplate = "{\"namespaces\":[\"%s/%s.*\"],\"primary\":[\"%s\"]," + "\"secondary\":[\"%s\"],\"auto_failover_policy\":{\"policy_type\":\"min_available\"," + "\"parameters\":{\"min_limit\":%s,\"usage_threshold\":80}}}"; - String newPolicyJson = String.format(newPolicyJsonTemplate, tenant, cluster, namespace, broker1Host, + String newPolicyJson = String.format(newPolicyJsonTemplate, tenant, namespace, broker1Host, broker2Host, 1); String newPolicyName = "my-ns-isolation-policies"; ObjectMapper jsonMapper = ObjectMapperFactory.create(); @@ -790,7 +789,7 @@ public void testNamespaceIsolationPoliciesForPrimaryAndSecondaryBrokers() throws SimpleResourceAllocationPolicies simpleResourceAllocationPolicies = new SimpleResourceAllocationPolicies( pulsar1); - ServiceUnitId serviceUnit = LoadBalancerTestingUtils.makeBundles(nsFactory, tenant, cluster, namespace, 1)[0]; + ServiceUnitId serviceUnit = LoadBalancerTestingUtils.makeBundles(nsFactory, tenant, namespace, 1)[0]; BrokerTopicLoadingPredicate brokerTopicLoadingPredicate = new BrokerTopicLoadingPredicate() { @Override public boolean isEnablePersistentTopics(String brokerId) { @@ -830,7 +829,7 @@ public boolean isEnableNonPersistentTopics(String brokerId) { // (2) now we will have isolation policy : primary=broker1, secondary=broker2, minLimit=2 - newPolicyJson = String.format(newPolicyJsonTemplate, tenant, cluster, namespace, broker1Host, + newPolicyJson = String.format(newPolicyJsonTemplate, tenant, namespace, broker1Host, broker2Host, 2); nsPolicyData = jsonMapper.readValue(newPolicyJson.getBytes(), NamespaceIsolationDataImpl.class); admin1.clusters().createNamespaceIsolationPolicy("use", newPolicyName, nsPolicyData); @@ -866,7 +865,7 @@ public void testLoadSheddingWithNamespaceIsolationPolicies() throws Exception { final String cluster = "use"; final String tenant = "my-tenant"; - final String namespace = "my-tenant/use/my-ns"; + final String namespace = "my-tenant/my-ns"; final String bundle = "0x00000000_0xffffffff"; final String brokerHost = pulsar1.getAdvertisedAddress(); final String brokerAddress = brokerHost + ":8080"; @@ -967,17 +966,12 @@ public void testRemoveDeadBrokerTimeAverageData() throws Exception { assertEquals(data.size(), 1); } - @DataProvider(name = "isV1") - public Object[][] isV1() { - return new Object[][] {{true}, {false}}; - } - - @Test(dataProvider = "isV1") - public void testBundleDataDefaultValue(boolean isV1) throws Exception { + @Test + public void testBundleDataDefaultValue() throws Exception { final String cluster = "use"; final String tenant = "my-tenant"; final String namespace = "my-ns"; - NamespaceName ns = isV1 ? NamespaceName.get(tenant, cluster, namespace) : NamespaceName.get(tenant, namespace); + NamespaceName ns = NamespaceName.get(tenant, namespace); admin1.clusters().createCluster(cluster, ClusterData.builder() .serviceUrl(pulsar1.getWebServiceAddress()).build()); admin1.tenants().createTenant(tenant, diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/lookup/http/HttpTopicLookupv2Test.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/lookup/http/HttpTopicLookupv2Test.java index c8a75af36602b..7ed70ed1701f5 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/lookup/http/HttpTopicLookupv2Test.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/lookup/http/HttpTopicLookupv2Test.java @@ -28,6 +28,7 @@ import com.google.common.collect.Sets; import java.lang.reflect.Field; import java.net.URI; +import java.util.LinkedHashSet; import java.util.Optional; import java.util.Set; import java.util.TreeSet; @@ -42,7 +43,7 @@ import org.apache.pulsar.broker.authorization.AuthorizationService; import org.apache.pulsar.broker.lookup.NamespaceData; import org.apache.pulsar.broker.lookup.RedirectData; -import org.apache.pulsar.broker.lookup.v1.TopicLookup; +import org.apache.pulsar.broker.lookup.v2.TopicLookup; import org.apache.pulsar.broker.namespace.NamespaceService; import org.apache.pulsar.broker.namespace.TopicExistsInfo; import org.apache.pulsar.broker.resources.ClusterResources; @@ -85,7 +86,11 @@ public void setUp() throws Exception { clusters.add("use"); clusters.add("usc"); clusters.add("usw"); - ClusterData useData = ClusterData.builder().serviceUrl("http://broker.messaging.use.example.com:8080").build(); + LinkedHashSet peerClusters = new LinkedHashSet<>(); + peerClusters.add("usc"); + peerClusters.add("usw"); + ClusterData useData = ClusterData.builder().serviceUrl("http://broker.messaging.use.example.com:8080") + .peerClusterNames(peerClusters).build(); ClusterData uscData = ClusterData.builder().serviceUrl("http://broker.messaging.usc.example.com:8080").build(); ClusterData uswData = ClusterData.builder().serviceUrl("http://broker.messaging.usw.example.com:8080").build(); doReturn(config).when(pulsar).getConfiguration(); @@ -99,6 +104,8 @@ public void setUp() throws Exception { when(resources.getClusterResources()).thenReturn(clusters); when(pulsar.getPulsarResources()).thenReturn(resources); when(resources.getNamespaceResources()).thenReturn(namespaceResources); + when(namespaceResources.getPoliciesAsync(any(NamespaceName.class))) + .thenReturn(CompletableFuture.completedFuture(Optional.empty())); doReturn(ns).when(pulsar).getNamespaceService(); BrokerService brokerService = mock(BrokerService.class); @@ -112,6 +119,13 @@ public void setUp() throws Exception { @Test public void crossColoLookup() throws Exception { + // Set up namespace policies with replication clusters that do NOT include the local + // cluster "use", so the lookup will redirect to a peer cluster. + Policies crossColoPolicies = new Policies(); + crossColoPolicies.replication_clusters = Sets.newHashSet("usc"); + when(namespaceResources.getPoliciesAsync(NamespaceName.get("myprop", "ns2"))) + .thenReturn(CompletableFuture.completedFuture(Optional.of(crossColoPolicies))); + TopicLookup destLookup = spy(TopicLookup.class); doReturn(false).when(destLookup).isRequestHttps(); destLookup.setPulsar(pulsar); @@ -120,13 +134,13 @@ public void crossColoLookup() throws Exception { uriField.setAccessible(true); UriInfo uriInfo = mock(UriInfo.class); uriField.set(destLookup, uriInfo); - URI uri = URI.create("http://localhost:8080/lookup/v2/destination/topic/myprop/usc/ns2/topic1"); + URI uri = URI.create("http://localhost:8080/lookup/v2/topic/persistent/myprop/ns2/topic1"); doReturn(uri).when(uriInfo).getRequestUri(); config.setAuthorizationEnabled(true); AsyncResponse asyncResponse = mock(AsyncResponse.class); destLookup.lookupTopicAsync(asyncResponse, TopicDomain.persistent.value(), "myprop", - "usc", "ns2", "topic1", false, null, null); + "ns2", "topic1", false, null, null); ArgumentCaptor arg = ArgumentCaptor.forClass(Throwable.class); verify(asyncResponse).resume(arg.capture()); @@ -146,7 +160,7 @@ public void testLookupTopicNotExist() throws Exception { uriField.setAccessible(true); UriInfo uriInfo = mock(UriInfo.class); uriField.set(destLookup, uriInfo); - URI uri = URI.create("http://localhost:8080/lookup/v2/destination/topic/myprop/usc/ns2/topic1"); + URI uri = URI.create("http://localhost:8080/lookup/v2/topic/persistent/myprop/ns2/topic1"); doReturn(uri).when(uriInfo).getRequestUri(); config.setAuthorizationEnabled(true); @@ -160,7 +174,7 @@ public void testLookupTopicNotExist() throws Exception { AsyncResponse asyncResponse1 = mock(AsyncResponse.class); destLookup.lookupTopicAsync(asyncResponse1, TopicDomain.persistent.value(), "myprop", - "usc", "ns2", "topic_not_exist", false, null, null); + "ns2", "topic_not_exist", false, null, null); ArgumentCaptor arg = ArgumentCaptor.forClass(Throwable.class); verify(asyncResponse1).resume(arg.capture()); @@ -194,13 +208,13 @@ public void testNotEnoughLookupPermits() throws Exception { uriField.setAccessible(true); UriInfo uriInfo = mock(UriInfo.class); uriField.set(destLookup, uriInfo); - URI uri = URI.create("http://localhost:8080/lookup/v2/destination/topic/myprop/usc/ns2/topic1"); + URI uri = URI.create("http://localhost:8080/lookup/v2/topic/persistent/myprop/ns2/topic1"); doReturn(uri).when(uriInfo).getRequestUri(); config.setAuthorizationEnabled(true); AsyncResponse asyncResponse1 = mock(AsyncResponse.class); destLookup.lookupTopicAsync(asyncResponse1, TopicDomain.persistent.value(), "myprop", - "usc", "ns2", "topic1", false, null, null); + "ns2", "topic1", false, null, null); ArgumentCaptor arg = ArgumentCaptor.forClass(Throwable.class); verify(asyncResponse1).resume(arg.capture()); @@ -212,12 +226,11 @@ public void testNotEnoughLookupPermits() throws Exception { @Test public void testValidateReplicationSettingsOnNamespace() throws Exception { - final String property = "my-prop"; - final String cluster = "global"; + final String tenant = "my-prop"; final String ns1 = "ns1"; final String ns2 = "ns2"; - NamespaceName namespaceName1 = NamespaceName.get(property + "/" + cluster + "/" + ns1); - NamespaceName namespaceName2 = NamespaceName.get(property + "/" + cluster + "/" + ns2); + NamespaceName namespaceName1 = NamespaceName.get(tenant, ns1); + NamespaceName namespaceName2 = NamespaceName.get(tenant, ns2); TopicLookup destLookup = spy(TopicLookup.class); doReturn(false).when(destLookup).isRequestHttps(); @@ -234,7 +247,7 @@ public void testValidateReplicationSettingsOnNamespace() throws Exception { CompletableFuture> nullPolicies = new CompletableFuture<>(); nullPolicies.complete(Optional.empty()); doReturn(nullPolicies).when(namespaceResources).getPoliciesAsync(namespaceName1); - destLookup.lookupTopicAsync(asyncResponse, TopicDomain.persistent.value(), property, cluster, + destLookup.lookupTopicAsync(asyncResponse, TopicDomain.persistent.value(), tenant, ns1, "empty-cluster", false, null, null); verify(asyncResponse).resume(arg.capture()); assertEquals(arg.getValue().getResponse().getStatus(), Status.NOT_FOUND.getStatusCode()); @@ -244,7 +257,7 @@ public void testValidateReplicationSettingsOnNamespace() throws Exception { doReturn(emptyPolicies).when(namespaceResources).getPoliciesAsync(namespaceName1); asyncResponse = mock(AsyncResponse.class); arg = ArgumentCaptor.forClass(RestException.class); - destLookup.lookupTopicAsync(asyncResponse, TopicDomain.persistent.value(), property, cluster, + destLookup.lookupTopicAsync(asyncResponse, TopicDomain.persistent.value(), tenant, ns1, "empty-cluster", false, null, null); verify(asyncResponse).resume(arg.capture()); assertEquals(arg.getValue().getResponse().getStatus(), Status.PRECONDITION_FAILED.getStatusCode()); @@ -256,7 +269,7 @@ public void testValidateReplicationSettingsOnNamespace() throws Exception { policies2.replication_clusters = Sets.newHashSet("invalid-localCluster"); policies2Future.complete(Optional.of(policies2)); doReturn(policies2Future).when(namespaceResources).getPoliciesAsync(namespaceName2); - destLookup.lookupTopicAsync(asyncResponse, TopicDomain.persistent.value(), property, cluster, ns2, + destLookup.lookupTopicAsync(asyncResponse, TopicDomain.persistent.value(), tenant, ns2, "invalid-localCluster", false, null, null); verify(asyncResponse).resume(arg.capture()); assertEquals(arg.getValue().getResponse().getStatus(), Status.PRECONDITION_FAILED.getStatusCode()); @@ -275,7 +288,7 @@ public void testValidateReplicationSettingsOnNamespace() throws Exception { CompletableFuture booleanFuture = new CompletableFuture<>(); booleanFuture.complete(false); doReturn(future).when(namespaceService).checkNonPartitionedTopicExists(any(TopicName.class)); - destLookup.lookupTopicAsync(asyncResponse, TopicDomain.persistent.value(), property, cluster, ns2, + destLookup.lookupTopicAsync(asyncResponse, TopicDomain.persistent.value(), tenant, ns2, "invalid-localCluster", false, null, null); verify(asyncResponse).resume(arg.capture()); assertEquals(arg.getValue().getResponse().getStatus(), Status.PRECONDITION_FAILED.getStatusCode()); @@ -302,7 +315,7 @@ public void topicNotFound() throws Exception { uriField.setAccessible(true); UriInfo uriInfo = mock(UriInfo.class); uriField.set(destLookup, uriInfo); - URI uri = URI.create("http://localhost:8080/lookup/v2/destination/topic/myprop/usc/ns2/topic1"); + URI uri = URI.create("http://localhost:8080/lookup/v2/topic/persistent/myprop/ns2/topic1"); doReturn(uri).when(uriInfo).getRequestUri(); config.setAuthorizationEnabled(true); NamespaceService namespaceService = pulsar.getNamespaceService(); @@ -315,7 +328,7 @@ public void topicNotFound() throws Exception { AsyncResponse asyncResponse1 = mock(AsyncResponse.class); // We used a nonexistent topic to test destLookup.lookupTopicAsync(asyncResponse1, TopicDomain.persistent.value(), "myprop", - "usc", "ns2", "topic2", false, null, null); + "ns2", "topic2", false, null, null); // Gets semaphore status Integer state2 = pulsar.getBrokerService().getLookupRequestSemaphore().availablePermits(); // If it is successfully released, it should be equal diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/namespace/NamespaceServiceTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/namespace/NamespaceServiceTest.java index 924dd9d11ba3f..a80bdbea51074 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/namespace/NamespaceServiceTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/namespace/NamespaceServiceTest.java @@ -133,8 +133,8 @@ public void testSplitAndOwnBundles() throws Exception { ownership.setAccessible(true); ownership.set(pulsar.getNamespaceService(), mockOwnershipCache); NamespaceService namespaceService = pulsar.getNamespaceService(); - NamespaceName nsname = NamespaceName.get("pulsar/global/ns1"); - TopicName topicName = TopicName.get("persistent://pulsar/global/ns1/topic-1"); + NamespaceName nsname = NamespaceName.get("prop/ns-abc"); + TopicName topicName = TopicName.get("persistent://prop/ns-abc/topic-1"); NamespaceBundles bundles = namespaceService.getNamespaceBundleFactory().getBundles(nsname); NamespaceBundle originalBundle = bundles.findBundle(topicName); @@ -210,8 +210,8 @@ public void testSplitMapWithRefreshedStatMap() throws Exception { ownership.set(pulsar.getNamespaceService(), mockOwnershipCache); NamespaceService namespaceService = pulsar.getNamespaceService(); - NamespaceName nsname = NamespaceName.get("pulsar/global/ns1"); - TopicName topicName = TopicName.get("persistent://pulsar/global/ns1/topic-1"); + NamespaceName nsname = NamespaceName.get("prop/ns-abc"); + TopicName topicName = TopicName.get("persistent://prop/ns-abc/topic-1"); NamespaceBundles bundles = namespaceService.getNamespaceBundleFactory().getBundles(nsname); NamespaceBundle originalBundle = bundles.findBundle(topicName); @@ -265,8 +265,8 @@ public void testIsServiceUnitDisabled() throws Exception { ownership.set(pulsar.getNamespaceService(), mockOwnershipCache); NamespaceService namespaceService = pulsar.getNamespaceService(); - NamespaceName nsname = NamespaceName.get("pulsar/global/ns1"); - TopicName topicName = TopicName.get("persistent://pulsar/global/ns1/topic-1"); + NamespaceName nsname = NamespaceName.get("pulsar/ns1"); + TopicName topicName = TopicName.get("persistent://pulsar/ns1/topic-1"); NamespaceBundles bundles = namespaceService.getNamespaceBundleFactory().getBundles(nsname); NamespaceBundle originalBundle = bundles.findBundle(topicName); @@ -289,7 +289,7 @@ public void testRemoveOwnershipNamespaceBundle() throws Exception { ownership.set(pulsar.getNamespaceService(), ownershipCache); NamespaceService namespaceService = pulsar.getNamespaceService(); - NamespaceName nsname = NamespaceName.get("prop/use/ns1"); + NamespaceName nsname = NamespaceName.get("prop/ns1"); NamespaceBundles bundles = namespaceService.getNamespaceBundleFactory().getBundles(nsname); NamespaceBundle bundle = bundles.getBundles().get(0); @@ -302,7 +302,7 @@ public void testRemoveOwnershipNamespaceBundle() throws Exception { @Test public void testUnloadNamespaceBundleFailure() throws Exception { - final String topicName = "persistent://my-property/use/my-ns/my-topic1"; + final String topicName = "persistent://prop/ns-abc/my-topic1"; pulsarClient.newConsumer().topic(topicName).subscriptionName("my-subscriber-name").subscribe(); final var topics = pulsar.getBrokerService().getTopics(); @@ -332,7 +332,7 @@ public void testUnloadNamespaceBundleFailure() throws Exception { @Test(timeOut = 6000) public void testUnloadNamespaceBundleWithStuckTopic() throws Exception { - final String topicName = "persistent://my-property/use/my-ns/my-topic1"; + final String topicName = "persistent://prop/ns-abc/my-topic1"; Consumer consumer = pulsarClient.newConsumer().topic(topicName).subscriptionName("my-subscriber-name") .subscribe(); final var topics = pulsar.getBrokerService().getTopics(); @@ -437,8 +437,8 @@ public void testCreateNamespaceWithDefaultNumberOfBundles() throws Exception { ownership.setAccessible(true); ownership.set(pulsar.getNamespaceService(), mockOwnershipCache); NamespaceService namespaceService = pulsar.getNamespaceService(); - NamespaceName nsname = NamespaceName.get("pulsar/global/ns1"); - TopicName topicName = TopicName.get("persistent://pulsar/global/ns1/topic-1"); + NamespaceName nsname = NamespaceName.get("pulsar/ns1"); + TopicName topicName = TopicName.get("persistent://pulsar/ns1/topic-1"); NamespaceBundles bundles = namespaceService.getNamespaceBundleFactory().getBundles(nsname); NamespaceBundle originalBundle = bundles.findBundle(topicName); @@ -502,8 +502,8 @@ public void testRemoveOwnershipAndSplitBundle() throws Exception { ownership.set(pulsar.getNamespaceService(), ownershipCache); NamespaceService namespaceService = pulsar.getNamespaceService(); - NamespaceName nsname = NamespaceName.get("pulsar/global/ns1"); - TopicName topicName = TopicName.get("persistent://pulsar/global/ns1/topic-1"); + NamespaceName nsname = NamespaceName.get("pulsar/ns1"); + TopicName topicName = TopicName.get("persistent://pulsar/ns1/topic-1"); NamespaceBundles bundles = namespaceService.getNamespaceBundleFactory().getBundles(nsname); NamespaceBundle originalBundle = bundles.findBundle(topicName); @@ -549,8 +549,8 @@ public void testSplitBundleAndRemoveOldBundleFromOwnerShipCache() throws Excepti ownership.set(pulsar.getNamespaceService(), ownershipCache); NamespaceService namespaceService = pulsar.getNamespaceService(); - NamespaceName nsname = NamespaceName.get("pulsar/global/ns1"); - TopicName topicName = TopicName.get("persistent://pulsar/global/ns1/topic-1"); + NamespaceName nsname = NamespaceName.get("pulsar/ns1"); + TopicName topicName = TopicName.get("persistent://pulsar/ns1/topic-1"); NamespaceBundles bundles = namespaceService.getNamespaceBundleFactory().getBundles(nsname); NamespaceBundle splitBundle1 = bundles.findBundle(topicName); @@ -584,7 +584,7 @@ public void testSplitBundleAndRemoveOldBundleFromOwnerShipCache() throws Excepti @Test public void testSplitLargestBundle() throws Exception { - String namespace = "prop/test/ns-abc2"; + String namespace = "prop/ns-abc2"; String topic = "persistent://" + namespace + "/t1-"; int totalTopics = 100; @@ -632,7 +632,7 @@ public void testSplitLargestBundle() throws Exception { public void testSplitBUndleWithNoBundle() throws Exception { conf.setLoadManagerClassName(ModularLoadManagerImpl.class.getName()); restartBroker(); - String namespace = "prop/test/ns-abc2"; + String namespace = "prop/ns-abc2"; BundlesData bundleData = BundlesData.builder().numBundles(10).build(); admin.namespaces().createNamespace(namespace, bundleData); @@ -659,7 +659,7 @@ public void testSplitBundleWithHighestThroughput() throws Exception { conf.setLoadManagerClassName(ModularLoadManagerImpl.class.getName()); restartBroker(); - String namespace = "prop/test/ns-abc2"; + String namespace = "prop/ns-abc2"; String topic = "persistent://" + namespace + "/t1-"; int totalTopics = 100; @@ -721,7 +721,7 @@ public void testHeartbeatNamespaceMatch() throws Exception { @Test public void testModularLoadManagerRemoveInactiveBundleFromLoadData() throws Exception { - final String namespace = "pulsar/test/ns1"; + final String namespace = "prop/ns-abc"; final String topic1 = "persistent://" + namespace + "/topic1"; final String topic2 = "persistent://" + namespace + "/topic2"; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/namespace/OwnershipCacheTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/namespace/OwnershipCacheTest.java index 2c3182659f022..4b64cf7d290e4 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/namespace/OwnershipCacheTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/namespace/OwnershipCacheTest.java @@ -129,7 +129,7 @@ public void testConstructor() { public void testDisableOwnership() throws Exception { OwnershipCache cache = new OwnershipCache(this.pulsar, nsService); - NamespaceBundle testBundle = new NamespaceBundle(NamespaceName.get("pulsar/test/ns-1"), + NamespaceBundle testBundle = new NamespaceBundle(NamespaceName.get("pulsar/ns-1"), Range.closedOpen(0L, (long) Integer.MAX_VALUE), bundleFactory); assertFalse(cache.getOwnerAsync(testBundle).get().isPresent()); @@ -146,7 +146,7 @@ public void testDisableOwnership() throws Exception { @Test public void testGetOrSetOwner() throws Exception { OwnershipCache cache = new OwnershipCache(this.pulsar, nsService); - NamespaceBundle testFullBundle = new NamespaceBundle(NamespaceName.get("pulsar/test/ns-2"), + NamespaceBundle testFullBundle = new NamespaceBundle(NamespaceName.get("pulsar/ns-2"), Range.closedOpen(0L, (long) Integer.MAX_VALUE), bundleFactory); // case 1: no one owns the namespace @@ -192,7 +192,7 @@ public void testGetOrSetOwner() throws Exception { @Test public void testGetOwner() throws Exception { OwnershipCache cache = new OwnershipCache(this.pulsar, nsService); - NamespaceBundle testBundle = new NamespaceBundle(NamespaceName.get("pulsar/test/ns-3"), + NamespaceBundle testBundle = new NamespaceBundle(NamespaceName.get("pulsar/ns-3"), Range.closedOpen(0L, (long) Integer.MAX_VALUE), bundleFactory); // case 1: no one owns the namespace @@ -228,7 +228,7 @@ public void testGetOwner() throws Exception { assertEquals(data1, readOnlyData); - NamespaceBundle noneBundle = new NamespaceBundle(NamespaceName.get("pulsar/test/ns-none"), + NamespaceBundle noneBundle = new NamespaceBundle(NamespaceName.get("pulsar/ns-none"), Range.closedOpen(0L, (long) Integer.MAX_VALUE), bundleFactory); Optional res = cache @@ -239,7 +239,7 @@ public void testGetOwner() throws Exception { @Test public void testGetOwnedServiceUnit() throws Exception { OwnershipCache cache = new OwnershipCache(this.pulsar, nsService); - NamespaceName testNs = NamespaceName.get("pulsar/test/ns-5"); + NamespaceName testNs = NamespaceName.get("pulsar/ns-5"); NamespaceBundle testBundle = new NamespaceBundle(testNs, Range.closedOpen(0L, (long) Integer.MAX_VALUE), bundleFactory); @@ -299,7 +299,7 @@ public void testGetOwnedServiceUnit() throws Exception { @Test public void testGetOwnedServiceUnits() throws Exception { OwnershipCache cache = new OwnershipCache(this.pulsar, nsService); - NamespaceName testNs = NamespaceName.get("pulsar/test/ns-6"); + NamespaceName testNs = NamespaceName.get("pulsar/ns-6"); NamespaceBundle testBundle = new NamespaceBundle(testNs, Range.closedOpen(0L, (long) Integer.MAX_VALUE), bundleFactory); @@ -345,7 +345,7 @@ public void testGetOwnedServiceUnits() throws Exception { @Test public void testRemoveOwnership() throws Exception { OwnershipCache cache = new OwnershipCache(this.pulsar, nsService); - NamespaceName testNs = NamespaceName.get("pulsar/test/ns-7"); + NamespaceName testNs = NamespaceName.get("pulsar/ns-7"); NamespaceBundle bundle = new NamespaceBundle(testNs, Range.closedOpen(0L, (long) Integer.MAX_VALUE), bundleFactory); @@ -371,7 +371,7 @@ public void testRemoveOwnership() throws Exception { @Test public void testReestablishOwnership() throws Exception { OwnershipCache cache = new OwnershipCache(this.pulsar, nsService); - NamespaceBundle testFullBundle = new NamespaceBundle(NamespaceName.get("pulsar/test/ns-8"), + NamespaceBundle testFullBundle = new NamespaceBundle(NamespaceName.get("pulsar/ns-8"), Range.closedOpen(0L, (long) Integer.MAX_VALUE), bundleFactory); String testFullBundlePath = ServiceUnitUtils.path(testFullBundle); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/resourcegroup/ResourceGroupUsageAggregationTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/resourcegroup/ResourceGroupUsageAggregationTest.java index 664e9fdad1f78..ef20ac9d8f0c5 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/resourcegroup/ResourceGroupUsageAggregationTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/resourcegroup/ResourceGroupUsageAggregationTest.java @@ -265,7 +265,7 @@ private void verifyStats(String topicString, String rgName, final String tenantName = "pulsar-test"; final String nsName = "test"; final String tenantAndNsName = tenantName + "/" + nsName; - final String testProduceConsumeTopicName = "/test/prod-cons-topic"; + final String testProduceConsumeTopicName = "/prod-cons-topic"; final String produceConsumePersistentTopic = "persistent://" + tenantAndNsName + testProduceConsumeTopicName; final String produceConsumeNonPersistentTopic = "non-persistent://" + tenantAndNsName + testProduceConsumeTopicName; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerBkEnsemblesTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerBkEnsemblesTest.java index 8b84041524b6c..a7d73234989b4 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerBkEnsemblesTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerBkEnsemblesTest.java @@ -106,7 +106,7 @@ public void testCrashBrokerWithoutCursorLedgerLeak() throws Exception { .statsInterval(0, TimeUnit.SECONDS) .build(); - final String ns1 = "prop/usc/crash-broker"; + final String ns1 = "prop/crash-broker"; admin.namespaces().createNamespace(ns1); @@ -204,7 +204,7 @@ public void testSkipCorruptDataLedger() throws Exception { .statsInterval(0, TimeUnit.SECONDS) .build(); - final String ns1 = "prop/usc/crash-broker"; + final String ns1 = "prop/crash-broker"; final int totalMessages = 99; final int totalDataLedgers = 5; final int entriesPerLedger = 20; @@ -443,14 +443,14 @@ public void testTopicWithWildCardChar() throws Exception { .statsInterval(0, TimeUnit.SECONDS) .build(); - final String ns1 = "prop/usc/topicWithSpecialChar"; + final String ns1 = "prop/topicWithSpecialChar"; try { admin.namespaces().createNamespace(ns1); } catch (Exception e) { } - final String topic1 = "persistent://" + ns1 + "/`~!@#$%^&*()-_+=[]://{}|\\;:'\"<>,./?-30e04524"; + final String topic1 = "persistent://" + ns1 + "/`~!@#$%^&*()-_+=[]{}|\\;:'\"<>,.?-30e04524"; final String subName1 = "c1"; final byte[] content = "test".getBytes(); @@ -467,7 +467,7 @@ public void testTopicWithWildCardChar() throws Exception { @Test public void testDeleteTopicWithMissingData() throws Exception { - String namespace = BrokerTestUtil.newUniqueName("prop/usc"); + String namespace = BrokerTestUtil.newUniqueName("prop/ns"); admin.namespaces().createNamespace(namespace); String topic = BrokerTestUtil.newUniqueName(namespace + "/my-topic"); @@ -512,7 +512,7 @@ public void testDeleteTopicWithMissingData() throws Exception { @Test public void testDeleteTopicWithoutTopicLoaded() throws Exception { - String namespace = BrokerTestUtil.newUniqueName("prop/usc"); + String namespace = BrokerTestUtil.newUniqueName("prop/ns"); admin.namespaces().createNamespace(namespace); String topic = BrokerTestUtil.newUniqueName(namespace + "/my-topic"); @@ -553,7 +553,7 @@ public void testConcurrentlyModifyCurrentLedger(boolean doReloadTopicAfterLedger Optional.empty(), null).get(); - final String namespace = BrokerTestUtil.newUniqueName("prop/usc"); + final String namespace = BrokerTestUtil.newUniqueName("prop/ns"); final String topic = BrokerTestUtil.newUniqueName("persistent://" + namespace + "/tp"); final String subscription = "s1"; admin.namespaces().createNamespace(namespace); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerBookieIsolationTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerBookieIsolationTest.java index 0ef3becfa9de6..7bef444e7f8e5 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerBookieIsolationTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerBookieIsolationTest.java @@ -130,10 +130,10 @@ protected void cleanup() throws Exception { public void testBookieIsolation() throws Exception { final String tenant1 = "tenant1"; final String cluster = "use"; - final String ns1 = String.format("%s/%s/%s", tenant1, cluster, "ns1"); - final String ns2 = String.format("%s/%s/%s", tenant1, cluster, "ns2"); - final String ns3 = String.format("%s/%s/%s", tenant1, cluster, "ns3"); - final String ns4 = String.format("%s/%s/%s", tenant1, cluster, "ns4"); + final String ns1 = String.format("%s/%s", tenant1, "ns1"); + final String ns2 = String.format("%s/%s", tenant1, "ns2"); + final String ns3 = String.format("%s/%s", tenant1, "ns3"); + final String ns4 = String.format("%s/%s", tenant1, "ns4"); final int totalPublish = 100; final String brokerBookkeeperClientIsolationGroups = "default-group"; @@ -310,7 +310,7 @@ private LedgerManager getLedgerManager(BookieImpl bookie1) throws IllegalAccessE public void testSetRackInfoAndAffinityGroupDuringProduce() throws Exception { final String tenant1 = "tenant1"; final String cluster = "use"; - final String ns2 = String.format("%s/%s/%s", tenant1, cluster, "ns2"); + final String ns2 = String.format("%s/%s", tenant1, "ns2"); final int totalPublish = 100; final String brokerBookkeeperClientIsolationGroups = "default-group"; @@ -450,10 +450,10 @@ public void testSetRackInfoAndAffinityGroupDuringProduce() throws Exception { public void testStrictBookieIsolation() throws Exception { final String tenant1 = "tenant1"; final String cluster = "use"; - final String ns1 = String.format("%s/%s/%s", tenant1, cluster, "ns1"); - final String ns2 = String.format("%s/%s/%s", tenant1, cluster, "ns2"); - final String ns3 = String.format("%s/%s/%s", tenant1, cluster, "ns3"); - final String ns4 = String.format("%s/%s/%s", tenant1, cluster, "ns4"); + final String ns1 = String.format("%s/%s", tenant1, "ns1"); + final String ns2 = String.format("%s/%s", tenant1, "ns2"); + final String ns3 = String.format("%s/%s", tenant1, "ns3"); + final String ns4 = String.format("%s/%s", tenant1, "ns4"); final int totalPublish = 100; final String brokerBookkeeperClientIsolationGroups = "default-group"; @@ -616,10 +616,10 @@ public void testStrictBookieIsolation() throws Exception { public void testBookieIsolationWithSecondaryGroup() throws Exception { final String tenant1 = "tenant1"; final String cluster = "use"; - final String ns1 = String.format("%s/%s/%s", tenant1, cluster, "ns1"); - final String ns2 = String.format("%s/%s/%s", tenant1, cluster, "ns2"); - final String ns3 = String.format("%s/%s/%s", tenant1, cluster, "ns3"); - final String ns4 = String.format("%s/%s/%s", tenant1, cluster, "ns4"); + final String ns1 = String.format("%s/%s", tenant1, "ns1"); + final String ns2 = String.format("%s/%s", tenant1, "ns2"); + final String ns3 = String.format("%s/%s", tenant1, "ns3"); + final String ns4 = String.format("%s/%s", tenant1, "ns4"); final int totalPublish = 100; final String brokerBookkeeperClientIsolationGroups = "default-group"; @@ -773,8 +773,8 @@ public void testDeleteIsolationGroup() throws Exception { final String tenant1 = "tenant1"; final String cluster = "use"; - final String ns2 = String.format("%s/%s/%s", tenant1, cluster, "ns2"); - final String ns3 = String.format("%s/%s/%s", tenant1, cluster, "ns3"); + final String ns2 = String.format("%s/%s", tenant1, "ns2"); + final String ns3 = String.format("%s/%s", tenant1, "ns3"); final String brokerBookkeeperClientIsolationGroups = "default-group"; final String tenantNamespaceIsolationGroupsPrimary = "tenant1-isolation-primary"; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerServiceAutoTopicCreationTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerServiceAutoTopicCreationTest.java index dda26d7d63170..f8b672489fd51 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerServiceAutoTopicCreationTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerServiceAutoTopicCreationTest.java @@ -600,25 +600,6 @@ public void testExtensibleLoadManagerImplInternalTopicAutoCreations() } - @Test - public void testAutoPartitionedTopicNameWithClusterName() throws Exception { - pulsar.getConfiguration().setAllowAutoTopicCreation(true); - pulsar.getConfiguration().setAllowAutoTopicCreationType(TopicType.PARTITIONED); - pulsar.getConfiguration().setDefaultNumPartitions(3); - - final String topicString = "persistent://prop/ns-abc/testTopic/1"; - // When allowAutoTopicCreationWithLegacyNamingScheme as the default value is false, - // four-paragraph topic cannot be created. - pulsar.getConfiguration().setAllowAutoTopicCreationWithLegacyNamingScheme(false); - Assert.assertThrows(PulsarClientException.NotFoundException.class, - () -> pulsarClient.newProducer().topic(topicString).create()); - - pulsar.getConfiguration().setAllowAutoTopicCreationWithLegacyNamingScheme(true); - Producer producer = pulsarClient.newProducer().topic(topicString).create(); - Assert.assertEquals(producer.getTopic(), topicString); - producer.close(); - } - @Test public void testCreateTopicAfterGC() throws Exception { final String topic = BrokerTestUtil.newUniqueName("persistent://prop/ns-abc/tp"); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerServiceTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerServiceTest.java index db6a0b85ef654..7e328dcf0d99c 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerServiceTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerServiceTest.java @@ -1627,12 +1627,9 @@ public void testIsSystemTopic() { assertTrue(brokerService.isSystemTopic(TRANSACTION_COORDINATOR_ASSIGN)); assertTrue(brokerService.isSystemTopic(TRANSACTION_COORDINATOR_LOG)); - NamespaceName heartbeatNamespaceV1 = NamespaceService + NamespaceName heartbeatNamespace = NamespaceService .getHeartbeatNamespace(pulsar.getBrokerId(), pulsar.getConfig()); - NamespaceName heartbeatNamespaceV2 = NamespaceService - .getHeartbeatNamespaceV2(pulsar.getBrokerId(), pulsar.getConfig()); - assertTrue(brokerService.isSystemTopic("persistent://" + heartbeatNamespaceV1.toString() + "/healthcheck")); - assertTrue(brokerService.isSystemTopic(heartbeatNamespaceV2.toString() + "/healthcheck")); + assertTrue(brokerService.isSystemTopic("persistent://" + heartbeatNamespace.toString() + "/healthcheck")); } @Test @@ -2022,7 +2019,7 @@ public void testTlsWithAuthParams() throws Exception { @Test public void testPulsarMetadataEventSyncProducerCreation() throws Exception { - final String topicName = "persistent://prop/usw/my-ns/syncTopic"; + final String topicName = "persistent://prop/ns-abc/syncTopic"; pulsar.getConfiguration().setMetadataSyncEventTopic(topicName); PulsarMetadataEventSynchronizer sync = new PulsarMetadataEventSynchronizer(pulsar, topicName); // set invalid client for retry diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerTestBase.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerTestBase.java index 28577b05d59f5..9848293102cfa 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerTestBase.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerTestBase.java @@ -55,6 +55,11 @@ private void baseSetupCommon() throws Exception { new TenantInfoImpl(Sets.newHashSet("appid1"), Sets.newHashSet("test"))); admin.namespaces().createNamespace("prop/ns-abc"); admin.namespaces().setNamespaceReplicationClusters("prop/ns-abc", Sets.newHashSet("test"), false); + + admin.tenants().createTenant("my-property", + new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("test"))); + admin.namespaces().createNamespace("my-property/my-ns"); + admin.namespaces().setNamespaceReplicationClusters("my-property/my-ns", Sets.newHashSet("test"), false); } protected void createTransactionCoordinatorAssign() throws MetadataStoreException { diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/InactiveTopicDeleteTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/InactiveTopicDeleteTest.java index add3c0e50288a..bd53f772c2001 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/InactiveTopicDeleteTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/InactiveTopicDeleteTest.java @@ -37,7 +37,6 @@ import org.apache.pulsar.client.api.Producer; import org.apache.pulsar.common.naming.NamespaceName; import org.apache.pulsar.common.naming.TopicName; -import org.apache.pulsar.common.naming.TopicVersion; import org.apache.pulsar.common.policies.data.InactiveTopicDeleteMode; import org.apache.pulsar.common.policies.data.InactiveTopicPolicies; import org.apache.pulsar.common.policies.data.RetentionPolicies; @@ -609,29 +608,18 @@ public void testHealthTopicInactiveNotClean() throws Exception { conf.setBrokerDeleteInactiveTopicsFrequencySeconds(1); super.baseSetup(); // init topic - NamespaceName heartbeatNamespaceV1 = NamespaceService + NamespaceName heartbeatNamespace = NamespaceService .getHeartbeatNamespace(pulsar.getBrokerId(), pulsar.getConfig()); - final String healthCheckTopicV1 = "persistent://" + heartbeatNamespaceV1 + "/healthcheck"; + final String healthCheckTopic = "persistent://" + heartbeatNamespace + "/healthcheck"; - NamespaceName heartbeatNamespaceV2 = NamespaceService - .getHeartbeatNamespaceV2(pulsar.getBrokerId(), pulsar.getConfig()); - final String healthCheckTopicV2 = "persistent://" + heartbeatNamespaceV2 + "/healthcheck"; + admin.brokers().healthcheck(); - admin.brokers().healthcheck(TopicVersion.V1); - admin.brokers().healthcheck(TopicVersion.V2); - - List v1Partitions = pulsar - .getPulsarResources() - .getTopicResources() - .getExistingPartitions(TopicName.get(healthCheckTopicV1)) - .get(10, TimeUnit.SECONDS); - List v2Partitions = pulsar + List partitions = pulsar .getPulsarResources() .getTopicResources() - .getExistingPartitions(TopicName.get(healthCheckTopicV2)) + .getExistingPartitions(TopicName.get(healthCheckTopic)) .get(10, TimeUnit.SECONDS); - Assert.assertTrue(v1Partitions.contains(healthCheckTopicV1)); - Assert.assertTrue(v2Partitions.contains(healthCheckTopicV2)); + Assert.assertTrue(partitions.contains(healthCheckTopic)); } @Test diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/OneWayReplicatorTestBase.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/OneWayReplicatorTestBase.java index adc363cf7cd77..1c43b27e1ecc9 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/OneWayReplicatorTestBase.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/OneWayReplicatorTestBase.java @@ -485,6 +485,7 @@ protected void setTopicLevelClusters(String topic, List clusters, Pulsar Awaitility.await().untilAsserted(() -> { TopicPolicies policies = TopicPolicyTestUtils.getTopicPolicies(pulsar.getTopicPoliciesService(), topicName, global); + Assert.assertNotNull(policies, "Topic policies not yet available"); assertEquals(new HashSet<>(policies.getReplicationClusters()), expected); if (partitions == 0) { checkNonPartitionedTopicLevelClusters(topicName.toString(), clusters, admin, pulsar, diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/OpportunisticStripingTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/OpportunisticStripingTest.java index c5007d1c64c2e..1c76f84cb3ee0 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/OpportunisticStripingTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/OpportunisticStripingTest.java @@ -62,7 +62,7 @@ public void testOpportunisticStriping() throws Exception { .statsInterval(0, TimeUnit.SECONDS) .build();) { - final String ns1 = "prop/usc/opportunistic1"; + final String ns1 = "prop/opportunistic1"; admin.namespaces().createNamespace(ns1); final String topic1 = "persistent://" + ns1 + "/my-topic"; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PartitionKeyTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PartitionKeyTest.java index b0109c3ddcbf0..80aa5f198cc76 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PartitionKeyTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PartitionKeyTest.java @@ -43,7 +43,7 @@ public void cleanup() throws Exception { @Test(timeOut = 10000) public void testPartitionKey() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/testPartitionKey"; + final String topicName = "persistent://prop/ns-abc/testPartitionKey"; org.apache.pulsar.client.api.Consumer consumer = pulsarClient.newConsumer().topic(topicName) .subscriptionName("my-subscription").subscribe(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PeerReplicatorTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PeerReplicatorTest.java index 5a5bf807f2e0f..2fd6e09529de2 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PeerReplicatorTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PeerReplicatorTest.java @@ -91,8 +91,8 @@ public void testPeerClusterTopicLookup(String protocol) throws Exception { final String serviceUrl = protocol.equalsIgnoreCase("http") ? pulsar3.getWebServiceAddress() : pulsar3.getBrokerServiceUrl(); - final String namespace1 = "pulsar/global/peer1-" + protocol; - final String namespace2 = "pulsar/global/peer2-" + protocol; + final String namespace1 = "pulsar/peer1-" + protocol; + final String namespace2 = "pulsar/peer2-" + protocol; admin1.namespaces().createNamespace(namespace1); admin1.namespaces().createNamespace(namespace2); // add replication cluster @@ -196,7 +196,7 @@ public void testPeerClusterInReplicationClusterListChange() throws Exception { admin1.clusters().updatePeerClusterNames("r3", null); final String serviceUrl = pulsar3.getBrokerServiceUrl(); - final String namespace1 = BrokerTestUtil.newUniqueName("pulsar/global/peer-change-repl-ns"); + final String namespace1 = BrokerTestUtil.newUniqueName("pulsar/peer-change-repl-ns"); admin1.namespaces().createNamespace(namespace1); // add replication cluster admin1.namespaces().setNamespaceReplicationClusters(namespace1, Sets.newHashSet("r1"), false); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentDispatcherFailoverConsumerTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentDispatcherFailoverConsumerTest.java index 9ac922ce46958..8f1b23e26d9f7 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentDispatcherFailoverConsumerTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentDispatcherFailoverConsumerTest.java @@ -101,8 +101,8 @@ public class PersistentDispatcherFailoverConsumerTest { protected PulsarTestContext pulsarTestContext; - final String successTopicName = "persistent://part-perf/global/perf.t1/ptopic"; - final String failTopicName = "persistent://part-perf/global/perf.t1/pfailTopic"; + final String successTopicName = "persistent://part-perf/perf.t1/ptopic"; + final String failTopicName = "persistent://part-perf/perf.t1/pfailTopic"; @BeforeMethod public void setup() throws Exception { diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentFailoverE2ETest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentFailoverE2ETest.java index cbfc5b1d236b4..7359957ab3399 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentFailoverE2ETest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentFailoverE2ETest.java @@ -169,7 +169,7 @@ FailoverConsumer createConsumer(String topicName, String subName, String listene @Test public void testSimpleConsumerEventsWithoutPartition() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/failover-topic1-" + System.currentTimeMillis(); + final String topicName = "persistent://prop/ns-abc/failover-topic1-" + System.currentTimeMillis(); final String subName = "sub1"; final int numMsgs = 100; @@ -314,7 +314,7 @@ public void testSimpleConsumerEventsWithPartition() throws Exception { int numPartitions = 4; final String topicName = BrokerTestUtil.newUniqueName( - "persistent://prop/use/ns-abc/testSimpleConsumerEventsWithPartition"); + "persistent://prop/ns-abc/testSimpleConsumerEventsWithPartition"); final TopicName destName = TopicName.get(topicName); final String subName = "sub1"; final int numMsgs = 100; @@ -501,7 +501,7 @@ public void testSimpleConsumerEventsWithPartition() throws Exception { @Test public void testActiveConsumerFailoverWithDelay() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/failover-topic3"; + final String topicName = "persistent://prop/ns-abc/failover-topic3"; final String subName = "sub1"; final int numMsgs = 100; List> receivedMessages = new ArrayList<>(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentQueueE2ETest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentQueueE2ETest.java index 4b92bfdc81c78..66248710efacb 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentQueueE2ETest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentQueueE2ETest.java @@ -85,7 +85,7 @@ private void deleteTopic(String topicName) { @Test public void testSimpleConsumerEvents() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/shared-topic1"; + final String topicName = "persistent://prop/ns-abc/shared-topic1"; final String subName = "sub1"; final int numMsgs = 100; @@ -186,7 +186,7 @@ public void testSimpleConsumerEvents() throws Exception { @Test public void testReplayOnConsumerDisconnect() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/shared-topic3"; + final String topicName = "persistent://prop/ns-abc/shared-topic3"; final String subName = "sub3"; final int numMsgs = 100; @@ -240,7 +240,7 @@ public void testReplayOnConsumerDisconnect() throws Exception { // how the round robin distribution algorithm is behaving @Test(enabled = false) public void testRoundRobinBatchDistribution() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/shared-topic5"; + final String topicName = "persistent://prop/ns-abc/shared-topic5"; final String subName = "sub5"; final int numMsgs = 137; /* some random number different than default batch size of 100 */ @@ -312,7 +312,7 @@ public void testRoundRobinBatchDistribution() throws Exception { @Test(timeOut = 300000) public void testSharedSingleAckedNormalTopic() throws Exception { String key = "test1"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-shared-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 50; @@ -383,7 +383,7 @@ public void testSharedSingleAckedNormalTopic() throws Exception { @Test(timeOut = 60000) public void testCancelReadRequestOnLastDisconnect() throws Exception { String key = "testCancelReadRequestOnLastDisconnect"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-shared-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 10; @@ -459,7 +459,7 @@ public void testCancelReadRequestOnLastDisconnect() throws Exception { @Test public void testUnackedCountWithRedeliveries() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/testUnackedCountWithRedeliveries"; + final String topicName = "persistent://prop/ns-abc/testUnackedCountWithRedeliveries"; final String subName = "sub3"; final int numMsgs = 10; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentTopicConcurrentTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentTopicConcurrentTest.java index 2f8a924635116..72e1c4f4e700a 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentTopicConcurrentTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentTopicConcurrentTest.java @@ -68,7 +68,7 @@ public class PersistentTopicConcurrentTest extends MockedBookKeeperTestCase { @SuppressWarnings("unused") private ManagedCursor cursorMock; - final String successTopicName = "persistent://prop/use/ns-abc/successTopic"; + final String successTopicName = "persistent://prop/ns-abc/successTopic"; final String successSubName = "successSub"; private static final Logger log = LoggerFactory.getLogger(PersistentTopicTest.class); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentTopicTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentTopicTest.java index bd817de553ba8..93bb6f86ffaf2 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentTopicTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/PersistentTopicTest.java @@ -167,9 +167,9 @@ public class PersistentTopicTest extends MockedBookKeeperTestCase { private ManagedLedger ledgerMock; private ManagedCursor cursorMock; - final String successTopicName = "persistent://prop/use/ns-abc/successTopic"; - final String successPartitionTopicName = "persistent://prop/use/ns-abc/successTopic-partition-0"; - final String failTopicName = "persistent://prop/use/ns-abc/failTopic"; + final String successTopicName = "persistent://prop/ns-abc/successTopic"; + final String successPartitionTopicName = "persistent://prop/ns-abc/successTopic-partition-0"; + final String failTopicName = "persistent://prop/ns-abc/failTopic"; final String successSubName = "successSub"; final String successSubName2 = "successSub2"; private static final Logger log = LoggerFactory.getLogger(PersistentTopicTest.class); @@ -266,7 +266,7 @@ public void testCreateTopic() { doReturn(new ManagedLedgerConfig()).when(ledgerMock).getConfig(); doReturn(new ArrayList<>()).when(ledgerMock).getCursors(); - final String topicName = "persistent://prop/use/ns-abc/topic1"; + final String topicName = "persistent://prop/ns-abc/topic1"; doAnswer(invocationOnMock -> { ((OpenLedgerCallback) invocationOnMock.getArguments()[2]).openLedgerComplete(ledgerMock, null); return null; @@ -290,7 +290,7 @@ public void testCreateTopic() { @Test public void testCreateTopicMLFailure() { - final String jinxedTopicName = "persistent://prop/use/ns-abc/topic3"; + final String jinxedTopicName = "persistent://prop/ns-abc/topic3"; doAnswer(invocationOnMock -> { new Thread(() -> ((OpenLedgerCallback) invocationOnMock.getArguments()[2]) .openLedgerFailed(new ManagedLedgerException("Managed ledger failure"), null)).start(); @@ -388,7 +388,7 @@ public void testDispatcherSingleConsumerReadFailed() { @Test public void testPublishMessageMLFailure() throws Exception { - final String successTopicName = "persistent://prop/use/ns-abc/successTopic"; + final String successTopicName = "persistent://prop/ns-abc/successTopic"; final ManagedLedger ledgerMock = mock(ManagedLedger.class); doReturn(new ManagedLedgerConfig()).when(ledgerMock).getConfig(); @@ -1690,7 +1690,7 @@ private PulsarAdmin mockReplicationAdmin() { */ @Test public void testAtomicReplicationRemoval() throws Exception { - final String globalTopicName = "persistent://prop/global/ns-abc/successTopic"; + final String globalTopicName = "persistent://prop/ns-abc/successTopic"; String localCluster = "local"; String remoteCluster = "remote"; final ManagedLedger ledgerMock = mock(ManagedLedger.class); @@ -1757,7 +1757,7 @@ public CompletableFuture createAsync() { @SuppressWarnings("unchecked") @Test public void testClosingReplicationProducerTwice() throws Exception { - final String globalTopicName = "persistent://prop/global/ns/testClosingReplicationProducerTwice"; + final String globalTopicName = "persistent://prop/ns/testClosingReplicationProducerTwice"; String localCluster = "local"; String remoteCluster = "remote"; final ManagedLedger ledgerMock = mock(ManagedLedger.class); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorGlobalNSTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorGlobalNSTest.java index 690f248845bce..16d34d9b86923 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorGlobalNSTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorGlobalNSTest.java @@ -94,7 +94,7 @@ public void cleanup() throws Exception { public void testRemoveLocalClusterOnGlobalNamespace() throws Exception { log.info("--- Starting ReplicatorTest::testRemoveLocalClusterOnGlobalNamespace ---"); - final String namespace = "pulsar/global/removeClusterTest"; + final String namespace = "pulsar/removeClusterTest"; admin1.namespaces().createNamespace(namespace); admin1.namespaces().setNamespaceReplicationClusters(namespace, Sets.newHashSet("r1", "r2", "r3"), false); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorRemoveClusterTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorRemoveClusterTest.java index e62e3a6e85687..34e99fd20b3be 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorRemoveClusterTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorRemoveClusterTest.java @@ -49,7 +49,6 @@ public void beforeMethod(Method m) throws Exception { methodName = m.getName(); admin1.namespaces().removeBacklogQuota("pulsar/ns"); admin1.namespaces().removeBacklogQuota("pulsar/ns1"); - admin1.namespaces().removeBacklogQuota("pulsar/global/ns"); } @Override diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorTest.java index eee8eaef97a9b..0980c1869c1fe 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorTest.java @@ -136,7 +136,6 @@ public void beforeMethod(Method m) throws Exception { if (admin1 != null) { admin1.namespaces().removeBacklogQuota("pulsar/ns"); admin1.namespaces().removeBacklogQuota("pulsar/ns1"); - admin1.namespaces().removeBacklogQuota("pulsar/global/ns"); } } @@ -258,7 +257,7 @@ public void testConcurrentReplicator() throws Exception { @DataProvider(name = "namespace") public Object[][] namespaceNameProvider() { - return new Object[][] { { "pulsar/ns" }, { "pulsar/global/ns" } }; + return new Object[][] { { "pulsar/ns" } }; } @Test(dataProvider = "namespace") @@ -1250,7 +1249,7 @@ public void testReplicatedCluster() throws Exception { log.info("--- Starting ReplicatorTest::testReplicatedCluster ---"); - final String namespace = BrokerTestUtil.newUniqueName("pulsar/global/repl"); + final String namespace = BrokerTestUtil.newUniqueName("pulsar/repl"); final String topicName = BrokerTestUtil.newUniqueName("persistent://" + namespace + "/topic1"); admin1.namespaces().createNamespace(namespace); admin1.namespaces().setNamespaceReplicationClusters(namespace, Sets.newHashSet("r1", "r2", "r3"), false); @@ -1617,7 +1616,7 @@ private void initTransaction(int coordinatorSize, PulsarAdmin admin, String serv public void testLookupAnotherCluster() throws Exception { log.info("--- Starting ReplicatorTest::testLookupAnotherCluster ---"); - String namespace = "pulsar/r2/cross-cluster-ns"; + String namespace = "pulsar/cross-cluster-ns"; admin1.namespaces().createNamespace(namespace); final TopicName topicName = TopicName .get("persistent://" + namespace + "/topic"); @@ -1654,7 +1653,7 @@ public void testReplicatorWithFailedAck() throws Exception { log.info("--- Starting ReplicatorTest::testReplication ---"); - String namespace = BrokerTestUtil.newUniqueName("pulsar/global/ns"); + String namespace = BrokerTestUtil.newUniqueName("pulsar/ns"); admin1.namespaces().createNamespace(namespace, Sets.newHashSet("r1")); final TopicName dest = TopicName .get(BrokerTestUtil.newUniqueName("persistent://" + namespace + "/ackFailedTopic")); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorTestBase.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorTestBase.java index 7b1200e79c24c..a7250928bd11b 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorTestBase.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ReplicatorTestBase.java @@ -287,9 +287,17 @@ protected void setup() throws Exception { .brokerClientTlsTrustStoreType(keyStoreType) .build()); + // Remove r4 from existing namespace replication clusters before shrinking the tenant, + // since canUpdateCluster validation prevents removing a cluster that namespaces still reference. + Set targetClusters = Sets.newHashSet("r1", "r2", "r3"); + if (admin1.tenants().getTenants().contains("pulsar")) { + for (String ns : admin1.namespaces().getNamespaces("pulsar")) { + admin1.namespaces().setNamespaceReplicationClusters(ns, targetClusters, false); + } + } updateTenantInfo("pulsar", new TenantInfoImpl(Sets.newHashSet("appid1", "appid2", "appid3"), - Sets.newHashSet("r1", "r2", "r3"))); + targetClusters)); admin1.namespaces().createNamespace("pulsar/ns", Sets.newHashSet("r1", "r2", "r3")); admin1.namespaces().createNamespace("pulsar/ns1", Sets.newHashSet("r1", "r2")); @@ -311,14 +319,7 @@ protected void setup() throws Exception { assertEquals(admin2.clusters().getCluster(cluster3).getBrokerServiceUrlTls(), pulsar3.getBrokerServiceUrlTls()); assertEquals(admin2.clusters().getCluster(cluster4).getBrokerServiceUrlTls(), pulsar4.getBrokerServiceUrlTls()); - // Also create V1 namespace for compatibility check - admin1.clusters().createCluster("global", ClusterData.builder() - .serviceUrl("http://global:8080") - .serviceUrlTls("https://global:8443") - .build()); - admin1.namespaces().createNamespace("pulsar/global/ns"); - admin1.namespaces().setNamespaceReplicationClusters("pulsar/global/ns", - Sets.newHashSet(cluster1, cluster2, cluster3), false); + Thread.sleep(100); log.info("--- ReplicatorTestBase::setup completed ---"); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ResendRequestTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ResendRequestTest.java index e925c8c920411..2b6ff1575e0d6 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ResendRequestTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ResendRequestTest.java @@ -37,7 +37,6 @@ import org.apache.pulsar.client.api.PulsarClient; import org.apache.pulsar.client.api.SubscriptionType; import org.apache.pulsar.client.impl.ConsumerBase; -import org.apache.pulsar.common.policies.data.TenantInfoImpl; import org.apache.pulsar.common.util.collections.GrowableArrayBlockingQueue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,7 +52,7 @@ public class ResendRequestTest extends BrokerTestBase { @BeforeMethod @Override public void setup() throws Exception { - super.internalSetup(); + super.baseSetup(); } @AfterMethod(alwaysRun = true) @@ -65,7 +64,7 @@ public void cleanup() throws Exception { @Test(timeOut = testTimeout) public void testExclusiveSingleAckedNormalTopic() throws Exception { String key = "testExclusiveSingleAckedNormalTopic"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 10; @@ -158,7 +157,7 @@ public void testExclusiveSingleAckedNormalTopic() throws Exception { @Test(timeOut = testTimeout) public void testSharedSingleAckedNormalTopic() throws Exception { String key = "testSharedSingleAckedNormalTopic"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-shared-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 10; @@ -245,7 +244,7 @@ public void testSharedSingleAckedNormalTopic() throws Exception { @Test(timeOut = testTimeout) public void testFailoverSingleAckedNormalTopic() throws Exception { String key = "testFailoverSingleAckedNormalTopic"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-failover-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 10; @@ -363,7 +362,7 @@ public void testFailoverSingleAckedNormalTopic() throws Exception { @Test(timeOut = testTimeout) public void testExclusiveCumulativeAckedNormalTopic() throws Exception { String key = "testExclusiveCumulativeAckedNormalTopic"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 10; @@ -420,15 +419,12 @@ public void testExclusiveCumulativeAckedNormalTopic() throws Exception { @Test(timeOut = testTimeout) public void testExclusiveSingleAckedPartitionedTopic() throws Exception { String key = "testExclusiveSingleAckedPartitionedTopic"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 10; final int numberOfPartitions = 4; - TenantInfoImpl tenantInfo = createDefaultTenantInfo(); - admin.tenants().createTenant("prop", tenantInfo); admin.topics().createPartitionedTopic(topicName, numberOfPartitions); - // Special step to create partitioned topic // 1. producer connect Producer producer = pulsarClient.newProducer().topic(topicName) @@ -476,16 +472,13 @@ public void testExclusiveSingleAckedPartitionedTopic() throws Exception { @Test(timeOut = testTimeout) public void testSharedSingleAckedPartitionedTopic() throws Exception { String key = "testSharedSingleAckedPartitionedTopic"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-shared-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 10; final int numberOfPartitions = 3; - TenantInfoImpl tenantInfo = createDefaultTenantInfo(); - admin.tenants().createTenant("prop", tenantInfo); admin.topics().createPartitionedTopic(topicName, numberOfPartitions); Random rn = new Random(); - // Special step to create partitioned topic // 1. producer connect Producer producer = pulsarClient.newProducer().topic(topicName) @@ -577,16 +570,13 @@ public void testSharedSingleAckedPartitionedTopic() throws Exception { @Test(timeOut = testTimeout) public void testFailoverSingleAckedPartitionedTopic() throws Exception { String key = "testFailoverSingleAckedPartitionedTopic"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-failover-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 10; final int numberOfPartitions = 3; - TenantInfoImpl tenantInfo = createDefaultTenantInfo(); - admin.tenants().createTenant("prop", tenantInfo); admin.topics().createPartitionedTopic(topicName, numberOfPartitions); Random rn = new Random(); - // Special step to create partitioned topic // 1. producer connect Producer producer = pulsarClient.newProducer().topic(topicName) @@ -668,7 +658,7 @@ public void testFailoverSingleAckedPartitionedTopic() throws Exception { @Test(timeOut = testTimeout) public void testFailoverInactiveConsumer() throws Exception { String key = "testFailoverInactiveConsumer"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-failover-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 10; @@ -694,7 +684,7 @@ public void testFailoverInactiveConsumer() throws Exception { log.info("Producer produced " + message); } - // 4. Receive messages + // 4. Receive messages - determine which consumer is active (depends on topic name hash) int receivedConsumer1 = 0, receivedConsumer2 = 0; Message message1; Message message2; @@ -716,18 +706,28 @@ public void testFailoverInactiveConsumer() throws Exception { log.info("Consumer 2 receives = " + receivedConsumer2); log.info("Total receives = " + (receivedConsumer2 + receivedConsumer1)); assertEquals(receivedConsumer2 + receivedConsumer1, totalMessages); - // Consumer 2 is on Stand By - assertEquals(receivedConsumer1, 0); + // One consumer is active, the other is on standby + Consumer activeConsumer; + Consumer standbyConsumer; + if (receivedConsumer1 == totalMessages) { + activeConsumer = consumer1; + standbyConsumer = consumer2; + assertEquals(receivedConsumer2, 0); + } else { + activeConsumer = consumer2; + standbyConsumer = consumer1; + assertEquals(receivedConsumer1, 0); + } - // 5. Consumer 2 asks for a redelivery but the request is ignored - log.info("Consumer 2 asks for resend"); - consumer2.redeliverUnacknowledgedMessages(); + // 5. Active consumer asks for a redelivery and gets the messages redelivered + log.info("Active consumer asks for resend"); + activeConsumer.redeliverUnacknowledgedMessages(); Thread.sleep(1000); - message1 = consumer1.receive(500, TimeUnit.MILLISECONDS); - message2 = consumer2.receive(500, TimeUnit.MILLISECONDS); - assertNull(message1); - assertNotNull(message2); + Message standbyMsg = standbyConsumer.receive(500, TimeUnit.MILLISECONDS); + Message activeMsg = activeConsumer.receive(500, TimeUnit.MILLISECONDS); + assertNull(standbyMsg); + assertNotNull(activeMsg); } @SuppressWarnings("unchecked") diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ServerCnxTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ServerCnxTest.java index 9cfd7dc245a6d..f0907031882e7 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ServerCnxTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/ServerCnxTest.java @@ -188,14 +188,13 @@ public class ServerCnxTest { private final int currentProtocolVersion = ProtocolVersion.values()[ProtocolVersion.values().length - 1] .getValue(); - protected final String successTopicName = "persistent://prop/use/ns-abc/successTopic"; - private final String failTopicName = "persistent://prop/use/ns-abc/failTopic"; - private final String nonOwnedTopicName = "persistent://prop/use/ns-abc/success-not-owned-topic"; - private final String encryptionRequiredTopicName = "persistent://prop/use/ns-abc/successEncryptionRequiredTopic"; + protected final String successTopicName = "persistent://prop/ns-abc/successTopic"; + private final String failTopicName = "persistent://prop/ns-abc/failTopic"; + private final String nonOwnedTopicName = "persistent://prop/ns-abc/success-not-owned-topic"; + private final String encryptionRequiredTopicName = "persistent://prop/ns-abc/successEncryptionRequiredTopic"; private final String successSubName = "successSub"; private final String nonExistentTopicName = - "persistent://nonexistent-prop/nonexistent-cluster/nonexistent-namespace/successNonExistentTopic"; - private final String topicWithNonLocalCluster = "persistent://prop/usw/ns-abc/successTopic"; + "persistent://nonexistent-prop/nonexistent-namespace/successNonExistentTopic"; private final List matchingTopics = Arrays.asList( "persistent://use/ns-abc/topic-1", "persistent://use/ns-abc/topic-2"); @@ -1715,13 +1714,6 @@ public void testClusterAccess() throws Exception { "prod-name", Collections.emptyMap(), false); channel.writeInbound(clientCommand); assertTrue(getResponse() instanceof CommandProducerSuccess); - - resetChannel(); - setChannelConnected(); - clientCommand = Commands.newProducer(topicWithNonLocalCluster, 1 /* producer id */, 1 /* request id */, - "prod-name", Collections.emptyMap(), false); - channel.writeInbound(clientCommand); - assertTrue(getResponse() instanceof CommandError); channel.finish(); } diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/SubscriptionConsumerCompatibilityTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/SubscriptionConsumerCompatibilityTest.java index 9f7516c2e3267..779de4c2b524c 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/SubscriptionConsumerCompatibilityTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/SubscriptionConsumerCompatibilityTest.java @@ -49,7 +49,7 @@ public class SubscriptionConsumerCompatibilityTest { private PulsarTestContext pulsarTestContext; private ManagedLedger ledgerMock; private ManagedCursorImpl cursorMock; - private final String successTopicName = "persistent://prop/use/ns-abc/successTopic"; + private final String successTopicName = "persistent://prop/ns-abc/successTopic"; private final String subName = "subscriptionName"; @BeforeMethod diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/SubscriptionSeekTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/SubscriptionSeekTest.java index 556a3124522c7..549c1e990f861 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/SubscriptionSeekTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/SubscriptionSeekTest.java @@ -109,7 +109,7 @@ protected void cleanup() throws Exception { @Test public void testSeek() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/testSeek"; + final String topicName = "persistent://prop/ns-abc/testSeek"; @Cleanup Producer producer = pulsarClient.newProducer().topic(topicName).create(); @@ -165,7 +165,7 @@ public void testSeek() throws Exception { @Test public void testSeekIsByReceive() throws PulsarClientException { - final String topicName = "persistent://prop/use/ns-abc/testSeekIsByReceive"; + final String topicName = "persistent://prop/ns-abc/testSeekIsByReceive"; @Cleanup Producer producer = pulsarClient.newProducer().topic(topicName).create(); @@ -190,7 +190,7 @@ public void testSeekIsByReceive() throws PulsarClientException { @Test public void testSeekForBatch() throws Exception { - final String topicName = "persistent://prop/use/ns-abcd/testSeekForBatch"; + final String topicName = "persistent://prop/ns-abc/testSeekForBatch"; String subscriptionName = "my-subscription-batch"; @Cleanup @@ -248,7 +248,7 @@ public void testSeekForBatch() throws Exception { @Test public void testSeekForBatchMessageAndSpecifiedBatchIndex() throws Exception { - final String topicName = "persistent://prop/use/ns-abcd/testSeekForBatchMessageAndSpecifiedBatchIndex"; + final String topicName = "persistent://prop/ns-abc/testSeekForBatchMessageAndSpecifiedBatchIndex"; String subscriptionName = "my-subscription-batch"; @Cleanup @@ -331,7 +331,7 @@ public void testSeekForBatchMessageAndSpecifiedBatchIndex() throws Exception { @Test public void testSeekForBatchByAdmin() throws PulsarClientException, ExecutionException, InterruptedException, PulsarAdminException { - final String topicName = "persistent://prop/use/ns-abcd/testSeekForBatchByAdmin-" + final String topicName = "persistent://prop/ns-abc/testSeekForBatchByAdmin-" + UUID.randomUUID().toString(); String subscriptionName = "my-subscription-batch"; @@ -415,7 +415,7 @@ public void testSeekForBatchByAdmin() throws PulsarClientException, ExecutionExc @Test public void testConcurrentResetCursor() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/testConcurrentReset_" + System.currentTimeMillis(); + final String topicName = "persistent://prop/ns-abc/testConcurrentReset_" + System.currentTimeMillis(); final String subscriptionName = "test-sub-name"; @Cleanup @@ -465,7 +465,7 @@ public void run() { @Test public void testConcurrentResetCursorByTimestamp() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/testConcurrentResetTimestamp_" + final String topicName = "persistent://prop/ns-abc/testConcurrentResetTimestamp_" + System.currentTimeMillis(); final String subscriptionName = "test-sub-name"; @@ -521,7 +521,7 @@ public void testConcurrentResetCursorByTimestamp() throws Exception { @Test public void testSeekOnPartitionedTopic() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/testSeekPartitions"; + final String topicName = "persistent://prop/ns-abc/testSeekPartitions"; admin.topics().createPartitionedTopic(topicName, 2); @Cleanup @@ -537,7 +537,7 @@ public void testSeekOnPartitionedTopic() throws Exception { @Test public void testSeekWithNonOwnerTopicMessage() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/testNonOwnerTopicMessage"; + final String topicName = "persistent://prop/ns-abc/testNonOwnerTopicMessage"; admin.topics().createPartitionedTopic(topicName, 2); @Cleanup @@ -553,7 +553,7 @@ public void testSeekWithNonOwnerTopicMessage() throws Exception { @Test public void testSeekTime() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/testSeekTime"; + final String topicName = "persistent://prop/ns-abc/testSeekTime"; String resetTimeStr = "100s"; long resetTimeInMillis = TimeUnit.SECONDS .toMillis(RelativeTimeUtil.parseRelativeTimeInSeconds(resetTimeStr)); @@ -591,7 +591,7 @@ public void testSeekTime() throws Exception { @Test(timeOut = 30_000) public void testSeekByTimestamp() throws Exception { - String topicName = "persistent://prop/use/ns-abc/testSeekByTimestamp"; + String topicName = "persistent://prop/ns-abc/testSeekByTimestamp"; admin.topics().createNonPartitionedTopic(topicName); admin.topics().createSubscription(topicName, "my-sub", MessageId.earliest); @@ -636,7 +636,7 @@ public void testSeekByTimestamp() throws Exception { @Test(timeOut = 30_000) public void testSeekByTimestampWithSkipNonRecoverableData() throws Exception { - String topicName = "persistent://prop/use/ns-abc/testSeekByTimestampWithSkipNonRecoverableData"; + String topicName = "persistent://prop/ns-abc/testSeekByTimestampWithSkipNonRecoverableData"; admin.topics().createNonPartitionedTopic(topicName); admin.topics().createSubscription(topicName, "my-sub", MessageId.earliest); @@ -719,7 +719,7 @@ public void testSeekByTimestampWithSkipNonRecoverableData() throws Exception { @Test(timeOut = 30_000) public void testSeekByTimestampWithLedgerTrim() throws Exception { - String topicName = "persistent://prop/use/ns-abc/testSeekByTimestampWithLedgerTrim"; + String topicName = "persistent://prop/ns-abc/testSeekByTimestampWithLedgerTrim"; admin.topics().createNonPartitionedTopic(topicName); admin.topics().createSubscription(topicName, "my-sub", MessageId.earliest); @@ -783,7 +783,7 @@ public void testSeekByTimestampWithLedgerTrim() throws Exception { @Test public void testSeekTimeByFunction() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/test" + UUID.randomUUID(); + final String topicName = "persistent://prop/ns-abc/test" + UUID.randomUUID(); int partitionNum = 4; int msgNum = 20; admin.topics().createPartitionedTopic(topicName, partitionNum); @@ -830,7 +830,7 @@ public void testSeekTimeByFunction() throws Exception { @Test public void testSeekTimeOnPartitionedTopic() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/testSeekTimePartitions"; + final String topicName = "persistent://prop/ns-abc/testSeekTimePartitions"; final String resetTimeStr = "100s"; final int partitions = 2; long resetTimeInMillis = TimeUnit.SECONDS @@ -888,7 +888,7 @@ public void testSeekTimeOnPartitionedTopic() throws Exception { @Test public void testShouldCloseAllConsumersForMultipleConsumerDispatcherWhenSeek() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/testShouldCloseAllConsumersFor" + final String topicName = "persistent://prop/ns-abc/testShouldCloseAllConsumersFor" + "MultipleConsumerDispatcherWhenSeek"; // Disable pre-fetch in consumer to track the messages received @Cleanup @@ -929,7 +929,7 @@ public void testShouldCloseAllConsumersForMultipleConsumerDispatcherWhenSeek() t @Test public void testOnlyCloseActiveConsumerForSingleActiveConsumerDispatcherWhenSeek() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/testOnlyCloseActiveConsumer" + final String topicName = "persistent://prop/ns-abc/testOnlyCloseActiveConsumer" + "ForSingleActiveConsumerDispatcherWhenSeek"; // Disable pre-fetch in consumer to track the messages received @Cleanup @@ -974,7 +974,7 @@ public void testOnlyCloseActiveConsumerForSingleActiveConsumerDispatcherWhenSeek @Test public void testSeekByFunction() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/test" + UUID.randomUUID(); + final String topicName = "persistent://prop/ns-abc/test" + UUID.randomUUID(); int partitionNum = 4; int msgNum = 160; admin.topics().createPartitionedTopic(topicName, partitionNum); @@ -1052,8 +1052,8 @@ private List creatProducerAndSendMsg(String topic, int msgNum) throws @Test public void testSeekByFunctionAndMultiTopic() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/test" + UUID.randomUUID(); - final String topicName2 = "persistent://prop/use/ns-abc/test" + UUID.randomUUID(); + final String topicName = "persistent://prop/ns-abc/test" + UUID.randomUUID(); + final String topicName2 = "persistent://prop/ns-abc/test" + UUID.randomUUID(); int partitionNum = 3; int msgNum = 15; admin.topics().createPartitionedTopic(topicName, partitionNum); @@ -1166,7 +1166,7 @@ protected void handleError(CommandError error) { @Test public void testExceptionBySeekFunction() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/test" + UUID.randomUUID(); + final String topicName = "persistent://prop/ns-abc/test" + UUID.randomUUID(); creatProducerAndSendMsg(topicName, 10); @Cleanup org.apache.pulsar.client.api.Consumer consumer = pulsarClient diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/ChecksumTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/ChecksumTest.java index 0270bc28183d0..c110512b8548d 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/ChecksumTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/ChecksumTest.java @@ -52,7 +52,7 @@ protected void cleanup() throws Exception { @Test public void verifyChecksumStoredInManagedLedger() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/topic0"; + final String topicName = "persistent://prop/ns-abc/topic0"; Producer producer = pulsarClient.newProducer().topic(topicName).create(); @@ -79,7 +79,7 @@ public void verifyChecksumStoredInManagedLedger() throws Exception { @Test public void verifyChecksumSentToConsumer() throws Exception { - final String topicName = "persistent://prop/use/ns-abc/topic-1"; + final String topicName = "persistent://prop/ns-abc/topic-1"; Producer producer = pulsarClient.newProducer().topic(topicName).create(); RawReader reader = RawReader.create(pulsarClient, topicName, "sub").get(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/PersistentSubscriptionTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/PersistentSubscriptionTest.java index 72e9dd19ffdb9..85b0c09c93d55 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/PersistentSubscriptionTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/persistent/PersistentSubscriptionTest.java @@ -76,7 +76,7 @@ public class PersistentSubscriptionTest { private Consumer consumerMock; private ManagedLedgerConfig managedLedgerConfigMock; - final String successTopicName = "persistent://prop/use/ns-abc/successTopic"; + final String successTopicName = "persistent://prop/ns-abc/successTopic"; final String subName = "subscriptionName"; final TxnID txnID1 = new TxnID(1, 1); @@ -164,7 +164,7 @@ public void testCanAcknowledgeAndAbortForTransaction() throws Exception { persistentSubscription.transactionIndividualAcknowledge(txnID2, positionsPair).get(); fail("Single acknowledge for transaction2 should fail. "); } catch (ExecutionException e) { - assertEquals(e.getCause().getMessage(), "[persistent://prop/use/ns-abc/successTopic][subscriptionName] " + assertEquals(e.getCause().getMessage(), "[persistent://prop/ns-abc/successTopic][subscriptionName] " + "Transaction:(1,2) try to ack message:2:1 in pending ack status."); } @@ -177,7 +177,7 @@ public void testCanAcknowledgeAndAbortForTransaction() throws Exception { fail("Cumulative acknowledge for transaction2 should fail. "); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof TransactionConflictException); - assertEquals(e.getCause().getMessage(), "[persistent://prop/use/ns-abc/successTopic]" + assertEquals(e.getCause().getMessage(), "[persistent://prop/ns-abc/successTopic]" + "[subscriptionName] Transaction:(1,2) try to cumulative batch ack position: " + "2:50 within range of current currentPosition: 1:100"); } diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/ManagedCursorMetricsTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/ManagedCursorMetricsTest.java index 1ea9455840aab..77c75faa843d8 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/ManagedCursorMetricsTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/ManagedCursorMetricsTest.java @@ -20,6 +20,7 @@ import static org.apache.pulsar.broker.stats.BrokerOpenTelemetryTestUtil.assertMetricLongSumValue; import static org.assertj.core.api.Assertions.assertThat; +import com.google.common.collect.Sets; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -45,6 +46,8 @@ import org.apache.pulsar.client.api.SubscriptionType; import org.apache.pulsar.client.impl.ConsumerImpl; import org.apache.pulsar.client.impl.PulsarTestClient; +import org.apache.pulsar.common.policies.data.ClusterData; +import org.apache.pulsar.common.policies.data.TenantInfoImpl; import org.apache.pulsar.common.stats.Metrics; import org.awaitility.Awaitility; import org.testng.Assert; @@ -59,6 +62,13 @@ public class ManagedCursorMetricsTest extends MockedPulsarServiceBaseTest { @Override protected void setup() throws Exception { super.internalSetup(); + + admin.clusters().createCluster("test", + ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); + admin.tenants().createTenant("my-namespace", + new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("test"))); + admin.namespaces().createNamespace("my-namespace/my-ns"); + admin.namespaces().setNamespaceReplicationClusters("my-namespace/my-ns", Sets.newHashSet("test"), false); } @Override @@ -101,7 +111,7 @@ protected void customizeMainPulsarTestContextBuilder(PulsarTestContext.Builder p @Test public void testManagedCursorMetrics() throws Exception { final String subName = "my-sub"; - final String topicName = "persistent://my-namespace/use/my-ns/my-topic1"; + final String topicName = "persistent://my-namespace/my-ns/my-topic1"; /** Before create cursor. Verify metrics will not be generated. **/ // Create ManagedCursorMetrics and verify empty. ManagedCursorMetrics metrics = new ManagedCursorMetrics(pulsar); @@ -253,7 +263,7 @@ public void testManagedCursorMetrics() throws Exception { * TODO verify "brk_ml_cursor_persistZookeeperErrors". * This is not easy to implement, we can use {@link #mockZooKeeper} to fail ZK, but we cannot identify whether * the request is triggered by the "create new ledger then write ZK" or the "persistent cursor then write ZK". - * The cursor path is "/managed-ledgers/my-namespace/use/my-ns/persistent/my-topic1/my-sub". Maybe we can + * The cursor path is "/managed-ledgers/my-namespace/my-ns/persistent/my-topic1/my-sub". Maybe we can * mock/spy ManagedCursorImpl to overridden this case in another PR. */ mockZooKeeper.unsetAlwaysFail(); @@ -279,7 +289,7 @@ private ManagedCursor getManagedCursor(String topicName, String subscriptionName public void testCursorReadWriteMetrics() throws Exception { final String subName1 = "read-write-sub-1"; final String subName2 = "read-write-sub-2"; - final String topicName = "persistent://my-namespace/use/my-ns/read-write"; + final String topicName = "persistent://my-namespace/my-ns/read-write"; final int messageSize = 10; ManagedCursorMetrics metrics = new ManagedCursorMetrics(pulsar); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/ManagedLedgerMetricsTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/ManagedLedgerMetricsTest.java index 394af363d99b2..dcab95067b8a8 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/ManagedLedgerMetricsTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/ManagedLedgerMetricsTest.java @@ -94,7 +94,7 @@ public void testManagedLedgerMetrics() throws Exception { List list1 = metrics.generate(); Assert.assertTrue(list1.isEmpty()); - var topicName = "persistent://my-property/use/my-ns/my-topic1"; + var topicName = "persistent://my-property/my-ns/my-topic1"; @Cleanup Producer producer = pulsarClient.newProducer().topic(topicName).create(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/OpenTelemetryBrokerOperabilityStatsTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/OpenTelemetryBrokerOperabilityStatsTest.java index e197f3bc62192..4991c0e5719e5 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/OpenTelemetryBrokerOperabilityStatsTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/OpenTelemetryBrokerOperabilityStatsTest.java @@ -58,21 +58,26 @@ protected void cleanup() throws Exception { @Test public void testBrokerConnection() throws Exception { - var topicName = BrokerTestUtil.newUniqueName("persistent://my-namespace/use/my-ns/testBrokerConnection"); + var topicName = BrokerTestUtil.newUniqueName("persistent://my-property/my-ns/testBrokerConnection"); @Cleanup var producer = pulsarClient.newProducer().topic(topicName).create(); + // The broker's internal client may have already connected during setup, + // so use >= 1 for cumulative counts that include setup connections. var metrics = pulsarTestContext.getOpenTelemetryMetricReader().collectAllMetrics(); assertMetricLongSumValue(metrics, BrokerOperabilityMetrics.CONNECTION_COUNTER_METRIC_NAME, - OpenTelemetryAttributes.ConnectionStatus.OPEN.attributes, 1); + OpenTelemetryAttributes.ConnectionStatus.OPEN.attributes, + actual -> assertThat(actual).isGreaterThanOrEqualTo(1)); assertMetricLongSumValue(metrics, BrokerOperabilityMetrics.CONNECTION_COUNTER_METRIC_NAME, OpenTelemetryAttributes.ConnectionStatus.CLOSE.attributes, 0); assertMetricLongSumValue(metrics, BrokerOperabilityMetrics.CONNECTION_COUNTER_METRIC_NAME, - OpenTelemetryAttributes.ConnectionStatus.ACTIVE.attributes, 1); + OpenTelemetryAttributes.ConnectionStatus.ACTIVE.attributes, + actual -> assertThat(actual).isGreaterThanOrEqualTo(1)); assertMetricLongSumValue(metrics, BrokerOperabilityMetrics.CONNECTION_CREATE_COUNTER_METRIC_NAME, - ConnectionCreateStatus.SUCCESS.attributes, 1); + ConnectionCreateStatus.SUCCESS.attributes, + actual -> assertThat(actual).isGreaterThanOrEqualTo(1)); assertMetricLongSumValue(metrics, BrokerOperabilityMetrics.CONNECTION_CREATE_COUNTER_METRIC_NAME, ConnectionCreateStatus.FAILURE.attributes, 0); @@ -80,7 +85,8 @@ public void testBrokerConnection() throws Exception { metrics = pulsarTestContext.getOpenTelemetryMetricReader().collectAllMetrics(); assertMetricLongSumValue(metrics, BrokerOperabilityMetrics.CONNECTION_COUNTER_METRIC_NAME, - OpenTelemetryAttributes.ConnectionStatus.CLOSE.attributes, 1); + OpenTelemetryAttributes.ConnectionStatus.CLOSE.attributes, + actual -> assertThat(actual).isGreaterThanOrEqualTo(1)); pulsar.getConfiguration().setAuthenticationEnabled(true); @@ -93,21 +99,25 @@ public void testBrokerConnection() throws Exception { metrics = pulsarTestContext.getOpenTelemetryMetricReader().collectAllMetrics(); assertMetricLongSumValue(metrics, BrokerOperabilityMetrics.CONNECTION_COUNTER_METRIC_NAME, - OpenTelemetryAttributes.ConnectionStatus.OPEN.attributes, 2); + OpenTelemetryAttributes.ConnectionStatus.OPEN.attributes, + actual -> assertThat(actual).isGreaterThanOrEqualTo(2)); assertMetricLongSumValue(metrics, BrokerOperabilityMetrics.CONNECTION_COUNTER_METRIC_NAME, - OpenTelemetryAttributes.ConnectionStatus.CLOSE.attributes, 2); + OpenTelemetryAttributes.ConnectionStatus.CLOSE.attributes, + actual -> assertThat(actual).isGreaterThanOrEqualTo(2)); assertMetricLongSumValue(metrics, BrokerOperabilityMetrics.CONNECTION_COUNTER_METRIC_NAME, - OpenTelemetryAttributes.ConnectionStatus.ACTIVE.attributes, 0); + OpenTelemetryAttributes.ConnectionStatus.ACTIVE.attributes, + actual -> assertThat(actual).isGreaterThanOrEqualTo(0)); assertMetricLongSumValue(metrics, BrokerOperabilityMetrics.CONNECTION_CREATE_COUNTER_METRIC_NAME, - ConnectionCreateStatus.SUCCESS.attributes, 1); + ConnectionCreateStatus.SUCCESS.attributes, + actual -> assertThat(actual).isGreaterThanOrEqualTo(1)); assertMetricLongSumValue(metrics, BrokerOperabilityMetrics.CONNECTION_CREATE_COUNTER_METRIC_NAME, ConnectionCreateStatus.FAILURE.attributes, 1); } @Test public void testPublishLatency() throws Exception { - final var topicName = BrokerTestUtil.newUniqueName("persistent://my-namespace/use/my-ns/testPublishLatency"); + final var topicName = BrokerTestUtil.newUniqueName("persistent://my-property/my-ns/testPublishLatency"); @Cleanup final var producer = pulsarClient.newProducer().topic(topicName).create(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/PrometheusMetricsTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/PrometheusMetricsTest.java index 4a99576d0f549..993e62e6eff64 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/PrometheusMetricsTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/PrometheusMetricsTest.java @@ -45,6 +45,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -391,16 +392,16 @@ public void testMetricsAvgMsgSize2() throws Exception { @Test public void testPerTopicStats() throws Exception { - Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic1").create(); - Producer p2 = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic2").create(); + Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic1").create(); + Producer p2 = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic2").create(); Consumer c1 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("test") .subscribe(); Consumer c2 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic2") + .topic("persistent://my-property/my-ns/my-topic2") .subscriptionName("test") .subscribe(); @@ -426,59 +427,67 @@ public void testPerTopicStats() throws Exception { System.out.println(e.getKey() + ": " + e.getValue()); }); + Comparator byTopic = Comparator.comparing(m -> m.tags.getOrDefault("topic", "")); + // There should be 2 metrics with different tags for each topic - List cm = (List) metrics.get("pulsar_storage_write_latency_le_1"); + List cm = new ArrayList<>(metrics.get("pulsar_storage_write_latency_le_1")); assertEquals(cm.size(), 2); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic2"); - assertEquals(cm.get(1).tags.get("namespace"), "my-property/use/my-ns"); + cm.sort(byTopic); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/my-ns/my-topic2"); + assertEquals(cm.get(1).tags.get("namespace"), "my-property/my-ns"); - cm = (List) metrics.get("pulsar_producers_count"); + cm = new ArrayList<>(metrics.get("pulsar_producers_count")); assertEquals(cm.size(), 2); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic2"); - assertEquals(cm.get(1).tags.get("namespace"), "my-property/use/my-ns"); + cm.sort(byTopic); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/my-ns/my-topic2"); + assertEquals(cm.get(1).tags.get("namespace"), "my-property/my-ns"); - cm = (List) metrics.get("pulsar_topic_load_times_count"); + cm = new ArrayList<>(metrics.get("pulsar_topic_load_times_count")); assertEquals(cm.size(), 1); assertEquals(cm.get(0).tags.get("cluster"), "test"); - cm = (List) metrics.get("topic_load_failed_total"); + cm = new ArrayList<>(metrics.get("topic_load_failed_total")); assertEquals(cm.size(), 1); assertEquals(cm.get(0).tags.get("cluster"), "test"); - cm = (List) metrics.get("pulsar_in_bytes_total"); + cm = new ArrayList<>(metrics.get("pulsar_in_bytes_total")); assertEquals(cm.size(), 2); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic2"); - assertEquals(cm.get(1).tags.get("namespace"), "my-property/use/my-ns"); + cm.sort(byTopic); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/my-ns/my-topic2"); + assertEquals(cm.get(1).tags.get("namespace"), "my-property/my-ns"); - cm = (List) metrics.get("pulsar_in_messages_total"); + cm = new ArrayList<>(metrics.get("pulsar_in_messages_total")); assertEquals(cm.size(), 2); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic2"); - assertEquals(cm.get(1).tags.get("namespace"), "my-property/use/my-ns"); + cm.sort(byTopic); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/my-ns/my-topic2"); + assertEquals(cm.get(1).tags.get("namespace"), "my-property/my-ns"); - cm = (List) metrics.get("pulsar_out_bytes_total"); + cm = new ArrayList<>(metrics.get("pulsar_out_bytes_total")); assertEquals(cm.size(), 2); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); + cm.sort(byTopic); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); assertEquals(cm.get(0).tags.get("subscription"), "test"); - assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic2"); - assertEquals(cm.get(1).tags.get("namespace"), "my-property/use/my-ns"); + assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/my-ns/my-topic2"); + assertEquals(cm.get(1).tags.get("namespace"), "my-property/my-ns"); assertEquals(cm.get(1).tags.get("subscription"), "test"); - cm = (List) metrics.get("pulsar_out_messages_total"); + cm = new ArrayList<>(metrics.get("pulsar_out_messages_total")); assertEquals(cm.size(), 2); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); + cm.sort(byTopic); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); assertEquals(cm.get(0).tags.get("subscription"), "test"); - assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic2"); - assertEquals(cm.get(1).tags.get("namespace"), "my-property/use/my-ns"); + assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/my-ns/my-topic2"); + assertEquals(cm.get(1).tags.get("namespace"), "my-property/my-ns"); assertEquals(cm.get(1).tags.get("subscription"), "test"); p1.close(); @@ -489,16 +498,16 @@ public void testPerTopicStats() throws Exception { @Test public void testPerBrokerStats() throws Exception { - Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic1").create(); - Producer p2 = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic2").create(); + Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic1").create(); + Producer p2 = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic2").create(); Consumer c1 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("test") .subscribe(); Consumer c2 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic2") + .topic("persistent://my-property/my-ns/my-topic2") .subscriptionName("test") .subscribe(); @@ -585,10 +594,10 @@ public void testPerBrokerStats() throws Exception { */ @Test public void testPerTopicStatsReconnect() throws Exception { - Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic1").create(); + Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic1").create(); Consumer c1 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("test") .subscribe(); @@ -613,7 +622,7 @@ public void testPerTopicStatsReconnect() throws Exception { } Consumer c2 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("test") .subscribe(); @@ -636,27 +645,27 @@ public void testPerTopicStatsReconnect() throws Exception { List cm = (List) metrics.get("pulsar_in_bytes_total"); assertEquals(cm.size(), 1); assertEquals(cm.get(0).value, (messageSizeBytes * messages * 2)); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); cm = (List) metrics.get("pulsar_in_messages_total"); assertEquals(cm.size(), 1); assertEquals(cm.get(0).value, (messages * 2)); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); cm = (List) metrics.get("pulsar_out_bytes_total"); assertEquals(cm.size(), 1); assertEquals(cm.get(0).value, (messageSizeBytes * messages * 2)); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); assertEquals(cm.get(0).tags.get("subscription"), "test"); cm = (List) metrics.get("pulsar_out_messages_total"); assertEquals(cm.size(), 1); assertEquals(cm.get(0).value, (messages * 2)); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); assertEquals(cm.get(0).tags.get("subscription"), "test"); } @@ -892,10 +901,10 @@ public void testPerTopicExpiredStat() throws Exception { @Test public void testBundlesMetrics() throws Exception { - Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic1").create(); + Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic1").create(); Consumer c1 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("test") .subscribe(); @@ -960,10 +969,10 @@ public void testBundlesMetrics() throws Exception { @Test public void testNonPersistentSubMetrics() throws Exception { Producer p1 = - pulsarClient.newProducer().topic("non-persistent://my-property/use/my-ns/my-topic1").create(); + pulsarClient.newProducer().topic("non-persistent://my-property/my-ns/my-topic1").create(); Consumer c1 = pulsarClient.newConsumer() - .topic("non-persistent://my-property/use/my-ns/my-topic1") + .topic("non-persistent://my-property/my-ns/my-topic1") .subscriptionName("test") .subscribe(); @@ -999,16 +1008,16 @@ public void testNonPersistentSubMetrics() throws Exception { @Test public void testPerNamespaceStats() throws Exception { - Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic1").create(); - Producer p2 = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic2").create(); + Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic1").create(); + Producer p2 = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic2").create(); Consumer c1 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("test") .subscribe(); Consumer c2 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic2") + .topic("persistent://my-property/my-ns/my-topic2") .subscriptionName("test") .subscribe(); @@ -1039,28 +1048,28 @@ public void testPerNamespaceStats() throws Exception { List cm = (List) metrics.get("pulsar_storage_write_latency_le_1"); assertEquals(cm.size(), 1); assertNull(cm.get(0).tags.get("topic")); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); cm = (List) metrics.get("pulsar_producers_count"); assertEquals(cm.size(), 1); assertNull(cm.get(0).tags.get("topic")); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); cm = (List) metrics.get("pulsar_in_bytes_total"); assertEquals(cm.size(), 1); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); cm = (List) metrics.get("pulsar_in_messages_total"); assertEquals(cm.size(), 1); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); cm = (List) metrics.get("pulsar_out_bytes_total"); assertEquals(cm.size(), 1); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); cm = (List) metrics.get("pulsar_out_messages_total"); assertEquals(cm.size(), 1); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); p1.close(); p2.close(); @@ -1070,18 +1079,18 @@ public void testPerNamespaceStats() throws Exception { @Test public void testPerProducerStats() throws Exception { - Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic1") + Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic1") .producerName("producer1").create(); - Producer p2 = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic2") + Producer p2 = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic2") .producerName("producer2").create(); Consumer c1 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("Test") .subscribe(); Consumer c2 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic2") + .topic("persistent://my-property/my-ns/my-topic2") .subscriptionName("Test") .subscribe(); @@ -1108,27 +1117,31 @@ public void testPerProducerStats() throws Exception { System.out.println(e.getKey() + ": " + e.getValue()); }); - List cm = (List) metrics.get("pulsar_producer_msg_rate_in"); + Comparator byTopic = Comparator.comparing(m -> m.tags.getOrDefault("topic", "")); + + List cm = new ArrayList<>(metrics.get("pulsar_producer_msg_rate_in")); assertEquals(cm.size(), 2); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); + cm.sort(byTopic); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); assertEquals(cm.get(0).tags.get("producer_name"), "producer1"); assertEquals(cm.get(0).tags.get("producer_id"), "0"); - assertEquals(cm.get(1).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic2"); + assertEquals(cm.get(1).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/my-ns/my-topic2"); assertEquals(cm.get(1).tags.get("producer_name"), "producer2"); assertEquals(cm.get(1).tags.get("producer_id"), "1"); - cm = (List) metrics.get("pulsar_producer_msg_throughput_in"); + cm = new ArrayList<>(metrics.get("pulsar_producer_msg_throughput_in")); assertEquals(cm.size(), 2); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); + cm.sort(byTopic); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); assertEquals(cm.get(0).tags.get("producer_name"), "producer1"); assertEquals(cm.get(0).tags.get("producer_id"), "0"); - assertEquals(cm.get(1).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic2"); + assertEquals(cm.get(1).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/my-ns/my-topic2"); assertEquals(cm.get(1).tags.get("producer_name"), "producer2"); assertEquals(cm.get(1).tags.get("producer_id"), "1"); @@ -1140,16 +1153,16 @@ public void testPerProducerStats() throws Exception { @Test public void testPerConsumerStats() throws Exception { - Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic1").create(); - Producer p2 = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic2").create(); + Producer p1 = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic1").create(); + Producer p2 = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic2").create(); Consumer c1 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("test") .subscribe(); Consumer c2 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic2") + .topic("persistent://my-property/my-ns/my-topic2") .subscriptionName("test") .subscribe(); @@ -1176,44 +1189,51 @@ public void testPerConsumerStats() throws Exception { System.out.println(e.getKey() + ": " + e.getValue()); }); + // Sort by topic, then by consumer_id presence (subscription-level first, then consumer-level) + Comparator byTopicAndConsumer = Comparator + .comparing((Metric m) -> m.tags.getOrDefault("topic", "")) + .thenComparing(m -> m.tags.getOrDefault("consumer_id", "")); + // There should be 1 metric aggregated per namespace - List cm = (List) metrics.get("pulsar_out_bytes_total"); + List cm = new ArrayList<>(metrics.get("pulsar_out_bytes_total")); assertEquals(cm.size(), 4); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); + cm.sort(byTopicAndConsumer); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); assertEquals(cm.get(0).tags.get("subscription"), "test"); - assertEquals(cm.get(1).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); + assertEquals(cm.get(1).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); assertEquals(cm.get(1).tags.get("subscription"), "test"); assertEquals(cm.get(1).tags.get("consumer_id"), "0"); - assertEquals(cm.get(2).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(2).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic2"); + assertEquals(cm.get(2).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(2).tags.get("topic"), "persistent://my-property/my-ns/my-topic2"); assertEquals(cm.get(2).tags.get("subscription"), "test"); - assertEquals(cm.get(3).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(3).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic2"); + assertEquals(cm.get(3).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(3).tags.get("topic"), "persistent://my-property/my-ns/my-topic2"); assertEquals(cm.get(3).tags.get("subscription"), "test"); assertEquals(cm.get(3).tags.get("consumer_id"), "1"); - cm = (List) metrics.get("pulsar_out_messages_total"); + cm = new ArrayList<>(metrics.get("pulsar_out_messages_total")); assertEquals(cm.size(), 4); - assertEquals(cm.get(0).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); + cm.sort(byTopicAndConsumer); + assertEquals(cm.get(0).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(0).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); assertEquals(cm.get(0).tags.get("subscription"), "test"); - assertEquals(cm.get(1).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic1"); + assertEquals(cm.get(1).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(1).tags.get("topic"), "persistent://my-property/my-ns/my-topic1"); assertEquals(cm.get(1).tags.get("subscription"), "test"); assertEquals(cm.get(1).tags.get("consumer_id"), "0"); - assertEquals(cm.get(2).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(2).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic2"); + assertEquals(cm.get(2).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(2).tags.get("topic"), "persistent://my-property/my-ns/my-topic2"); assertEquals(cm.get(2).tags.get("subscription"), "test"); - assertEquals(cm.get(3).tags.get("namespace"), "my-property/use/my-ns"); - assertEquals(cm.get(3).tags.get("topic"), "persistent://my-property/use/my-ns/my-topic2"); + assertEquals(cm.get(3).tags.get("namespace"), "my-property/my-ns"); + assertEquals(cm.get(3).tags.get("topic"), "persistent://my-property/my-ns/my-topic2"); assertEquals(cm.get(3).tags.get("subscription"), "test"); assertEquals(cm.get(3).tags.get("consumer_id"), "1"); @@ -1251,9 +1271,9 @@ public void testDuplicateMetricTypeDefinitions() throws Exception { Set allPrometheusSuffixString = allPrometheusSuffixEnums(); Producer p1 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic1").create(); + .topic("persistent://my-property/my-ns/my-topic1").create(); Producer p2 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic2").create(); + .topic("persistent://my-property/my-ns/my-topic2").create(); for (int i = 0; i < 10; i++) { String message = "my-message-" + i; p1.send(message.getBytes()); @@ -1358,9 +1378,9 @@ public static Set allPrometheusSuffixEnums(){ @Test public void testManagedLedgerCacheStats() throws Exception { Producer p1 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic1").create(); + .topic("persistent://my-property/my-ns/my-topic1").create(); Producer p2 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic2").create(); + .topic("persistent://my-property/my-ns/my-topic2").create(); for (int i = 0; i < 10; i++) { String message = "my-message-" + i; p1.send(message.getBytes()); @@ -1391,14 +1411,17 @@ public void testManagedLedgerCacheStats() throws Exception { @Test public void testManagedLedgerStats() throws Exception { + admin.namespaces().createNamespace("my-property/my-ns2"); + admin.namespaces().setNamespaceReplicationClusters("my-property/my-ns2", Sets.newHashSet("test"), false); + Producer p1 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic1").create(); + .topic("persistent://my-property/my-ns/my-topic1").create(); Producer p2 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic2").create(); + .topic("persistent://my-property/my-ns/my-topic2").create(); Producer p3 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns2/my-topic1").create(); + .topic("persistent://my-property/my-ns2/my-topic1").create(); Producer p4 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns2/my-topic2").create(); + .topic("persistent://my-property/my-ns2/my-topic2").create(); for (int i = 0; i < 10; i++) { String message = "my-message-" + i; p1.send(message.getBytes()); @@ -1459,13 +1482,13 @@ public void testManagedLedgerStats() throws Exception { assertEquals(cm.size(), 2); assertEquals(cm.get(0).tags.get("cluster"), "test"); String ns = cm.get(0).tags.get("namespace"); - assertTrue(ns.equals("my-property/use/my-ns") || ns.equals("my-property/use/my-ns2")); + assertTrue(ns.equals("my-property/my-ns/persistent") || ns.equals("my-property/my-ns2/persistent")); cm = (List) metrics.get("pulsar_ml_AddEntryMessagesRate"); assertEquals(cm.size(), 2); assertEquals(cm.get(0).tags.get("cluster"), "test"); ns = cm.get(0).tags.get("namespace"); - assertTrue(ns.equals("my-property/use/my-ns") || ns.equals("my-property/use/my-ns2")); + assertTrue(ns.equals("my-property/my-ns/persistent") || ns.equals("my-property/my-ns2/persistent")); p1.close(); p2.close(); @@ -1477,11 +1500,11 @@ public void testManagedLedgerStats() throws Exception { public void testManagedLedgerBookieClientStats() throws Exception { @Cleanup Producer p1 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic1").create(); + .topic("persistent://my-property/my-ns/my-topic1").create(); @Cleanup Producer p2 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic2").create(); + .topic("persistent://my-property/my-ns/my-topic2").create(); for (int i = 0; i < 10; i++) { String message = "my-message-" + i; p1.send(message.getBytes()); @@ -1719,7 +1742,7 @@ public void testParsingWithNegativeInfinityValue() { @Test public void testManagedCursorPersistStats() throws Exception { final String subName = "my-sub"; - final String topicName = "persistent://my-namespace/use/my-ns/my-topic1"; + final String topicName = "persistent://my-property/my-ns/my-topic1"; final int messageSize = 10; Consumer consumer = pulsarClient.newConsumer() @@ -1766,7 +1789,7 @@ public void testManagedCursorPersistStats() throws Exception { @Test public void testBrokerConnection() throws Exception { - final String topicName = "persistent://my-namespace/use/my-ns/my-topic1"; + final String topicName = "persistent://my-property/my-ns/my-topic1"; Producer producer = pulsarClient.newProducer() .topic(topicName) @@ -1863,7 +1886,7 @@ void testParseMetrics() throws IOException { @Test public void testCompaction() throws Exception { - final String topicName = "persistent://my-namespace/use/my-ns/my-compaction1"; + final String topicName = "persistent://my-property/my-ns/my-compaction1"; Producer producer = pulsarClient.newProducer() .topic(topicName) @@ -2016,9 +2039,9 @@ public void testSplitTopicAndPartitionLabel() throws Exception { @Test public void testMetricsGroupedByTypeDefinitions() throws Exception { Producer p1 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic1").create(); + .topic("persistent://my-property/my-ns/my-topic1").create(); Producer p2 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic2").create(); + .topic("persistent://my-property/my-ns/my-topic2").create(); for (int i = 0; i < 10; i++) { String message = "my-message-" + i; p1.send(message.getBytes()); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/TransactionMetricsTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/TransactionMetricsTest.java index 8d5cb9dc39148..a3db0a36604f1 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/TransactionMetricsTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/stats/TransactionMetricsTest.java @@ -378,7 +378,7 @@ public void testDuplicateMetricTypeDefinitions() throws Exception { pulsar.getTransactionMetadataStoreService().getStores().size() == 2); Producer p1 = pulsarClient .newProducer() - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .sendTimeout(0, TimeUnit.SECONDS) .create(); Transaction transaction = pulsarClient diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/systopic/PartitionedSystemTopicTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/systopic/PartitionedSystemTopicTest.java index 28f401bfc5123..89cbbb2655336 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/systopic/PartitionedSystemTopicTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/systopic/PartitionedSystemTopicTest.java @@ -55,7 +55,6 @@ import org.apache.pulsar.common.naming.NamespaceName; import org.apache.pulsar.common.naming.SystemTopicNames; import org.apache.pulsar.common.naming.TopicName; -import org.apache.pulsar.common.naming.TopicVersion; import org.apache.pulsar.common.policies.data.BacklogQuota; import org.apache.pulsar.common.policies.data.TenantInfo; import org.apache.pulsar.common.policies.data.TenantInfoImpl; @@ -166,14 +165,14 @@ public void testProduceAndConsumeUnderSystemNamespace() throws Exception { @Test public void testHealthCheckTopicNotOffload() throws Exception { - NamespaceName namespaceName = NamespaceService.getHeartbeatNamespaceV2(pulsar.getBrokerId(), + NamespaceName namespaceName = NamespaceService.getHeartbeatNamespace(pulsar.getBrokerId(), pulsar.getConfig()); TopicName topicName = TopicName.get("persistent", namespaceName, HealthChecker.HEALTH_CHECK_TOPIC_SUFFIX); PersistentTopic persistentTopic = (PersistentTopic) pulsar.getBrokerService() .getTopic(topicName.toString(), true).get().get(); ManagedLedgerConfig config = persistentTopic.getManagedLedger().getConfig(); config.setLedgerOffloader(NullLedgerOffloader.INSTANCE); - admin.brokers().healthcheck(TopicVersion.V2); + admin.brokers().healthcheck(); admin.topics().triggerOffload(topicName.toString(), MessageId.earliest); Awaitility.await().untilAsserted(() -> { Assert.assertEquals(persistentTopic.getManagedLedger().getOffloadedSize(), 0); @@ -185,8 +184,8 @@ public void testHealthCheckTopicNotOffload() throws Exception { @Test public void testSystemNamespaceNotCreateChangeEventsTopic() throws Exception { - admin.brokers().healthcheck(TopicVersion.V2); - NamespaceName namespaceName = NamespaceService.getHeartbeatNamespaceV2(pulsar.getBrokerId(), + admin.brokers().healthcheck(); + NamespaceName namespaceName = NamespaceService.getHeartbeatNamespace(pulsar.getBrokerId(), pulsar.getConfig()); TopicName topicName = TopicName.get("persistent", namespaceName, SystemTopicNames.NAMESPACE_EVENTS_LOCAL_NAME); Optional optionalTopic = pulsar.getBrokerService() @@ -203,8 +202,8 @@ public void testSystemNamespaceNotCreateChangeEventsTopic() throws Exception { @Test public void testHeartbeatTopicNotAllowedToSendEvent() throws Exception { - admin.brokers().healthcheck(TopicVersion.V2); - NamespaceName namespaceName = NamespaceService.getHeartbeatNamespaceV2(pulsar.getBrokerId(), + admin.brokers().healthcheck(); + NamespaceName namespaceName = NamespaceService.getHeartbeatNamespace(pulsar.getBrokerId(), pulsar.getConfig()); TopicName topicName = TopicName.get("persistent", namespaceName, SystemTopicNames.NAMESPACE_EVENTS_LOCAL_NAME); for (int partition = 0; partition < PARTITIONS; partition++) { @@ -218,8 +217,8 @@ public void testHeartbeatTopicNotAllowedToSendEvent() throws Exception { @Test public void testHeartbeatTopicBeDeleted() throws Exception { - admin.brokers().healthcheck(TopicVersion.V2); - NamespaceName namespaceName = NamespaceService.getHeartbeatNamespaceV2(pulsar.getBrokerId(), + admin.brokers().healthcheck(); + NamespaceName namespaceName = NamespaceService.getHeartbeatNamespace(pulsar.getBrokerId(), pulsar.getConfig()); TopicName heartbeatTopicName = TopicName.get("persistent", namespaceName, HealthChecker.HEALTH_CHECK_TOPIC_SUFFIX); @@ -235,8 +234,8 @@ public void testHeartbeatTopicBeDeleted() throws Exception { @Test public void testHeartbeatNamespaceNotCreateTransactionInternalTopic() throws Exception { - admin.brokers().healthcheck(TopicVersion.V2); - NamespaceName namespaceName = NamespaceService.getHeartbeatNamespaceV2(pulsar.getBrokerId(), + admin.brokers().healthcheck(); + NamespaceName namespaceName = NamespaceService.getHeartbeatNamespace(pulsar.getBrokerId(), pulsar.getConfig()); TopicName topicName = TopicName.get("persistent", namespaceName, SystemTopicNames.TRANSACTION_BUFFER_SNAPSHOT); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/web/WebServiceTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/web/WebServiceTest.java index 5a666f30ac35b..0f9ccdf4af714 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/web/WebServiceTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/web/WebServiceTest.java @@ -271,10 +271,10 @@ public void testTlsAuthDisallowInsecure() throws Exception { public void testRateLimiting() throws Exception { setupEnv(false, false, false, false, 10.0, false); - // setupEnv makes a HTTP call to create the cluster. + // setupEnv makes HTTP calls to create the cluster, tenant, and namespace. var metrics = pulsarTestContext.getOpenTelemetryMetricReader().collectAllMetrics(); assertMetricLongSumValue(metrics, RateLimitingFilter.RATE_LIMIT_REQUEST_COUNT_METRIC_NAME, - Result.ACCEPTED.attributes, 1); + Result.ACCEPTED.attributes, 3); assertThat(metrics).noneSatisfy(metricData -> assertThat(metricData) .hasName(RateLimitingFilter.RATE_LIMIT_REQUEST_COUNT_METRIC_NAME) .hasLongSumSatisfying( @@ -288,7 +288,7 @@ public void testRateLimiting() throws Exception { metrics = pulsarTestContext.getOpenTelemetryMetricReader().collectAllMetrics(); assertMetricLongSumValue(metrics, RateLimitingFilter.RATE_LIMIT_REQUEST_COUNT_METRIC_NAME, - Result.ACCEPTED.attributes, 6); + Result.ACCEPTED.attributes, 8); assertThat(metrics).noneSatisfy(metricData -> assertThat(metricData) .hasName(RateLimitingFilter.RATE_LIMIT_REQUEST_COUNT_METRIC_NAME) .hasLongSumSatisfying( @@ -306,7 +306,7 @@ public void testRateLimiting() throws Exception { metrics = pulsarTestContext.getOpenTelemetryMetricReader().collectAllMetrics(); assertMetricLongSumValue(metrics, RateLimitingFilter.RATE_LIMIT_REQUEST_COUNT_METRIC_NAME, - Result.ACCEPTED.attributes, value -> assertThat(value).isGreaterThan(6)); + Result.ACCEPTED.attributes, value -> assertThat(value).isGreaterThan(8)); assertMetricLongSumValue(metrics, RateLimitingFilter.RATE_LIMIT_REQUEST_COUNT_METRIC_NAME, Result.REJECTED.attributes, value -> assertThat(value).isPositive()); } @@ -561,9 +561,9 @@ private void setupEnv(boolean enableFilter, boolean enableTls, boolean enableAut } brokerLookUpUrl = brokerUrlBase - + "/lookup/v2/destination/persistent/my-property/local/my-namespace/my-topic"; + + "/lookup/v2/topic/persistent/my-property/my-namespace/my-topic"; brokerLookUpUrlTls = brokerUrlBaseTls - + "/lookup/v2/destination/persistent/my-property/local/my-namespace/my-topic"; + + "/lookup/v2/topic/persistent/my-property/my-namespace/my-topic"; @Cleanup PulsarAdmin pulsarAdmin = adminBuilder.serviceHttpUrl(serviceUrl).build(); @@ -573,6 +573,13 @@ private void setupEnv(boolean enableFilter, boolean enableTls, boolean enableAut } catch (ConflictException ce) { // This is OK. } + try { + pulsarAdmin.tenants().createTenant("my-property", + TenantInfo.builder().allowedClusters(Sets.newHashSet(config.getClusterName())).build()); + pulsarAdmin.namespaces().createNamespace("my-property/my-namespace"); + } catch (Exception e) { + // This is OK. + } } @AfterMethod(alwaysRun = true) diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/AuthorizationProducerConsumerTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/AuthorizationProducerConsumerTest.java index 1dd99e00e88cf..166740ec7a067 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/AuthorizationProducerConsumerTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/AuthorizationProducerConsumerTest.java @@ -660,7 +660,7 @@ public void testGrantPermission() throws Exception { setup(); AuthorizationService authorizationService = new AuthorizationService(conf, null); - TopicName topicName = TopicName.get("persistent://prop/cluster/ns/t1"); + TopicName topicName = TopicName.get("persistent://prop/ns/t1"); String role = "test-role"; Assert.assertFalse(authorizationService.canProduce(topicName, role, null)); Assert.assertFalse(authorizationService.canConsume(topicName, role, null, "sub1")); @@ -736,7 +736,7 @@ public void testAuthData() throws Exception { setup(); AuthorizationService authorizationService = new AuthorizationService(conf, null); - TopicName topicName = TopicName.get("persistent://prop/cluster/ns/t1"); + TopicName topicName = TopicName.get("persistent://prop/ns/t1"); String role = "test-role"; authorizationService.grantPermissionAsync(topicName, null, role, "auth-json").get(); Assert.assertEquals(TestAuthorizationProviderWithGrantPermission.authDataJson, "auth-json"); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/BrokerServiceLookupTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/BrokerServiceLookupTest.java index e00e6d69ce818..7501a178f0dc1 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/BrokerServiceLookupTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/BrokerServiceLookupTest.java @@ -406,7 +406,7 @@ public void testMultipleBrokerDifferentClusterLookup() throws Exception { /**** start broker-2 ****/ final String newCluster = "use2"; - final String property = "my-property2"; + final String tenant = "my-property2"; ServiceConfiguration conf2 = new ServiceConfiguration(); conf2.setAdvertisedAddress("localhost"); conf2.setBrokerShutdownTimeoutMs(0L); @@ -424,9 +424,9 @@ public void testMultipleBrokerDifferentClusterLookup() throws Exception { .serviceUrl(pulsar.getWebServiceAddress()) .brokerServiceUrl(broker2ServiceUrl) .build()); - admin.tenants().createTenant(property, + admin.tenants().createTenant(tenant, new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet(newCluster))); - admin.namespaces().createNamespace(property + "/" + newCluster + "/my-ns"); + admin.namespaces().createNamespace(tenant + "/my-ns"); @Cleanup PulsarTestContext pulsarTestContext2 = createAdditionalPulsarTestContext(conf2); @@ -450,10 +450,10 @@ public void testMultipleBrokerDifferentClusterLookup() throws Exception { /**** started broker-2 ****/ // load namespace-bundle by calling Broker2 - Consumer consumer = pulsarClient.newConsumer().topic("persistent://my-property2/use2/my-ns/my-topic1") + Consumer consumer = pulsarClient.newConsumer().topic("persistent://my-property2/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscribe(); Producer producer = pulsarClient2.newProducer(Schema.BYTES) - .topic("persistent://my-property2/use2/my-ns/my-topic1") + .topic("persistent://my-property2/my-ns/my-topic1") .create(); for (int i = 0; i < 10; i++) { @@ -1052,23 +1052,21 @@ private int calculateLookupRequestCount() throws Exception { @Test(timeOut = 10000) public void testPartitionedMetadataWithDeprecatedVersion() throws Exception { - final String cluster = "use2"; - final String property = "my-property2"; + final String cluster = "test"; + final String tenant = "my-property2"; final String namespace = "my-ns"; final String topicName = "my-partitioned"; final int totalPartitions = 10; - final TopicName dest = TopicName.get("persistent", property, cluster, namespace, topicName); - admin.clusters().createCluster(cluster, - ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); - admin.tenants().createTenant(property, + final TopicName dest = TopicName.get("persistent", tenant, namespace, topicName); + admin.tenants().createTenant(tenant, new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet(cluster))); - admin.namespaces().createNamespace(property + "/" + cluster + "/" + namespace); + admin.namespaces().createNamespace(tenant + "/" + namespace); admin.topics().createPartitionedTopic(dest.toString(), totalPartitions); URI brokerServiceUrl = new URI(pulsar.getSafeWebServiceAddress()); URL url = brokerServiceUrl.toURL(); - String path = String.format("admin/%s/partitions", dest.getLookupName()); + String path = String.format("admin/v2/%s/partitions", dest.getLookupName()); AsyncHttpClient httpClient = getHttpClient("Pulsar-Java-1.20"); PartitionedTopicMetadata metadata = getPartitionedMetadata(httpClient, url, path); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/ClientErrorsTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/ClientErrorsTest.java index f8f8a098d29bc..91aaef6c225c4 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/ClientErrorsTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/ClientErrorsTest.java @@ -70,10 +70,10 @@ public void testMockBrokerService() throws PulsarClientException { @Cleanup PulsarClient client = PulsarClient.builder().serviceUrl(mockBrokerService.getBrokerAddress()).build(); try { - Consumer consumer = client.newConsumer().topic("persistent://prop/use/ns/t1") + Consumer consumer = client.newConsumer().topic("persistent://prop/ns/t1") .subscriptionName("sub1").subscribe(); - Producer producer = client.newProducer().topic("persistent://prop/use/ns/t1").create(); + Producer producer = client.newProducer().topic("persistent://prop/ns/t1").create(); Thread.sleep(ASYNC_EVENT_COMPLETION_WAIT); producer.send("message".getBytes()); Thread.sleep(ASYNC_EVENT_COMPLETION_WAIT); @@ -89,12 +89,12 @@ public void testMockBrokerService() throws PulsarClientException { @Test public void testProducerCreateFailWithoutRetry() throws Exception { - producerCreateFailWithoutRetry("persistent://prop/use/ns/t1"); + producerCreateFailWithoutRetry("persistent://prop/ns/t1"); } @Test public void testPartitionedProducerCreateFailWithoutRetry() throws Exception { - producerCreateFailWithoutRetry("persistent://prop/use/ns/part-t1"); + producerCreateFailWithoutRetry("persistent://prop/ns/part-t1"); } private void producerCreateFailWithoutRetry(String topic) throws Exception { @@ -125,12 +125,12 @@ private void producerCreateFailWithoutRetry(String topic) throws Exception { @Test public void testProducerCreateSuccessAfterRetry() throws Exception { - producerCreateSuccessAfterRetry("persistent://prop/use/ns/t1"); + producerCreateSuccessAfterRetry("persistent://prop/ns/t1"); } @Test public void testPartitionedProducerCreateSuccessAfterRetry() throws Exception { - producerCreateSuccessAfterRetry("persistent://prop/use/ns/part-t1"); + producerCreateSuccessAfterRetry("persistent://prop/ns/part-t1"); } private void producerCreateSuccessAfterRetry(String topic) throws Exception { @@ -158,12 +158,12 @@ private void producerCreateSuccessAfterRetry(String topic) throws Exception { @Test public void testProducerCreateFailAfterRetryTimeout() throws Exception { - producerCreateFailAfterRetryTimeout("persistent://prop/use/ns/t1"); + producerCreateFailAfterRetryTimeout("persistent://prop/ns/t1"); } @Test public void testPartitionedProducerCreateFailAfterRetryTimeout() throws Exception { - producerCreateFailAfterRetryTimeout("persistent://prop/use/ns/part-t1"); + producerCreateFailAfterRetryTimeout("persistent://prop/ns/part-t1"); } private void producerCreateFailAfterRetryTimeout(String topic) throws Exception { @@ -204,12 +204,12 @@ private void producerCreateFailAfterRetryTimeout(String topic) throws Exception @Test public void testCreatedProducerSendsCloseProducerAfterTimeout() throws Exception { - producerCreatedThenFailsRetryTimeout("persistent://prop/use/ns/t1"); + producerCreatedThenFailsRetryTimeout("persistent://prop/ns/t1"); } @Test public void testCreatedPartitionedProducerSendsCloseProducerAfterTimeout() throws Exception { - producerCreatedThenFailsRetryTimeout("persistent://prop/use/ns/part-t1"); + producerCreatedThenFailsRetryTimeout("persistent://prop/ns/part-t1"); } private void producerCreatedThenFailsRetryTimeout(String topic) throws Exception { @@ -251,12 +251,12 @@ private void producerCreatedThenFailsRetryTimeout(String topic) throws Exception @Test public void testCreatedConsumerSendsCloseConsumerAfterTimeout() throws Exception { - consumerCreatedThenFailsRetryTimeout("persistent://prop/use/ns/t1"); + consumerCreatedThenFailsRetryTimeout("persistent://prop/ns/t1"); } @Test public void testCreatedPartitionedConsumerSendsCloseConsumerAfterTimeout() throws Exception { - consumerCreatedThenFailsRetryTimeout("persistent://prop/use/ns/part-t1"); + consumerCreatedThenFailsRetryTimeout("persistent://prop/ns/part-t1"); } private void consumerCreatedThenFailsRetryTimeout(String topic) throws Exception { @@ -296,12 +296,12 @@ private void consumerCreatedThenFailsRetryTimeout(String topic) throws Exception @Test public void testProducerFailDoesNotFailOtherProducer() throws Exception { - producerFailDoesNotFailOtherProducer("persistent://prop/use/ns/t1", "persistent://prop/use/ns/t2"); + producerFailDoesNotFailOtherProducer("persistent://prop/ns/t1", "persistent://prop/ns/t2"); } @Test public void testPartitionedProducerFailDoesNotFailOtherProducer() throws Exception { - producerFailDoesNotFailOtherProducer("persistent://prop/use/ns/part-t1", "persistent://prop/use/ns/part-t2"); + producerFailDoesNotFailOtherProducer("persistent://prop/ns/part-t1", "persistent://prop/ns/part-t2"); } private void producerFailDoesNotFailOtherProducer(String topic1, String topic2) throws Exception { @@ -338,12 +338,12 @@ private void producerFailDoesNotFailOtherProducer(String topic1, String topic2) @Test public void testProducerContinuousRetryAfterSendFail() throws Exception { - producerContinuousRetryAfterSendFail("persistent://prop/use/ns/t1"); + producerContinuousRetryAfterSendFail("persistent://prop/ns/t1"); } @Test public void testPartitionedProducerContinuousRetryAfterSendFail() throws Exception { - producerContinuousRetryAfterSendFail("persistent://prop/use/ns/part-t1"); + producerContinuousRetryAfterSendFail("persistent://prop/ns/part-t1"); } private void producerContinuousRetryAfterSendFail(String topic) throws Exception { @@ -385,12 +385,12 @@ private void producerContinuousRetryAfterSendFail(String topic) throws Exception @Test public void testSubscribeFailWithoutRetry() throws Exception { - subscribeFailWithoutRetry("persistent://prop/use/ns/t1"); + subscribeFailWithoutRetry("persistent://prop/ns/t1"); } @Test public void testPartitionedSubscribeFailWithoutRetry() throws Exception { - subscribeFailWithoutRetry("persistent://prop/use/ns/part-t1"); + subscribeFailWithoutRetry("persistent://prop/ns/part-t1"); } @Test @@ -398,7 +398,7 @@ public void testLookupWithDisconnection() throws Exception { @Cleanup PulsarClient client = PulsarClient.builder().serviceUrl(mockBrokerService.getBrokerAddress()).build(); final AtomicInteger counter = new AtomicInteger(0); - String topic = "persistent://prop/use/ns/t1"; + String topic = "persistent://prop/ns/t1"; mockBrokerService.setHandlePartitionLookup((ctx, lookup) -> { ctx.writeAndFlush(Commands.newPartitionMetadataResponse(0, lookup.getRequestId())); @@ -457,12 +457,12 @@ private void subscribeFailWithoutRetry(String topic) throws Exception { @Test public void testSubscribeSuccessAfterRetry() throws Exception { - subscribeSuccessAfterRetry("persistent://prop/use/ns/t1"); + subscribeSuccessAfterRetry("persistent://prop/ns/t1"); } @Test public void testPartitionedSubscribeSuccessAfterRetry() throws Exception { - subscribeSuccessAfterRetry("persistent://prop/use/ns/part-t1"); + subscribeSuccessAfterRetry("persistent://prop/ns/part-t1"); } private void subscribeSuccessAfterRetry(String topic) throws Exception { @@ -489,12 +489,12 @@ private void subscribeSuccessAfterRetry(String topic) throws Exception { @Test public void testSubscribeFailAfterRetryTimeout() throws Exception { - subscribeFailAfterRetryTimeout("persistent://prop/use/ns/t1"); + subscribeFailAfterRetryTimeout("persistent://prop/ns/t1"); } @Test public void testPartitionedSubscribeFailAfterRetryTimeout() throws Exception { - subscribeFailAfterRetryTimeout("persistent://prop/use/ns/part-t1"); + subscribeFailAfterRetryTimeout("persistent://prop/ns/part-t1"); } private void subscribeFailAfterRetryTimeout(String topic) throws Exception { @@ -527,12 +527,12 @@ private void subscribeFailAfterRetryTimeout(String topic) throws Exception { @Test public void testSubscribeFailDoesNotFailOtherConsumer() throws Exception { - subscribeFailDoesNotFailOtherConsumer("persistent://prop/use/ns/t1", "persistent://prop/use/ns/t2"); + subscribeFailDoesNotFailOtherConsumer("persistent://prop/ns/t1", "persistent://prop/ns/t2"); } @Test public void testPartitionedSubscribeFailDoesNotFailOtherConsumer() throws Exception { - subscribeFailDoesNotFailOtherConsumer("persistent://prop/use/ns/part-t1", "persistent://prop/use/ns/part-t2"); + subscribeFailDoesNotFailOtherConsumer("persistent://prop/ns/part-t1", "persistent://prop/ns/part-t2"); } private void subscribeFailDoesNotFailOtherConsumer(String topic1, String topic2) throws Exception { @@ -587,7 +587,7 @@ public void testPartitionedProducerFailOnInitialization() throws Throwable { client.newProducer() .enableLazyStartPartitionedProducers(true) .accessMode(ProducerAccessMode.Shared) - .topic("persistent://prop/use/ns/multi-part-t1").create(); + .topic("persistent://prop/ns/multi-part-t1").create(); fail("Should have failed with an authorization error"); } catch (Exception e) { assertTrue(e instanceof PulsarClientException.AuthorizationException); @@ -605,7 +605,7 @@ public void testPartitionedProducerFailOnSending() throws Throwable { PulsarClient client = PulsarClient.builder().serviceUrl(mockBrokerService.getHttpAddress()).build(); final AtomicInteger producerCounter = new AtomicInteger(0); final AtomicInteger closeCounter = new AtomicInteger(0); - final String topicName = "persistent://prop/use/ns/multi-part-t1"; + final String topicName = "persistent://prop/ns/multi-part-t1"; mockBrokerService.setHandleProducer((ctx, producer) -> { if (producerCounter.incrementAndGet() == 2) { @@ -684,7 +684,7 @@ public void testOneProducerFailShouldCloseAllProducersInPartitionedProducer() th }); try { - client.newProducer().topic("persistent://prop/use/ns/multi-part-t1").create(); + client.newProducer().topic("persistent://prop/ns/multi-part-t1").create(); fail("Should have failed with an authorization error"); } catch (Exception e) { assertTrue(e instanceof PulsarClientException.AuthorizationException); @@ -720,7 +720,7 @@ public void testOneConsumerFailShouldCloseAllConsumersInPartitionedConsumer() th }); try { - client.newConsumer().topic("persistent://prop/use/ns/multi-part-t1").subscriptionName("sub1").subscribe(); + client.newConsumer().topic("persistent://prop/ns/multi-part-t1").subscriptionName("sub1").subscribe(); fail("Should have failed with an authorization error"); } catch (PulsarClientException.AuthorizationException e) { } @@ -752,7 +752,7 @@ public void testFlowSendWhenPartitionedSubscribeCompletes() throws Exception { } }); - client.newConsumer().topic("persistent://prop/use/ns/multi-part-t1").subscriptionName("sub1").subscribe(); + client.newConsumer().topic("persistent://prop/ns/multi-part-t1").subscriptionName("sub1").subscribe(); if (fail.get()) { fail("Flow command should have been sent after all 4 partitions subscribe successfully"); @@ -789,7 +789,7 @@ public void testProducerReconnect() throws Exception { @Cleanup PulsarClient client = PulsarClient.builder().serviceUrl(mockBrokerService.getBrokerAddress()).build(); - Producer producer = client.newProducer().topic("persistent://prop/use/ns/t1").create(); + Producer producer = client.newProducer().topic("persistent://prop/ns/t1").create(); // close the cnx after creating the producer channelCtx.get().channel().close().get(); @@ -827,7 +827,7 @@ public void testConsumerReconnect() throws Exception { @Cleanup PulsarClient client = PulsarClient.builder().serviceUrl(mockBrokerService.getBrokerAddress()).build(); - client.newConsumer().topic("persistent://prop/use/ns/t1").subscriptionName("sub1").subscribe(); + client.newConsumer().topic("persistent://prop/ns/t1").subscriptionName("sub1").subscribe(); // close the cnx after creating the producer channelCtx.get().channel().close(); @@ -853,7 +853,7 @@ public void testCommandErrorMessageIsNull() throws Exception { }); try { - client.newProducer().topic("persistent://prop/use/ns/t1").create(); + client.newProducer().topic("persistent://prop/ns/t1").create(); fail(); } catch (Exception e) { assertTrue(e instanceof PulsarClientException.AuthorizationException); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/DispatcherBlockConsumerTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/DispatcherBlockConsumerTest.java index 9f9f1afa1f61e..8bb64f8e98578 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/DispatcherBlockConsumerTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/DispatcherBlockConsumerTest.java @@ -520,7 +520,7 @@ public void testBlockDispatcherStats() throws Exception { int orginalDispatcherLimit = conf.getMaxUnackedMessagesPerSubscription(); try { - final String topicName = "persistent://prop/use/ns-abc/blockDispatch"; + final String topicName = "persistent://my-property/my-ns/blockDispatch"; final String subName = "blockDispatch"; final int timeWaitToSync = 100; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/MockBrokerService.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/MockBrokerService.java index 6e2db9ade0104..261eacac21567 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/MockBrokerService.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/MockBrokerService.java @@ -85,8 +85,8 @@ public class MockBrokerService { private class GenericResponseHandler extends AbstractHandler { private final ObjectMapper objectMapper = new ObjectMapper(); - private final String lookupURI = "/lookup/v2/destination/persistent"; - private final String partitionMetadataURI = "/admin/persistent"; + private final String lookupURI = "/lookup/v2/topic/persistent"; + private final String partitionMetadataURI = "/admin/v2/persistent"; private final PartitionedTopicMetadata singlePartitionedTopicMetadata = new PartitionedTopicMetadata(1); private final PartitionedTopicMetadata multiPartitionedTopicMetadata = new PartitionedTopicMetadata(4); private final PartitionedTopicMetadata nonPartitionedTopicMetadata = new PartitionedTopicMetadata(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/NonPersistentTopicTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/NonPersistentTopicTest.java index a5fca4587b3e0..284e6a6892856 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/NonPersistentTopicTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/NonPersistentTopicTest.java @@ -576,7 +576,7 @@ public void testReplicator() throws Exception { ReplicationClusterManager replication = new ReplicationClusterManager(); replication.setupReplicationCluster(); try { - final String globalTopicName = "non-persistent://pulsar/global/ns/nonPersistentTopic"; + final String globalTopicName = "non-persistent://pulsar/ns/nonPersistentTopic"; final int timeWaitToSync = 100; NonPersistentTopicStats stats; @@ -1090,11 +1090,10 @@ void setupReplicationCluster() throws Exception { .brokerServiceUrlTls(pulsar1.getBrokerServiceUrlTls()) .build()); - admin1.clusters().createCluster("global", ClusterData.builder().serviceUrl("http://global:8080").build()); admin1.tenants().createTenant("pulsar", new TenantInfoImpl( Sets.newHashSet("appid1", "appid2", "appid3"), Sets.newHashSet("r1", "r2", "r3"))); - admin1.namespaces().createNamespace("pulsar/global/ns"); - admin1.namespaces().setNamespaceReplicationClusters("pulsar/global/ns", + admin1.namespaces().createNamespace("pulsar/ns"); + admin1.namespaces().setNamespaceReplicationClusters("pulsar/ns", Sets.newHashSet("r1", "r2", "r3"), false); assertEquals(admin2.clusters().getCluster("r1").getServiceUrl(), url1.toString()); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/ProxyProtocolTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/ProxyProtocolTest.java index fa3b00c7ffe52..6cdd3720f2d0b 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/ProxyProtocolTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/ProxyProtocolTest.java @@ -27,19 +27,27 @@ import org.apache.pulsar.client.impl.auth.AuthenticationTls; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @Test(groups = "broker-api") public class ProxyProtocolTest extends TlsProducerConsumerBase { private static final Logger log = LoggerFactory.getLogger(ProxyProtocolTest.class); + @BeforeMethod + @Override + protected void setup() throws Exception { + super.setup(); + internalSetUpForNamespace(); + } + @Test public void testSniProxyProtocol() throws Exception { // Client should try to connect to proxy and pass broker-url as SNI header String proxyUrl = pulsar.getBrokerServiceUrlTls(); String brokerServiceUrl = "pulsar+ssl://unresolvable-address:6651"; - String topicName = "persistent://my-property/use/my-ns/my-topic1"; + String topicName = "persistent://my-property/my-ns/my-topic1"; ClientBuilder clientBuilder = PulsarClient.builder().serviceUrl(brokerServiceUrl) .tlsTrustCertsFilePath(CA_CERT_FILE_PATH).enableTls(true).allowTlsInsecureConnection(false) @@ -62,7 +70,7 @@ public void testSniProxyProtocolWithInvalidProxyUrl() throws Exception { String brokerServiceUrl = "pulsar+ssl://1.1.1.1:6651"; String proxyHost = "invalid-url"; String proxyUrl = "pulsar+ssl://" + proxyHost + ":5555"; - String topicName = "persistent://my-property/use/my-ns/my-topic1"; + String topicName = "persistent://my-property/my-ns/my-topic1"; ClientBuilder clientBuilder = PulsarClient.builder().serviceUrl(brokerServiceUrl) .tlsTrustCertsFilePath(CA_CERT_FILE_PATH).enableTls(true).allowTlsInsecureConnection(false) @@ -88,7 +96,7 @@ public void testSniProxyProtocolWithoutTls() throws Exception { // Client should try to connect to proxy and pass broker-url as SNI header String proxyUrl = pulsar.getBrokerServiceUrl(); String brokerServiceUrl = "pulsar+ssl://1.1.1.1:6651"; - String topicName = "persistent://my-property/use/my-ns/my-topic1"; + String topicName = "persistent://my-property/my-ns/my-topic1"; ClientBuilder clientBuilder = PulsarClient.builder().serviceUrl(brokerServiceUrl) .proxyServiceUrl(proxyUrl, ProxyProtocol.SNI).operationTimeout(1000, TimeUnit.MILLISECONDS); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/SimpleProducerConsumerStatTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/SimpleProducerConsumerStatTest.java index 3ec079137be69..9baa86fc7905d 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/SimpleProducerConsumerStatTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/SimpleProducerConsumerStatTest.java @@ -97,7 +97,7 @@ public Object[][] batchingEnabled() { public void testSyncProducerAndConsumer(int batchMessageDelayMs, int ackTimeoutSec) throws Exception { log.info("-- Starting {} test --", methodName); ConsumerBuilder consumerBuilder = pulsarClient.newConsumer() - .topic("persistent://my-property/tp1/my-ns/my-topic1").subscriptionName("my-subscriber-name"); + .topic("persistent://my-property/my-ns/my-topic1").subscriptionName("my-subscriber-name"); // Cumulative Ack-counter works if ackTimeOutTimer-task is enabled boolean isAckTimeoutTaskEnabledForCumulativeAck = ackTimeoutSec > 0; @@ -108,7 +108,7 @@ public void testSyncProducerAndConsumer(int batchMessageDelayMs, int ackTimeoutS Consumer consumer = consumerBuilder.subscribe(); ProducerBuilder producerBuilder = pulsarClient.newProducer() - .topic("persistent://my-property/tp1/my-ns/my-topic1"); + .topic("persistent://my-property/my-ns/my-topic1"); if (batchMessageDelayMs != 0) { producerBuilder.enableBatching(true).batchingMaxPublishDelay(batchMessageDelayMs, TimeUnit.MILLISECONDS) .batchingMaxMessages(5); @@ -144,7 +144,7 @@ public void testSyncProducerAndConsumer(int batchMessageDelayMs, int ackTimeoutS public void testAsyncProducerAndAsyncAck(int batchMessageDelayMs, int ackTimeoutSec) throws Exception { log.info("-- Starting {} test --", methodName); ConsumerBuilder consumerBuilder = pulsarClient.newConsumer() - .topic("persistent://my-property/tp1/my-ns/my-topic2").subscriptionName("my-subscriber-name"); + .topic("persistent://my-property/my-ns/my-topic2").subscriptionName("my-subscriber-name"); if (ackTimeoutSec > 0) { consumerBuilder.ackTimeout(ackTimeoutSec, TimeUnit.SECONDS); } @@ -152,7 +152,7 @@ public void testAsyncProducerAndAsyncAck(int batchMessageDelayMs, int ackTimeout Consumer consumer = consumerBuilder.subscribe(); ProducerBuilder producerBuilder = pulsarClient.newProducer() - .topic("persistent://my-property/tp1/my-ns/my-topic2") + .topic("persistent://my-property/my-ns/my-topic2") .messageRoutingMode(MessageRoutingMode.SinglePartition); if (batchMessageDelayMs != 0) { producerBuilder.enableBatching(true).batchingMaxPublishDelay(batchMessageDelayMs, TimeUnit.MILLISECONDS) @@ -202,7 +202,7 @@ public void testAsyncProducerAndReceiveAsyncAndAsyncAck(int batchMessageDelayMs, throws Exception { log.info("-- Starting {} test --", methodName); ConsumerBuilder consumerBuilder = pulsarClient.newConsumer() - .topic("persistent://my-property/tp1/my-ns/my-topic2").subscriptionName("my-subscriber-name"); + .topic("persistent://my-property/my-ns/my-topic2").subscriptionName("my-subscriber-name"); if (ackTimeoutSec > 0) { consumerBuilder.ackTimeout(ackTimeoutSec, TimeUnit.SECONDS); } @@ -210,7 +210,7 @@ public void testAsyncProducerAndReceiveAsyncAndAsyncAck(int batchMessageDelayMs, Consumer consumer = consumerBuilder.subscribe(); ProducerBuilder producerBuilder = pulsarClient.newProducer() - .topic("persistent://my-property/tp1/my-ns/my-topic2") + .topic("persistent://my-property/my-ns/my-topic2") .messageRoutingMode(MessageRoutingMode.SinglePartition); if (batchMessageDelayMs != 0) { producerBuilder.enableBatching(true).batchingMaxPublishDelay(batchMessageDelayMs, TimeUnit.MILLISECONDS) @@ -265,7 +265,7 @@ public void testMessageListener(int batchMessageDelayMs) throws Exception { int numMessages = 100; final CountDownLatch latch = new CountDownLatch(numMessages); - Consumer consumer = pulsarClient.newConsumer().topic("persistent://my-property/tp1/my-ns/my-topic3") + Consumer consumer = pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic3") .subscriptionName("my-subscriber-name").ackTimeout(100, TimeUnit.SECONDS) .messageListener((consumer1, msg) -> { assertNotNull(msg, "Message cannot be null"); @@ -276,7 +276,7 @@ public void testMessageListener(int batchMessageDelayMs) throws Exception { }).subscribe(); ProducerBuilder producerBuilder = pulsarClient.newProducer() - .topic("persistent://my-property/tp1/my-ns/my-topic3"); + .topic("persistent://my-property/my-ns/my-topic3"); if (batchMessageDelayMs != 0) { producerBuilder.enableBatching(true).batchingMaxPublishDelay(batchMessageDelayMs, TimeUnit.MILLISECONDS) .batchingMaxMessages(5); @@ -309,11 +309,11 @@ public void testMessageListener(int batchMessageDelayMs) throws Exception { public void testSendTimeout(int batchMessageDelayMs) throws Exception { log.info("-- Starting {} test --", methodName); - Consumer consumer = pulsarClient.newConsumer().topic("persistent://my-property/tp1/my-ns/my-topic5") + Consumer consumer = pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic5") .subscriptionName("my-subscriber-name").subscribe(); ProducerBuilder producerBuilder = pulsarClient.newProducer() - .topic("persistent://my-property/tp1/my-ns/my-topic5").sendTimeout(1, TimeUnit.SECONDS); + .topic("persistent://my-property/my-ns/my-topic5").sendTimeout(1, TimeUnit.SECONDS); if (batchMessageDelayMs != 0) { producerBuilder.enableBatching(true) .batchingMaxPublishDelay(2L * batchMessageDelayMs, TimeUnit.MILLISECONDS) @@ -356,7 +356,7 @@ public void testSendTimeout(int batchMessageDelayMs) throws Exception { @Test public void testBatchMessagesRateOut() throws PulsarClientException, InterruptedException, PulsarAdminException { log.info("-- Starting {} test --", methodName); - String topicName = "persistent://my-property/cluster/my-ns/testBatchMessagesRateOut"; + String topicName = "persistent://my-property/my-ns/testBatchMessagesRateOut"; double produceRate = 17; int batchSize = 5; Consumer consumer = pulsarClient.newConsumer().topic(topicName).subscriptionName("my-subscriber-name") @@ -402,7 +402,7 @@ public void testAddBrokerLatencyStats() throws Exception { log.info("-- Starting {} test --", methodName); ProducerBuilder producerBuilder = pulsarClient.newProducer() - .topic("persistent://my-property/tp1/my-ns/my-topic1"); + .topic("persistent://my-property/my-ns/my-topic1"); Producer producer = producerBuilder.create(); @@ -447,7 +447,7 @@ public void testAddBrokerLatencyStats() throws Exception { public void testProducerPendingQueueSizeStats(boolean batchingEnabled) throws Exception { log.info("-- Starting {} test --", methodName); ProducerBuilder producerBuilder = pulsarClient.newProducer() - .topic("persistent://my-property/tp1/my-ns/my-topic1"); + .topic("persistent://my-property/my-ns/my-topic1"); @Cleanup Producer producer = producerBuilder.enableBatching(batchingEnabled).create(); @@ -528,7 +528,7 @@ public void testPartitionTopicStats() throws Exception { public void testMsgRateExpired() throws Exception { log.info("-- Starting {} test --", methodName); - String topicName = "persistent://my-property/tp1/my-ns/" + methodName; + String topicName = "persistent://my-property/my-ns/" + methodName; String subName = "my-sub"; admin.topics().createSubscription(topicName, subName, MessageId.latest); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/SimpleTypedProducerConsumerTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/SimpleTypedProducerConsumerTest.java index 9a112f5c4d042..293d3adcb876b 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/SimpleTypedProducerConsumerTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/SimpleTypedProducerConsumerTest.java @@ -76,13 +76,13 @@ public void testJsonProducerAndConsumer() throws Exception { Consumer consumer = pulsarClient .newConsumer(jsonSchema) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name") .subscribe(); Producer producer = pulsarClient .newProducer(jsonSchema) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .create(); for (int i = 0; i < 10; i++) { @@ -134,13 +134,13 @@ public void testJsonProducerAndConsumerWithPrestoredSchema() throws Exception { Consumer consumer = pulsarClient .newConsumer(jsonSchema) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name") .subscribe(); Producer producer = pulsarClient .newProducer(jsonSchema) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .create(); consumer.close(); @@ -191,13 +191,13 @@ public void testProtobufProducerAndConsumer() throws Exception { Consumer consumer = pulsarClient .newConsumer(protobufSchema) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name") .subscribe(); Producer producer = pulsarClient .newProducer(protobufSchema) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .create(); for (int i = 0; i < 10; i++) { @@ -255,7 +255,7 @@ public void testProtobufConsumerWithWrongPrestoredSchema() throws Exception { .newConsumer(AvroSchema.of (SchemaDefinition.builder(). withPojo(org.apache.pulsar.client.api.schema.proto.Test.TestMessageWrong.class).build())) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name") .subscribe(); @@ -272,13 +272,13 @@ public void testAvroProducerAndConsumer() throws Exception { Consumer consumer = pulsarClient .newConsumer(avroSchema) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name") .subscribe(); Producer producer = pulsarClient .newProducer(avroSchema) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .create(); for (int i = 0; i < 10; i++) { @@ -338,7 +338,7 @@ public void testAvroConsumerWithWrongRestoredSchema() throws Exception { Consumer consumer = pulsarClient .newConsumer(AvroSchema.of(SchemaDefinition.builder(). withPojo(AvroEncodedPojo.class).withAlwaysAllowNull(false).build())) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name") .subscribe(); @@ -441,7 +441,7 @@ public void testAvroProducerAndAutoSchemaConsumer() throws Exception { Producer producer = pulsarClient .newProducer(avroSchema) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .create(); for (int i = 0; i < 10; i++) { @@ -451,7 +451,7 @@ public void testAvroProducerAndAutoSchemaConsumer() throws Exception { Consumer consumer = pulsarClient .newConsumer(Schema.AUTO_CONSUME()) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name") .subscriptionInitialPosition(SubscriptionInitialPosition.Earliest) .subscribe(); @@ -490,7 +490,7 @@ public void testAvroProducerAndAutoSchemaReader() throws Exception { Producer producer = pulsarClient .newProducer(avroSchema) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .create(); for (int i = 0; i < 10; i++) { @@ -500,7 +500,7 @@ public void testAvroProducerAndAutoSchemaReader() throws Exception { Reader reader = pulsarClient .newReader(Schema.AUTO_CONSUME()) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .startMessageId(MessageId.earliest) .create(); @@ -537,7 +537,7 @@ public void testAutoBytesProducer() throws Exception { try (Producer producer = pulsarClient .newProducer(avroSchema) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .create()) { for (int i = 0; i < 10; i++) { String message = "my-message-" + i; @@ -547,7 +547,7 @@ public void testAutoBytesProducer() throws Exception { try (Producer producer = pulsarClient .newProducer(Schema.AUTO_PRODUCE_BYTES()) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .create()) { // try to produce junk data for (int i = 10; i < 20; i++) { @@ -572,7 +572,7 @@ public void testAutoBytesProducer() throws Exception { Consumer consumer = pulsarClient .newConsumer(Schema.AUTO_CONSUME()) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name") .subscriptionInitialPosition(SubscriptionInitialPosition.Earliest) .subscribe(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TlsProducerConsumerTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TlsProducerConsumerTest.java index bfb18c26a71a4..8513442d99821 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TlsProducerConsumerTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TlsProducerConsumerTest.java @@ -63,10 +63,10 @@ public void testTlsLargeSizeMessage() throws Exception { internalSetUpForClient(true, pulsar.getBrokerServiceUrlTls()); internalSetUpForNamespace(); - Consumer consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + Consumer consumer = pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscribe(); - Producer producer = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic1") + Producer producer = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic1") .create(); for (int i = 0; i < 10; i++) { byte[] message = new byte[messageSize]; @@ -98,7 +98,7 @@ public void testTlsClientAuthOverBinaryProtocol() throws Exception { // Test 1 - Using TLS on binary protocol without sending certs - expect failure internalSetUpForClient(false, pulsar.getBrokerServiceUrlTls()); try { - pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe(); Assert.fail("Server should have failed the TLS handshake since client didn't ."); } catch (Exception ex) { @@ -108,7 +108,7 @@ public void testTlsClientAuthOverBinaryProtocol() throws Exception { // Test 2 - Using TLS on binary protocol - sending certs internalSetUpForClient(true, pulsar.getBrokerServiceUrlTls()); try { - pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe(); } catch (Exception ex) { Assert.fail("Should not fail since certs are sent."); @@ -126,7 +126,7 @@ public void testTlsClientAuthOverHTTPProtocol() throws Exception { // Test 1 - Using TLS on https without sending certs - expect failure internalSetUpForClient(false, pulsar.getWebServiceAddressTls()); try { - pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe(); Assert.fail("Server should have failed the TLS handshake since client didn't ."); } catch (Exception ex) { @@ -136,7 +136,7 @@ public void testTlsClientAuthOverHTTPProtocol() throws Exception { // Test 2 - Using TLS on https - sending certs internalSetUpForClient(true, pulsar.getWebServiceAddressTls()); try { - pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Exclusive).subscribe(); } catch (Exception ex) { Assert.fail("Should not fail since certs are sent."); @@ -146,7 +146,8 @@ public void testTlsClientAuthOverHTTPProtocol() throws Exception { @Test(timeOut = 60000) public void testTlsCertsFromDynamicStream() throws Exception { log.info("-- Starting {} test --", methodName); - String topicName = "persistent://my-property/use/my-ns/my-topic1"; + internalSetUpForNamespace(); + String topicName = "persistent://my-property/my-ns/my-topic1"; ClientBuilder clientBuilder = PulsarClient.builder().serviceUrl(pulsar.getBrokerServiceUrlTls()) .enableTls(true).allowTlsInsecureConnection(false) .operationTimeout(1000, TimeUnit.MILLISECONDS); @@ -170,7 +171,7 @@ public void testTlsCertsFromDynamicStream() throws Exception { PersistentTopic topicRef = (PersistentTopic) pulsar.getBrokerService().getTopicReference(topicName).get(); topicRef.close(false); - Producer producer = pulsarClient.newProducer().topic("persistent://my-property/use/my-ns/my-topic1") + Producer producer = pulsarClient.newProducer().topic("persistent://my-property/my-ns/my-topic1") .createAsync().get(30, TimeUnit.SECONDS); for (int i = 0; i < 10; i++) { producer.send(("test" + i).getBytes()); @@ -203,6 +204,7 @@ public void testTlsCertsFromDynamicStream() throws Exception { @Test public void testTlsCertsFromDynamicStreamExpiredAndRenewCert() throws Exception { log.info("-- Starting {} test --", methodName); + internalSetUpForNamespace(); ClientBuilder clientBuilder = PulsarClient.builder().serviceUrl(pulsar.getBrokerServiceUrlTls()) .enableTls(true).allowTlsInsecureConnection(false) .autoCertRefreshSeconds(1) @@ -224,7 +226,7 @@ public void testTlsCertsFromDynamicStreamExpiredAndRenewCert() throws Exception PulsarClient pulsarClient = clientBuilder.build(); Consumer consumer = null; try { - consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + consumer = pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscribe(); Assert.fail("should have failed due to invalid tls cert"); } catch (PulsarClientException e) { @@ -233,7 +235,7 @@ public void testTlsCertsFromDynamicStreamExpiredAndRenewCert() throws Exception sleepSeconds(2); certIndex.set(0); try { - consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + consumer = pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscribe(); Assert.fail("should have failed due to invalid tls cert"); } catch (PulsarClientException e) { @@ -242,7 +244,7 @@ public void testTlsCertsFromDynamicStreamExpiredAndRenewCert() throws Exception sleepSeconds(2); trustStoreIndex.set(0); sleepSeconds(2); - consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic1") + consumer = pulsarClient.newConsumer().topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscribe(); consumer.close(); log.info("-- Exiting {} test --", methodName); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TlsSniTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TlsSniTest.java index ddd8e2fa45d5a..115909e288aac 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TlsSniTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TlsSniTest.java @@ -25,11 +25,19 @@ import java.util.concurrent.TimeUnit; import lombok.Cleanup; import org.apache.pulsar.client.impl.auth.AuthenticationTls; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @Test(groups = "broker-api") public class TlsSniTest extends TlsProducerConsumerBase { + @BeforeMethod + @Override + protected void setup() throws Exception { + super.setup(); + internalSetUpForNamespace(); + } + /** * Verify that using an IP-address in the broker service URL will work with using the SNI capabilities * of the client. If we try to create an {@link javax.net.ssl.SSLEngine} with a peer host that is an @@ -39,7 +47,7 @@ public class TlsSniTest extends TlsProducerConsumerBase { */ @Test public void testIpAddressInBrokerServiceUrl() throws Exception { - String topicName = "persistent://my-property/use/my-ns/my-topic1"; + String topicName = "persistent://my-property/my-ns/my-topic1"; URI brokerServiceUrlTls = new URI(pulsar.getBrokerServiceUrlTls()); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TopicReaderTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TopicReaderTest.java index 0183b50a08685..6c133d6c1093a 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TopicReaderTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TopicReaderTest.java @@ -989,7 +989,7 @@ public void testMultiReaderReachEndOfTopicOnMessageWithBatches() throws Exceptio @Test public void testMessageAvailableAfterRestart() throws Exception { - String topic = "persistent://my-property/use/my-ns/testMessageAvailableAfterRestart"; + String topic = "persistent://my-property/my-ns/testMessageAvailableAfterRestart"; String content = "my-message-1"; // stop retention from cleaning up @@ -1025,7 +1025,7 @@ public void testMessageAvailableAfterRestart() throws Exception { @Test public void testMultiReaderMessageAvailableAfterRestart() throws Exception { - String topic = "persistent://my-property/use/my-ns/testMessageAvailableAfterRestart2"; + String topic = "persistent://my-property/my-ns/testMessageAvailableAfterRestart2"; String content = "my-message-1"; admin.topics().createPartitionedTopic(topic, 3); // stop retention from cleaning up diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/v1/V1ProducerConsumerBase.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/v1/V1ProducerConsumerBase.java deleted file mode 100644 index 31c129e1ff3bb..0000000000000 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/v1/V1ProducerConsumerBase.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.client.api.v1; - -import com.google.common.collect.Sets; -import java.lang.reflect.Method; -import java.util.Set; -import org.apache.pulsar.broker.auth.MockedPulsarServiceBaseTest; -import org.apache.pulsar.common.policies.data.ClusterData; -import org.apache.pulsar.common.policies.data.TenantInfoImpl; -import org.testng.Assert; -import org.testng.annotations.BeforeMethod; - -public abstract class V1ProducerConsumerBase extends MockedPulsarServiceBaseTest { - protected String methodName; - - @BeforeMethod(alwaysRun = true) - public void beforeMethod(Method m) throws Exception { - methodName = m.getName(); - } - - public void producerBaseSetup() throws Exception { - admin.clusters().createCluster("use", ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); - admin.tenants().createTenant("my-property", - new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("use"))); - admin.namespaces().createNamespace("my-property/use/my-ns"); - } - - protected void testMessageOrderAndDuplicates(Set messagesReceived, String receivedMessage, - String expectedMessage) { - // Make sure that messages are received in order - Assert.assertEquals(receivedMessage, expectedMessage, - "Received message " + receivedMessage + " did not match the expected message " + expectedMessage); - - // Make sure that there are no duplicates - Assert.assertTrue(messagesReceived.add(receivedMessage), "Received duplicate message " + receivedMessage); - } - -} diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/v1/V1ProducerConsumerTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/v1/V1ProducerConsumerTest.java deleted file mode 100644 index 386036184d3b0..0000000000000 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/v1/V1ProducerConsumerTest.java +++ /dev/null @@ -1,2386 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.client.api.v1; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; -import com.google.common.collect.Sets; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.CyclicBarrier; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; -import lombok.Cleanup; -import org.apache.bookkeeper.mledger.ManagedLedgerFactory; -import org.apache.bookkeeper.mledger.impl.ManagedLedgerImpl; -import org.apache.bookkeeper.mledger.impl.cache.EntryCache; -import org.apache.bookkeeper.mledger.impl.cache.EntryCacheManager; -import org.apache.commons.lang3.reflect.FieldUtils; -import org.apache.pulsar.broker.PulsarService; -import org.apache.pulsar.broker.service.persistent.PersistentTopic; -import org.apache.pulsar.client.api.Consumer; -import org.apache.pulsar.client.api.ConsumerBuilder; -import org.apache.pulsar.client.api.ConsumerCryptoFailureAction; -import org.apache.pulsar.client.api.CryptoKeyReader; -import org.apache.pulsar.client.api.EncryptionKeyInfo; -import org.apache.pulsar.client.api.Message; -import org.apache.pulsar.client.api.MessageId; -import org.apache.pulsar.client.api.Producer; -import org.apache.pulsar.client.api.ProducerBuilder; -import org.apache.pulsar.client.api.PulsarClient; -import org.apache.pulsar.client.api.PulsarClientException; -import org.apache.pulsar.client.api.Schema; -import org.apache.pulsar.client.api.SubscriptionType; -import org.apache.pulsar.client.api.TypedMessageBuilder; -import org.apache.pulsar.client.impl.ConsumerImpl; -import org.apache.pulsar.client.impl.MessageIdImpl; -import org.apache.pulsar.client.impl.TypedMessageBuilderImpl; -import org.apache.pulsar.common.naming.TopicName; -import org.apache.pulsar.common.protocol.Commands; -import org.apache.pulsar.common.util.FutureUtil; -import org.awaitility.Awaitility; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -/** - * Basic tests using the deprecated client APIs from Pulsar-1.x. - */ -@Test(groups = "flaky") -public class V1ProducerConsumerTest extends V1ProducerConsumerBase { - - private static final Logger log = LoggerFactory.getLogger(V1ProducerConsumerTest.class); - private static final long BATCHING_MAX_PUBLISH_DELAY_THRESHOLD = 1; - - @BeforeMethod(alwaysRun = true) - @Override - protected void setup() throws Exception { - super.internalSetup(); - super.producerBaseSetup(); - } - - @AfterMethod(alwaysRun = true) - @Override - protected void cleanup() throws Exception { - super.internalCleanup(); - } - - @DataProvider(name = "batch") - public Object[][] codecProvider() { - return new Object[][] { { 0 }, { 1000 } }; - } - - @Test(dataProvider = "batch") - public void testSyncProducerAndConsumer(int batchMessageDelayMs) throws Exception { - log.info("-- Starting {} test --", methodName); - - Consumer consumer = pulsarClient.newConsumer(Schema.STRING) - .topic("persistent://my-property/use/my-ns/my-topic1") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .subscribe(); - - ProducerBuilder producerBuilder = pulsarClient.newProducer(Schema.STRING) - .topic("persistent://my-property/use/my-ns/my-topic1"); - - if (batchMessageDelayMs != 0) { - producerBuilder.enableBatching(true) - .batchingMaxPublishDelay(batchMessageDelayMs, TimeUnit.MILLISECONDS) - .batchingMaxMessages(5); - } else { - producerBuilder.enableBatching(false); - } - - Producer producer = producerBuilder.create(); - for (int i = 0; i < 10; i++) { - producer.send("my-message-" + i); - } - - Message msg = null; - Set messageSet = new HashSet<>(); - for (int i = 0; i < 10; i++) { - msg = consumer.receive(5, TimeUnit.SECONDS); - String receivedMessage = msg.getValue(); - log.debug("Received message: [{}]", receivedMessage); - String expectedMessage = "my-message-" + i; - testMessageOrderAndDuplicates(messageSet, receivedMessage, expectedMessage); - } - // Acknowledge the consumption of all messages at once - consumer.acknowledgeCumulative(msg); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } - - @Test(dataProvider = "batch") - public void testAsyncProducerAndAsyncAck(int batchMessageDelayMs) throws Exception { - log.info("-- Starting {} test --", methodName); - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic2") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic2") - .batchingMaxMessages(5) - .batchingMaxPublishDelay(BATCHING_MAX_PUBLISH_DELAY_THRESHOLD, TimeUnit.MILLISECONDS) - .enableBatching(batchMessageDelayMs != 0) - .create(); - - List> futures = new ArrayList<>(); - - // Asynchronously produce messages - for (int i = 0; i < 10; i++) { - final String message = "my-message-" + i; - Future future = producer.sendAsync(message.getBytes()); - futures.add(future); - } - - log.info("Waiting for async publish to complete"); - for (Future future : futures) { - future.get(); - } - - Message msg = null; - Set messageSet = new HashSet<>(); - for (int i = 0; i < 10; i++) { - msg = consumer.receive(5, TimeUnit.SECONDS); - String receivedMessage = new String(msg.getData()); - log.info("Received message: [{}]", receivedMessage); - String expectedMessage = "my-message-" + i; - testMessageOrderAndDuplicates(messageSet, receivedMessage, expectedMessage); - } - - // Asynchronously acknowledge upto and including the last message - Future ackFuture = consumer.acknowledgeCumulativeAsync(msg); - log.info("Waiting for async ack to complete"); - ackFuture.get(); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } - - @Test(dataProvider = "batch", timeOut = 100000) - public void testMessageListener(int batchMessageDelayMs) throws Exception { - log.info("-- Starting {} test --", methodName); - - int numMessages = 100; - final CountDownLatch latch = new CountDownLatch(numMessages); - - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic3") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .messageListener((c, msg) -> { - Assert.assertNotNull(msg, "Message cannot be null"); - String receivedMessage = new String(msg.getData()); - log.debug("Received message [{}] in the listener", receivedMessage); - c.acknowledgeAsync(msg); - latch.countDown(); - }) - .subscribe(); - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic3") - .batchingMaxMessages(5) - .batchingMaxPublishDelay(BATCHING_MAX_PUBLISH_DELAY_THRESHOLD, TimeUnit.MILLISECONDS) - .enableBatching(batchMessageDelayMs != 0) - .create(); - - List> futures = new ArrayList<>(); - - // Asynchronously produce messages - for (int i = 0; i < numMessages; i++) { - final String message = "my-message-" + i; - Future future = producer.sendAsync(message.getBytes()); - futures.add(future); - } - - log.info("Waiting for async publish to complete"); - for (Future future : futures) { - future.get(); - } - - log.info("Waiting for message listener to ack all messages"); - assertTrue(latch.await(numMessages, TimeUnit.SECONDS), "Timed out waiting for message listener acks"); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } - - @Test(dataProvider = "batch") - public void testBackoffAndReconnect(int batchMessageDelayMs) throws Exception { - log.info("-- Starting {} test --", methodName); - // Create consumer and producer - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic4") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .startMessageIdInclusive() - .subscribe(); - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic4") - .batchingMaxMessages(5) - .batchingMaxPublishDelay(BATCHING_MAX_PUBLISH_DELAY_THRESHOLD, TimeUnit.MILLISECONDS) - .enableBatching(batchMessageDelayMs != 0) - .create(); - - // Produce messages - CompletableFuture lastFuture = null; - for (int i = 0; i < 10; i++) { - lastFuture = producer.sendAsync(("my-message-" + i).getBytes()).thenApply(msgId -> { - log.info("Published message id: {}", msgId); - return msgId; - }); - } - - lastFuture.get(); - - Message msg = null; - for (int i = 0; i < 10; i++) { - msg = consumer.receive(5, TimeUnit.SECONDS); - log.info("Received: [{}]", new String(msg.getData())); - } - - // Restart the broker and wait for the backoff to kick in. The client library will try to reconnect, and once - // the broker is up, the consumer should receive the duplicate messages. - log.info("-- Restarting broker --"); - restartBroker(); - - msg = null; - log.info("Receiving duplicate messages.."); - for (int i = 0; i < 10; i++) { - msg = consumer.receive(5, TimeUnit.SECONDS); - log.info("Received: [{}]", new String(msg.getData())); - Assert.assertNotNull(msg, "Message cannot be null"); - } - consumer.acknowledgeCumulative(msg); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } - - @Test(dataProvider = "batch") - public void testSendTimeout(int batchMessageDelayMs) throws Exception { - log.info("-- Starting {} test --", methodName); - - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic5") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic5") - .batchingMaxMessages(5) - .batchingMaxPublishDelay(2 * BATCHING_MAX_PUBLISH_DELAY_THRESHOLD, TimeUnit.MILLISECONDS) - .enableBatching(batchMessageDelayMs != 0) - .sendTimeout(1, TimeUnit.SECONDS) - .create(); - - final String message = "my-message"; - - // Trigger the send timeout - stopBroker(); - - Future future = producer.sendAsync(message.getBytes()); - - try { - future.get(); - Assert.fail("Send operation should have failed"); - } catch (ExecutionException e) { - // Expected - } - - startBroker(); - - // We should not have received any message - Message msg = consumer.receive(3, TimeUnit.SECONDS); - Assert.assertNull(msg); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } - - @Test - public void testInvalidSequence() throws Exception { - log.info("-- Starting {} test --", methodName); - - PulsarClient client1 = PulsarClient.builder().serviceUrl(pulsar.getWebServiceAddress()).build(); - client1.close(); - - try { - client1.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic6") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .subscribe(); - Assert.fail("Should fail"); - } catch (PulsarClientException e) { - Assert.assertTrue(e instanceof PulsarClientException.AlreadyClosedException); - } - - try { - client1.newProducer().topic("persistent://my-property/use/my-ns/my-topic6").create(); - Assert.fail("Should fail"); - } catch (PulsarClientException e) { - Assert.assertTrue(e instanceof PulsarClientException.AlreadyClosedException); - } - - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic6") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic6") - .create(); - - try { - TypedMessageBuilder builder = producer.newMessage().value("InvalidMessage".getBytes()); - Message msg = ((TypedMessageBuilderImpl) builder).getMessage(); - consumer.acknowledge(msg); - } catch (PulsarClientException.InvalidMessageException e) { - // ok - } - - consumer.close(); - - try { - consumer.receive(); - Assert.fail("Should fail"); - } catch (PulsarClientException.AlreadyClosedException e) { - // ok - } - - try { - consumer.unsubscribe(); - Assert.fail("Should fail"); - } catch (PulsarClientException.AlreadyClosedException e) { - // ok - } - - - producer.close(); - - try { - producer.send("message".getBytes()); - Assert.fail("Should fail"); - } catch (PulsarClientException.AlreadyClosedException e) { - // ok - } - - } - - @Test - public void testSillyUser() throws Exception { - try { - PulsarClient.builder().serviceUrl("invalid://url").build(); - Assert.fail("should fail"); - } catch (PulsarClientException e) { - Assert.assertTrue(e instanceof PulsarClientException.InvalidServiceURL); - } - - try { - pulsarClient.newProducer().sendTimeout(-1, TimeUnit.SECONDS); - Assert.fail("should fail"); - } catch (IllegalArgumentException e) { - // ok - } - - try { - pulsarClient.newProducer().topic("invalid://topic").create(); - Assert.fail("should fail"); - } catch (PulsarClientException e) { - Assert.assertTrue(e instanceof PulsarClientException.InvalidTopicNameException); - } - - try { - pulsarClient.newConsumer().messageListener(null); - Assert.fail("should fail"); - } catch (NullPointerException e) { - // ok - } - - try { - pulsarClient.newConsumer().subscriptionType(null); - Assert.fail("should fail"); - } catch (NullPointerException e) { - // ok - } - - try { - pulsarClient.newConsumer().receiverQueueSize(-1); - Assert.fail("should fail"); - } catch (IllegalArgumentException e) { - // ok - } - - try { - pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic7") - .subscriptionName(null) - .subscribe(); - Assert.fail("Should fail"); - } catch (IllegalArgumentException e) { - // expected - } - - try { - pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic7") - .subscriptionName("") - .subscribe(); - Assert.fail("Should fail"); - } catch (IllegalArgumentException e) { - // Expected - } - - try { - pulsarClient.newConsumer() - .topic("invalid://topic7") - .subscriptionName(null) - .subscribe(); - Assert.fail("Should fail"); - } catch (IllegalArgumentException e) { - // Expected - } - - } - - // This is to test that the flow control counter doesn't get corrupted while concurrent receives during - // reconnections - @Test(dataProvider = "batch") - public void testConcurrentConsumerReceiveWhileReconnect(int batchMessageDelayMs) throws Exception { - final int recvQueueSize = 100; - final int numConsumersThreads = 10; - String topic = "persistent://my-property/use/my-ns/my-topic-" + UUID.randomUUID().toString(); - - String subName = UUID.randomUUID().toString(); - final Consumer consumer = pulsarClient.newConsumer() - .topic(topic) - .subscriptionName(subName) - .startMessageIdInclusive() - .receiverQueueSize(recvQueueSize).subscribe(); - @Cleanup("shutdownNow") - ExecutorService executor = Executors.newCachedThreadPool(); - - final CyclicBarrier barrier = new CyclicBarrier(numConsumersThreads + 1); - for (int i = 0; i < numConsumersThreads; i++) { - executor.submit(new Callable() { - @Override - public Void call() throws Exception { - barrier.await(); - consumer.receive(); - return null; - } - }); - } - - barrier.await(); - // there will be 10 threads calling receive() from the same consumer and will block - Thread.sleep(100); - - // we restart the broker to reconnect - restartBroker(); - Thread.sleep(2000); - - // publish 100 messages so that the consumers blocked on receive() will now get the messages - Producer producer = pulsarClient.newProducer() - .topic(topic) - .batchingMaxPublishDelay(BATCHING_MAX_PUBLISH_DELAY_THRESHOLD, TimeUnit.MILLISECONDS) - .batchingMaxMessages(5) - .enableBatching(batchMessageDelayMs != 0) - .create(); - for (int i = 0; i < recvQueueSize; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - - ConsumerImpl consumerImpl = (ConsumerImpl) consumer; - // The available permits should be 10 and num messages in the queue should be 90 - Awaitility.await().untilAsserted(() -> - Assert.assertEquals(consumerImpl.getAvailablePermits(), numConsumersThreads)); - Assert.assertEquals(consumerImpl.numMessagesInQueue(), recvQueueSize - numConsumersThreads); - - barrier.reset(); - for (int i = 0; i < numConsumersThreads; i++) { - executor.submit(new Callable() { - @Override - public Void call() throws Exception { - barrier.await(); - consumer.receive(); - return null; - } - }); - } - barrier.await(); - - // The available permits should be 20 and num messages in the queue should be 80 - Awaitility.await().untilAsserted(() -> - Assert.assertEquals(consumerImpl.getAvailablePermits(), numConsumersThreads * 2)); - Assert.assertEquals(consumerImpl.numMessagesInQueue(), recvQueueSize - (numConsumersThreads * 2)); - - // clear the queue - while (true) { - Message msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg == null) { - break; - } - } - - // The available permits should be 0 and num messages in the queue should be 0 - Assert.assertEquals(consumerImpl.getAvailablePermits(), 0); - Assert.assertEquals(consumerImpl.numMessagesInQueue(), 0); - - barrier.reset(); - for (int i = 0; i < numConsumersThreads; i++) { - executor.submit(new Callable() { - @Override - public Void call() throws Exception { - barrier.await(); - consumer.receive(); - return null; - } - }); - } - barrier.await(); - // we again make 10 threads call receive() and get blocked - Thread.sleep(100); - - restartBroker(); - - // The available permits should be 10 and num messages in the queue should be 90 - Awaitility.await().untilAsserted(() -> { - Assert.assertEquals(consumerImpl.getAvailablePermits(), numConsumersThreads); - Assert.assertEquals(consumerImpl.numMessagesInQueue(), recvQueueSize - numConsumersThreads); - }); - - consumer.close(); - } - - @Test - public void testSendBigMessageSize() throws Exception { - log.info("-- Starting {} test --", methodName); - - final String topic = "persistent://my-property/use/my-ns/bigMsg"; - Producer producer = pulsarClient.newProducer().topic(topic).create(); - - // Messages are allowed up to MaxMessageSize - producer.newMessage().value(new byte[Commands.DEFAULT_MAX_MESSAGE_SIZE]); - - try { - producer.send(new byte[Commands.DEFAULT_MAX_MESSAGE_SIZE + 1]); - fail("Should have thrown exception"); - } catch (PulsarClientException.InvalidMessageException e) { - // OK - } - } - - @Override - protected void beforePulsarStart(PulsarService pulsar) throws Exception { - super.beforePulsarStart(pulsar); - doAnswer(i0 -> { - ManagedLedgerFactory factory = (ManagedLedgerFactory) spy(i0.callRealMethod()); - doAnswer(i1 -> { - EntryCacheManager manager = (EntryCacheManager) spy(i1.callRealMethod()); - doAnswer(i2 -> spy(i2.callRealMethod())).when(manager).getEntryCache(any()); - return manager; - }).when(factory).getEntryCacheManager(); - return factory; - }).when(pulsar).getDefaultManagedLedgerFactory(); - } - - /** - * Usecase 1: Only 1 Active Subscription - 1 subscriber - Produce Messages - EntryCache should cache messages - - * EntryCache should be cleaned : Once active subscription consumes messages - * - * Usecase 2: 2 Active Subscriptions (faster and slower) and slower gets closed - 2 subscribers - Produce Messages - - * 1 faster-subscriber consumes all messages and another slower-subscriber none - EntryCache should have cached - * messages as slower-subscriber has not consumed messages yet - close slower-subscriber - EntryCache should be - * cleared. - * - * @throws Exception - */ - @Test(groups = "quarantine") - public void testActiveAndInActiveConsumerEntryCacheBehavior() throws Exception { - log.info("-- Starting {} test --", methodName); - - final long batchMessageDelayMs = 100; - final int receiverSize = 10; - final String topicName = "cache-topic-" + UUID.randomUUID().toString(); - final String sub1 = "faster-sub1"; - final String sub2 = "slower-sub2"; - - /************ usecase-1: *************/ - // 1. Subscriber Faster subscriber - Consumer subscriber1 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/" + topicName) - .subscriptionName(sub1) - .subscriptionType(SubscriptionType.Shared) - .receiverQueueSize(receiverSize) - .subscribe(); - final String topic = "persistent://my-property/use/my-ns/" + topicName; - Producer producer = pulsarClient.newProducer() - .topic(topic) - .enableBatching(batchMessageDelayMs != 0) - .batchingMaxPublishDelay(batchMessageDelayMs, TimeUnit.MILLISECONDS) - .batchingMaxMessages(5) - .create(); - - PersistentTopic topicRef = (PersistentTopic) pulsar.getBrokerService().getTopicReference(topic).get(); - ManagedLedgerImpl ledger = (ManagedLedgerImpl) topicRef.getManagedLedger(); - - EntryCache entryCache = (EntryCache) FieldUtils.readField(ledger, "entryCache", true); - - Message msg = null; - // 2. Produce messages - for (int i = 0; i < 30; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - // 3. Consume messages - for (int i = 0; i < 30; i++) { - msg = subscriber1.receive(5, TimeUnit.SECONDS); - subscriber1.acknowledge(msg); - } - - // Verify: EntryCache has been invalidated - verify(entryCache, atLeastOnce()).invalidateEntries(any()); - - // sleep for a second: as ledger.updateCursorRateLimit RateLimiter will allow to invoke cursor-update after a - // second - Thread.sleep(1000); // - // produce-consume one more message to trigger : ledger.internalReadFromLedger(..) which updates cursor and - // EntryCache - producer.send("message".getBytes()); - msg = subscriber1.receive(5, TimeUnit.SECONDS); - - /************ usecase-2: *************/ - // 1.b Subscriber slower-subscriber - Consumer subscriber2 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/" + topicName) - .subscriptionName(sub2) - .subscriptionType(SubscriptionType.Shared) - .receiverQueueSize(1) - .subscribe(); - // Produce messages - final int moreMessages = 10; - for (int i = 0; i < receiverSize + moreMessages; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - // Consume messages - for (int i = 0; i < receiverSize + moreMessages; i++) { - msg = subscriber1.receive(5, TimeUnit.SECONDS); - subscriber1.acknowledge(msg); - } - - // sleep for a second: as ledger.updateCursorRateLimit RateLimiter will allow to invoke cursor-update after a - // second - Thread.sleep(1000); // - // produce-consume one more message to trigger : ledger.internalReadFromLedger(..) which updates cursor and - // EntryCache - producer.send("message".getBytes()); - msg = subscriber1.receive(5, TimeUnit.SECONDS); - - // Verify: as active-subscriber2 has not consumed messages: EntryCache must have those entries in cache - retryStrategically((test) -> entryCache.getSize() > 0, 10, 100); - assertTrue(entryCache.getSize() != 0); - - // 3.b Close subscriber2: which will trigger cache to clear the cache - subscriber2.close(); - - // retry strategically until broker clean up closed subscribers and invalidate all cache entries - retryStrategically((test) -> entryCache.getSize() == 0, 5, 100); - - // Verify: EntryCache should be cleared - assertEquals(entryCache.getSize(), 0); - subscriber1.close(); - log.info("-- Exiting {} test --", methodName); - } - - - @Test(timeOut = 2000) - public void testAsyncProducerAndConsumer() throws Exception { - log.info("-- Starting {} test --", methodName); - - final int totalMsg = 100; - final Set produceMsgs = new HashSet<>(); - final Set consumeMsgs = new HashSet<>(); - - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic1") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .subscribe(); - - // produce message - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic1") - .create(); - for (int i = 0; i < totalMsg; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - produceMsgs.add(message); - } - - log.info(" start receiving messages :"); - CountDownLatch latch = new CountDownLatch(totalMsg); - // receive messages - @Cleanup("shutdownNow") - ExecutorService executor = Executors.newFixedThreadPool(1); - receiveAsync(consumer, totalMsg, 0, latch, consumeMsgs, executor); - - latch.await(); - - // verify message produced correctly - assertEquals(produceMsgs.size(), totalMsg); - // verify produced and consumed messages must be exactly same - produceMsgs.removeAll(consumeMsgs); - assertTrue(produceMsgs.isEmpty()); - - producer.close(); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } - - @Test(timeOut = 2000) - public void testAsyncProducerAndConsumerWithZeroQueueSize() throws Exception { - log.info("-- Starting {} test --", methodName); - - final int totalMsg = 100; - final Set produceMsgs = new HashSet<>(); - final Set consumeMsgs = new HashSet<>(); - - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic1") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .subscribe(); - - // produce message - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic1") - .create(); - for (int i = 0; i < totalMsg; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - produceMsgs.add(message); - } - - log.info(" start receiving messages :"); - CountDownLatch latch = new CountDownLatch(totalMsg); - // receive messages - @Cleanup("shutdownNow") - ExecutorService executor = Executors.newFixedThreadPool(1); - receiveAsync(consumer, totalMsg, 0, latch, consumeMsgs, executor); - - latch.await(); - - // verify message produced correctly - assertEquals(produceMsgs.size(), totalMsg); - // verify produced and consumed messages must be exactly same - produceMsgs.removeAll(consumeMsgs); - assertTrue(produceMsgs.isEmpty()); - - producer.close(); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } - - @Test - public void testSendCallBack() throws Exception { - log.info("-- Starting {} test --", methodName); - - final int totalMsg = 100; - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic1") - .enableBatching(false) - .create(); - for (int i = 0; i < totalMsg; i++) { - final String message = "my-message-" + i; - final AtomicInteger msgLength = new AtomicInteger(); - CompletableFuture future = producer.sendAsync(message.getBytes()).handle((r, ex) -> { - if (ex != null) { - log.error("Message send failed:", ex); - } else { - msgLength.set(message.length()); - } - return null; - }); - future.get(); - assertEquals(message.getBytes().length, msgLength.get()); - } - } - - /** - * consume message from consumer1 and send acknowledgement from different consumer subscribed under same - * subscription-name. - * - * @throws Exception - */ - @Test(timeOut = 30000) - public void testSharedConsumerAckDifferentConsumer() throws Exception { - log.info("-- Starting {} test --", methodName); - - ConsumerBuilder cb = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic1") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Shared) - .acknowledgmentGroupTime(0, TimeUnit.SECONDS) - .receiverQueueSize(1); - Consumer consumer1 = cb.subscribe(); - Consumer consumer2 = cb.subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic1") - .create(); - for (int i = 0; i < 10; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - - Messagemsg = null; - Set> consumerMsgSet1 = new HashSet<>(); - Set> consumerMsgSet2 = new HashSet<>(); - for (int i = 0; i < 5; i++) { - msg = consumer1.receive(); - consumerMsgSet1.add(msg); - - msg = consumer2.receive(); - consumerMsgSet2.add(msg); - } - - consumerMsgSet1.forEach(m -> { - try { - consumer2.acknowledge(m); - } catch (PulsarClientException e) { - fail(); - } - }); - consumerMsgSet2.forEach(m -> { - try { - consumer1.acknowledge(m); - } catch (PulsarClientException e) { - fail(); - } - }); - - consumer1.redeliverUnacknowledgedMessages(); - consumer2.redeliverUnacknowledgedMessages(); - - try { - if (consumer1.receive(100, TimeUnit.MILLISECONDS) != null - || consumer2.receive(100, TimeUnit.MILLISECONDS) != null) { - fail(); - } - } finally { - consumer1.close(); - consumer2.close(); - } - - log.info("-- Exiting {} test --", methodName); - } - - private void receiveAsync(Consumer consumer, int totalMessage, int currentMessage, CountDownLatch latch, - final Set consumeMsg, ExecutorService executor) throws PulsarClientException { - if (currentMessage < totalMessage) { - CompletableFuture> future = consumer.receiveAsync(); - future.handle((msg, exception) -> { - if (exception == null) { - // add message to consumer-queue to verify with produced messages - consumeMsg.add(new String(msg.getData())); - try { - consumer.acknowledge(msg); - } catch (PulsarClientException e1) { - fail("message acknowledge failed", e1); - } - // consume next message - executor.execute(() -> { - try { - receiveAsync(consumer, totalMessage, currentMessage + 1, latch, consumeMsg, executor); - } catch (PulsarClientException e) { - fail("message receive failed", e); - } - }); - latch.countDown(); - } - return null; - }); - } - } - - /** - * Verify: Consumer stops receiving msg when reach unack-msg limit and starts receiving once acks messages 1. - * Produce X (600) messages 2. Consumer has receive size (10) and receive message without acknowledging 3. Consumer - * will stop receiving message after unAckThreshold = 500 4. Consumer acks messages and starts consuming remaining - * messages This testcase enables checksum sending while producing message and broker verifies the checksum for the - * message. - * - * @throws Exception - */ - @Test - public void testConsumerBlockingWithUnAckedMessages() throws Exception { - log.info("-- Starting {} test --", methodName); - - int unAckedMessages = pulsar.getConfiguration().getMaxUnackedMessagesPerConsumer(); - try { - final int unAckedMessagesBufferSize = 500; - final int receiverQueueSize = 10; - final int totalProducedMsgs = 600; - - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessagesBufferSize); - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .subscriptionName("subscriber-1") - .receiverQueueSize(receiverQueueSize) - .subscriptionType(SubscriptionType.Shared) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .create(); - - // (1) Produced Messages - for (int i = 0; i < totalProducedMsgs; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - - // (2) try to consume messages: but will be able to consume number of messages = unAckedMessagesBufferSize - Messagemsg = null; - List> messages = new ArrayList<>(); - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages.add(msg); - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - // client must receive number of messages = unAckedMessagesBufferSize rather all produced messages - assertEquals(messages.size(), unAckedMessagesBufferSize); - - // start acknowledging messages - messages.forEach(m -> { - try { - consumer.acknowledge(m); - } catch (PulsarClientException e) { - fail("ack failed", e); - } - }); - - // try to consume remaining messages - int remainingMessages = totalProducedMsgs - messages.size(); - for (int i = 0; i < remainingMessages; i++) { - msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages.add(msg); - log.info("Received message: " + new String(msg.getData())); - } - } - - // total received-messages should match to produced messages - assertEquals(totalProducedMsgs, messages.size()); - producer.close(); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } catch (Exception e) { - fail(); - } finally { - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessages); - } - } - - /** - * Verify: iteration of a. message receive w/o acking b. stop receiving msg c. ack msgs d. started receiving msgs - * - * 1. Produce total X (1500) messages 2. Consumer consumes messages without acking until stop receiving from broker - * due to reaching ack-threshold (500) 3. Consumer acks messages after stop getting messages 4. Consumer again tries - * to consume messages 5. Consumer should be able to complete consuming all 1500 messages in 3 iteration (1500/500) - * - * @throws Exception - */ - @Test - public void testConsumerBlockingWithUnAckedMessagesMultipleIteration() throws Exception { - log.info("-- Starting {} test --", methodName); - - int unAckedMessages = pulsar.getConfiguration().getMaxUnackedMessagesPerConsumer(); - try { - final int unAckedMessagesBufferSize = 500; - final int receiverQueueSize = 10; - final int totalProducedMsgs = 1500; - - // receiver consumes messages in iteration after acknowledging broker - final int totalReceiveIteration = totalProducedMsgs / unAckedMessagesBufferSize; - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessagesBufferSize); - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .subscriptionName("subscriber-1") - .receiverQueueSize(receiverQueueSize) - .subscriptionType(SubscriptionType.Shared) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .create(); - - // (1) Produced Messages - for (int i = 0; i < totalProducedMsgs; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - - int totalReceivedMessages = 0; - // (2) Receive Messages - for (int j = 0; j < totalReceiveIteration; j++) { - - Messagemsg = null; - List> messages = new ArrayList<>(); - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages.add(msg); - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - // client must receive number of messages = unAckedMessagesBufferSize rather all produced messages - assertEquals(messages.size(), unAckedMessagesBufferSize); - - // start acknowledging messages - messages.forEach(m -> { - try { - consumer.acknowledge(m); - } catch (PulsarClientException e) { - fail("ack failed", e); - } - }); - totalReceivedMessages += messages.size(); - } - - // total received-messages should match to produced messages - assertEquals(totalReceivedMessages, totalProducedMsgs); - producer.close(); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } catch (Exception e) { - fail(); - } finally { - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessages); - } - } - - /** - * Verify: Consumer1 which doesn't send ack will not impact Consumer2 which sends ack for consumed message. - * - * @throws Exception - */ - @Test - public void testMutlipleSharedConsumerBlockingWithUnAckedMessages() throws Exception { - log.info("-- Starting {} test --", methodName); - - int unAckedMessages = pulsar.getConfiguration().getMaxUnackedMessagesPerConsumer(); - try { - final int maxUnackedMessages = 20; - final int receiverQueueSize = 10; - final int totalProducedMsgs = 100; - int totalReceiveMessages = 0; - - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(maxUnackedMessages); - Consumer consumer1 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .subscriptionName("subscriber-1") - .receiverQueueSize(receiverQueueSize) - .subscriptionType(SubscriptionType.Shared) - .subscribe(); - - @Cleanup - PulsarClient newPulsarClient = newPulsarClient(lookupUrl.toString(), 0); // Creates new client connection - Consumer consumer2 = newPulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .subscriptionName("subscriber-1") - .receiverQueueSize(receiverQueueSize) - .subscriptionType(SubscriptionType.Shared) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .create(); - - // (1) Produced Messages - for (int i = 0; i < totalProducedMsgs; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - - // (2) Consumer1: consume without ack: - // try to consume messages: but will be able to consume number of messages = maxUnackedMessages - Messagemsg = null; - List> messages = new ArrayList<>(); - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer1.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages.add(msg); - totalReceiveMessages++; - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - // client must receive number of messages = unAckedMessagesBufferSize rather all produced messages - assertEquals(messages.size(), maxUnackedMessages); - - // (3.1) Consumer2 will start consuming messages without ack: it should stop after maxUnackedMessages - messages.clear(); - for (int i = 0; i < totalProducedMsgs - maxUnackedMessages; i++) { - msg = consumer2.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages.add(msg); - totalReceiveMessages++; - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - assertEquals(messages.size(), maxUnackedMessages); - // (3.2) ack for all maxUnackedMessages - messages.forEach(m -> { - try { - consumer2.acknowledge(m); - } catch (PulsarClientException e) { - fail("shouldn't have failed ", e); - } - }); - - // (4) Consumer2 consumer and ack: so it should consume all remaining messages - messages.clear(); - for (int i = 0; i < totalProducedMsgs - (2 * maxUnackedMessages); i++) { - msg = consumer2.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages.add(msg); - totalReceiveMessages++; - consumer2.acknowledge(msg); - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - - // verify total-consumer messages = total-produce messages - assertEquals(totalProducedMsgs, totalReceiveMessages); - producer.close(); - consumer1.close(); - consumer2.close(); - log.info("-- Exiting {} test --", methodName); - } catch (Exception e) { - fail(); - } finally { - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessages); - } - } - - @Test - public void testShouldNotBlockConsumerIfRedeliverBeforeReceive() throws Exception { - log.info("-- Starting {} test --", methodName); - - int unAckedMessages = pulsar.getConfiguration().getMaxUnackedMessagesPerConsumer(); - int totalReceiveMsg = 0; - try { - final int receiverQueueSize = 20; - final int totalProducedMsgs = 100; - - ConsumerImpl consumer = (ConsumerImpl) pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .subscriptionName("subscriber-1") - .receiverQueueSize(receiverQueueSize) - .ackTimeout(1, TimeUnit.SECONDS) - .subscriptionType(SubscriptionType.Shared) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .enableBatching(false) - .create(); - - // (1) Produced Messages - for (int i = 0; i < totalProducedMsgs; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - - // (2) wait for consumer to receive messages - Thread.sleep(1000); - assertEquals(consumer.numMessagesInQueue(), receiverQueueSize); - - // (3) wait for messages to expire, we should've received more - Thread.sleep(2000); - assertEquals(consumer.numMessagesInQueue(), receiverQueueSize); - - for (int i = 0; i < totalProducedMsgs; i++) { - Messagemsg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - consumer.acknowledge(msg); - totalReceiveMsg++; - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - - // total received-messages should match to produced messages - assertEquals(totalProducedMsgs, totalReceiveMsg); - producer.close(); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } catch (Exception e) { - fail(); - } finally { - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessages); - } - } - - @Test - public void testUnackBlockRedeliverMessages() throws Exception { - log.info("-- Starting {} test --", methodName); - - int unAckedMessages = pulsar.getConfiguration().getMaxUnackedMessagesPerConsumer(); - int totalReceiveMsg = 0; - try { - final int unAckedMessagesBufferSize = 20; - final int receiverQueueSize = 10; - final int totalProducedMsgs = 100; - - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessagesBufferSize); - ConsumerImpl consumer = (ConsumerImpl) pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .subscriptionName("subscriber-1") - .receiverQueueSize(receiverQueueSize) - .subscriptionType(SubscriptionType.Shared) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .create(); - - // (1) Produced Messages - for (int i = 0; i < totalProducedMsgs; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - - // (2) try to consume messages: but will be able to consume number of messages = unAckedMessagesBufferSize - Messagemsg = null; - List> messages = new ArrayList<>(); - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages.add(msg); - totalReceiveMsg++; - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - - consumer.redeliverUnacknowledgedMessages(); - - Thread.sleep(1000); - int alreadyConsumedMessages = messages.size(); - messages.clear(); - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - consumer.acknowledge(msg); - totalReceiveMsg++; - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - - // total received-messages should match to produced messages - assertEquals(totalProducedMsgs + alreadyConsumedMessages, totalReceiveMsg); - producer.close(); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } catch (Exception e) { - fail(); - } finally { - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessages); - } - } - - @Test(dataProvider = "batch") - public void testUnackedBlockAtBatch(int batchMessageDelayMs) throws Exception { - log.info("-- Starting {} test --", methodName); - - int unAckedMessages = pulsar.getConfiguration().getMaxUnackedMessagesPerConsumer(); - try { - final int maxUnackedMessages = 20; - final int receiverQueueSize = 10; - final int totalProducedMsgs = 100; - int totalReceiveMessages = 0; - - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(maxUnackedMessages); - Consumer consumer1 = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .subscriptionName("subscriber-1") - .subscriptionType(SubscriptionType.Shared) - .receiverQueueSize(receiverQueueSize) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .enableBatching(batchMessageDelayMs != 0) - .batchingMaxPublishDelay(BATCHING_MAX_PUBLISH_DELAY_THRESHOLD, TimeUnit.MILLISECONDS) - .batchingMaxMessages(5) - .create(); - - List> futures = new ArrayList<>(); - // (1) Produced Messages - for (int i = 0; i < totalProducedMsgs; i++) { - String message = "my-message-" + i; - futures.add(producer.sendAsync(message.getBytes())); - } - - FutureUtil.waitForAll(futures).get(); - - // (2) Consumer1: consume without ack: - // try to consume messages: but will be able to consume number of messages = maxUnackedMessages - Messagemsg = null; - List> messages = new ArrayList<>(); - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer1.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages.add(msg); - totalReceiveMessages++; - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - // should be blocked due to unack-msgs and should not consume all msgs - assertNotEquals(messages.size(), totalProducedMsgs); - // ack for all maxUnackedMessages - messages.forEach(m -> { - try { - consumer1.acknowledge(m); - } catch (PulsarClientException e) { - fail("shouldn't have failed ", e); - } - }); - - // (3) Consumer consumes and ack: so it should consume all remaining messages - messages.clear(); - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer1.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages.add(msg); - totalReceiveMessages++; - consumer1.acknowledge(msg); - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - // verify total-consumer messages = total-produce messages - assertEquals(totalProducedMsgs, totalReceiveMessages); - producer.close(); - consumer1.close(); - log.info("-- Exiting {} test --", methodName); - } catch (Exception e) { - fail(); - } finally { - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessages); - } - } - - /** - * Verify: Consumer2 sends ack of Consumer1 and consumer1 should be unblock if it is blocked due to unack-messages. - * - * @throws Exception - */ - @Test - public void testBlockUnackConsumerAckByDifferentConsumer() throws Exception { - log.info("-- Starting {} test --", methodName); - - int unAckedMessages = pulsar.getConfiguration().getMaxUnackedMessagesPerConsumer(); - try { - final int maxUnackedMessages = 20; - final int receiverQueueSize = 10; - final int totalProducedMsgs = 100; - int totalReceiveMessages = 0; - - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(maxUnackedMessages); - ConsumerBuilder consumerBuilder = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .subscriptionName("subscriber-1") - .receiverQueueSize(receiverQueueSize) - .subscriptionType(SubscriptionType.Shared); - - Consumer consumer1 = consumerBuilder.subscribe(); - Consumer consumer2 = consumerBuilder.subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .create(); - - // (1) Produced Messages - for (int i = 0; i < totalProducedMsgs; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - - // (2) Consumer1: consume without ack: - // try to consume messages: but will be able to consume number of messages = maxUnackedMessages - Messagemsg = null; - List> messages = new ArrayList<>(); - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer1.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages.add(msg); - totalReceiveMessages++; - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - - assertEquals(messages.size(), maxUnackedMessages); // consumer1 - - // (3) ack for all UnackedMessages from consumer2 - messages.forEach(m -> { - try { - consumer2.acknowledge(m); - } catch (PulsarClientException e) { - fail("shouldn't have failed ", e); - } - }); - - // (4) consumer1 will consumer remaining msgs and consumer2 will ack those messages - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer1.receive(1, TimeUnit.SECONDS); - if (msg != null) { - totalReceiveMessages++; - consumer2.acknowledge(msg); - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer2.receive(1, TimeUnit.SECONDS); - if (msg != null) { - totalReceiveMessages++; - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - - // verify total-consumer messages = total-produce messages - assertEquals(totalProducedMsgs, totalReceiveMessages); - producer.close(); - consumer1.close(); - consumer2.close(); - log.info("-- Exiting {} test --", methodName); - } catch (Exception e) { - fail(); - } finally { - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessages); - } - } - - @Test - public void testEnabledChecksumClient() throws Exception { - log.info("-- Starting {} test --", methodName); - - final int totalMsg = 10; - - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/my-topic1") - .subscriptionName("my-subscriber-name") - .subscribe(); - - final int batchMessageDelayMs = 300; - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic1") - .enableBatching(true) - .batchingMaxPublishDelay(batchMessageDelayMs, TimeUnit.MILLISECONDS) - .batchingMaxMessages(5) - .create(); - - for (int i = 0; i < totalMsg; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - - Messagemsg = null; - Set messageSet = new HashSet<>(); - for (int i = 0; i < totalMsg; i++) { - msg = consumer.receive(5, TimeUnit.SECONDS); - String receivedMessage = new String(msg.getData()); - log.debug("Received message: [{}]", receivedMessage); - String expectedMessage = "my-message-" + i; - testMessageOrderAndDuplicates(messageSet, receivedMessage, expectedMessage); - } - // Acknowledge the consumption of all messages at once - consumer.acknowledgeCumulative(msg); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } - - /** - * It verifies that redelivery-of-specific messages: that redelivers all those messages even when consumer gets - * blocked due to unacked messages. - * - * Usecase: produce message with 10ms interval: so, consumer can consume only 10 messages without acking - * - * @throws Exception - */ - @Test - public void testBlockUnackedConsumerRedeliverySpecificMessagesProduceWithPause() throws Exception { - log.info("-- Starting {} test --", methodName); - - int unAckedMessages = pulsar.getConfiguration().getMaxUnackedMessagesPerConsumer(); - try { - final int unAckedMessagesBufferSize = 10; - final int receiverQueueSize = 20; - final int totalProducedMsgs = 20; - - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessagesBufferSize); - ConsumerImpl consumer = (ConsumerImpl) pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .subscriptionName("subscriber-1") - .subscriptionType(SubscriptionType.Shared) - .receiverQueueSize(receiverQueueSize) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .create(); - - // (1) Produced Messages - for (int i = 0; i < totalProducedMsgs; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - Thread.sleep(10); - } - - // (2) try to consume messages: but will be able to consume number of messages = unAckedMessagesBufferSize - Messagemsg = null; - List> messages1 = new ArrayList<>(); - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages1.add(msg); - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - - // client should not receive all produced messages and should be blocked due to unack-messages - assertEquals(messages1.size(), unAckedMessagesBufferSize); - Set redeliveryMessages = messages1.stream().map(m -> { - return (MessageIdImpl) m.getMessageId(); - }).collect(Collectors.toSet()); - - // (3) redeliver all consumed messages - consumer.redeliverUnacknowledgedMessages(Sets.newHashSet(redeliveryMessages)); - Thread.sleep(1000); - - Set messages2 = new HashSet<>(); - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages2.add((MessageIdImpl) msg.getMessageId()); - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - - assertEquals(messages1.size(), messages2.size()); - // (4) Verify: redelivered all previous unacked-consumed messages - messages2.removeAll(redeliveryMessages); - assertEquals(messages2.size(), 0); - producer.close(); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } catch (Exception e) { - fail(); - } finally { - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessages); - } - } - - /** - * It verifies that redelivery-of-specific messages: that redelivers all those messages even when consumer gets - * blocked due to unacked messages - * - * Usecase: Consumer starts consuming only after all messages have been produced. So, consumer consumes total - * receiver-queue-size number messages => ask for redelivery and receives all messages again. - * - * @throws Exception - */ - @Test - public void testBlockUnackedConsumerRedeliverySpecificMessagesCloseConsumerWhileProduce() throws Exception { - log.info("-- Starting {} test --", methodName); - - int unAckedMessages = pulsar.getConfiguration().getMaxUnackedMessagesPerConsumer(); - try { - final int unAckedMessagesBufferSize = 10; - final int receiverQueueSize = 20; - final int totalProducedMsgs = 50; - - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessagesBufferSize); - // Only subscribe consumer - ConsumerImpl consumer = (ConsumerImpl) pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .subscriptionName("subscriber-1") - .receiverQueueSize(receiverQueueSize) - .subscriptionType(SubscriptionType.Shared) - .subscribe(); - consumer.close(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .create(); - - // (1) Produced Messages - for (int i = 0; i < totalProducedMsgs; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - Thread.sleep(10); - } - - // (1.a) start consumer again - consumer = (ConsumerImpl) pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .receiverQueueSize(receiverQueueSize) - .subscriptionName("subscriber-1") - .subscriptionType(SubscriptionType.Shared) - .subscribe(); - - // (2) try to consume messages: but will be able to consume number of messages = unAckedMessagesBufferSize - Messagemsg = null; - List> messages1 = new ArrayList<>(); - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages1.add(msg); - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - - // client should not receive all produced messages and should be blocked due to unack-messages - assertEquals(messages1.size(), unAckedMessagesBufferSize); - Set redeliveryMessages = messages1.stream().map(m -> { - return (MessageIdImpl) m.getMessageId(); - }).collect(Collectors.toSet()); - - // (3) redeliver all consumed messages - consumer.redeliverUnacknowledgedMessages(Sets.newHashSet(redeliveryMessages)); - Thread.sleep(1000); - - Set messages2 = new HashSet<>(); - for (int i = 0; i < totalProducedMsgs; i++) { - msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages2.add((MessageIdImpl) msg.getMessageId()); - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - - assertEquals(messages1.size(), messages2.size()); - // (4) Verify: redelivered all previous unacked-consumed messages - messages2.removeAll(redeliveryMessages); - assertEquals(messages2.size(), 0); - producer.close(); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } catch (Exception e) { - fail(); - } finally { - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(unAckedMessages); - } - } - - @Test - public void testPriorityConsumer() throws Exception { - log.info("-- Starting {} test --", methodName); - - @Cleanup - PulsarClient newPulsarClient = newPulsarClient(lookupUrl.toString(), 0); // Creates new client connection - Consumer consumer1 = - newPulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic2") - .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Shared) - .priorityLevel(1).receiverQueueSize(5).subscribe(); - - @Cleanup - PulsarClient newPulsarClient1 = newPulsarClient(lookupUrl.toString(), 0); // Creates new client connection - Consumer consumer2 = - newPulsarClient1.newConsumer().topic("persistent://my-property/use/my-ns/my-topic2") - .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Shared) - .priorityLevel(1).receiverQueueSize(5).subscribe(); - - @Cleanup - PulsarClient newPulsarClient2 = newPulsarClient(lookupUrl.toString(), 0); // Creates new client connection - Consumer consumer3 = - newPulsarClient2.newConsumer().topic("persistent://my-property/use/my-ns/my-topic2") - .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Shared) - .priorityLevel(1).receiverQueueSize(5).subscribe(); - - @Cleanup - PulsarClient newPulsarClient3 = newPulsarClient(lookupUrl.toString(), 0); // Creates new client connection - Consumer consumer4 = - newPulsarClient3.newConsumer().topic("persistent://my-property/use/my-ns/my-topic2") - .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Shared) - .priorityLevel(2).receiverQueueSize(5).subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic2") - .create(); - List> futures = new ArrayList<>(); - - // Asynchronously produce messages - for (int i = 0; i < 15; i++) { - final String message = "my-message-" + i; - Future future = producer.sendAsync(message.getBytes()); - futures.add(future); - } - - log.info("Waiting for async publish to complete"); - for (Future future : futures) { - future.get(); - } - - for (int i = 0; i < 20; i++) { - consumer1.receive(100, TimeUnit.MILLISECONDS); - consumer2.receive(100, TimeUnit.MILLISECONDS); - } - - /** - * a. consumer1 and consumer2 now has more permits (as received and sent more permits) b. try to produce more - * messages: which will again distribute among consumer1 and consumer2 and should not dispatch to consumer4 - * - */ - for (int i = 0; i < 5; i++) { - final String message = "my-message-" + i; - Future future = producer.sendAsync(message.getBytes()); - futures.add(future); - } - - Assert.assertNull(consumer4.receive(100, TimeUnit.MILLISECONDS)); - - // Asynchronously acknowledge upto and including the last message - producer.close(); - consumer1.close(); - consumer2.close(); - consumer3.close(); - consumer4.close(); - log.info("-- Exiting {} test --", methodName); - } - - /** - *
-     * Verifies Dispatcher dispatches messages properly with shared-subscription consumers with combination of blocked
-     * and unblocked consumers.
-     *
-     * 1. Dispatcher will have 5 consumers : c1, c2, c3, c4, c5.
-     *      Out of which : c1,c2,c4,c5 will be blocked due to MaxUnackedMessages limit.
-     * 2. So, dispatcher should moves round-robin and make sure it delivers unblocked consumer : c3
-     * 
- * - * @throws Exception - */ - @Test - public void testSharedSamePriorityConsumer() throws Exception { - log.info("-- Starting {} test --", methodName); - - final int queueSize = 5; - int maxUnAckMsgs = pulsar.getConfiguration().getMaxConcurrentLookupRequest(); - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(queueSize); - - Consumer c1 = pulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic2") - .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Shared) - .receiverQueueSize(queueSize).subscribe(); - - @Cleanup - PulsarClient newPulsarClient = newPulsarClient(lookupUrl.toString(), 0); // Creates new client connection - Consumer c2 = newPulsarClient.newConsumer().topic("persistent://my-property/use/my-ns/my-topic2") - .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Shared) - .receiverQueueSize(queueSize).subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/my-topic2") - .enableBatching(false) - .create(); - List> futures = new ArrayList<>(); - - // Asynchronously produce messages - final int totalPublishMessages = 500; - for (int i = 0; i < totalPublishMessages; i++) { - final String message = "my-message-" + i; - Future future = producer.sendAsync(message.getBytes()); - futures.add(future); - } - - log.info("Waiting for async publish to complete"); - for (Future future : futures) { - future.get(); - } - - List> messages = new ArrayList<>(); - - // let consumer1 and consumer2 cosume messages up to the queue will be full - for (int i = 0; i < totalPublishMessages; i++) { - Messagemsg = c1.receive(500, TimeUnit.MILLISECONDS); - if (msg != null) { - messages.add(msg); - } else { - break; - } - } - for (int i = 0; i < totalPublishMessages; i++) { - Messagemsg = c2.receive(500, TimeUnit.MILLISECONDS); - if (msg != null) { - messages.add(msg); - } else { - break; - } - } - - Assert.assertEquals(queueSize * 2, messages.size()); - - // create new consumers with the same priority - @Cleanup - PulsarClient newPulsarClient1 = newPulsarClient(lookupUrl.toString(), 0); // Creates new client connection - Consumer c3 = newPulsarClient1.newConsumer().topic("persistent://my-property/use/my-ns/my-topic2") - .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Shared) - .receiverQueueSize(queueSize).subscribe(); - - @Cleanup - PulsarClient newPulsarClient2 = newPulsarClient(lookupUrl.toString(), 0); // Creates new client connection - Consumer c4 = newPulsarClient2.newConsumer().topic("persistent://my-property/use/my-ns/my-topic2") - .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Shared) - .receiverQueueSize(queueSize).subscribe(); - - @Cleanup - PulsarClient newPulsarClient3 = newPulsarClient(lookupUrl.toString(), 0); // Creates new client connection - Consumer c5 = newPulsarClient3.newConsumer().topic("persistent://my-property/use/my-ns/my-topic2") - .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Shared) - .receiverQueueSize(queueSize).subscribe(); - - // c1 and c2 are blocked: so, let c3, c4 and c5 consume rest of the messages - - for (int i = 0; i < totalPublishMessages; i++) { - Messagemsg = c4.receive(500, TimeUnit.MILLISECONDS); - if (msg != null) { - messages.add(msg); - } else { - break; - } - } - - for (int i = 0; i < totalPublishMessages; i++) { - Messagemsg = c5.receive(500, TimeUnit.MILLISECONDS); - if (msg != null) { - messages.add(msg); - } else { - break; - } - } - - for (int i = 0; i < totalPublishMessages; i++) { - Message msg = c3.receive(500, TimeUnit.MILLISECONDS); - if (msg != null) { - messages.add(msg); - c3.acknowledge(msg); - } else { - break; - } - } - - // total messages must be consumed by all consumers - Assert.assertEquals(messages.size(), totalPublishMessages); - - // Asynchronously acknowledge upto and including the last message - producer.close(); - c1.close(); - c2.close(); - c3.close(); - c4.close(); - c5.close(); - pulsar.getConfiguration().setMaxUnackedMessagesPerConsumer(maxUnAckMsgs); - log.info("-- Exiting {} test --", methodName); - } - - @Test - public void testRedeliveryFailOverConsumer() throws Exception { - log.info("-- Starting {} test --", methodName); - - final int receiverQueueSize = 10; - - // Only subscribe consumer - ConsumerImpl consumer = (ConsumerImpl) pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .subscriptionName("subscriber-1") - .receiverQueueSize(receiverQueueSize) - .subscriptionType(SubscriptionType.Failover) - .acknowledgmentGroupTime(0, TimeUnit.SECONDS) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/unacked-topic") - .create(); - - // (1) First round to produce-consume messages - int consumeMsgInParts = 4; - for (int i = 0; i < receiverQueueSize; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - Thread.sleep(10); - } - // (1.a) consume first consumeMsgInParts msgs and trigger redeliver - Message msg = null; - List> messages1 = new ArrayList<>(); - for (int i = 0; i < consumeMsgInParts; i++) { - msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages1.add(msg); - consumer.acknowledge(msg); - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - assertEquals(messages1.size(), consumeMsgInParts); - consumer.redeliverUnacknowledgedMessages(); - - // (1.b) consume second consumeMsgInParts msgs and trigger redeliver - messages1.clear(); - for (int i = 0; i < consumeMsgInParts; i++) { - msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages1.add(msg); - consumer.acknowledge(msg); - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - assertEquals(messages1.size(), consumeMsgInParts); - consumer.redeliverUnacknowledgedMessages(); - - // (2) Second round to produce-consume messages - for (int i = 0; i < receiverQueueSize; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - Thread.sleep(100); - } - - int remainingMsgs = (2 * receiverQueueSize) - (2 * consumeMsgInParts); - messages1.clear(); - for (int i = 0; i < remainingMsgs; i++) { - msg = consumer.receive(1, TimeUnit.SECONDS); - if (msg != null) { - messages1.add(msg); - consumer.acknowledge(msg); - log.info("Received message: " + new String(msg.getData())); - } else { - break; - } - } - assertEquals(messages1.size(), remainingMsgs); - - producer.close(); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - - } - - @Test(timeOut = 5000) - public void testFailReceiveAsyncOnConsumerClose() throws Exception { - log.info("-- Starting {} test --", methodName); - - // (1) simple consumers - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/failAsyncReceive-1") - .subscriptionName("my-subscriber-name") - .subscribe(); - consumer.close(); - // receive messages - try { - consumer.receiveAsync().get(1, TimeUnit.SECONDS); - fail("it should have failed because consumer is already closed"); - } catch (ExecutionException e) { - assertTrue(e.getCause() instanceof PulsarClientException.AlreadyClosedException); - } - - // (2) Partitioned-consumer - int numPartitions = 4; - TopicName topicName = TopicName.get("persistent://my-property/use/my-ns/failAsyncReceive-2"); - admin.topics().createPartitionedTopic(topicName.toString(), numPartitions); - Consumer partitionedConsumer = pulsarClient.newConsumer().topic(topicName.toString()) - .subscriptionName("my-partitioned-subscriber") - .subscribe(); - partitionedConsumer.close(); - // receive messages - try { - partitionedConsumer.receiveAsync().get(1, TimeUnit.SECONDS); - fail("it should have failed because consumer is already closed"); - } catch (ExecutionException e) { - assertTrue(e.getCause() instanceof PulsarClientException.AlreadyClosedException); - } - - log.info("-- Exiting {} test --", methodName); - } - - @Test - public void testECDSAEncryption() throws Exception { - log.info("-- Starting {} test --", methodName); - - class EncKeyReader implements CryptoKeyReader { - - EncryptionKeyInfo keyInfo = new EncryptionKeyInfo(); - - @Override - public EncryptionKeyInfo getPublicKey(String keyName, Map keyMeta) { - String certFilePath = "./src/test/resources/certificate/public-key." + keyName; - if (Files.isReadable(Paths.get(certFilePath))) { - try { - keyInfo.setKey(Files.readAllBytes(Paths.get(certFilePath))); - return keyInfo; - } catch (IOException e) { - Assert.fail("Failed to read certificate from " + certFilePath); - } - } else { - Assert.fail("Certificate file " + certFilePath + " is not present or not readable."); - } - return null; - } - - @Override - public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMeta) { - String certFilePath = "./src/test/resources/certificate/private-key." + keyName; - if (Files.isReadable(Paths.get(certFilePath))) { - try { - keyInfo.setKey(Files.readAllBytes(Paths.get(certFilePath))); - return keyInfo; - } catch (IOException e) { - Assert.fail("Failed to read certificate from " + certFilePath); - } - } else { - Assert.fail("Certificate file " + certFilePath + " is not present or not readable."); - } - return null; - } - } - - final int totalMsg = 10; - - Set messageSet = new HashSet<>(); - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/myecdsa-topic1") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .cryptoKeyReader(new EncKeyReader()) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/myecdsa-topic1") - .addEncryptionKey("client-ecdsa.pem") - .cryptoKeyReader(new EncKeyReader()) - .create(); - for (int i = 0; i < totalMsg; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - - Message msg = null; - - for (int i = 0; i < totalMsg; i++) { - msg = consumer.receive(5, TimeUnit.SECONDS); - String receivedMessage = new String(msg.getData()); - log.debug("Received message: [{}]", receivedMessage); - String expectedMessage = "my-message-" + i; - testMessageOrderAndDuplicates(messageSet, receivedMessage, expectedMessage); - } - // Acknowledge the consumption of all messages at once - consumer.acknowledgeCumulative(msg); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } - - @Test - public void testRSAEncryption() throws Exception { - log.info("-- Starting {} test --", methodName); - - class EncKeyReader implements CryptoKeyReader { - - EncryptionKeyInfo keyInfo = new EncryptionKeyInfo(); - - @Override - public EncryptionKeyInfo getPublicKey(String keyName, Map keyMeta) { - String certFilePath = "./src/test/resources/certificate/public-key." + keyName; - if (Files.isReadable(Paths.get(certFilePath))) { - try { - keyInfo.setKey(Files.readAllBytes(Paths.get(certFilePath))); - return keyInfo; - } catch (IOException e) { - Assert.fail("Failed to read certificate from " + certFilePath); - } - } else { - Assert.fail("Certificate file " + certFilePath + " is not present or not readable."); - } - return null; - } - - @Override - public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMeta) { - String certFilePath = "./src/test/resources/certificate/private-key." + keyName; - if (Files.isReadable(Paths.get(certFilePath))) { - try { - keyInfo.setKey(Files.readAllBytes(Paths.get(certFilePath))); - return keyInfo; - } catch (IOException e) { - Assert.fail("Failed to read certificate from " + certFilePath); - } - } else { - Assert.fail("Certificate file " + certFilePath + " is not present or not readable."); - } - return null; - } - } - - final int totalMsg = 10; - - Set messageSet = new HashSet<>(); - Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/my-ns/myrsa-topic1") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .cryptoKeyReader(new EncKeyReader()) - .subscribe(); - - Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/myrsa-topic1") - .addEncryptionKey("client-rsa.pem") - .cryptoKeyReader(new EncKeyReader()) - .create(); - Producer producer2 = pulsarClient.newProducer() - .topic("persistent://my-property/use/my-ns/myrsa-topic1") - .addEncryptionKey("client-rsa.pem") - .cryptoKeyReader(new EncKeyReader()) - .create(); - for (int i = 0; i < totalMsg; i++) { - String message = "my-message-" + i; - producer.send(message.getBytes()); - } - for (int i = totalMsg; i < totalMsg * 2; i++) { - String message = "my-message-" + i; - producer2.send(message.getBytes()); - } - - Message msg = null; - - for (int i = 0; i < totalMsg * 2; i++) { - msg = consumer.receive(5, TimeUnit.SECONDS); - String receivedMessage = new String(msg.getData()); - log.debug("Received message: [{}]", receivedMessage); - String expectedMessage = "my-message-" + i; - testMessageOrderAndDuplicates(messageSet, receivedMessage, expectedMessage); - } - // Acknowledge the consumption of all messages at once - consumer.acknowledgeCumulative(msg); - consumer.close(); - log.info("-- Exiting {} test --", methodName); - } - - @Test - public void testEncryptionFailure() throws Exception { - log.info("-- Starting {} test --", methodName); - - class EncKeyReader implements CryptoKeyReader { - - EncryptionKeyInfo keyInfo = new EncryptionKeyInfo(); - - @Override - public EncryptionKeyInfo getPublicKey(String keyName, Map keyMeta) { - String certFilePath = "./src/test/resources/certificate/public-key." + keyName; - if (Files.isReadable(Paths.get(certFilePath))) { - try { - keyInfo.setKey(Files.readAllBytes(Paths.get(certFilePath))); - return keyInfo; - } catch (IOException e) { - log.error("Failed to read certificate from {}", certFilePath); - } - } - return null; - } - - @Override - public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMeta) { - String certFilePath = "./src/test/resources/certificate/private-key." + keyName; - if (Files.isReadable(Paths.get(certFilePath))) { - try { - keyInfo.setKey(Files.readAllBytes(Paths.get(certFilePath))); - return keyInfo; - } catch (IOException e) { - log.error("Failed to read certificate from {}", certFilePath); - } - } - return null; - } - } - - final int totalMsg = 10; - - Message msg = null; - Set messageSet = new HashSet<>(); - Consumer consumer = pulsarClient.newConsumer(Schema.STRING) - .topic("persistent://my-property/use/my-ns/myenc-topic1") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .subscribe(); - - try { - // 1. Invalid key name - pulsarClient.newProducer(Schema.STRING) - .topic("persistent://my-property/use/myenc-ns/myenc-topic1") - .enableBatching(false) - .addEncryptionKey("client-non-existant-rsa.pem") - .cryptoKeyReader(new EncKeyReader()) - .create(); - Assert.fail("Producer creation should not succeed if failing to read key"); - } catch (Exception e) { - // ok - } - - // 2. Producer with valid key name - Producer producer = pulsarClient.newProducer(Schema.STRING) - .topic("persistent://my-property/use/my-ns/myenc-topic1") - .enableBatching(false) - .addEncryptionKey("client-rsa.pem") - .cryptoKeyReader(new EncKeyReader()) - .create(); - - for (int i = 0; i < totalMsg; i++) { - producer.send("my-message-" + i); - } - - // 3. KeyReder is not set by consumer - // Receive should fail since key reader is not setup - msg = consumer.receive(5, TimeUnit.SECONDS); - Assert.assertNull(msg, "Receive should have failed with no keyreader"); - - // 4. Set consumer config to consume even if decryption fails - consumer.close(); - consumer = pulsarClient.newConsumer(Schema.STRING) - .topic("persistent://my-property/use/my-ns/myenc-topic1") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .cryptoFailureAction(ConsumerCryptoFailureAction.CONSUME) - .subscribe(); - - int msgNum = 0; - try { - // Receive should proceed and deliver encrypted message - msg = consumer.receive(5, TimeUnit.SECONDS); - String receivedMessage = msg.getValue(); - String expectedMessage = "my-message-" + (msgNum++); - Assert.assertNotEquals(receivedMessage, expectedMessage, "Received encrypted message " + receivedMessage - + " should not match the expected message " + expectedMessage); - consumer.acknowledgeCumulative(msg); - } catch (Exception e) { - Assert.fail("Failed to receive message even aftet ConsumerCryptoFailureAction.CONSUME is set."); - } - - // 5. Set keyreader and failure action - consumer.close(); - consumer = pulsarClient.newConsumer(Schema.STRING) - .topic("persistent://my-property/use/my-ns/myenc-topic1") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .cryptoKeyReader(new EncKeyReader()) - .cryptoFailureAction(ConsumerCryptoFailureAction.FAIL) - .subscribe(); - - for (int i = msgNum; i < totalMsg - 1; i++) { - msg = consumer.receive(5, TimeUnit.SECONDS); - String receivedMessage = msg.getValue(); - log.debug("Received message: [{}]", receivedMessage); - String expectedMessage = "my-message-" + i; - testMessageOrderAndDuplicates(messageSet, receivedMessage, expectedMessage); - } - // Acknowledge the consumption of all messages at once - consumer.acknowledgeCumulative(msg); - consumer.close(); - - // 6. Set consumer config to discard if decryption fails - consumer.close(); - consumer = pulsarClient.newConsumer(Schema.STRING) - .topic("persistent://my-property/use/my-ns/myenc-topic1") - .subscriptionName("my-subscriber-name") - .subscriptionType(SubscriptionType.Exclusive) - .cryptoFailureAction(ConsumerCryptoFailureAction.DISCARD) - .subscribe(); - - // Receive should proceed and discard encrypted messages - msg = consumer.receive(5, TimeUnit.SECONDS); - Assert.assertNull(msg, "Message received even after ConsumerCryptoFailureAction.DISCARD is set."); - - log.info("-- Exiting {} test --", methodName); - } - -} diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/BrokerClientIntegrationTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/BrokerClientIntegrationTest.java index 6b5fa99b5e8f2..ac426bb2f8f58 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/BrokerClientIntegrationTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/BrokerClientIntegrationTest.java @@ -94,7 +94,6 @@ import org.apache.pulsar.client.impl.schema.writer.JacksonJsonWriter; import org.apache.pulsar.common.naming.NamespaceBundle; import org.apache.pulsar.common.naming.TopicName; -import org.apache.pulsar.common.policies.data.ClusterData; import org.apache.pulsar.common.policies.data.PersistentTopicInternalStats; import org.apache.pulsar.common.policies.data.RetentionPolicies; import org.apache.pulsar.common.protocol.PulsarHandler; @@ -529,7 +528,7 @@ public void testResetCursor(SubscriptionType subType) throws Exception { */ @Test public void testMaxConcurrentTopicLoading() throws Exception { - final String topicName = "persistent://prop/usw/my-ns/cocurrentLoadingTopic"; + final String topicName = "persistent://my-property/my-ns/cocurrentLoadingTopic"; int concurrentTopic = pulsar.getConfiguration().getMaxConcurrentTopicLoadRequest(); final int concurrentLookupRequests = 20; @Cleanup("shutdownNow") @@ -588,7 +587,7 @@ public void testMaxConcurrentTopicLoading() throws Exception { @Test public void testCloseConnectionOnInternalServerError() throws Exception { - final String topicName = "persistent://prop/usw/my-ns/newTopic"; + final String topicName = "persistent://my-property/my-ns/newTopic"; @Cleanup final PulsarClient pulsarClient = PulsarClient.builder() @@ -664,15 +663,12 @@ public long getTimestamp() { public void testCleanProducer() throws Exception { log.info("-- Starting {} test --", methodName); - admin.clusters().createCluster("global", ClusterData.builder().build()); - admin.namespaces().createNamespace("my-property/global/lookup"); - final int operationTimeOut = 500; @Cleanup PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(lookupUrl.toString()) .statsInterval(0, TimeUnit.SECONDS).operationTimeout(operationTimeOut, TimeUnit.MILLISECONDS).build(); CountDownLatch latch = new CountDownLatch(1); - pulsarClient.newProducer().topic("persistent://my-property/global/lookup/my-topic1").createAsync() + pulsarClient.newProducer().topic("persistent://my-property/lookup/my-topic1").createAsync() .handle((producer, e) -> { latch.countDown(); return null; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/ConnectionPoolTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/ConnectionPoolTest.java index d739d93f1bf18..5d8fc9fb56ef9 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/ConnectionPoolTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/ConnectionPoolTest.java @@ -59,6 +59,7 @@ public class ConnectionPoolTest extends MockedPulsarServiceBaseTest { @Override protected void setup() throws Exception { super.internalSetup(); + setupDefaultTenantAndNamespace(); brokerPort = pulsar.getBrokerListenPort().get(); serviceUrl = "pulsar://non-existing-dns-name:" + brokerPort; } @@ -88,7 +89,7 @@ public void testSingleIpAddress() throws Exception { brokerPort))) .thenReturn(CompletableFuture.completedFuture(result)); - client.newProducer().topic("persistent://sample/standalone/ns/my-topic").create(); + client.newProducer().topic("persistent://public/default/my-topic").create(); client.close(); eventLoop.shutdownGracefully(); @@ -96,7 +97,7 @@ public void testSingleIpAddress() throws Exception { @Test public void testSelectConnectionForSameProducer() throws Exception { - final String topicName = BrokerTestUtil.newUniqueName("persistent://sample/standalone/ns/tp_"); + final String topicName = BrokerTestUtil.newUniqueName("persistent://public/default/tp_"); admin.topics().createNonPartitionedTopic(topicName); final CommandCloseProducer commandCloseProducer = new CommandCloseProducer(); // 10 connection per broker. @@ -146,7 +147,7 @@ public void testDoubleIpAddress() throws Exception { .thenReturn(CompletableFuture.completedFuture(result)); // Create producer should succeed by trying the 2nd IP - client.newProducer().topic("persistent://sample/standalone/ns/my-topic").create(); + client.newProducer().topic("persistent://public/default/my-topic").create(); client.close(); eventLoop.shutdownGracefully(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/ConsumerConfigurationTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/ConsumerConfigurationTest.java index 7b37d78c2e0ac..98237c60e8031 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/ConsumerConfigurationTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/ConsumerConfigurationTest.java @@ -30,18 +30,18 @@ @Test(groups = "broker-impl") public class ConsumerConfigurationTest extends MockedPulsarServiceBaseTest { - private static String persistentTopic = "persistent://my-property/use/my-ns/persist"; - private static String nonPersistentTopic = "non-persistent://my-property/use/my-ns/nopersist"; + private static String persistentTopic = "persistent://my-property/my-ns/persist"; + private static String nonPersistentTopic = "non-persistent://my-property/my-ns/nopersist"; @BeforeMethod @Override public void setup() throws Exception { super.internalSetup(); - admin.clusters().createCluster("use", ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); + admin.clusters().createCluster("test", ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); admin.tenants().createTenant("my-property", - new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("use"))); - admin.namespaces().createNamespace("my-property/use/my-ns"); + new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("test"))); + admin.namespaces().createNamespace("my-property/my-ns"); } @AfterMethod(alwaysRun = true) diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/KeyStoreTlsProducerConsumerTestWithAuthTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/KeyStoreTlsProducerConsumerTestWithAuthTest.java index 47e1e27f5f303..41b31315454e5 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/KeyStoreTlsProducerConsumerTestWithAuthTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/KeyStoreTlsProducerConsumerTestWithAuthTest.java @@ -199,7 +199,7 @@ public void testTlsLargeSizeMessage() throws Exception { final int messageSize = 16 * 1024 + 1; log.info("-- message size -- {}", messageSize); - String topicName = "persistent://my-property/use/my-ns/testTlsLargeSizeMessage" + String topicName = "persistent://my-property/my-ns/testTlsLargeSizeMessage" + System.currentTimeMillis(); internalSetUpForClient(true, pulsar.getBrokerServiceUrlTls()); @@ -235,7 +235,7 @@ public void testTlsClientAuthOverBinaryProtocol() throws Exception { final int messageSize = 16 * 1024 + 1; log.info("-- message size -- {}", messageSize); - String topicName = "persistent://my-property/use/my-ns/testTlsClientAuthOverBinaryProtocol" + String topicName = "persistent://my-property/my-ns/testTlsClientAuthOverBinaryProtocol" + System.currentTimeMillis(); internalSetUpForNamespace(); @@ -268,7 +268,7 @@ public void testTlsClientAuthOverHTTPProtocol() throws Exception { final int messageSize = 16 * 1024 + 1; log.info("-- message size -- {}", messageSize); - String topicName = "persistent://my-property/use/my-ns/testTlsClientAuthOverHTTPProtocol" + String topicName = "persistent://my-property/my-ns/testTlsClientAuthOverHTTPProtocol" + System.currentTimeMillis(); internalSetUpForNamespace(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/KeyStoreTlsProducerConsumerTestWithoutAuthTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/KeyStoreTlsProducerConsumerTestWithoutAuthTest.java index cfccd25df3f76..989b63b9378c9 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/KeyStoreTlsProducerConsumerTestWithoutAuthTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/KeyStoreTlsProducerConsumerTestWithoutAuthTest.java @@ -148,7 +148,7 @@ public void testTlsLargeSizeMessage() throws Exception { final int messageSize = 16 * 1024 + 1; log.info("-- message size -- {}", messageSize); - String topicName = "persistent://my-property/use/my-ns/testTlsLargeSizeMessage" + String topicName = "persistent://my-property/my-ns/testTlsLargeSizeMessage" + System.currentTimeMillis(); internalSetUpForClient(true, pulsar.getBrokerServiceUrlTls()); @@ -184,7 +184,7 @@ public void testTlsClientAuthOverBinaryProtocol() throws Exception { final int messageSize = 16 * 1024 + 1; log.info("-- message size -- {}", messageSize); - String topicName = "persistent://my-property/use/my-ns/testTlsClientAuthOverBinaryProtocol" + String topicName = "persistent://my-property/my-ns/testTlsClientAuthOverBinaryProtocol" + System.currentTimeMillis(); internalSetUpForNamespace(); @@ -216,7 +216,7 @@ public void testTlsClientAuthOverHTTPProtocol() throws Exception { final int messageSize = 16 * 1024 + 1; log.info("-- message size -- {}", messageSize); - String topicName = "persistent://my-property/use/my-ns/testTlsClientAuthOverHTTPProtocol" + String topicName = "persistent://my-property/my-ns/testTlsClientAuthOverHTTPProtocol" + System.currentTimeMillis(); internalSetUpForNamespace(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/MessageChecksumTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/MessageChecksumTest.java index dfd30ad371bc3..c475e8aa61c1a 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/MessageChecksumTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/MessageChecksumTest.java @@ -116,7 +116,7 @@ public void testChecksumCompatibilityInMixedVersionBrokerCluster(MixedVersionSce throws Exception { // GIVEN final String topicName = - "persistent://prop/use/ns-abc/testChecksumBackwardsCompatibilityWithOldBrokerWithoutChecksumHandling"; + "persistent://prop/ns-abc/testChecksumBackwardsCompatibilityWithOldBrokerWithoutChecksumHandling"; if (mixedVersionScenario == MixedVersionScenario.CONNECTED_TO_OLD_THEN_NEW_VERSION) { // Given, the client thinks it's connected to a broker that doesn't support message checksums @@ -220,7 +220,7 @@ private void waitUntilMessageIsPendingWithCalculatedChecksum(ProducerImpl pro public void testTamperingMessageIsDetected() throws Exception { // GIVEN ProducerImpl producer = (ProducerImpl) pulsarClient.newProducer() - .topic("persistent://prop/use/ns-abc/testTamperingMessageIsDetected") + .topic("persistent://prop/ns-abc/testTamperingMessageIsDetected") .enableBatching(false) .messageRoutingMode(MessageRoutingMode.SinglePartition) .create(); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/MessageChunkingTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/MessageChunkingTest.java index d8a3698636d92..84c2d3b5b98ce 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/MessageChunkingTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/MessageChunkingTest.java @@ -437,7 +437,7 @@ public void testResendChunkMessages() throws Exception { @Test public void testExpireIncompleteChunkMessage() throws Exception{ - final String topicName = "persistent://prop/use/ns-abc/expireMsg"; + final String topicName = "persistent://my-property/my-ns/expireMsg"; // 1. producer connect ProducerImpl producer = (ProducerImpl) pulsarClient.newProducer() diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/MessageIdTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/MessageIdTest.java index 375bbff8a4df4..ea399af2bc2ab 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/MessageIdTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/MessageIdTest.java @@ -62,7 +62,7 @@ protected void cleanup() throws Exception { public void producerSendAsync(TopicType topicType) throws PulsarClientException, PulsarAdminException { // Given String key = "producerSendAsync-" + topicType; - final String topicName = "persistent://prop/cluster/namespace/topic-" + key; + final String topicName = "persistent://my-property/my-ns/topic-" + key; final String subscriptionName = "my-subscription-" + key; final String messagePrefix = "my-message-" + key + "-"; final int numberOfMessages = 30; @@ -129,7 +129,7 @@ public void producerSendAsync(TopicType topicType) throws PulsarClientException, public void producerSend(TopicType topicType) throws PulsarClientException, PulsarAdminException { // Given String key = "producerSend-" + topicType; - final String topicName = "persistent://prop/cluster/namespace/topic-" + key; + final String topicName = "persistent://my-property/my-ns/topic-" + key; final String subscriptionName = "my-subscription-" + key; final String messagePrefix = "my-message-" + key + "-"; final int numberOfMessages = 30; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/PerMessageUnAcknowledgedRedeliveryTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/PerMessageUnAcknowledgedRedeliveryTest.java index 31057c6d5a302..eddcd393a8b5b 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/PerMessageUnAcknowledgedRedeliveryTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/PerMessageUnAcknowledgedRedeliveryTest.java @@ -27,7 +27,6 @@ import org.apache.pulsar.client.api.MessageRoutingMode; import org.apache.pulsar.client.api.Producer; import org.apache.pulsar.client.api.SubscriptionType; -import org.apache.pulsar.common.policies.data.TenantInfoImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.annotations.AfterMethod; @@ -43,7 +42,7 @@ public class PerMessageUnAcknowledgedRedeliveryTest extends BrokerTestBase { @Override @BeforeMethod public void setup() throws Exception { - super.internalSetup(); + super.baseSetup(); } @Override @@ -55,7 +54,7 @@ public void cleanup() throws Exception { @Test(timeOut = testTimeout) public void testSharedAckedNormalTopic() throws Exception { String key = "testSharedAckedNormalTopic"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 15; @@ -153,7 +152,7 @@ public void testSharedAckedNormalTopic() throws Exception { @Test(timeOut = testTimeout) public void testUnAckedMessageTrackerSize() throws Exception { String key = "testUnAckedMessageTrackerSize"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 15; @@ -195,7 +194,7 @@ public void testUnAckedMessageTrackerSize() throws Exception { @Test(timeOut = testTimeout) public void testExclusiveAckedNormalTopic() throws Exception { String key = "testExclusiveAckedNormalTopic"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 15; @@ -293,7 +292,7 @@ public void testExclusiveAckedNormalTopic() throws Exception { @Test(timeOut = testTimeout) public void testFailoverAckedNormalTopic() throws Exception { String key = "testFailoverAckedNormalTopic"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 15; @@ -397,13 +396,11 @@ private static long getUnackedMessagesCountInPartitionedConsumer(Consumer topicNames = Lists.newArrayList(topicName1, topicName2, topicName3); TenantInfoImpl tenantInfo = createDefaultTenantInfo(); admin.tenants().createTenant("prop", tenantInfo); + admin.namespaces().createNamespace("prop/ns-abc1"); + admin.namespaces().createNamespace("prop/ns-abc2"); + admin.namespaces().createNamespace("prop/ns-abc3"); admin.topics().createPartitionedTopic(topicName2, 2); admin.topics().createPartitionedTopic(topicName3, 3); @@ -140,7 +142,7 @@ public void testDifferentTopicsNameSubscribe() throws Exception { @Test(timeOut = testTimeout) public void testRetryClusterTopic() throws Exception { String key = "testRetryClusterTopic"; - final String topicName = "persistent://prop/use/ns-abc1/topic-1-" + key; + final String topicName = "persistent://prop/ns-abc1/topic-1-" + key; TenantInfoImpl tenantInfo = createDefaultTenantInfo(); final String namespace = "prop/ns-abc1"; admin.tenants().createTenant("prop", tenantInfo); @@ -160,13 +162,14 @@ public void testGetConsumersAndGetTopics() throws Exception { String key = "TopicsConsumerGet"; final String subscriptionName = "my-ex-subscription-" + key; - final String topicName1 = "persistent://prop/use/ns-abc/topic-1-" + key; - final String topicName2 = "persistent://prop/use/ns-abc/topic-2-" + key; - final String topicName3 = "persistent://prop/use/ns-abc/topic-3-" + key; + final String topicName1 = "persistent://prop/ns-abc/topic-1-" + key; + final String topicName2 = "persistent://prop/ns-abc/topic-2-" + key; + final String topicName3 = "persistent://prop/ns-abc/topic-3-" + key; List topicNames = Lists.newArrayList(topicName1, topicName2); TenantInfoImpl tenantInfo = createDefaultTenantInfo(); admin.tenants().createTenant("prop", tenantInfo); + admin.namespaces().createNamespace("prop/ns-abc"); admin.topics().createPartitionedTopic(topicName2, 2); admin.topics().createPartitionedTopic(topicName3, 3); @@ -258,13 +261,14 @@ public void testSyncProducerAndConsumer() throws Exception { final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 30; - final String topicName1 = "persistent://prop/use/ns-abc/topic-1-" + key; - final String topicName2 = "persistent://prop/use/ns-abc/topic-2-" + key; - final String topicName3 = "persistent://prop/use/ns-abc/topic-3-" + key; + final String topicName1 = "persistent://prop/ns-abc/topic-1-" + key; + final String topicName2 = "persistent://prop/ns-abc/topic-2-" + key; + final String topicName3 = "persistent://prop/ns-abc/topic-3-" + key; List topicNames = Lists.newArrayList(topicName1, topicName2, topicName3); TenantInfoImpl tenantInfo = createDefaultTenantInfo(); admin.tenants().createTenant("prop", tenantInfo); + admin.namespaces().createNamespace("prop/ns-abc"); admin.topics().createPartitionedTopic(topicName2, 2); admin.topics().createPartitionedTopic(topicName3, 3); @@ -324,13 +328,14 @@ public void testAsyncConsumer() throws Exception { final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 30; - final String topicName1 = "persistent://prop/use/ns-abc/topic-1-" + key; - final String topicName2 = "persistent://prop/use/ns-abc/topic-2-" + key; - final String topicName3 = "persistent://prop/use/ns-abc/topic-3-" + key; + final String topicName1 = "persistent://prop/ns-abc/topic-1-" + key; + final String topicName2 = "persistent://prop/ns-abc/topic-2-" + key; + final String topicName3 = "persistent://prop/ns-abc/topic-3-" + key; List topicNames = Lists.newArrayList(topicName1, topicName2, topicName3); TenantInfoImpl tenantInfo = createDefaultTenantInfo(); admin.tenants().createTenant("prop", tenantInfo); + admin.namespaces().createNamespace("prop/ns-abc"); admin.topics().createPartitionedTopic(topicName2, 2); admin.topics().createPartitionedTopic(topicName3, 3); @@ -409,13 +414,14 @@ public void testConsumerUnackedRedelivery() throws Exception { final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 30; - final String topicName1 = "persistent://prop/use/ns-abc/topic-1-" + key; - final String topicName2 = "persistent://prop/use/ns-abc/topic-2-" + key; - final String topicName3 = "persistent://prop/use/ns-abc/topic-3-" + key; + final String topicName1 = "persistent://prop/ns-abc/topic-1-" + key; + final String topicName2 = "persistent://prop/ns-abc/topic-2-" + key; + final String topicName3 = "persistent://prop/ns-abc/topic-3-" + key; List topicNames = Lists.newArrayList(topicName1, topicName2, topicName3); TenantInfoImpl tenantInfo = createDefaultTenantInfo(); admin.tenants().createTenant("prop", tenantInfo); + admin.namespaces().createNamespace("prop/ns-abc"); admin.topics().createPartitionedTopic(topicName2, 2); admin.topics().createPartitionedTopic(topicName3, 3); @@ -548,9 +554,10 @@ public void testConsumerUnackedRedelivery() throws Exception { @Test public void testTopicNameValid() throws Exception{ - final String topicName = "persistent://prop/use/ns-abc/testTopicNameValid"; + final String topicName = "persistent://prop/ns-abc/testTopicNameValid"; TenantInfoImpl tenantInfo = createDefaultTenantInfo(); admin.tenants().createTenant("prop", tenantInfo); + admin.namespaces().createNamespace("prop/ns-abc"); admin.topics().createPartitionedTopic(topicName, 3); Consumer consumer = pulsarClient.newConsumer() .topic(topicName) @@ -606,13 +613,14 @@ public void testSubscribeUnsubscribeSingleTopic() throws Exception { final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 30; - final String topicName1 = "persistent://prop/use/ns-abc/topic-1-" + key; - final String topicName2 = "persistent://prop/use/ns-abc/topic-2-" + key; - final String topicName3 = "persistent://prop/use/ns-abc/topic-3-" + key; + final String topicName1 = "persistent://prop/ns-abc/topic-1-" + key; + final String topicName2 = "persistent://prop/ns-abc/topic-2-" + key; + final String topicName3 = "persistent://prop/ns-abc/topic-3-" + key; List topicNames = Lists.newArrayList(topicName1, topicName2, topicName3); TenantInfoImpl tenantInfo = createDefaultTenantInfo(); admin.tenants().createTenant("prop", tenantInfo); + admin.namespaces().createNamespace("prop/ns-abc"); admin.topics().createPartitionedTopic(topicName2, 2); admin.topics().createPartitionedTopic(topicName3, 3); @@ -771,11 +779,12 @@ public void testTopicsNameSubscribeWithBuilderFail() throws Exception { String key = "TopicsNameSubscribeWithBuilder"; final String subscriptionName = "my-ex-subscription-" + key; - final String topicName2 = "persistent://prop/use/ns-abc/topic-2-" + key; - final String topicName3 = "persistent://prop/use/ns-abc/topic-3-" + key; + final String topicName2 = "persistent://prop/ns-abc/topic-2-" + key; + final String topicName3 = "persistent://prop/ns-abc/topic-3-" + key; TenantInfoImpl tenantInfo = createDefaultTenantInfo(); admin.tenants().createTenant("prop", tenantInfo); + admin.namespaces().createNamespace("prop/ns-abc"); admin.topics().createPartitionedTopic(topicName2, 2); admin.topics().createPartitionedTopic(topicName3, 3); @@ -841,11 +850,12 @@ public void testMultiTopicsMessageListener() throws Exception { // set latch larger than totalMessages, so timeout message get resend CountDownLatch latch = new CountDownLatch(totalMessages * 3); - final String topicName1 = "persistent://prop/use/ns-abc/topic-1-" + key; + final String topicName1 = "persistent://prop/ns-abc/topic-1-" + key; List topicNames = Lists.newArrayList(topicName1); TenantInfoImpl tenantInfo = createDefaultTenantInfo(); admin.tenants().createTenant("prop", tenantInfo); + admin.namespaces().createNamespace("prop/ns-abc"); admin.topics().createPartitionedTopic(topicName1, 2); // 1. producer connect @@ -1076,13 +1086,11 @@ public void testDefaultBacklogTTL() throws Exception { int totalMessages = 10; this.conf.setTtlDurationDefaultInSeconds(defaultTTLSec); - final String namespace = "prop/use/expiry"; + final String namespace = "prop/expiry"; final String topicName = "persistent://" + namespace + "/expiry"; final String subName = "expiredSub"; - admin.clusters().createCluster("use", ClusterData.builder().serviceUrl(brokerUrl.toString()).build()); - - admin.tenants().createTenant("prop", new TenantInfoImpl(null, Sets.newHashSet("use"))); + admin.tenants().createTenant("prop", new TenantInfoImpl(null, Sets.newHashSet("test"))); admin.namespaces().createNamespace(namespace); Consumer consumer = pulsarClient.newConsumer().topic(topicName).subscriptionName(subName) @@ -1118,13 +1126,14 @@ public void testGetLastMessageId() throws Exception { final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 30; - final String topicName1 = "persistent://prop/use/ns-abc/topic-1-" + key; - final String topicName2 = "persistent://prop/use/ns-abc/topic-2-" + key; - final String topicName3 = "persistent://prop/use/ns-abc/topic-3-" + key; + final String topicName1 = "persistent://prop/ns-abc/topic-1-" + key; + final String topicName2 = "persistent://prop/ns-abc/topic-2-" + key; + final String topicName3 = "persistent://prop/ns-abc/topic-3-" + key; List topicNames = Lists.newArrayList(topicName1, topicName2, topicName3); TenantInfoImpl tenantInfo = createDefaultTenantInfo(); admin.tenants().createTenant("prop", tenantInfo); + admin.namespaces().createNamespace("prop/ns-abc"); admin.topics().createPartitionedTopic(topicName2, 2); admin.topics().createPartitionedTopic(topicName3, 3); @@ -1245,13 +1254,12 @@ public void testGetLastMessageId() throws Exception { @Test(timeOut = testTimeout) public void multiTopicsInDifferentNameSpace() throws PulsarAdminException, PulsarClientException { List topics = new ArrayList<>(); - topics.add("persistent://prop/use/ns-abc/topic-1"); - topics.add("persistent://prop/use/ns-abc/topic-2"); - topics.add("persistent://prop/use/ns-abc1/topic-3"); - admin.clusters().createCluster("use", ClusterData.builder().serviceUrl(brokerUrl.toString()).build()); - admin.tenants().createTenant("prop", new TenantInfoImpl(null, Sets.newHashSet("use"))); - admin.namespaces().createNamespace("prop/use/ns-abc"); - admin.namespaces().createNamespace("prop/use/ns-abc1"); + topics.add("persistent://prop/ns-abc/topic-1"); + topics.add("persistent://prop/ns-abc/topic-2"); + topics.add("persistent://prop/ns-abc1/topic-3"); + admin.tenants().createTenant("prop", new TenantInfoImpl(null, Sets.newHashSet("test"))); + admin.namespaces().createNamespace("prop/ns-abc"); + admin.namespaces().createNamespace("prop/ns-abc1"); Consumer consumer = pulsarClient.newConsumer() .topics(topics) .subscriptionName("multiTopicSubscription") @@ -1259,15 +1267,15 @@ public void multiTopicsInDifferentNameSpace() throws PulsarAdminException, Pulsa .subscribe(); // create Producer Producer producer = pulsarClient.newProducer(Schema.STRING) - .topic("persistent://prop/use/ns-abc/topic-1") + .topic("persistent://prop/ns-abc/topic-1") .producerName("producer") .create(); Producer producer1 = pulsarClient.newProducer(Schema.STRING) - .topic("persistent://prop/use/ns-abc/topic-2") + .topic("persistent://prop/ns-abc/topic-2") .producerName("producer1") .create(); Producer producer2 = pulsarClient.newProducer(Schema.STRING) - .topic("persistent://prop/use/ns-abc1/topic-3") + .topic("persistent://prop/ns-abc1/topic-3") .producerName("producer2") .create(); //send message diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/UnAcknowledgedMessagesTimeoutTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/UnAcknowledgedMessagesTimeoutTest.java index be6fcf888dc1d..0883c329b21ab 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/UnAcknowledgedMessagesTimeoutTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/UnAcknowledgedMessagesTimeoutTest.java @@ -139,7 +139,7 @@ public void testExclusiveSingleAckedNormalTopic(boolean isRedeliveryTracker) thr @Test(dataProvider = "variationsRedeliveryTracker") public void testExclusiveCumulativeAckedNormalTopic(boolean isRedeliveryTracker) throws Exception { String key = "testExclusiveCumulativeAckedNormalTopic"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; final int totalMessages = 10; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/ZeroQueueSizeTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/ZeroQueueSizeTest.java index 700e0859de644..8f10281bcd038 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/ZeroQueueSizeTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/impl/ZeroQueueSizeTest.java @@ -87,7 +87,7 @@ public void invalidQueueSizeConfig() { @Test(expectedExceptions = PulsarClientException.InvalidConfigurationException.class) public void zeroQueueSizeReceiveAsyncInCompatibility() throws PulsarClientException { String key = "zeroQueueSizeReceiveAsyncInCompatibility"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; Consumer consumer = pulsarClient.newConsumer().topic(topicName).subscriptionName(subscriptionName) @@ -98,7 +98,7 @@ public void zeroQueueSizeReceiveAsyncInCompatibility() throws PulsarClientExcept @Test(expectedExceptions = PulsarClientException.class) public void zeroQueueSizePartitionedTopicInCompatibility() throws PulsarClientException, PulsarAdminException { String key = "zeroQueueSizePartitionedTopicInCompatibility"; - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; int numberOfPartitions = 3; admin.topics().createPartitionedTopic(topicName, numberOfPartitions); @@ -110,7 +110,7 @@ public void zeroQueueSizeNormalConsumer() throws PulsarClientException { String key = "nonZeroQueueSizeNormalConsumer"; // 1. Config - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; @@ -147,7 +147,7 @@ public void zeroQueueSizeConsumerListener() throws Exception { String key = "zeroQueueSizeConsumerListener"; // 1. Config - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; @@ -191,7 +191,7 @@ public void zeroQueueSizeSharedSubscription() throws PulsarClientException { String key = "zeroQueueSizeSharedSubscription"; // 1. Config - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; @@ -232,7 +232,7 @@ public void zeroQueueSizeFailoverSubscription() throws PulsarClientException { String key = "zeroQueueSizeFailoverSubscription"; // 1. Config - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; @@ -288,12 +288,12 @@ public void zeroQueueSizeFailoverSubscription() throws PulsarClientException { public void testFailedZeroQueueSizeBatchMessage() throws PulsarClientException { int batchMessageDelayMs = 100; - Consumer consumer = pulsarClient.newConsumer().topic("persistent://prop-xyz/use/ns-abc/topic1") + Consumer consumer = pulsarClient.newConsumer().topic("persistent://prop/ns-abc/topic1") .subscriptionName("my-subscriber-name").subscriptionType(SubscriptionType.Shared).receiverQueueSize(0) .subscribe(); ProducerBuilder producerBuilder = pulsarClient.newProducer() - .topic("persistent://prop-xyz/use/ns-abc/topic1") + .topic("persistent://prop/ns-abc/topic1") .messageRoutingMode(MessageRoutingMode.SinglePartition); if (batchMessageDelayMs != 0) { @@ -592,7 +592,7 @@ public void testZeroQueueSizeConsumerWithPayloadProcessorReceiveBatchMessage() t String key = "payloadProcessorReceiveBatchMessage"; // 1. Config - final String topicName = "persistent://prop/use/ns-abc/topic-" + key; + final String topicName = "persistent://prop/ns-abc/topic-" + key; final String subscriptionName = "my-ex-subscription-" + key; final String messagePredicate = "my-message-" + key + "-"; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/common/naming/NamespaceBundleTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/common/naming/NamespaceBundleTest.java index 77bee080b89a1..65d6de246fa2e 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/common/naming/NamespaceBundleTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/common/naming/NamespaceBundleTest.java @@ -60,7 +60,7 @@ public void testConstructor() { } try { - new NamespaceBundle(NamespaceName.get("pulsar/use/ns"), + new NamespaceBundle(NamespaceName.get("pulsar/ns"), Range.range(0L, BoundType.CLOSED, 0L, BoundType.OPEN), null); fail("Should have failed w/ illegal argument exception"); } catch (IllegalArgumentException iae) { @@ -68,7 +68,7 @@ public void testConstructor() { } try { - new NamespaceBundle(NamespaceName.get("pulsar/use/ns"), Range.range(0L, BoundType.OPEN, 1L, BoundType.OPEN), + new NamespaceBundle(NamespaceName.get("pulsar/ns"), Range.range(0L, BoundType.OPEN, 1L, BoundType.OPEN), null); fail("Should have failed w/ illegal argument exception"); } catch (IllegalArgumentException iae) { @@ -76,7 +76,7 @@ public void testConstructor() { } try { - new NamespaceBundle(NamespaceName.get("pulsar/use/ns"), + new NamespaceBundle(NamespaceName.get("pulsar/ns"), Range.range(1L, BoundType.CLOSED, 1L, BoundType.OPEN), null); fail("Should have failed w/ illegal argument exception"); } catch (IllegalArgumentException iae) { @@ -84,7 +84,7 @@ public void testConstructor() { } try { - new NamespaceBundle(NamespaceName.get("pulsar/use/ns"), + new NamespaceBundle(NamespaceName.get("pulsar/ns"), Range.range(0L, BoundType.CLOSED, 1L, BoundType.CLOSED), null); fail("Should have failed w/ illegal argument exception"); } catch (IllegalArgumentException iae) { @@ -92,7 +92,7 @@ public void testConstructor() { } try { - new NamespaceBundle(NamespaceName.get("pulsar/use/ns"), + new NamespaceBundle(NamespaceName.get("pulsar/ns"), Range.range(0L, BoundType.CLOSED, NamespaceBundles.FULL_UPPER_BOUND, BoundType.OPEN), null); fail("Should have failed w/ illegal argument exception"); } catch (IllegalArgumentException iae) { @@ -100,20 +100,20 @@ public void testConstructor() { } try { - new NamespaceBundle(NamespaceName.get("pulsar/use/ns"), + new NamespaceBundle(NamespaceName.get("pulsar/ns"), Range.range(0L, BoundType.CLOSED, NamespaceBundles.FULL_UPPER_BOUND, BoundType.CLOSED), null); fail("Should have failed w/ null pointer exception"); } catch (NullPointerException npe) { // OK, expected } - NamespaceBundle bundle = new NamespaceBundle(NamespaceName.get("pulsar/use/ns"), + NamespaceBundle bundle = new NamespaceBundle(NamespaceName.get("pulsar/ns"), Range.range(0L, BoundType.CLOSED, 1L, BoundType.OPEN), factory); assertEquals((long) bundle.getKeyRange().lowerEndpoint(), 0L); assertEquals(bundle.getKeyRange().lowerBoundType(), BoundType.CLOSED); assertEquals((long) bundle.getKeyRange().upperEndpoint(), 1L); assertEquals(bundle.getKeyRange().upperBoundType(), BoundType.OPEN); - assertEquals(bundle.getNamespaceObject().toString(), "pulsar/use/ns"); + assertEquals(bundle.getNamespaceObject().toString(), "pulsar/ns"); } @SuppressWarnings("unchecked") @@ -127,10 +127,10 @@ private NamespaceBundleFactory getNamespaceBundleFactory() { @Test public void testGetBundle() { - NamespaceBundle bundle = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + NamespaceBundle bundle = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(0L, BoundType.CLOSED, 0xffffffffL, BoundType.CLOSED)); assertNotNull(bundle); - NamespaceBundle bundle2 = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + NamespaceBundle bundle2 = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(0L, BoundType.CLOSED, 0xffffffffL, BoundType.CLOSED)); // Don't call equals and make sure those two are the same instance assertEquals(bundle, bundle2); @@ -139,9 +139,9 @@ public void testGetBundle() { @Test public void testCompareTo() { - NamespaceBundle bundle = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + NamespaceBundle bundle = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(0L, BoundType.CLOSED, 0x40000000L, BoundType.OPEN)); - NamespaceBundle bundle2 = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + NamespaceBundle bundle2 = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(0x20000000L, BoundType.CLOSED, 0x40000000L, BoundType.OPEN)); try { bundle.compareTo(bundle2); @@ -150,65 +150,65 @@ public void testCompareTo() { // OK, expected } - NamespaceBundle bundle0 = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + NamespaceBundle bundle0 = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(0L, BoundType.CLOSED, 0x10000000L, BoundType.OPEN)); assertTrue(bundle0.compareTo(bundle2) < 0); assertTrue(bundle2.compareTo(bundle0) > 0); - NamespaceBundle bundle1 = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + NamespaceBundle bundle1 = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(0L, BoundType.CLOSED, 0x20000000L, BoundType.OPEN)); assertTrue(bundle1.compareTo(bundle2) < 0); - NamespaceBundle bundle3 = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + NamespaceBundle bundle3 = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(0L, BoundType.CLOSED, 0x40000000L, BoundType.OPEN)); assertEquals(bundle.compareTo(bundle3), 0); - NamespaceBundle otherBundle = factory.getBundle(NamespaceName.get("pulsar/use/ns2"), + NamespaceBundle otherBundle = factory.getBundle(NamespaceName.get("pulsar/ns2"), Range.range(0x10000000L, BoundType.CLOSED, 0x30000000L, BoundType.OPEN)); assertTrue(otherBundle.compareTo(bundle0) > 0); } @Test public void testEquals() throws Exception { - NamespaceBundle bundle = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + NamespaceBundle bundle = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(0L, BoundType.CLOSED, 0x40000000L, BoundType.OPEN)); - NamespaceBundle bundle2 = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + NamespaceBundle bundle2 = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(0x20000000L, BoundType.CLOSED, 0x40000000L, BoundType.OPEN)); assertNotEquals(bundle2, bundle); - NamespaceBundle bundle0 = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + NamespaceBundle bundle0 = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(0L, BoundType.CLOSED, 0x40000000L, BoundType.OPEN)); assertEquals(bundle, bundle0); - NamespaceBundle otherBundle = factory.getBundle(NamespaceName.get("pulsar/use/ns2"), + NamespaceBundle otherBundle = factory.getBundle(NamespaceName.get("pulsar/ns2"), Range.range(0L, BoundType.CLOSED, 0x40000000L, BoundType.OPEN)); assertNotEquals(bundle, otherBundle); } @Test public void testIncludes() { - TopicName topicName = TopicName.get("persistent://pulsar/use/ns1/topic-1"); + TopicName topicName = TopicName.get("persistent://pulsar/ns1/topic-1"); Long hashKey = factory.getLongHashCode(topicName.toString()); Long upper = Math.max(hashKey + 1, NamespaceBundles.FULL_UPPER_BOUND); BoundType upperType = upper.equals(NamespaceBundles.FULL_UPPER_BOUND) ? BoundType.CLOSED : BoundType.OPEN; NamespaceBundle bundle = factory.getBundle(topicName.getNamespaceObject(), Range.range(hashKey / 2, BoundType.CLOSED, upper, upperType)); assertTrue(bundle.includes(topicName)); - bundle = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + bundle = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(upper, BoundType.CLOSED, NamespaceBundles.FULL_UPPER_BOUND, BoundType.CLOSED)); assertFalse(bundle.includes(topicName)); - NamespaceBundle otherBundle = factory.getBundle(NamespaceName.get("pulsar/use/ns2"), + NamespaceBundle otherBundle = factory.getBundle(NamespaceName.get("pulsar/ns2"), Range.range(0L, BoundType.CLOSED, 0x40000000L, BoundType.OPEN)); assertFalse(otherBundle.includes(topicName)); } @Test public void testToString() { - NamespaceBundle bundle0 = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + NamespaceBundle bundle0 = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(0L, BoundType.CLOSED, 0x10000000L, BoundType.OPEN)); - assertEquals(bundle0.toString(), "pulsar/use/ns1/0x00000000_0x10000000"); - bundle0 = factory.getBundle(NamespaceName.get("pulsar/use/ns1"), + assertEquals(bundle0.toString(), "pulsar/ns1/0x00000000_0x10000000"); + bundle0 = factory.getBundle(NamespaceName.get("pulsar/ns1"), Range.range(0x10000000L, BoundType.CLOSED, NamespaceBundles.FULL_UPPER_BOUND, BoundType.CLOSED)); - assertEquals(bundle0.toString(), "pulsar/use/ns1/0x10000000_0xffffffff"); + assertEquals(bundle0.toString(), "pulsar/ns1/0x10000000_0xffffffff"); } } diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/common/naming/NamespaceBundlesTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/common/naming/NamespaceBundlesTest.java index ae51bec40f824..ed1884ba7134a 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/common/naming/NamespaceBundlesTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/common/naming/NamespaceBundlesTest.java @@ -67,7 +67,7 @@ public void testConstructor() throws Exception { long[] partitions = new long[]{0L, 0x10000000L, 0x40000000L, 0xffffffffL}; - NamespaceBundles bundles = new NamespaceBundles(NamespaceName.get("pulsar/use/ns2"), factory, + NamespaceBundles bundles = new NamespaceBundles(NamespaceName.get("pulsar/ns2"), factory, Optional.empty(), partitions); Field partitionField = NamespaceBundles.class.getDeclaredField("partitions"); Field nsField = NamespaceBundles.class.getDeclaredField("nsname"); @@ -79,7 +79,7 @@ public void testConstructor() throws Exception { // the same instance assertEquals(partitions.length, partFld.length); NamespaceName nsFld = (NamespaceName) nsField.get(bundles); - assertEquals(nsFld.toString(), "pulsar/use/ns2"); + assertEquals(nsFld.toString(), "pulsar/ns2"); ArrayList bundleList = (ArrayList) bundlesField.get(bundles); assertEquals(bundleList.size(), 3); assertEquals(bundleList.get(0), @@ -123,13 +123,13 @@ public void testFindBundle() throws Exception { partitions.add(0xb0000000L); partitions.add(0xc0000000L); partitions.add(0xffffffffL); - NamespaceBundles bundles = new NamespaceBundles(NamespaceName.get("pulsar/global/ns1"), + NamespaceBundles bundles = new NamespaceBundles(NamespaceName.get("pulsar/ns1"), factory, Optional.empty(), partitions); - TopicName topicName = TopicName.get("persistent://pulsar/global/ns1/topic-1"); + TopicName topicName = TopicName.get("persistent://pulsar/ns1/topic-1"); NamespaceBundle bundle = bundles.findBundle(topicName); assertTrue(bundle.includes(topicName)); - topicName = TopicName.get("persistent://pulsar/use/ns2/topic-2"); + topicName = TopicName.get("persistent://pulsar/ns2/topic-2"); try { bundles.findBundle(topicName); fail("Should have failed due to mismatched namespace name"); @@ -150,15 +150,15 @@ public void testFindBundle() throws Exception { bundles = new NamespaceBundles(topicName.getNamespaceObject(), factory, Optional.empty(), newPar); bundles.findBundle(topicName); fail("Should have failed due to out-of-range"); - } catch (IndexOutOfBoundsException iae) { + } catch (IllegalArgumentException iae) { // OK, expected } } @Test public void testSplitBundles() throws Exception { - NamespaceName nsname = NamespaceName.get("pulsar/global/ns1"); - TopicName topicName = TopicName.get("persistent://pulsar/global/ns1/topic-1"); + NamespaceName nsname = NamespaceName.get("pulsar/ns1"); + TopicName topicName = TopicName.get("persistent://pulsar/ns1/topic-1"); NamespaceBundles bundles = factory.getBundles(nsname); NamespaceBundle bundle = bundles.findBundle(topicName); final int numberSplitBundles = 4; @@ -212,8 +212,8 @@ public void testSplitBundles() throws Exception { @Test public void testSplitBundleInTwo() throws Exception { final int noBundles = 2; - NamespaceName nsname = NamespaceName.get("pulsar/global/ns1"); - TopicName topicName = TopicName.get("persistent://pulsar/global/ns1/topic-1"); + NamespaceName nsname = NamespaceName.get("pulsar/ns1"); + TopicName topicName = TopicName.get("persistent://pulsar/ns1/topic-1"); NamespaceBundles bundles = factory.getBundles(nsname); NamespaceBundle bundle = bundles.findBundle(topicName); // (1) split : [0x00000000,0xffffffff] => [0x00000000_0x7fffffff,0x7fffffff_0xffffffff] @@ -243,7 +243,7 @@ public void testSplitBundleInTwo() throws Exception { @Test public void testSplitBundleByFixBoundary() throws Exception { - NamespaceName nsname = NamespaceName.get("pulsar/global/ns1"); + NamespaceName nsname = NamespaceName.get("pulsar/ns1"); NamespaceBundles bundles = factory.getBundles(nsname); NamespaceBundle bundleToSplit = bundles.getBundles().get(0); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactedTopicTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactedTopicTest.java index f5e79c8a81218..a2c656d7fa055 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactedTopicTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactedTopicTest.java @@ -87,11 +87,11 @@ public Object[][] batchEnabledProvider() { public void setup() throws Exception { super.internalSetup(); - admin.clusters().createCluster("use", + admin.clusters().createCluster("test", ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); admin.tenants().createTenant("my-property", - new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("use"))); - admin.namespaces().createNamespace("my-property/use/my-ns"); + new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("test"))); + admin.namespaces().createNamespace("my-property/my-ns"); } @AfterMethod(alwaysRun = true) @@ -277,7 +277,7 @@ public void testCleanupOldCompactedTopicLedger() throws Exception { public void testCompactWithEmptyMessage(boolean batchEnabled) throws Exception { final String key = "1"; byte[] msgBytes = "".getBytes(); - final String topic = "persistent://my-property/use/my-ns/testCompactWithEmptyMessage-" + UUID.randomUUID(); + final String topic = "persistent://my-property/my-ns/testCompactWithEmptyMessage-" + UUID.randomUUID(); admin.topics().createPartitionedTopic(topic, 1); final int messages = 10; @@ -334,7 +334,7 @@ public void testCompactWithEmptyMessage(boolean batchEnabled) throws Exception { public void testReadMessageFromCompactedLedger() throws Exception { final String key = "1"; String msg = "test compaction msg"; - final String topic = "persistent://my-property/use/my-ns/testCompactWithEmptyMessage-" + UUID.randomUUID(); + final String topic = "persistent://my-property/my-ns/testCompactWithEmptyMessage-" + UUID.randomUUID(); admin.topics().createPartitionedTopic(topic, 1); final int numMessages = 10; @@ -385,7 +385,7 @@ public void testReadMessageFromCompactedLedger() throws Exception { @Test public void testLastMessageIdForCompactedLedger() throws Exception { - String topic = "persistent://my-property/use/my-ns/testLastMessageIdForCompactedLedger-" + UUID.randomUUID(); + String topic = "persistent://my-property/my-ns/testLastMessageIdForCompactedLedger-" + UUID.randomUUID(); final String key = "1"; Producer producer = pulsarClient.newProducer(Schema.STRING).topic(topic).enableBatching(false).create(); final int numMessages = 10; @@ -456,7 +456,7 @@ public void testLastMessageIdForCompactedLedger() throws Exception { @Test public void testDoNotLossTheLastCompactedLedgerData() throws Exception { - String topic = "persistent://my-property/use/my-ns/testDoNotLossTheLastCompactedLedgerData-" + String topic = "persistent://my-property/my-ns/testDoNotLossTheLastCompactedLedgerData-" + UUID.randomUUID(); final int numMessages = 2000; final int keys = 200; @@ -515,7 +515,7 @@ public void testDoNotLossTheLastCompactedLedgerData() throws Exception { @Test public void testReadCompactedDataWhenLedgerRolloverKickIn() throws Exception { - String topic = "persistent://my-property/use/my-ns/testReadCompactedDataWhenLedgerRolloverKickIn-" + String topic = "persistent://my-property/my-ns/testReadCompactedDataWhenLedgerRolloverKickIn-" + UUID.randomUUID(); final int numMessages = 2000; final int keys = 200; @@ -590,7 +590,7 @@ public void testReadCompactedDataWhenLedgerRolloverKickIn() throws Exception { @Test(timeOut = 120000) public void testCompactionWithTopicUnloading() throws Exception { - String topic = "persistent://my-property/use/my-ns/testCompactionWithTopicUnloading-" + String topic = "persistent://my-property/my-ns/testCompactionWithTopicUnloading-" + UUID.randomUUID(); final int numMessages = 2000; final int keys = 500; @@ -655,7 +655,7 @@ public void testCompactionWithTopicUnloading() throws Exception { @Test(timeOut = 1000 * 30) public void testReader() throws Exception { - final String ns = "my-property/use/my-ns"; + final String ns = "my-property/my-ns"; String topic = "persistent://" + ns + "/t1"; @Cleanup @@ -692,7 +692,7 @@ public void testReader() throws Exception { @Test public void testHasMessageAvailableWithNullValueMessage() throws Exception { - String topic = "persistent://my-property/use/my-ns/testHasMessageAvailable-" + String topic = "persistent://my-property/my-ns/testHasMessageAvailable-" + UUID.randomUUID(); final int numMessages = 10; @Cleanup @@ -738,7 +738,7 @@ public void testHasMessageAvailableWithNullValueMessage() throws Exception { @Test public void testReadCompleteMessagesDuringTopicUnloading() throws Exception { - String topic = "persistent://my-property/use/my-ns/testReadCompleteMessagesDuringTopicUnloading-" + String topic = "persistent://my-property/my-ns/testReadCompleteMessagesDuringTopicUnloading-" + UUID.randomUUID(); final int numMessages = 1000; @Cleanup @@ -802,7 +802,7 @@ public void testReadCompleteMessagesDuringTopicUnloading() throws Exception { @Test public void testReadCompactedLatestMessageWithInclusive() throws Exception { - String topic = "persistent://my-property/use/my-ns/testLedgerRollover-" + String topic = "persistent://my-property/my-ns/testLedgerRollover-" + UUID.randomUUID(); final int numMessages = 1; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactionRetentionTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactionRetentionTest.java index fd687a2350bd0..dd44c6b5acfd6 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactionRetentionTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactionRetentionTest.java @@ -224,8 +224,8 @@ public void testRetentionPolicesForSystemTopic() throws Exception { for (String eventTopic : SystemTopicNames.EVENTS_TOPIC_NAMES) { checkSystemTopicRetentionPolicy(topicPrefix + eventTopic); } - checkSystemTopicRetentionPolicy(topicPrefix + SystemTopicNames.TRANSACTION_COORDINATOR_ASSIGN); - checkSystemTopicRetentionPolicy(topicPrefix + SystemTopicNames.TRANSACTION_COORDINATOR_LOG); + // TRANSACTION_COORDINATOR_ASSIGN and TRANSACTION_COORDINATOR_LOG are only recognized as system + // topics when in the pulsar/system namespace (via startsWith check), so they are not tested here. checkSystemTopicRetentionPolicy(topicPrefix + SystemTopicNames.PENDING_ACK_STORE_SUFFIX); // Check common topics. diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactionTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactionTest.java index 077cf9d0b11b0..2f32a72d319f9 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactionTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactionTest.java @@ -1825,20 +1825,13 @@ public void testReadUnCompacted(boolean batchEnabled) @SneakyThrows @Test public void testHealthCheckTopicNotCompacted() { - NamespaceName heartbeatNamespaceV1 = + NamespaceName heartbeatNamespace = NamespaceService.getHeartbeatNamespace(pulsar.getBrokerId(), pulsar.getConfiguration()); - String topicV1 = "persistent://" + heartbeatNamespaceV1.toString() + "/healthcheck"; - NamespaceName heartbeatNamespaceV2 = - NamespaceService.getHeartbeatNamespaceV2(pulsar.getBrokerId(), pulsar.getConfiguration()); - String topicV2 = heartbeatNamespaceV2.toString() + "/healthcheck"; - Producer producer1 = pulsarClient.newProducer().topic(topicV1).create(); - Producer producer2 = pulsarClient.newProducer().topic(topicV2).create(); - Optional topicReferenceV1 = pulsar.getBrokerService().getTopic(topicV1, false).join(); - Optional topicReferenceV2 = pulsar.getBrokerService().getTopic(topicV2, false).join(); - assertFalse(((SystemTopic) topicReferenceV1.get()).isCompactionEnabled()); - assertFalse(((SystemTopic) topicReferenceV2.get()).isCompactionEnabled()); - producer1.close(); - producer2.close(); + String topic = "persistent://" + heartbeatNamespace.toString() + "/healthcheck"; + Producer producer = pulsarClient.newProducer().topic(topic).create(); + Optional topicReference = pulsar.getBrokerService().getTopic(topic, false).join(); + assertFalse(((SystemTopic) topicReference.get()).isCompactionEnabled()); + producer.close(); } @Test(timeOut = 60000) diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactorTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactorTest.java index 0aeb49312be57..108ef985f7fcc 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactorTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/CompactorTest.java @@ -90,11 +90,11 @@ public class CompactorTest extends MockedPulsarServiceBaseTest { public void setup() throws Exception { super.internalSetup(); - admin.clusters().createCluster("use", + admin.clusters().createCluster("test", ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); admin.tenants().createTenant("my-property", - new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("use"))); - admin.namespaces().createNamespace("my-property/use/my-ns"); + new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("test"))); + admin.namespaces().createNamespace("my-property/my-ns"); compactionScheduler = Executors.newSingleThreadScheduledExecutor( new ThreadFactoryBuilder().setNameFormat("compactor").setDaemon(true).build()); @@ -170,7 +170,7 @@ protected List compactAndVerify(String topic, Map expect @Test public void testCompaction() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; final int numMessages = 1000; final int maxKeys = 10; @@ -198,7 +198,7 @@ public void testCompaction() throws Exception { @Test public void testAllCompactedOut() throws Exception { - String topicName = BrokerTestUtil.newUniqueName("persistent://my-property/use/my-ns/testAllCompactedOut"); + String topicName = BrokerTestUtil.newUniqueName("persistent://my-property/my-ns/testAllCompactedOut"); // set retain null key to true boolean oldRetainNullKey = pulsar.getConfig().isTopicCompactionRetainNullKey(); pulsar.getConfig().setTopicCompactionRetainNullKey(true); @@ -223,7 +223,7 @@ public void testAllCompactedOut() throws Exception { var attributes = Attributes.builder() .put(OpenTelemetryAttributes.PULSAR_DOMAIN, "persistent") .put(OpenTelemetryAttributes.PULSAR_TENANT, "my-property") - .put(OpenTelemetryAttributes.PULSAR_NAMESPACE, "my-property/use/my-ns") + .put(OpenTelemetryAttributes.PULSAR_NAMESPACE, "my-property/my-ns") .put(OpenTelemetryAttributes.PULSAR_TOPIC, topicName) .build(); var metrics = pulsarTestContext.getOpenTelemetryMetricReader().collectAllMetrics(); @@ -275,7 +275,7 @@ public void testAllCompactedOut() throws Exception { @Test public void testCompactAddCompact() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; @Cleanup Producer producer = pulsarClient.newProducer().topic(topic) @@ -313,7 +313,7 @@ public void testCompactAddCompact() throws Exception { @Test public void testCompactedInOrder() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; @Cleanup Producer producer = pulsarClient.newProducer().topic(topic) @@ -345,7 +345,7 @@ public void testCompactedInOrder() throws Exception { @Test public void testCompactEmptyTopic() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; // trigger creation of topic on server side pulsarClient.newConsumer().topic(topic).subscriptionName("sub1").subscribe().close(); @@ -367,7 +367,7 @@ public void testPhaseOneLoopTimeConfiguration() { @Test public void testCompactedWithConcurrentSend() throws Exception { - String topic = "persistent://my-property/use/my-ns/testCompactedWithConcurrentSend"; + String topic = "persistent://my-property/my-ns/testCompactedWithConcurrentSend"; @Cleanup Producer producer = pulsarClient.newProducer().topic(topic) diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/EventTimeOrderCompactorTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/EventTimeOrderCompactorTest.java index de2aecd51d1bc..85a420824e0e5 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/EventTimeOrderCompactorTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/EventTimeOrderCompactorTest.java @@ -73,7 +73,7 @@ protected Compactor getCompactor() { @Test public void testCompactedOutByEventTime() throws Exception { - String topicName = BrokerTestUtil.newUniqueName("persistent://my-property/use/my-ns/testCompactedOutByEventTime"); + String topicName = BrokerTestUtil.newUniqueName("persistent://my-property/my-ns/testCompactedOutByEventTime"); this.restartBroker(); @Cleanup @@ -95,7 +95,7 @@ public void testCompactedOutByEventTime() throws Exception { var attributes = Attributes.builder() .put(OpenTelemetryAttributes.PULSAR_DOMAIN, "persistent") .put(OpenTelemetryAttributes.PULSAR_TENANT, "my-property") - .put(OpenTelemetryAttributes.PULSAR_NAMESPACE, "my-property/use/my-ns") + .put(OpenTelemetryAttributes.PULSAR_NAMESPACE, "my-property/my-ns") .put(OpenTelemetryAttributes.PULSAR_TOPIC, topicName) .build(); var metrics = pulsarTestContext.getOpenTelemetryMetricReader().collectAllMetrics(); @@ -145,7 +145,7 @@ public void testCompactedOutByEventTime() throws Exception { @Test public void testCompactWithEventTimeAddCompact() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; @Cleanup Producer producer = pulsarClient.newProducer().topic(topic) diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/ServiceUnitStateCompactionTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/ServiceUnitStateCompactionTest.java index 20de7a8d0de40..1dc6a9cca8f31 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/ServiceUnitStateCompactionTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/ServiceUnitStateCompactionTest.java @@ -148,10 +148,10 @@ private ServiceUnitState nextInvalidState(ServiceUnitState from) { public void setup() throws Exception { super.internalSetup(); - admin.clusters().createCluster("use", ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); + admin.clusters().createCluster("test", ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); admin.tenants().createTenant("my-property", - new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("use"))); - admin.namespaces().createNamespace("my-property/use/my-ns"); + new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("test"))); + admin.namespaces().createNamespace("my-property/my-ns"); compactionScheduler = Executors.newSingleThreadScheduledExecutor( new ThreadFactoryBuilder().setNameFormat("compaction-%d").setDaemon(true).build()); @@ -183,12 +183,12 @@ public record TestData( } TestData generateTestData() throws PulsarAdminException, PulsarClientException { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; final int numMessages = 20; final int maxKeys = 5; // Configure retention to ensue data is retained for reader - admin.namespaces().setRetention("my-property/use/my-ns", new RetentionPolicies(-1, -1)); + admin.namespaces().setRetention("my-property/my-ns", new RetentionPolicies(-1, -1)); Producer producer = pulsarClient.newProducer(schema) .topic(topic) @@ -328,7 +328,7 @@ public void testCompactionWithReader() throws Exception { @Test public void testCompactionWithTableview() throws Exception { var tv = pulsar.getClient().newTableViewBuilder(schema) - .topic("persistent://my-property/use/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .loadConf(Map.of( "topicCompactionStrategyClassName", ServiceUnitStateDataConflictResolver.class.getName())) @@ -383,7 +383,7 @@ public void testCompactionWithTableview() throws Exception { @Test public void testReadCompactedBeforeCompaction() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; Producer producer = pulsarClient.newProducer(schema) .topic(topic) @@ -430,7 +430,7 @@ public void testReadCompactedBeforeCompaction() throws Exception { @Test public void testReadEntriesAfterCompaction() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; Producer producer = pulsarClient.newProducer(schema) .topic(topic) @@ -472,7 +472,7 @@ public void testReadEntriesAfterCompaction() throws Exception { @Test public void testSeekEarliestAfterCompaction() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; Producer producer = pulsarClient.newProducer(schema) .topic(topic) @@ -523,7 +523,7 @@ public void testSeekEarliestAfterCompaction() throws Exception { @Test public void testSlowTableviewAfterCompaction() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; String strategyClassName = "topicCompactionStrategyClassName"; strategy.checkBrokers(true); @@ -572,7 +572,7 @@ public void testSlowTableviewAfterCompaction() throws Exception { }); // Configure retention to ensue data is retained for reader - admin.namespaces().setRetention("my-property/use/my-ns", + admin.namespaces().setRetention("my-property/my-ns", new RetentionPolicies(-1, -1)); Producer producer = pulsarClient.newProducer(schema) @@ -644,7 +644,7 @@ public void testSlowTableviewAfterCompaction() throws Exception { @Test public void testSlowReceiveTableviewAfterCompaction() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; String strategyClassName = "topicCompactionStrategyClassName"; pulsarClient.newConsumer(schema) @@ -662,7 +662,7 @@ public void testSlowReceiveTableviewAfterCompaction() throws Exception { .create(); // Configure retention to ensue data is retained for reader - admin.namespaces().setRetention("my-property/use/my-ns", + admin.namespaces().setRetention("my-property/my-ns", new RetentionPolicies(-1, -1)); Producer producer = pulsarClient.newProducer(schema) @@ -718,7 +718,7 @@ public void testSlowReceiveTableviewAfterCompaction() throws Exception { @Test public void testBrokerRestartAfterCompaction() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; Producer producer = pulsarClient.newProducer(schema) .topic(topic) @@ -767,7 +767,7 @@ public void testBrokerRestartAfterCompaction() throws Exception { @Test public void testCompactEmptyTopic() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; Producer producer = pulsarClient.newProducer(schema) .topic(topic) @@ -795,7 +795,7 @@ public void testCompactEmptyTopic() throws Exception { @Test public void testWholeBatchCompactedOut() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; // subscribe before sending anything, so that we get all messages pulsarClient.newConsumer(schema).topic(topic).subscriptionName("sub1") @@ -832,7 +832,7 @@ public void testWholeBatchCompactedOut() throws Exception { } public void testCompactionWithLastDeletedKey() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; Producer producer = pulsarClient.newProducer(schema).topic(topic) .compressionType(MSG_COMPRESSION_TYPE) @@ -863,7 +863,7 @@ public void testCompactionWithLastDeletedKey() throws Exception { @Test(timeOut = 20000) public void testEmptyCompactionLedger() throws Exception { - String topic = "persistent://my-property/use/my-ns/my-topic1"; + String topic = "persistent://my-property/my-ns/my-topic1"; Producer producer = pulsarClient.newProducer(schema).topic(topic) .compressionType(MSG_COMPRESSION_TYPE) @@ -893,7 +893,7 @@ public void testEmptyCompactionLedger() throws Exception { @Test(timeOut = 20000) public void testAllEmptyCompactionLedger() throws Exception { final String topic = - "persistent://my-property/use/my-ns/testAllEmptyCompactionLedger" + UUID.randomUUID().toString(); + "persistent://my-property/my-ns/testAllEmptyCompactionLedger" + UUID.randomUUID().toString(); final int messages = 10; @@ -929,7 +929,7 @@ public void testAllEmptyCompactionLedger() throws Exception { public void testCompactMultipleTimesWithoutEmptyMessage() throws PulsarClientException, ExecutionException, InterruptedException { final String topic = - "persistent://my-property/use/my-ns/testCompactMultipleTimesWithoutEmptyMessage" + UUID.randomUUID() + "persistent://my-property/my-ns/testCompactMultipleTimesWithoutEmptyMessage" + UUID.randomUUID() .toString(); final int messages = 10; @@ -980,7 +980,7 @@ public void testCompactMultipleTimesWithoutEmptyMessage() @Test(timeOut = 200000) public void testReadUnCompacted() throws PulsarClientException, ExecutionException, InterruptedException { - final String topic = "persistent://my-property/use/my-ns/testReadUnCompacted" + UUID.randomUUID().toString(); + final String topic = "persistent://my-property/my-ns/testReadUnCompacted" + UUID.randomUUID().toString(); final int messages = 10; final String key = "1"; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/StrategicCompactionTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/StrategicCompactionTest.java index 2ca03c55b30f5..48aa4690e5ba9 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/compaction/StrategicCompactionTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/compaction/StrategicCompactionTest.java @@ -20,6 +20,7 @@ import static org.apache.pulsar.broker.loadbalance.extensions.channel.ServiceUnitStateTableViewImpl.MSG_COMPRESSION_TYPE; import static org.testng.Assert.assertEquals; +import com.google.common.collect.Sets; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.util.ArrayList; import java.util.HashMap; @@ -46,7 +47,9 @@ import org.apache.pulsar.client.api.Schema; import org.apache.pulsar.client.api.SubscriptionInitialPosition; import org.apache.pulsar.client.api.TableView; +import org.apache.pulsar.common.policies.data.ClusterData; import org.apache.pulsar.common.policies.data.PersistentTopicInternalStats; +import org.apache.pulsar.common.policies.data.TenantInfoImpl; import org.apache.pulsar.common.topics.TopicCompactionStrategy; import org.apache.pulsar.common.util.FutureUtil; import org.testng.Assert; @@ -66,6 +69,13 @@ public class StrategicCompactionTest extends MockedPulsarServiceBaseTest { @Override public void setup() throws Exception { super.internalSetup(); + + admin.clusters().createCluster("test", + ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); + admin.tenants().createTenant("my-property", + new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("test"))); + admin.namespaces().createNamespace("my-property/my-ns"); + compactionScheduler = Executors.newSingleThreadScheduledExecutor( new ThreadFactoryBuilder().setNameFormat("compaction-%d").setDaemon(true).build()); bk = pulsar.getBookKeeperClientFactory().create(this.conf, null, null, Optional.empty(), null).get(); @@ -92,7 +102,7 @@ public void testNumericOrderCompaction() throws Exception { strategy = new NumericOrderCompactionStrategy(); - String topic = "persistent://my-property/use/my-ns/numeric-order-compaction"; + String topic = "persistent://my-property/my-ns/numeric-order-compaction"; final int numMessages = 50; final int maxKeys = 5; @@ -172,7 +182,7 @@ public void testNumericOrderCompaction() throws Exception { @Test(timeOut = 20000) public void testSameBatchCompactToSameBatch() throws Exception { final String topic = - "persistent://my-property/use/my-ns/testSameBatchCompactToSameBatch" + UUID.randomUUID(); + "persistent://my-property/my-ns/testSameBatchCompactToSameBatch" + UUID.randomUUID(); // Use odd number to make sure the last message is flush by `reader.hasNext() == false`. final int messages = 11; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/schema/SchemaTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/schema/SchemaTest.java index 9bf1f5e404854..95527cf173e97 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/schema/SchemaTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/schema/SchemaTest.java @@ -20,7 +20,6 @@ import static org.apache.pulsar.common.naming.TopicName.PUBLIC_TENANT; import static org.apache.pulsar.schema.compatibility.SchemaCompatibilityCheckTest.randomName; -import static org.assertj.core.api.Assertions.assertThat; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotEquals; @@ -41,7 +40,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -894,102 +892,6 @@ public void testDeleteTopicAndSchema() throws Exception { } } - @Test - public void testDeleteTopicAndSchemaForV1() throws Exception { - final String tenant = PUBLIC_TENANT; - final String cluster = CLUSTER_NAME; - final String namespace = "test-namespace-" + randomName(16); - final String topicOne = "not-partitioned-topic"; - final String topic2 = "persistent://" + tenant + "/" + cluster + "/" + namespace + "/partitioned-topic"; - - // persistent, non-partitioned v1/topic - final String topic1 = TopicName.get( - TopicDomain.persistent.value(), - tenant, - cluster, - namespace, - topicOne).toString(); - - // persistent, partitioned v1/topic - admin.topics().createPartitionedTopic(topic2, 1); - - Producer p11 = pulsarClient.newProducer(Schema.JSON(Schemas.PersonOne.class)) - .topic(topic1) - .create(); - - Producer p12 = pulsarClient.newProducer(Schema.JSON(Schemas.PersonThree.class)) - .topic(topic1) - .create(); - - Producer p21 = pulsarClient.newProducer(Schema.JSON(Schemas.PersonThree.class)) - .topic(topic2) - .create(); - - List> schemaFutures1 = - this.getPulsar().getSchemaRegistryService().getAllSchemas(TopicName.get(topic1).getSchemaName()).get(); - FutureUtil.waitForAll(schemaFutures1).get(); - List schemas1 = schemaFutures1.stream().map(future -> { - try { - return future.get(); - } catch (Exception e) { - return null; - } - }).filter(Objects::nonNull).toList(); - assertEquals(schemas1.size(), 2); - for (SchemaRegistry.SchemaAndMetadata schema : schemas1) { - assertNotNull(schema); - } - - List> schemaFutures2 = - this.getPulsar().getSchemaRegistryService().getAllSchemas(TopicName.get(topic2).getSchemaName()).get(); - FutureUtil.waitForAll(schemaFutures2).get(); - List schemas2 = schemaFutures2.stream().map(future -> { - try { - return future.get(); - } catch (Exception e) { - return null; - } - }).filter(Objects::nonNull).toList(); - assertEquals(schemas2.size(), 1); - for (SchemaRegistry.SchemaAndMetadata schema : schemas2) { - assertNotNull(schema); - } - - // not-force delete topic - try { - admin.topics().delete(topic1, false); - fail(); - } catch (Exception e) { - assertThat(e.getMessage()) - .isNotNull() - .startsWith("Topic has 2 clients"); - } - assertEquals(this.getPulsar().getSchemaRegistryService() - .trimDeletedSchemaAndGetList(TopicName.get(topic1).getSchemaName()).get().size(), 2); - try { - admin.topics().deletePartitionedTopic(topic2, false); - fail(); - } catch (Exception e) { - assertThat(e.getMessage()) - .isNotNull() - .startsWith("Topic has 1 client"); - } - assertEquals(this.getPulsar().getSchemaRegistryService() - .trimDeletedSchemaAndGetList(TopicName.get(topic2).getSchemaName()).get().size(), 1); - - // Close producer to avoid reconnect. - p11.close(); - p12.close(); - p21.close(); - // force and delete-schema when delete topic - admin.topics().delete(topic1, true); - assertEquals(this.getPulsar().getSchemaRegistryService() - .trimDeletedSchemaAndGetList(TopicName.get(topic1).getSchemaName()).get().size(), 0); - admin.topics().deletePartitionedTopic(topic2, true); - assertEquals(this.getPulsar().getSchemaRegistryService() - .trimDeletedSchemaAndGetList(TopicName.get(topic2).getSchemaName()).get().size(), 0); - } - @Test public void testDeleteTopicAndSchemaForV2() throws Exception { final String tenant = PUBLIC_TENANT; diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/stats/client/PulsarBrokerStatsClientTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/stats/client/PulsarBrokerStatsClientTest.java index ed5262e14f90d..d8b18df4c29ea 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/stats/client/PulsarBrokerStatsClientTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/stats/client/PulsarBrokerStatsClientTest.java @@ -85,7 +85,7 @@ public void testServiceException() throws Exception { // Ok } try { - client.getBrokerResourceAvailability("prop/cluster/ns"); + client.getBrokerResourceAvailability("prop/ns"); } catch (PulsarAdminException e) { // Ok } diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/websocket/proxy/ProxyAuthorizationTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/websocket/proxy/ProxyAuthorizationTest.java index 75edae8eeee57..5614d6943ee36 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/websocket/proxy/ProxyAuthorizationTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/websocket/proxy/ProxyAuthorizationTest.java @@ -84,42 +84,42 @@ protected void cleanup() throws Exception { public void test() throws Exception { AuthorizationService auth = service.getAuthorizationService(); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null)); admin.clusters().createCluster(configClusterName, ClusterData.builder().build()); admin.tenants().createTenant("p1", new TenantInfoImpl(Sets.newHashSet("role1"), Sets.newHashSet("c1"))); waitForChange(); - admin.namespaces().createNamespace("p1/c1/ns1"); + admin.namespaces().createNamespace("p1/ns1"); waitForChange(); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null)); - admin.namespaces().grantPermissionOnNamespace("p1/c1/ns1", "my-role", EnumSet.of(AuthAction.produce)); + admin.namespaces().grantPermissionOnNamespace("p1/ns1", "my-role", EnumSet.of(AuthAction.produce)); waitForChange(); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null)); - assertTrue(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null)); + assertTrue(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null)); - String topic = "persistent://p1/c1/ns1/ds2"; + String topic = "persistent://p1/ns1/ds2"; admin.topics().createNonPartitionedTopic(topic); admin.topics().grantPermission(topic, "other-role", EnumSet.of(AuthAction.consume)); waitForChange(); - assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds2"), "other-role", null)); - assertTrue(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null)); - assertFalse(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds2"), "other-role", null)); - assertTrue(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds2"), "other-role", null, null)); - assertFalse(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds2"), "no-access-role", null, null)); + assertTrue(auth.canLookup(TopicName.get("persistent://p1/ns1/ds2"), "other-role", null)); + assertTrue(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null)); + assertFalse(auth.canProduce(TopicName.get("persistent://p1/ns1/ds2"), "other-role", null)); + assertTrue(auth.canConsume(TopicName.get("persistent://p1/ns1/ds2"), "other-role", null, null)); + assertFalse(auth.canConsume(TopicName.get("persistent://p1/ns1/ds2"), "no-access-role", null, null)); - assertFalse(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "no-access-role", null)); + assertFalse(auth.canLookup(TopicName.get("persistent://p1/ns1/ds1"), "no-access-role", null)); - admin.namespaces().grantPermissionOnNamespace("p1/c1/ns1", "my-role", EnumSet.allOf(AuthAction.class)); + admin.namespaces().grantPermissionOnNamespace("p1/ns1", "my-role", EnumSet.allOf(AuthAction.class)); waitForChange(); - assertTrue(auth.canProduce(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null)); - assertTrue(auth.canConsume(TopicName.get("persistent://p1/c1/ns1/ds1"), "my-role", null, null)); + assertTrue(auth.canProduce(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null)); + assertTrue(auth.canConsume(TopicName.get("persistent://p1/ns1/ds1"), "my-role", null, null)); - admin.namespaces().deleteNamespace("p1/c1/ns1", true); + admin.namespaces().deleteNamespace("p1/ns1", true); admin.tenants().deleteTenant("p1"); admin.clusters().deleteCluster("c1"); } diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/websocket/proxy/ProxyPublishConsumeTlsTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/websocket/proxy/ProxyPublishConsumeTlsTest.java index 1c5439d4b9e96..77f58c87e05cc 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/websocket/proxy/ProxyPublishConsumeTlsTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/websocket/proxy/ProxyPublishConsumeTlsTest.java @@ -99,9 +99,9 @@ protected void cleanup() throws Exception { public void socketTest() throws Exception { String consumerUri = "wss://localhost:" + proxyServer.getListenPortHTTPS().get() - + "/ws/consumer/persistent/my-property/use/my-ns/my-topic/my-sub"; + + "/ws/v2/consumer/persistent/my-property/my-ns/my-topic/my-sub"; String producerUri = "wss://localhost:" + proxyServer.getListenPortHTTPS().get() - + "/ws/producer/persistent/my-property/use/my-ns/my-topic/"; + + "/ws/v2/producer/persistent/my-property/my-ns/my-topic/"; URI consumeUri = URI.create(consumerUri); URI produceUri = URI.create(producerUri); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/websocket/proxy/v1/V1ProxyAuthenticationTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/websocket/proxy/v1/V1ProxyAuthenticationTest.java deleted file mode 100644 index ccc09bd0b048f..0000000000000 --- a/pulsar-broker/src/test/java/org/apache/pulsar/websocket/proxy/v1/V1ProxyAuthenticationTest.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.websocket.proxy.v1; - -import static org.apache.pulsar.broker.BrokerTestUtil.spyWithClassAndConstructorArgs; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doReturn; -import com.google.common.collect.Sets; -import java.net.URI; -import java.util.Optional; -import java.util.concurrent.Future; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.Invocation; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import lombok.Cleanup; -import org.apache.pulsar.client.api.v1.V1ProducerConsumerBase; -import org.apache.pulsar.metadata.impl.ZKMetadataStore; -import org.apache.pulsar.websocket.WebSocketService; -import org.apache.pulsar.websocket.proxy.SimpleConsumerSocket; -import org.apache.pulsar.websocket.proxy.SimpleProducerSocket; -import org.apache.pulsar.websocket.service.ProxyServer; -import org.apache.pulsar.websocket.service.WebSocketProxyConfiguration; -import org.apache.pulsar.websocket.service.WebSocketServiceStarter; -import org.awaitility.Awaitility; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; -import org.eclipse.jetty.websocket.client.WebSocketClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -@Test(groups = "websocket") -public class V1ProxyAuthenticationTest extends V1ProducerConsumerBase { - - private ProxyServer proxyServer; - private WebSocketService service; - private WebSocketClient consumeClient; - private WebSocketClient produceClient; - - @BeforeMethod - public void setup() throws Exception { - super.internalSetup(); - super.producerBaseSetup(); - - WebSocketProxyConfiguration config = new WebSocketProxyConfiguration(); - config.setWebServicePort(Optional.of(0)); - config.setClusterName("use"); - config.setAuthenticationEnabled(true); - // If this is not set, 500 error occurs. - config.setConfigurationMetadataStoreUrl(GLOBAL_DUMMY_VALUE); - config.setSuperUserRoles(Sets.newHashSet("pulsar.super_user")); - - if (methodName.equals("authenticatedSocketTest") || methodName.equals("statsTest")) { - config.setAuthenticationProviders(Sets.newHashSet( - "org.apache.pulsar.websocket.proxy.MockAuthenticationProvider")); - } else { - config.setAuthenticationProviders(Sets.newHashSet( - "org.apache.pulsar.websocket.proxy.MockUnauthenticationProvider")); - } - if (methodName.equals("anonymousSocketTest")) { - config.setAnonymousUserRole("anonymousUser"); - } - - service = spyWithClassAndConstructorArgs(WebSocketService.class, config); - doReturn(registerCloseable(new ZKMetadataStore(mockZooKeeperGlobal))).when(service) - .createConfigMetadataStore(anyString(), anyInt(), anyBoolean()); - proxyServer = new ProxyServer(config); - WebSocketServiceStarter.start(proxyServer, service); - log.info("Proxy Server Started"); - } - - @AfterMethod(alwaysRun = true) - public void cleanup() throws Exception { - try { - consumeClient.stop(); - produceClient.stop(); - log.info("proxy clients are stopped successfully"); - } catch (Exception e) { - log.error(e.getMessage()); - } - - super.internalCleanup(); - if (service != null) { - service.close(); - } - if (proxyServer != null) { - proxyServer.stop(); - } - log.info("Finished Cleaning Up Test setup"); - - } - - private void socketTest() throws Exception { - final String topic = "prop/use/my-ns/my-topic1"; - final String consumerUri = "ws://localhost:" + proxyServer.getListenPortHTTP().get() - + "/ws/consumer/persistent/" + topic + "/my-sub"; - final String producerUri = "ws://localhost:" + proxyServer.getListenPortHTTP().get() - + "/ws/producer/persistent/" + topic; - URI consumeUri = URI.create(consumerUri); - URI produceUri = URI.create(producerUri); - - consumeClient = new WebSocketClient(); - SimpleConsumerSocket consumeSocket = new SimpleConsumerSocket(); - produceClient = new WebSocketClient(); - SimpleProducerSocket produceSocket = new SimpleProducerSocket(); - - consumeClient.start(); - ClientUpgradeRequest consumeRequest = new ClientUpgradeRequest(consumeUri); - Future consumerFuture = consumeClient.connect(consumeSocket, consumeRequest); - log.info("Connecting to : {}", consumeUri); - - ClientUpgradeRequest produceRequest = new ClientUpgradeRequest(produceUri); - produceClient.start(); - Future producerFuture = produceClient.connect(produceSocket, produceRequest); - Assert.assertTrue(consumerFuture.get().isOpen()); - Assert.assertTrue(producerFuture.get().isOpen()); - Awaitility.await().untilAsserted(() -> { - Assert.assertTrue(produceSocket.getBuffer().size() > 0); - Assert.assertEquals(produceSocket.getBuffer(), consumeSocket.getBuffer()); - }); - } - - @Test(timeOut = 10000) - public void authenticatedSocketTest() throws Exception { - socketTest(); - } - - @Test(timeOut = 10000) - public void anonymousSocketTest() throws Exception { - socketTest(); - } - - @Test(timeOut = 10000) - public void unauthenticatedSocketTest() { - Exception exception = null; - try { - socketTest(); - } catch (Exception e) { - exception = e; - } - Assert.assertTrue(exception instanceof java.util.concurrent.ExecutionException); - } - - @Test(timeOut = 10000) - public void statsTest() throws Exception { - final String topic = "prop/use/my-ns/my-topic2"; - final String consumerUri = "ws://localhost:" + proxyServer.getListenPortHTTP().get() - + "/ws/consumer/persistent/" + topic + "/my-sub"; - final String producerUri = "ws://localhost:" + proxyServer.getListenPortHTTP().get() - + "/ws/producer/persistent/" + topic; - URI consumeUri = URI.create(consumerUri); - URI produceUri = URI.create(producerUri); - - WebSocketClient consumeClient = new WebSocketClient(); - SimpleConsumerSocket consumeSocket = new SimpleConsumerSocket(); - WebSocketClient produceClient = new WebSocketClient(); - SimpleProducerSocket produceSocket = new SimpleProducerSocket(); - - final String baseUrl = "http://localhost:" + proxyServer.getListenPortHTTP().get() + "/admin/proxy-stats/"; - @Cleanup - Client client = ClientBuilder.newClient(); - - try { - consumeClient.start(); - ClientUpgradeRequest consumeRequest = new ClientUpgradeRequest(consumeUri); - Future consumerFuture = consumeClient.connect(consumeSocket, consumeRequest); - Assert.assertTrue(consumerFuture.get().isOpen()); - - produceClient.start(); - ClientUpgradeRequest produceRequest = new ClientUpgradeRequest(produceUri); - Future producerFuture = produceClient.connect(produceSocket, produceRequest); - Assert.assertTrue(producerFuture.get().isOpen()); - - Awaitility.await().untilAsserted(() -> Assert.assertTrue(consumeSocket.getReceivedMessagesCount() >= 3)); - - service.getProxyStats().generate(); - - verifyResponseStatus(client, baseUrl + "metrics"); - verifyResponseStatus(client, baseUrl + "stats"); - verifyResponseStatus(client, baseUrl + topic + "/stats"); - } finally { - consumeClient.stop(); - produceClient.stop(); - } - } - - private void verifyResponseStatus(Client client, String url) { - WebTarget webTarget = client.target(url); - Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON); - Response response = invocationBuilder.get(); - Assert.assertEquals(response.getStatus(), 200); - } - - private static final Logger log = LoggerFactory.getLogger(V1ProxyAuthenticationTest.class); -} diff --git a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/Brokers.java b/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/Brokers.java index eed73f38282ac..82a94e5067ba7 100644 --- a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/Brokers.java +++ b/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/Brokers.java @@ -25,7 +25,6 @@ import org.apache.pulsar.client.admin.PulsarAdminException.NotAuthorizedException; import org.apache.pulsar.client.admin.PulsarAdminException.NotFoundException; import org.apache.pulsar.common.conf.InternalConfigurationData; -import org.apache.pulsar.common.naming.TopicVersion; import org.apache.pulsar.common.policies.data.BrokerInfo; import org.apache.pulsar.common.policies.data.NamespaceOwnershipStatus; @@ -305,34 +304,26 @@ Map getOwnedNamespaces(String cluster, String * * @throws PulsarAdminException if the healthcheck fails. */ - @Deprecated void healthcheck() throws PulsarAdminException; /** * Run a healthcheck on the broker asynchronously. */ - @Deprecated CompletableFuture healthcheckAsync(); - /** - * Run a healthcheck on the broker. - * - * @throws PulsarAdminException if the healthcheck fails. - */ - void healthcheck(TopicVersion topicVersion) throws PulsarAdminException; - /** * Run a healthcheck on the target broker or on the broker. * @param brokerId target broker id to check the health. If empty, it checks the health on the connected broker. * * @throws PulsarAdminException if the healthcheck fails. */ - void healthcheck(TopicVersion topicVersion, Optional brokerId) throws PulsarAdminException; + void healthcheck(Optional brokerId) throws PulsarAdminException; /** - * Run a healthcheck on the broker asynchronously. + * Run a healthcheck on the target broker or on the broker asynchronously. + * @param brokerId target broker id to check the health. If empty, it checks the health on the connected broker. */ - CompletableFuture healthcheckAsync(TopicVersion topicVersion, Optional brokerId); + CompletableFuture healthcheckAsync(Optional brokerId); /** diff --git a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/Namespaces.java b/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/Namespaces.java index ba44484a21f20..50abc798e3173 100644 --- a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/Namespaces.java +++ b/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/Namespaces.java @@ -96,31 +96,6 @@ public interface Namespaces { */ CompletableFuture> getNamespacesAsync(String tenant); - /** - * Get the list of namespaces. - *

- * Get the list of all the namespaces for a certain tenant on single cluster. - *

- * Response Example: - * - *

-     * ["my-tenant/use/namespace1", "my-tenant/use/namespace2"]
-     * 
- * - * @param tenant - * Tenant name - * @param cluster - * Cluster name - * - * @throws NotAuthorizedException - * Don't have admin permission - * @throws NotFoundException - * Tenant or cluster does not exist - * @throws PulsarAdminException - * Unexpected error - */ - @Deprecated - List getNamespaces(String tenant, String cluster) throws PulsarAdminException; /** * Get the list of topics. diff --git a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/Properties.java b/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/Properties.java deleted file mode 100644 index 2b5403022d650..0000000000000 --- a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/Properties.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.client.admin; - -import java.util.List; -import org.apache.pulsar.client.admin.PulsarAdminException.ConflictException; -import org.apache.pulsar.client.admin.PulsarAdminException.NotAuthorizedException; -import org.apache.pulsar.client.admin.PulsarAdminException.NotFoundException; -import org.apache.pulsar.client.admin.PulsarAdminException.PreconditionFailedException; -import org.apache.pulsar.common.policies.data.TenantInfo; - -/** - * Admin interface for properties management. - * - * @deprecated see {@link Tenants} from {@link PulsarAdmin#tenants()} - */ -@Deprecated -public interface Properties { - /** - * Get the list of properties. - *

- * Get the list of all the properties. - *

- * Response Example: - * - *

-     * ["my-property", "other-property", "third-property"]
-     * 
- * - * @return the list of Pulsar tenants properties - * @throws NotAuthorizedException - * Don't have admin permission - * @throws PulsarAdminException - * Unexpected error - */ - List getProperties() throws PulsarAdminException; - - /** - * Get the config of the property. - *

- * Get the admin configuration for a given property. - * - * @param property - * Property name - * @return the property configuration - * - * @throws NotAuthorizedException - * Don't have admin permission - * @throws NotFoundException - * Property does not exist - * @throws PulsarAdminException - * Unexpected error - */ - TenantInfo getPropertyAdmin(String property) throws PulsarAdminException; - - /** - * Create a new property. - *

- * Provisions a new property. This operation requires Pulsar super-user privileges. - * - * @param property - * Property name - * @param config - * Config data - * - * @throws NotAuthorizedException - * Don't have admin permission - * @throws ConflictException - * Property already exists - * @throws PreconditionFailedException - * Property name is not valid - * @throws PulsarAdminException - * Unexpected error - */ - void createProperty(String property, TenantInfo config) throws PulsarAdminException; - - /** - * Update the admins for a property. - *

- * This operation requires Pulsar super-user privileges. - * - * @param property - * Property name - * @param config - * Config data - * - * @throws NotAuthorizedException - * Don't have admin permission - * @throws NotFoundException - * Property does not exist - * @throws PulsarAdminException - * Unexpected error - */ - void updateProperty(String property, TenantInfo config) throws PulsarAdminException; - - /** - * Delete an existing property. - *

- * Delete a property and all namespaces and topics under it. - * - * @param property - * Property name - * - * @throws NotAuthorizedException - * Don't have admin permission - * @throws NotFoundException - * The property does not exist - * @throws ConflictException - * The property still has active namespaces - * @throws PulsarAdminException - * Unexpected error - */ - void deleteProperty(String property) throws PulsarAdminException; -} diff --git a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/PulsarAdmin.java b/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/PulsarAdmin.java index 7f49a55d82972..e47a87b41b3a1 100644 --- a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/PulsarAdmin.java +++ b/pulsar-client-admin-api/src/main/java/org/apache/pulsar/client/admin/PulsarAdmin.java @@ -57,13 +57,6 @@ static PulsarAdminBuilder builder() { */ ResourceGroups resourcegroups(); - /** - * - * @deprecated since 2.0. See {@link #tenants()} - */ - @Deprecated - Properties properties(); - /** * @return the namespaces management object */ diff --git a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/naming/TopicVersion.java b/pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/naming/TopicVersion.java deleted file mode 100644 index c6904a383365e..0000000000000 --- a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/naming/TopicVersion.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.common.naming; - -public enum TopicVersion { - V1, - V2, -} diff --git a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/BrokerStatsImpl.java b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/BrokerStatsImpl.java index 6ddabe9837ef9..de158fbd80c7f 100644 --- a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/BrokerStatsImpl.java +++ b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/BrokerStatsImpl.java @@ -35,12 +35,10 @@ */ public class BrokerStatsImpl extends BaseResource implements BrokerStats { - private final WebTarget adminBrokerStats; private final WebTarget adminV2BrokerStats; public BrokerStatsImpl(WebTarget target, Authentication auth, long requestTimeoutMs) { super(auth, requestTimeoutMs); - adminBrokerStats = target.path("/admin/broker-stats"); adminV2BrokerStats = target.path("/admin/v2/broker-stats"); } @@ -113,8 +111,8 @@ public CompletableFuture getPendingBookieOpsStatsAsync() { public JsonObject getBrokerResourceAvailability(String namespace) throws PulsarAdminException { try { NamespaceName ns = NamespaceName.get(namespace); - WebTarget admin = ns.isV2() ? adminV2BrokerStats : adminBrokerStats; - String json = request(admin.path("/broker-resource-availability").path(ns.toString())).get(String.class); + String json = request(adminV2BrokerStats.path("/broker-resource-availability").path(ns.toString())) + .get(String.class); return new Gson().fromJson(json, JsonObject.class); } catch (Exception e) { throw getApiException(e); diff --git a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/BrokersImpl.java b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/BrokersImpl.java index b0cd3edeb21fe..fe33eac4393fc 100644 --- a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/BrokersImpl.java +++ b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/BrokersImpl.java @@ -30,7 +30,6 @@ import org.apache.pulsar.client.admin.PulsarAdminException; import org.apache.pulsar.client.api.Authentication; import org.apache.pulsar.common.conf.InternalConfigurationData; -import org.apache.pulsar.common.naming.TopicVersion; import org.apache.pulsar.common.policies.data.BrokerInfo; import org.apache.pulsar.common.policies.data.NamespaceOwnershipStatus; import org.apache.pulsar.common.util.Codec; @@ -167,34 +166,23 @@ public CompletableFuture backlogQuotaCheckAsync() { } @Override - @Deprecated public void healthcheck() throws PulsarAdminException { - healthcheck(TopicVersion.V1, Optional.empty()); + sync(() -> healthcheckAsync(Optional.empty())); } @Override - @Deprecated public CompletableFuture healthcheckAsync() { - return healthcheckAsync(TopicVersion.V1, Optional.empty()); + return healthcheckAsync(Optional.empty()); } - @Override - public void healthcheck(TopicVersion topicVersion) throws PulsarAdminException { - sync(() -> healthcheckAsync(topicVersion, Optional.empty())); + public void healthcheck(Optional brokerId) throws PulsarAdminException { + sync(() -> healthcheckAsync(brokerId)); } @Override - public void healthcheck(TopicVersion topicVersion, Optional brokerId) throws PulsarAdminException { - sync(() -> healthcheckAsync(topicVersion, brokerId)); - } - - @Override - public CompletableFuture healthcheckAsync(TopicVersion topicVersion, Optional brokerId) { + public CompletableFuture healthcheckAsync(Optional brokerId) { WebTarget path = adminBrokers.path("health"); - if (topicVersion != null) { - path = path.queryParam("topicVersion", topicVersion); - } if (brokerId.isPresent()) { path = path.queryParam("brokerId", brokerId.get()); } diff --git a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/LookupImpl.java b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/LookupImpl.java index 2482f2cc7a521..94194aa0fb35e 100644 --- a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/LookupImpl.java +++ b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/LookupImpl.java @@ -54,8 +54,7 @@ public String lookupTopic(String topic) throws PulsarAdminException { @Override public CompletableFuture lookupTopicAsync(String topic) { TopicName topicName = TopicName.get(topic); - String prefix = topicName.isV2() ? "/topic" : "/destination"; - WebTarget path = v2lookup.path(prefix).path(topicName.getLookupName()); + WebTarget path = v2lookup.path("/topic").path(topicName.getLookupName()); return asyncGetRequest(path, new FutureCallback() {}) .thenApply(lookupData -> useTls && StringUtils.isNotBlank(lookupData.getBrokerUrlTls()) @@ -117,8 +116,7 @@ public String getBundleRange(String topic) throws PulsarAdminException { @Override public CompletableFuture getBundleRangeAsync(String topic) { TopicName topicName = TopicName.get(topic); - String prefix = topicName.isV2() ? "/topic" : "/destination"; - WebTarget path = v2lookup.path(prefix).path(topicName.getLookupName()).path("bundle"); + WebTarget path = v2lookup.path("/topic").path(topicName.getLookupName()).path("bundle"); return asyncGetRequest(path, new FutureCallback(){}); } diff --git a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/NamespacesImpl.java b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/NamespacesImpl.java index b6baf628fef9f..47c5fc430f2ed 100644 --- a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/NamespacesImpl.java +++ b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/NamespacesImpl.java @@ -63,12 +63,10 @@ public class NamespacesImpl extends BaseResource implements Namespaces { - private final WebTarget adminNamespaces; private final WebTarget adminV2Namespaces; public NamespacesImpl(WebTarget web, Authentication auth, long requestTimeoutMs) { super(auth, requestTimeoutMs); - adminNamespaces = web.path("/admin/namespaces"); adminV2Namespaces = web.path("/admin/v2/namespaces"); } @@ -84,16 +82,6 @@ public CompletableFuture> getNamespacesAsync(String tenant) { }); } - @Override - public List getNamespaces(String tenant, String cluster) throws PulsarAdminException { - return sync(() -> getNamespacesAsync(tenant, cluster)); - } - - public CompletableFuture> getNamespacesAsync(String tenant, String cluster) { - WebTarget path = adminNamespaces.path(tenant).path(cluster); - return asyncGetRequest(path, new FutureCallback>() { - }); - } @Override public List getTopics(String namespace) throws PulsarAdminException { @@ -114,8 +102,7 @@ public CompletableFuture getBundlesAsync(String namespace) { @Override public CompletableFuture> getTopicsAsync(String namespace) { return asyncGetNamespaceParts(new FutureCallback>() { - }, namespace, - NamespaceName.get(namespace).isV2() ? "topics" : "destinations"); + }, namespace, "topics"); } @Override @@ -127,8 +114,7 @@ public List getTopics(String namespace, ListNamespaceTopicsOptions optio @Override public CompletableFuture> getTopicsAsync(String namespace, ListNamespaceTopicsOptions options) { NamespaceName ns = NamespaceName.get(namespace); - String action = ns.isV2() ? "topics" : "destinations"; - WebTarget path = namespacePath(ns, action); + WebTarget path = namespacePath(ns, "topics"); path = path .queryParam("mode", options.getMode()) .queryParam("includeSystemTopic", options.isIncludeSystemTopic()); @@ -157,18 +143,9 @@ public CompletableFuture createNamespaceAsync(String namespace, Set { - // For V1, we need to do it in 2 steps - return setNamespaceReplicationClustersAsync(namespace, clusters, false); - }); - } + Policies policies = new Policies(); + policies.replication_clusters = clusters; + return asyncPutRequest(path, Entity.entity(policies, MediaType.APPLICATION_JSON)); } @Override @@ -189,7 +166,7 @@ public void createNamespace(String namespace, Policies policies) throws PulsarAd @Override public CompletableFuture createNamespaceAsync(String namespace, Policies policies) { NamespaceName ns = NamespaceName.get(namespace); - WebTarget path = ns.isV2() ? namespacePath(ns) : namespacePath(ns, "policy"); + WebTarget path = namespacePath(ns); return asyncPutRequest(path, Entity.entity(policies, MediaType.APPLICATION_JSON)); } @@ -203,15 +180,9 @@ public CompletableFuture createNamespaceAsync(String namespace, BundlesDat NamespaceName ns = NamespaceName.get(namespace); WebTarget path = namespacePath(ns); - if (ns.isV2()) { - // For V2 API we pass full Policy class instance - Policies policies = new Policies(); - policies.bundles = bundlesData; - return asyncPutRequest(path, Entity.entity(policies, MediaType.APPLICATION_JSON)); - } else { - // For V1 API, we pass the BundlesData on creation - return asyncPutRequest(path, Entity.entity(bundlesData, MediaType.APPLICATION_JSON)); - } + Policies policies = new Policies(); + policies.bundles = bundlesData; + return asyncPutRequest(path, Entity.entity(policies, MediaType.APPLICATION_JSON)); } @Override @@ -504,8 +475,8 @@ public List getAntiAffinityNamespaces(String tenant, String cluster, Str @Override public CompletableFuture> getAntiAffinityNamespacesAsync( String tenant, String cluster, String namespaceAntiAffinityGroup) { - WebTarget path = adminNamespaces.path(cluster) - .path("antiAffinity").path(namespaceAntiAffinityGroup).queryParam("property", tenant); + WebTarget path = adminV2Namespaces.path(cluster) + .path("antiAffinity").path(namespaceAntiAffinityGroup).queryParam("tenant", tenant); return asyncGetRequest(path, new FutureCallback>() { }); } @@ -2024,8 +1995,7 @@ public CompletableFuture updateMigrationStateAsync(String namespace, boole } private WebTarget namespacePath(NamespaceName namespace, String... parts) { - final WebTarget base = namespace.isV2() ? adminV2Namespaces : adminNamespaces; - WebTarget namespacePath = base.path(namespace.toString()); + WebTarget namespacePath = adminV2Namespaces.path(namespace.toString()); namespacePath = WebTargets.addParts(namespacePath, parts); return namespacePath; } diff --git a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/NonPersistentTopicsImpl.java b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/NonPersistentTopicsImpl.java index e98d44fdc4a69..2368cf87dcf1f 100644 --- a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/NonPersistentTopicsImpl.java +++ b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/NonPersistentTopicsImpl.java @@ -35,12 +35,10 @@ public class NonPersistentTopicsImpl extends BaseResource implements NonPersistentTopics { - private final WebTarget adminNonPersistentTopics; private final WebTarget adminV2NonPersistentTopics; public NonPersistentTopicsImpl(WebTarget web, Authentication auth, long requestTimeoutMs) { super(auth, requestTimeoutMs); - adminNonPersistentTopics = web.path("/admin"); adminV2NonPersistentTopics = web.path("/admin/v2"); } @@ -138,15 +136,13 @@ private TopicName validateTopic(String topic) { } private WebTarget namespacePath(String domain, NamespaceName namespace, String... parts) { - final WebTarget base = namespace.isV2() ? adminV2NonPersistentTopics : adminNonPersistentTopics; - WebTarget namespacePath = base.path(domain).path(namespace.toString()); + WebTarget namespacePath = adminV2NonPersistentTopics.path(domain).path(namespace.toString()); namespacePath = WebTargets.addParts(namespacePath, parts); return namespacePath; } private WebTarget topicPath(TopicName topic, String... parts) { - final WebTarget base = topic.isV2() ? adminV2NonPersistentTopics : adminNonPersistentTopics; - WebTarget topicPath = base.path(topic.getRestPath()); + WebTarget topicPath = adminV2NonPersistentTopics.path(topic.getRestPath()); topicPath = WebTargets.addParts(topicPath, parts); return topicPath; } diff --git a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/PulsarAdminImpl.java b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/PulsarAdminImpl.java index 730ba05ddfa54..d1b5e2bb8f326 100644 --- a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/PulsarAdminImpl.java +++ b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/PulsarAdminImpl.java @@ -39,7 +39,6 @@ import org.apache.pulsar.client.admin.Namespaces; import org.apache.pulsar.client.admin.NonPersistentTopics; import org.apache.pulsar.client.admin.Packages; -import org.apache.pulsar.client.admin.Properties; import org.apache.pulsar.client.admin.ProxyStats; import org.apache.pulsar.client.admin.PulsarAdmin; import org.apache.pulsar.client.admin.ResourceGroups; @@ -85,7 +84,6 @@ public class PulsarAdminImpl implements PulsarAdmin { private final ProxyStats proxyStats; private final Tenants tenants; private final ResourceGroups resourcegroups; - private final Properties properties; private final Namespaces namespaces; private final Bookies bookies; private final TopicsImpl topics; @@ -175,7 +173,6 @@ public PulsarAdminImpl(String serviceUrl, ClientConfigurationData clientConfigDa this.proxyStats = new ProxyStatsImpl(root, auth, requestTimeoutMs); this.tenants = new TenantsImpl(root, auth, requestTimeoutMs); this.resourcegroups = new ResourceGroupsImpl(root, auth, requestTimeoutMs); - this.properties = new TenantsImpl(root, auth, requestTimeoutMs); this.namespaces = new NamespacesImpl(root, auth, requestTimeoutMs); this.topics = new TopicsImpl(root, auth, requestTimeoutMs); this.localTopicPolicies = new TopicPoliciesImpl(root, auth, requestTimeoutMs, false); @@ -286,15 +283,6 @@ public ResourceGroups resourcegroups() { return resourcegroups; } - /** - * - * @deprecated since 2.0. See {@link #tenants()} - */ - @Deprecated - public Properties properties() { - return properties; - } - /** * @return the namespaces management object */ diff --git a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/ResourceQuotasImpl.java b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/ResourceQuotasImpl.java index 68884d99448dd..35d76c601e492 100644 --- a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/ResourceQuotasImpl.java +++ b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/ResourceQuotasImpl.java @@ -30,12 +30,10 @@ public class ResourceQuotasImpl extends BaseResource implements ResourceQuotas { - private final WebTarget adminQuotas; private final WebTarget adminV2Quotas; public ResourceQuotasImpl(WebTarget web, Authentication auth, long requestTimeoutMs) { super(auth, requestTimeoutMs); - adminQuotas = web.path("/admin/resource-quotas"); adminV2Quotas = web.path("/admin/v2/resource-quotas"); } @@ -98,8 +96,7 @@ public CompletableFuture resetNamespaceBundleResourceQuotaAsync(String nam } private WebTarget namespacePath(NamespaceName namespace, String... parts) { - final WebTarget base = namespace.isV2() ? adminV2Quotas : adminQuotas; - WebTarget namespacePath = base.path(namespace.toString()); + WebTarget namespacePath = adminV2Quotas.path(namespace.toString()); namespacePath = WebTargets.addParts(namespacePath, parts); return namespacePath; } diff --git a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/SchemasImpl.java b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/SchemasImpl.java index 7f2383e1e52ef..72f8d62c0b4a3 100644 --- a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/SchemasImpl.java +++ b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/SchemasImpl.java @@ -45,11 +45,9 @@ public class SchemasImpl extends BaseResource implements Schemas { private final WebTarget adminV2; - private final WebTarget adminV1; public SchemasImpl(WebTarget web, Authentication auth, long requestTimeoutMs) { super(auth, requestTimeoutMs); - this.adminV1 = web.path("/admin/schemas"); this.adminV2 = web.path("/admin/v2/schemas"); } @@ -311,8 +309,7 @@ private WebTarget metadata(TopicName topicName) { } private WebTarget topicPath(TopicName topic, String... parts) { - final WebTarget base = topic.isV2() ? adminV2 : adminV1; - WebTarget topicPath = base.path(topic.getRestPath(false)); + WebTarget topicPath = adminV2.path(topic.getRestPath(false)); topicPath = WebTargets.addParts(topicPath, parts); return topicPath; } diff --git a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/TenantsImpl.java b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/TenantsImpl.java index c12f3754b4a92..41fdf05db0e45 100644 --- a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/TenantsImpl.java +++ b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/TenantsImpl.java @@ -23,15 +23,13 @@ import javax.ws.rs.client.Entity; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; -import org.apache.pulsar.client.admin.Properties; import org.apache.pulsar.client.admin.PulsarAdminException; import org.apache.pulsar.client.admin.Tenants; import org.apache.pulsar.client.api.Authentication; import org.apache.pulsar.common.policies.data.TenantInfo; import org.apache.pulsar.common.policies.data.TenantInfoImpl; -@SuppressWarnings("deprecation") -public class TenantsImpl extends BaseResource implements Tenants, Properties { +public class TenantsImpl extends BaseResource implements Tenants { private final WebTarget adminTenants; public TenantsImpl(WebTarget web, Authentication auth, long requestTimeoutMs) { @@ -105,33 +103,6 @@ public CompletableFuture deleteTenantAsync(String tenant, boolean force) { return asyncDeleteRequest(path); } - // Compat method names - - @Override - public void createProperty(String tenant, TenantInfo config) throws PulsarAdminException { - createTenant(tenant, config); - } - - @Override - public void updateProperty(String tenant, TenantInfo config) throws PulsarAdminException { - updateTenant(tenant, config); - } - - @Override - public void deleteProperty(String tenant) throws PulsarAdminException { - deleteTenant(tenant); - } - - @Override - public List getProperties() throws PulsarAdminException { - return getTenants(); - } - - @Override - public TenantInfo getPropertyAdmin(String tenant) throws PulsarAdminException { - return getTenantInfo(tenant); - } - public WebTarget getWebTarget() { return adminTenants; } diff --git a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/TopicPoliciesImpl.java b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/TopicPoliciesImpl.java index ca607fd63b343..7dd91b8d26435 100644 --- a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/TopicPoliciesImpl.java +++ b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/TopicPoliciesImpl.java @@ -48,13 +48,11 @@ import org.apache.pulsar.common.policies.data.SubscribeRate; public class TopicPoliciesImpl extends BaseResource implements TopicPolicies { - private final WebTarget adminTopics; private final WebTarget adminV2Topics; private final boolean isGlobal; protected TopicPoliciesImpl(WebTarget web, Authentication auth, long readTimeoutMs, boolean isGlobal) { super(auth, readTimeoutMs); - this.adminTopics = web.path("/admin"); this.adminV2Topics = web.path("/admin/v2"); this.isGlobal = isGlobal; } @@ -1389,8 +1387,7 @@ private TopicName validateTopic(String topic) { } private WebTarget topicPath(TopicName topic, String... parts) { - final WebTarget base = topic.isV2() ? adminV2Topics : adminTopics; - WebTarget topicPath = base.path(topic.getRestPath()); + WebTarget topicPath = adminV2Topics.path(topic.getRestPath()); topicPath = WebTargets.addParts(topicPath, parts); topicPath = addGlobalIfNeeded(topicPath); return topicPath; diff --git a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/TopicsImpl.java b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/TopicsImpl.java index 0eb6424c9577c..c4db94c319596 100644 --- a/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/TopicsImpl.java +++ b/pulsar-client-admin/src/main/java/org/apache/pulsar/client/admin/internal/TopicsImpl.java @@ -103,7 +103,6 @@ import org.slf4j.LoggerFactory; public class TopicsImpl extends BaseResource implements Topics { - private final WebTarget adminTopics; private final WebTarget adminV2Topics; // CHECKSTYLE.OFF: MemberName private static final String BATCH_HEADER = "X-Pulsar-num-batch-message"; @@ -144,7 +143,6 @@ public class TopicsImpl extends BaseResource implements Topics { public TopicsImpl(WebTarget web, Authentication auth, long requestTimeoutMs) { super(auth, requestTimeoutMs); - adminTopics = web.path("/admin"); adminV2Topics = web.path("/admin/v2"); } @@ -1255,15 +1253,13 @@ public CompletableFuture offloadStatusAsync(String topic) } private WebTarget namespacePath(String domain, NamespaceName namespace, String... parts) { - final WebTarget base = namespace.isV2() ? adminV2Topics : adminTopics; - WebTarget namespacePath = base.path(domain).path(namespace.toString()); + WebTarget namespacePath = adminV2Topics.path(domain).path(namespace.toString()); namespacePath = WebTargets.addParts(namespacePath, parts); return namespacePath; } private WebTarget topicPath(TopicName topic, String... parts) { - final WebTarget base = topic.isV2() ? adminV2Topics : adminTopics; - WebTarget topicPath = base.path(topic.getRestPath()); + WebTarget topicPath = adminV2Topics.path(topic.getRestPath()); topicPath = WebTargets.addParts(topicPath, parts); return topicPath; } diff --git a/pulsar-client-tools-test/src/test/java/org/apache/pulsar/admin/cli/PulsarAdminToolTest.java b/pulsar-client-tools-test/src/test/java/org/apache/pulsar/admin/cli/PulsarAdminToolTest.java index 785826f8b0038..a06f5d44665cf 100644 --- a/pulsar-client-tools-test/src/test/java/org/apache/pulsar/admin/cli/PulsarAdminToolTest.java +++ b/pulsar-client-tools-test/src/test/java/org/apache/pulsar/admin/cli/PulsarAdminToolTest.java @@ -18,6 +18,7 @@ */ package org.apache.pulsar.admin.cli; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; @@ -165,7 +166,7 @@ public void brokers() throws Exception { verify(mockBrokers).getRuntimeConfigurations(); brokers.run(split("healthcheck")); - verify(mockBrokers).healthcheck(null); + verify(mockBrokers).healthcheck(); brokers.run(split("version")); verify(mockBrokers).getVersion(); @@ -385,8 +386,8 @@ public void namespacesSetOffloadPolicies() throws Exception { // filesystem offload CmdNamespaces namespaces = new CmdNamespaces(() -> admin); namespaces.run(split( - "set-offload-policies myprop/clust/ns2 -d filesystem -oat 100M -oats 1h -oae 1h -orp bookkeeper-first")); - verify(mockNamespaces).setOffloadPolicies("myprop/clust/ns2", + "set-offload-policies myprop/ns2 -d filesystem -oat 100M -oats 1h -oae 1h -orp bookkeeper-first")); + verify(mockNamespaces).setOffloadPolicies("myprop/ns2", OffloadPoliciesImpl.create("filesystem", null, null, null, null, null, null, null, 64 * 1024 * 1024, 1024 * 1024, 100 * 1024 * 1024L, 3600L, 3600 * 1000L, OffloadedReadPriority.BOOKKEEPER_FIRST)); @@ -394,9 +395,9 @@ public void namespacesSetOffloadPolicies() throws Exception { // S3 offload CmdNamespaces namespaces2 = new CmdNamespaces(() -> admin); namespaces2.run(split( - "set-offload-policies myprop/clust/ns1 -r test-region -d aws-s3 -b test-bucket -e http://test.endpoint " + "set-offload-policies myprop/ns1 -r test-region -d aws-s3 -b test-bucket -e http://test.endpoint " + "-mbs 32M -rbs 5M -oat 10M -oats 100 -oae 10s -orp tiered-storage-first")); - verify(mockNamespaces).setOffloadPolicies("myprop/clust/ns1", + verify(mockNamespaces).setOffloadPolicies("myprop/ns1", OffloadPoliciesImpl.create("aws-s3", "test-region", "test-bucket", "http://test.endpoint", null, null, null, null, 32 * 1024 * 1024, 5 * 1024 * 1024, 10 * 1024 * 1024L, 100L, 10000L, OffloadedReadPriority.TIERED_STORAGE_FIRST)); @@ -415,124 +416,121 @@ public void namespaces() throws Exception { namespaces.run(split("list myprop")); verify(mockNamespaces).getNamespaces("myprop"); - namespaces.run(split("list-cluster myprop/clust")); - verify(mockNamespaces).getNamespaces("myprop", "clust"); + namespaces.run(split("topics myprop/ns1")); + verify(mockNamespaces).getTopics("myprop/ns1", ListNamespaceTopicsOptions.builder().build()); - namespaces.run(split("topics myprop/clust/ns1")); - verify(mockNamespaces).getTopics("myprop/clust/ns1", ListNamespaceTopicsOptions.builder().build()); + namespaces.run(split("policies myprop/ns1")); + verify(mockNamespaces).getPolicies("myprop/ns1"); - namespaces.run(split("policies myprop/clust/ns1")); - verify(mockNamespaces).getPolicies("myprop/clust/ns1"); + namespaces.run(split("create myprop/ns1")); + verify(mockNamespaces).createNamespace(eq("myprop/ns1"), any(Policies.class)); - namespaces.run(split("create myprop/clust/ns1")); - verify(mockNamespaces).createNamespace("myprop/clust/ns1"); + namespaces.run(split("delete myprop/ns1")); + verify(mockNamespaces).deleteNamespace("myprop/ns1", false); - namespaces.run(split("delete myprop/clust/ns1")); - verify(mockNamespaces).deleteNamespace("myprop/clust/ns1", false); + namespaces.run(split("permissions myprop/ns1")); + verify(mockNamespaces).getPermissions("myprop/ns1"); - namespaces.run(split("permissions myprop/clust/ns1")); - verify(mockNamespaces).getPermissions("myprop/clust/ns1"); - - namespaces.run(split("grant-permission myprop/clust/ns1 --role role1 --actions produce,consume")); - verify(mockNamespaces).grantPermissionOnNamespace("myprop/clust/ns1", "role1", + namespaces.run(split("grant-permission myprop/ns1 --role role1 --actions produce,consume")); + verify(mockNamespaces).grantPermissionOnNamespace("myprop/ns1", "role1", EnumSet.of(AuthAction.produce, AuthAction.consume)); - namespaces.run(split("revoke-permission myprop/clust/ns1 --role role1")); - verify(mockNamespaces).revokePermissionsOnNamespace("myprop/clust/ns1", "role1"); + namespaces.run(split("revoke-permission myprop/ns1 --role role1")); + verify(mockNamespaces).revokePermissionsOnNamespace("myprop/ns1", "role1"); - namespaces.run(split("set-clusters myprop/clust/ns1 -c use,usw,usc --skipCompareTopicPartitions")); - verify(mockNamespaces).setNamespaceReplicationClusters("myprop/clust/ns1", + namespaces.run(split("set-clusters myprop/ns1 -c use,usw,usc --skipCompareTopicPartitions")); + verify(mockNamespaces).setNamespaceReplicationClusters("myprop/ns1", Sets.newHashSet("use", "usw", "usc"), false); - namespaces.run(split("set-clusters myprop/clust/ns1 -c use,usw,usc")); - verify(mockNamespaces).setNamespaceReplicationClusters("myprop/clust/ns1", + namespaces.run(split("set-clusters myprop/ns1 -c use,usw,usc")); + verify(mockNamespaces).setNamespaceReplicationClusters("myprop/ns1", Sets.newHashSet("use", "usw", "usc"), true); - namespaces.run(split("get-clusters myprop/clust/ns1")); - verify(mockNamespaces).getNamespaceReplicationClusters("myprop/clust/ns1"); + namespaces.run(split("get-clusters myprop/ns1")); + verify(mockNamespaces).getNamespaceReplicationClusters("myprop/ns1"); - namespaces.run(split("set-allowed-clusters myprop/clust/ns1 -c use,usw,usc")); - verify(mockNamespaces).setNamespaceAllowedClusters("myprop/clust/ns1", + namespaces.run(split("set-allowed-clusters myprop/ns1 -c use,usw,usc")); + verify(mockNamespaces).setNamespaceAllowedClusters("myprop/ns1", Sets.newHashSet("use", "usw", "usc")); - namespaces.run(split("get-allowed-clusters myprop/clust/ns1")); - verify(mockNamespaces).getNamespaceAllowedClusters("myprop/clust/ns1"); + namespaces.run(split("get-allowed-clusters myprop/ns1")); + verify(mockNamespaces).getNamespaceAllowedClusters("myprop/ns1"); - namespaces.run(split("set-subscription-types-enabled myprop/clust/ns1 -t Shared,Failover")); - verify(mockNamespaces).setSubscriptionTypesEnabled("myprop/clust/ns1", + namespaces.run(split("set-subscription-types-enabled myprop/ns1 -t Shared,Failover")); + verify(mockNamespaces).setSubscriptionTypesEnabled("myprop/ns1", Sets.newHashSet(SubscriptionType.Shared, SubscriptionType.Failover)); - namespaces.run(split("get-subscription-types-enabled myprop/clust/ns1")); - verify(mockNamespaces).getSubscriptionTypesEnabled("myprop/clust/ns1"); + namespaces.run(split("get-subscription-types-enabled myprop/ns1")); + verify(mockNamespaces).getSubscriptionTypesEnabled("myprop/ns1"); - namespaces.run(split("remove-subscription-types-enabled myprop/clust/ns1")); - verify(mockNamespaces).removeSubscriptionTypesEnabled("myprop/clust/ns1"); + namespaces.run(split("remove-subscription-types-enabled myprop/ns1")); + verify(mockNamespaces).removeSubscriptionTypesEnabled("myprop/ns1"); - namespaces.run(split("get-schema-validation-enforce myprop/clust/ns1 -ap")); - verify(mockNamespaces).getSchemaValidationEnforced("myprop/clust/ns1", true); + namespaces.run(split("get-schema-validation-enforce myprop/ns1 -ap")); + verify(mockNamespaces).getSchemaValidationEnforced("myprop/ns1", true); namespaces.run(split( - "set-bookie-affinity-group myprop/clust/ns1 --primary-group test1 --secondary-group test2")); - verify(mockNamespaces).setBookieAffinityGroup("myprop/clust/ns1", + "set-bookie-affinity-group myprop/ns1 --primary-group test1 --secondary-group test2")); + verify(mockNamespaces).setBookieAffinityGroup("myprop/ns1", BookieAffinityGroupData.builder() .bookkeeperAffinityGroupPrimary("test1") .bookkeeperAffinityGroupSecondary("test2") .build()); - namespaces.run(split("get-bookie-affinity-group myprop/clust/ns1")); - verify(mockNamespaces).getBookieAffinityGroup("myprop/clust/ns1"); + namespaces.run(split("get-bookie-affinity-group myprop/ns1")); + verify(mockNamespaces).getBookieAffinityGroup("myprop/ns1"); - namespaces.run(split("delete-bookie-affinity-group myprop/clust/ns1")); - verify(mockNamespaces).deleteBookieAffinityGroup("myprop/clust/ns1"); + namespaces.run(split("delete-bookie-affinity-group myprop/ns1")); + verify(mockNamespaces).deleteBookieAffinityGroup("myprop/ns1"); - namespaces.run(split("set-replicator-dispatch-rate myprop/clust/ns1 -md 10 -bd 11 -dt 12")); - verify(mockNamespaces).setReplicatorDispatchRate("myprop/clust/ns1", DispatchRate.builder() + namespaces.run(split("set-replicator-dispatch-rate myprop/ns1 -md 10 -bd 11 -dt 12")); + verify(mockNamespaces).setReplicatorDispatchRate("myprop/ns1", DispatchRate.builder() .dispatchThrottlingRateInMsg(10) .dispatchThrottlingRateInByte(11) .ratePeriodInSecond(12) .build()); - namespaces.run(split("get-replicator-dispatch-rate myprop/clust/ns1")); - verify(mockNamespaces).getReplicatorDispatchRate("myprop/clust/ns1"); + namespaces.run(split("get-replicator-dispatch-rate myprop/ns1")); + verify(mockNamespaces).getReplicatorDispatchRate("myprop/ns1"); - namespaces.run(split("remove-replicator-dispatch-rate myprop/clust/ns1")); - verify(mockNamespaces).removeReplicatorDispatchRate("myprop/clust/ns1"); + namespaces.run(split("remove-replicator-dispatch-rate myprop/ns1")); + verify(mockNamespaces).removeReplicatorDispatchRate("myprop/ns1"); - assertFalse(namespaces.run(split("unload myprop/clust/ns1 -d broker"))); - verify(mockNamespaces, times(0)).unload("myprop/clust/ns1"); + assertFalse(namespaces.run(split("unload myprop/ns1 -d broker"))); + verify(mockNamespaces, times(0)).unload("myprop/ns1"); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("unload myprop/clust/ns1")); - verify(mockNamespaces).unload("myprop/clust/ns1"); + namespaces.run(split("unload myprop/ns1")); + verify(mockNamespaces).unload("myprop/ns1"); // message_age must have time limit, destination_storage must have size limit Assert.assertFalse(namespaces.run( - split("set-backlog-quota myprop/clust/ns1 -p producer_exception -l 10G -t message_age"))); + split("set-backlog-quota myprop/ns1 -p producer_exception -l 10G -t message_age"))); Assert.assertFalse(namespaces.run( - split("set-backlog-quota myprop/clust/ns1 -p producer_exception -lt 10h -t destination_storage"))); + split("set-backlog-quota myprop/ns1 -p producer_exception -lt 10h -t destination_storage"))); mockNamespaces = mock(Namespaces.class); when(admin.namespaces()).thenReturn(mockNamespaces); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("unload myprop/clust/ns1 -b 0x80000000_0xffffffff")); - verify(mockNamespaces).unloadNamespaceBundle("myprop/clust/ns1", "0x80000000_0xffffffff", null); + namespaces.run(split("unload myprop/ns1 -b 0x80000000_0xffffffff")); + verify(mockNamespaces).unloadNamespaceBundle("myprop/ns1", "0x80000000_0xffffffff", null); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("unload myprop/clust/ns1 -b 0x80000000_0xffffffff -d broker")); - verify(mockNamespaces).unloadNamespaceBundle("myprop/clust/ns1", "0x80000000_0xffffffff", "broker"); + namespaces.run(split("unload myprop/ns1 -b 0x80000000_0xffffffff -d broker")); + verify(mockNamespaces).unloadNamespaceBundle("myprop/ns1", "0x80000000_0xffffffff", "broker"); - namespaces.run(split("split-bundle myprop/clust/ns1 -b 0x00000000_0xffffffff")); - verify(mockNamespaces).splitNamespaceBundle("myprop/clust/ns1", "0x00000000_0xffffffff", + namespaces.run(split("split-bundle myprop/ns1 -b 0x00000000_0xffffffff")); + verify(mockNamespaces).splitNamespaceBundle("myprop/ns1", "0x00000000_0xffffffff", false, null); - namespaces.run(split("get-backlog-quotas myprop/clust/ns1")); - verify(mockNamespaces).getBacklogQuotaMap("myprop/clust/ns1"); + namespaces.run(split("get-backlog-quotas myprop/ns1")); + verify(mockNamespaces).getBacklogQuotaMap("myprop/ns1"); - namespaces.run(split("set-backlog-quota myprop/clust/ns1 -p producer_request_hold -l 10")); - verify(mockNamespaces).setBacklogQuota("myprop/clust/ns1", + namespaces.run(split("set-backlog-quota myprop/ns1 -p producer_request_hold -l 10")); + verify(mockNamespaces).setBacklogQuota("myprop/ns1", BacklogQuota.builder() .limitSize(10) .retentionPolicy(RetentionPolicy.producer_request_hold) @@ -543,8 +541,8 @@ public void namespaces() throws Exception { when(admin.namespaces()).thenReturn(mockNamespaces); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("set-backlog-quota myprop/clust/ns1 -p producer_exception -l 10K")); - verify(mockNamespaces).setBacklogQuota("myprop/clust/ns1", + namespaces.run(split("set-backlog-quota myprop/ns1 -p producer_exception -l 10K")); + verify(mockNamespaces).setBacklogQuota("myprop/ns1", BacklogQuota.builder() .limitSize(10 * 1024) .retentionPolicy(RetentionPolicy.producer_exception) @@ -555,8 +553,8 @@ public void namespaces() throws Exception { when(admin.namespaces()).thenReturn(mockNamespaces); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("set-backlog-quota myprop/clust/ns1 -p producer_exception -l 10M")); - verify(mockNamespaces).setBacklogQuota("myprop/clust/ns1", + namespaces.run(split("set-backlog-quota myprop/ns1 -p producer_exception -l 10M")); + verify(mockNamespaces).setBacklogQuota("myprop/ns1", BacklogQuota.builder() .limitSize(10 * 1024 * 1024) .retentionPolicy(RetentionPolicy.producer_exception) @@ -567,8 +565,8 @@ public void namespaces() throws Exception { when(admin.namespaces()).thenReturn(mockNamespaces); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("set-backlog-quota myprop/clust/ns1 -p producer_exception -l 10G")); - verify(mockNamespaces).setBacklogQuota("myprop/clust/ns1", + namespaces.run(split("set-backlog-quota myprop/ns1 -p producer_exception -l 10G")); + verify(mockNamespaces).setBacklogQuota("myprop/ns1", BacklogQuota.builder() .limitSize(10L * 1024 * 1024 * 1024) .retentionPolicy(RetentionPolicy.producer_exception) @@ -580,8 +578,8 @@ public void namespaces() throws Exception { namespaces = new CmdNamespaces(() -> admin); namespaces.run(split( - "set-backlog-quota myprop/clust/ns1 -p consumer_backlog_eviction -lt 10m -t message_age")); - verify(mockNamespaces).setBacklogQuota("myprop/clust/ns1", + "set-backlog-quota myprop/ns1 -p consumer_backlog_eviction -lt 10m -t message_age")); + verify(mockNamespaces).setBacklogQuota("myprop/ns1", BacklogQuota.builder() .limitTime(10 * 60) .retentionPolicy(RetentionPolicy.consumer_backlog_eviction) @@ -592,365 +590,341 @@ public void namespaces() throws Exception { when(admin.namespaces()).thenReturn(mockNamespaces); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("set-backlog-quota myprop/clust/ns1 -p producer_exception -lt 10000 -t message_age")); - verify(mockNamespaces).setBacklogQuota("myprop/clust/ns1", + namespaces.run(split("set-backlog-quota myprop/ns1 -p producer_exception -lt 10000 -t message_age")); + verify(mockNamespaces).setBacklogQuota("myprop/ns1", BacklogQuota.builder() .limitTime(10000) .retentionPolicy(RetentionPolicy.producer_exception) .build(), BacklogQuota.BacklogQuotaType.message_age); - namespaces.run(split("set-persistence myprop/clust/ns1 -e 2 -w 1 -a 1 -r 100.0")); - verify(mockNamespaces).setPersistence("myprop/clust/ns1", + namespaces.run(split("set-persistence myprop/ns1 -e 2 -w 1 -a 1 -r 100.0")); + verify(mockNamespaces).setPersistence("myprop/ns1", new PersistencePolicies(2, 1, 1, 100.0d)); - namespaces.run(split("get-persistence myprop/clust/ns1")); - verify(mockNamespaces).getPersistence("myprop/clust/ns1"); + namespaces.run(split("get-persistence myprop/ns1")); + verify(mockNamespaces).getPersistence("myprop/ns1"); - namespaces.run(split("remove-persistence myprop/clust/ns1")); - verify(mockNamespaces).removePersistence("myprop/clust/ns1"); + namespaces.run(split("remove-persistence myprop/ns1")); + verify(mockNamespaces).removePersistence("myprop/ns1"); - namespaces.run(split("get-max-subscriptions-per-topic myprop/clust/ns1")); - verify(mockNamespaces).getMaxSubscriptionsPerTopic("myprop/clust/ns1"); - namespaces.run(split("set-max-subscriptions-per-topic myprop/clust/ns1 -m 300")); - verify(mockNamespaces).setMaxSubscriptionsPerTopic("myprop/clust/ns1", 300); - namespaces.run(split("remove-max-subscriptions-per-topic myprop/clust/ns1")); - verify(mockNamespaces).removeMaxSubscriptionsPerTopic("myprop/clust/ns1"); + namespaces.run(split("get-max-subscriptions-per-topic myprop/ns1")); + verify(mockNamespaces).getMaxSubscriptionsPerTopic("myprop/ns1"); + namespaces.run(split("set-max-subscriptions-per-topic myprop/ns1 -m 300")); + verify(mockNamespaces).setMaxSubscriptionsPerTopic("myprop/ns1", 300); + namespaces.run(split("remove-max-subscriptions-per-topic myprop/ns1")); + verify(mockNamespaces).removeMaxSubscriptionsPerTopic("myprop/ns1"); - namespaces.run(split("set-message-ttl myprop/clust/ns1 -ttl 300")); - verify(mockNamespaces).setNamespaceMessageTTL("myprop/clust/ns1", 300); + namespaces.run(split("set-message-ttl myprop/ns1 -ttl 300")); + verify(mockNamespaces).setNamespaceMessageTTL("myprop/ns1", 300); - namespaces.run(split("set-subscription-expiration-time myprop/clust/ns1 -t 60")); - verify(mockNamespaces).setSubscriptionExpirationTime("myprop/clust/ns1", 60); + namespaces.run(split("set-subscription-expiration-time myprop/ns1 -t 60")); + verify(mockNamespaces).setSubscriptionExpirationTime("myprop/ns1", 60); - namespaces.run(split("get-deduplication myprop/clust/ns1")); - verify(mockNamespaces).getDeduplicationStatus("myprop/clust/ns1"); - namespaces.run(split("set-deduplication myprop/clust/ns1 --enable")); - verify(mockNamespaces).setDeduplicationStatus("myprop/clust/ns1", true); - namespaces.run(split("remove-deduplication myprop/clust/ns1")); - verify(mockNamespaces).removeDeduplicationStatus("myprop/clust/ns1"); + namespaces.run(split("get-deduplication myprop/ns1")); + verify(mockNamespaces).getDeduplicationStatus("myprop/ns1"); + namespaces.run(split("set-deduplication myprop/ns1 --enable")); + verify(mockNamespaces).setDeduplicationStatus("myprop/ns1", true); + namespaces.run(split("remove-deduplication myprop/ns1")); + verify(mockNamespaces).removeDeduplicationStatus("myprop/ns1"); - namespaces.run(split("set-auto-topic-creation myprop/clust/ns1 -e -t non-partitioned")); - verify(mockNamespaces).setAutoTopicCreation("myprop/clust/ns1", + namespaces.run(split("set-auto-topic-creation myprop/ns1 -e -t non-partitioned")); + verify(mockNamespaces).setAutoTopicCreation("myprop/ns1", AutoTopicCreationOverride.builder() .allowAutoTopicCreation(true) .topicType(TopicType.NON_PARTITIONED.toString()) .build()); - namespaces.run(split("get-auto-topic-creation myprop/clust/ns1")); - verify(mockNamespaces).getAutoTopicCreation("myprop/clust/ns1"); + namespaces.run(split("get-auto-topic-creation myprop/ns1")); + verify(mockNamespaces).getAutoTopicCreation("myprop/ns1"); - namespaces.run(split("remove-auto-topic-creation myprop/clust/ns1")); - verify(mockNamespaces).removeAutoTopicCreation("myprop/clust/ns1"); + namespaces.run(split("remove-auto-topic-creation myprop/ns1")); + verify(mockNamespaces).removeAutoTopicCreation("myprop/ns1"); - namespaces.run(split("set-auto-subscription-creation myprop/clust/ns1 -e")); - verify(mockNamespaces).setAutoSubscriptionCreation("myprop/clust/ns1", + namespaces.run(split("set-auto-subscription-creation myprop/ns1 -e")); + verify(mockNamespaces).setAutoSubscriptionCreation("myprop/ns1", AutoSubscriptionCreationOverride.builder().allowAutoSubscriptionCreation(true).build()); - namespaces.run(split("get-auto-subscription-creation myprop/clust/ns1")); - verify(mockNamespaces).getAutoSubscriptionCreation("myprop/clust/ns1"); + namespaces.run(split("get-auto-subscription-creation myprop/ns1")); + verify(mockNamespaces).getAutoSubscriptionCreation("myprop/ns1"); - namespaces.run(split("remove-auto-subscription-creation myprop/clust/ns1")); - verify(mockNamespaces).removeAutoSubscriptionCreation("myprop/clust/ns1"); + namespaces.run(split("remove-auto-subscription-creation myprop/ns1")); + verify(mockNamespaces).removeAutoSubscriptionCreation("myprop/ns1"); - namespaces.run(split("get-message-ttl myprop/clust/ns1")); - verify(mockNamespaces).getNamespaceMessageTTL("myprop/clust/ns1"); + namespaces.run(split("get-message-ttl myprop/ns1")); + verify(mockNamespaces).getNamespaceMessageTTL("myprop/ns1"); - namespaces.run(split("get-subscription-expiration-time myprop/clust/ns1")); - verify(mockNamespaces).getSubscriptionExpirationTime("myprop/clust/ns1"); + namespaces.run(split("get-subscription-expiration-time myprop/ns1")); + verify(mockNamespaces).getSubscriptionExpirationTime("myprop/ns1"); - namespaces.run(split("remove-subscription-expiration-time myprop/clust/ns1")); - verify(mockNamespaces).removeSubscriptionExpirationTime("myprop/clust/ns1"); + namespaces.run(split("remove-subscription-expiration-time myprop/ns1")); + verify(mockNamespaces).removeSubscriptionExpirationTime("myprop/ns1"); - namespaces.run(split("set-anti-affinity-group myprop/clust/ns1 -g group")); - verify(mockNamespaces).setNamespaceAntiAffinityGroup("myprop/clust/ns1", "group"); + namespaces.run(split("set-anti-affinity-group myprop/ns1 -g group")); + verify(mockNamespaces).setNamespaceAntiAffinityGroup("myprop/ns1", "group"); - namespaces.run(split("get-anti-affinity-group myprop/clust/ns1")); - verify(mockNamespaces).getNamespaceAntiAffinityGroup("myprop/clust/ns1"); + namespaces.run(split("get-anti-affinity-group myprop/ns1")); + verify(mockNamespaces).getNamespaceAntiAffinityGroup("myprop/ns1"); namespaces.run(split("get-anti-affinity-namespaces -p dummy -c cluster -g group")); verify(mockNamespaces).getAntiAffinityNamespaces("dummy", "cluster", "group"); - namespaces.run(split("delete-anti-affinity-group myprop/clust/ns1 ")); - verify(mockNamespaces).deleteNamespaceAntiAffinityGroup("myprop/clust/ns1"); + namespaces.run(split("delete-anti-affinity-group myprop/ns1 ")); + verify(mockNamespaces).deleteNamespaceAntiAffinityGroup("myprop/ns1"); - namespaces.run(split("set-retention myprop/clust/ns1 -t 1h -s 1M")); - verify(mockNamespaces).setRetention("myprop/clust/ns1", + namespaces.run(split("set-retention myprop/ns1 -t 1h -s 1M")); + verify(mockNamespaces).setRetention("myprop/ns1", new RetentionPolicies(60, 1)); // Test with default time unit (seconds) namespaces = new CmdNamespaces(() -> admin); reset(mockNamespaces); - namespaces.run(split("set-retention myprop/clust/ns1 -t 120 -s 20M")); - verify(mockNamespaces).setRetention("myprop/clust/ns1", + namespaces.run(split("set-retention myprop/ns1 -t 120 -s 20M")); + verify(mockNamespaces).setRetention("myprop/ns1", new RetentionPolicies(2, 20)); // Test with explicit time unit (seconds) namespaces = new CmdNamespaces(() -> admin); reset(mockNamespaces); - namespaces.run(split("set-retention myprop/clust/ns1 -t 120s -s 20M")); - verify(mockNamespaces).setRetention("myprop/clust/ns1", + namespaces.run(split("set-retention myprop/ns1 -t 120s -s 20M")); + verify(mockNamespaces).setRetention("myprop/ns1", new RetentionPolicies(2, 20)); // Test size with default size less than 1 mb namespaces = new CmdNamespaces(() -> admin); reset(mockNamespaces); - namespaces.run(split("set-retention myprop/clust/ns1 -t 120s -s 4096")); - verify(mockNamespaces).setRetention("myprop/clust/ns1", + namespaces.run(split("set-retention myprop/ns1 -t 120s -s 4096")); + verify(mockNamespaces).setRetention("myprop/ns1", new RetentionPolicies(2, 0)); // Test size with default size greater than 1mb namespaces = new CmdNamespaces(() -> admin); reset(mockNamespaces); - namespaces.run(split("set-retention myprop/clust/ns1 -t 180 -s " + (2 * 1024 * 1024))); - verify(mockNamespaces).setRetention("myprop/clust/ns1", + namespaces.run(split("set-retention myprop/ns1 -t 180 -s " + (2 * 1024 * 1024))); + verify(mockNamespaces).setRetention("myprop/ns1", new RetentionPolicies(3, 2)); - namespaces.run(split("get-retention myprop/clust/ns1")); - verify(mockNamespaces).getRetention("myprop/clust/ns1"); + namespaces.run(split("get-retention myprop/ns1")); + verify(mockNamespaces).getRetention("myprop/ns1"); - namespaces.run(split("remove-retention myprop/clust/ns1")); - verify(mockNamespaces).removeRetention("myprop/clust/ns1"); + namespaces.run(split("remove-retention myprop/ns1")); + verify(mockNamespaces).removeRetention("myprop/ns1"); - namespaces.run(split("set-delayed-delivery myprop/clust/ns1 -e -t 1s -md 5s")); - verify(mockNamespaces).setDelayedDeliveryMessages("myprop/clust/ns1", + namespaces.run(split("set-delayed-delivery myprop/ns1 -e -t 1s -md 5s")); + verify(mockNamespaces).setDelayedDeliveryMessages("myprop/ns1", DelayedDeliveryPolicies.builder().tickTime(1000).active(true) .maxDeliveryDelayInMillis(5000).build()); - namespaces.run(split("get-delayed-delivery myprop/clust/ns1")); - verify(mockNamespaces).getDelayedDelivery("myprop/clust/ns1"); + namespaces.run(split("get-delayed-delivery myprop/ns1")); + verify(mockNamespaces).getDelayedDelivery("myprop/ns1"); - namespaces.run(split("remove-delayed-delivery myprop/clust/ns1")); - verify(mockNamespaces).removeDelayedDeliveryMessages("myprop/clust/ns1"); + namespaces.run(split("remove-delayed-delivery myprop/ns1")); + verify(mockNamespaces).removeDelayedDeliveryMessages("myprop/ns1"); namespaces.run(split( - "set-inactive-topic-policies myprop/clust/ns1 -e -t 1s -m delete_when_no_subscriptions")); - verify(mockNamespaces).setInactiveTopicPolicies("myprop/clust/ns1", + "set-inactive-topic-policies myprop/ns1 -e -t 1s -m delete_when_no_subscriptions")); + verify(mockNamespaces).setInactiveTopicPolicies("myprop/ns1", new InactiveTopicPolicies( InactiveTopicDeleteMode.delete_when_no_subscriptions, 1, true)); - namespaces.run(split("get-inactive-topic-policies myprop/clust/ns1")); - verify(mockNamespaces).getInactiveTopicPolicies("myprop/clust/ns1"); + namespaces.run(split("get-inactive-topic-policies myprop/ns1")); + verify(mockNamespaces).getInactiveTopicPolicies("myprop/ns1"); - namespaces.run(split("remove-inactive-topic-policies myprop/clust/ns1")); - verify(mockNamespaces).removeInactiveTopicPolicies("myprop/clust/ns1"); + namespaces.run(split("remove-inactive-topic-policies myprop/ns1")); + verify(mockNamespaces).removeInactiveTopicPolicies("myprop/ns1"); - namespaces.run(split("clear-backlog myprop/clust/ns1 -force")); - verify(mockNamespaces).clearNamespaceBacklog("myprop/clust/ns1"); + namespaces.run(split("clear-backlog myprop/ns1 -force")); + verify(mockNamespaces).clearNamespaceBacklog("myprop/ns1"); mockNamespaces = mock(Namespaces.class); when(admin.namespaces()).thenReturn(mockNamespaces); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("set-message-ttl myprop/clust/ns1 -ttl 6m")); - verify(mockNamespaces).setNamespaceMessageTTL("myprop/clust/ns1", 6 * 60); + namespaces.run(split("set-message-ttl myprop/ns1 -ttl 6m")); + verify(mockNamespaces).setNamespaceMessageTTL("myprop/ns1", 6 * 60); - namespaces.run(split("clear-backlog -b 0x80000000_0xffffffff myprop/clust/ns1 -force")); - verify(mockNamespaces).clearNamespaceBundleBacklog("myprop/clust/ns1", "0x80000000_0xffffffff"); + namespaces.run(split("clear-backlog -b 0x80000000_0xffffffff myprop/ns1 -force")); + verify(mockNamespaces).clearNamespaceBundleBacklog("myprop/ns1", "0x80000000_0xffffffff"); mockNamespaces = mock(Namespaces.class); when(admin.namespaces()).thenReturn(mockNamespaces); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("clear-backlog -s my-sub myprop/clust/ns1 -force")); - verify(mockNamespaces).clearNamespaceBacklogForSubscription("myprop/clust/ns1", "my-sub"); + namespaces.run(split("clear-backlog -s my-sub myprop/ns1 -force")); + verify(mockNamespaces).clearNamespaceBacklogForSubscription("myprop/ns1", "my-sub"); mockNamespaces = mock(Namespaces.class); when(admin.namespaces()).thenReturn(mockNamespaces); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("clear-backlog -b 0x80000000_0xffffffff -s my-sub myprop/clust/ns1 -force")); - verify(mockNamespaces).clearNamespaceBundleBacklogForSubscription("myprop/clust/ns1", + namespaces.run(split("clear-backlog -b 0x80000000_0xffffffff -s my-sub myprop/ns1 -force")); + verify(mockNamespaces).clearNamespaceBundleBacklogForSubscription("myprop/ns1", "0x80000000_0xffffffff", "my-sub"); - namespaces.run(split("unsubscribe -s my-sub myprop/clust/ns1")); - verify(mockNamespaces).unsubscribeNamespace("myprop/clust/ns1", "my-sub"); + namespaces.run(split("unsubscribe -s my-sub myprop/ns1")); + verify(mockNamespaces).unsubscribeNamespace("myprop/ns1", "my-sub"); mockNamespaces = mock(Namespaces.class); when(admin.namespaces()).thenReturn(mockNamespaces); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("unsubscribe -b 0x80000000_0xffffffff -s my-sub myprop/clust/ns1")); - verify(mockNamespaces).unsubscribeNamespaceBundle("myprop/clust/ns1", "0x80000000_0xffffffff", "my-sub"); + namespaces.run(split("unsubscribe -b 0x80000000_0xffffffff -s my-sub myprop/ns1")); + verify(mockNamespaces).unsubscribeNamespaceBundle("myprop/ns1", "0x80000000_0xffffffff", "my-sub"); mockNamespaces = mock(Namespaces.class); when(admin.namespaces()).thenReturn(mockNamespaces); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("get-max-producers-per-topic myprop/clust/ns1")); - verify(mockNamespaces).getMaxProducersPerTopic("myprop/clust/ns1"); + namespaces.run(split("get-max-producers-per-topic myprop/ns1")); + verify(mockNamespaces).getMaxProducersPerTopic("myprop/ns1"); - namespaces.run(split("set-max-producers-per-topic myprop/clust/ns1 -p 1")); - verify(mockNamespaces).setMaxProducersPerTopic("myprop/clust/ns1", 1); + namespaces.run(split("set-max-producers-per-topic myprop/ns1 -p 1")); + verify(mockNamespaces).setMaxProducersPerTopic("myprop/ns1", 1); - namespaces.run(split("remove-max-producers-per-topic myprop/clust/ns1")); - verify(mockNamespaces).removeMaxProducersPerTopic("myprop/clust/ns1"); + namespaces.run(split("remove-max-producers-per-topic myprop/ns1")); + verify(mockNamespaces).removeMaxProducersPerTopic("myprop/ns1"); - namespaces.run(split("get-max-consumers-per-topic myprop/clust/ns1")); - verify(mockNamespaces).getMaxConsumersPerTopic("myprop/clust/ns1"); + namespaces.run(split("get-max-consumers-per-topic myprop/ns1")); + verify(mockNamespaces).getMaxConsumersPerTopic("myprop/ns1"); - namespaces.run(split("set-max-consumers-per-topic myprop/clust/ns1 -c 2")); - verify(mockNamespaces).setMaxConsumersPerTopic("myprop/clust/ns1", 2); + namespaces.run(split("set-max-consumers-per-topic myprop/ns1 -c 2")); + verify(mockNamespaces).setMaxConsumersPerTopic("myprop/ns1", 2); - namespaces.run(split("remove-max-consumers-per-topic myprop/clust/ns1")); - verify(mockNamespaces).removeMaxConsumersPerTopic("myprop/clust/ns1"); + namespaces.run(split("remove-max-consumers-per-topic myprop/ns1")); + verify(mockNamespaces).removeMaxConsumersPerTopic("myprop/ns1"); - namespaces.run(split("get-max-consumers-per-subscription myprop/clust/ns1")); - verify(mockNamespaces).getMaxConsumersPerSubscription("myprop/clust/ns1"); + namespaces.run(split("get-max-consumers-per-subscription myprop/ns1")); + verify(mockNamespaces).getMaxConsumersPerSubscription("myprop/ns1"); - namespaces.run(split("remove-max-consumers-per-subscription myprop/clust/ns1")); - verify(mockNamespaces).removeMaxConsumersPerSubscription("myprop/clust/ns1"); + namespaces.run(split("remove-max-consumers-per-subscription myprop/ns1")); + verify(mockNamespaces).removeMaxConsumersPerSubscription("myprop/ns1"); - namespaces.run(split("set-max-consumers-per-subscription myprop/clust/ns1 -c 3")); - verify(mockNamespaces).setMaxConsumersPerSubscription("myprop/clust/ns1", 3); + namespaces.run(split("set-max-consumers-per-subscription myprop/ns1 -c 3")); + verify(mockNamespaces).setMaxConsumersPerSubscription("myprop/ns1", 3); - namespaces.run(split("get-max-unacked-messages-per-subscription myprop/clust/ns1")); - verify(mockNamespaces).getMaxUnackedMessagesPerSubscription("myprop/clust/ns1"); + namespaces.run(split("get-max-unacked-messages-per-subscription myprop/ns1")); + verify(mockNamespaces).getMaxUnackedMessagesPerSubscription("myprop/ns1"); - namespaces.run(split("set-max-unacked-messages-per-subscription myprop/clust/ns1 -c 3")); - verify(mockNamespaces).setMaxUnackedMessagesPerSubscription("myprop/clust/ns1", 3); + namespaces.run(split("set-max-unacked-messages-per-subscription myprop/ns1 -c 3")); + verify(mockNamespaces).setMaxUnackedMessagesPerSubscription("myprop/ns1", 3); - namespaces.run(split("remove-max-unacked-messages-per-subscription myprop/clust/ns1")); - verify(mockNamespaces).removeMaxUnackedMessagesPerSubscription("myprop/clust/ns1"); + namespaces.run(split("remove-max-unacked-messages-per-subscription myprop/ns1")); + verify(mockNamespaces).removeMaxUnackedMessagesPerSubscription("myprop/ns1"); - namespaces.run(split("get-max-unacked-messages-per-consumer myprop/clust/ns1")); - verify(mockNamespaces).getMaxUnackedMessagesPerConsumer("myprop/clust/ns1"); + namespaces.run(split("get-max-unacked-messages-per-consumer myprop/ns1")); + verify(mockNamespaces).getMaxUnackedMessagesPerConsumer("myprop/ns1"); - namespaces.run(split("set-max-unacked-messages-per-consumer myprop/clust/ns1 -c 3")); - verify(mockNamespaces).setMaxUnackedMessagesPerConsumer("myprop/clust/ns1", 3); + namespaces.run(split("set-max-unacked-messages-per-consumer myprop/ns1 -c 3")); + verify(mockNamespaces).setMaxUnackedMessagesPerConsumer("myprop/ns1", 3); - namespaces.run(split("remove-max-unacked-messages-per-consumer myprop/clust/ns1")); - verify(mockNamespaces).removeMaxUnackedMessagesPerConsumer("myprop/clust/ns1"); + namespaces.run(split("remove-max-unacked-messages-per-consumer myprop/ns1")); + verify(mockNamespaces).removeMaxUnackedMessagesPerConsumer("myprop/ns1"); mockNamespaces = mock(Namespaces.class); when(admin.namespaces()).thenReturn(mockNamespaces); namespaces = new CmdNamespaces(() -> admin); - namespaces.run(split("set-dispatch-rate myprop/clust/ns1 -md -1 -bd -1 -dt 2")); - verify(mockNamespaces).setDispatchRate("myprop/clust/ns1", DispatchRate.builder() + namespaces.run(split("set-dispatch-rate myprop/ns1 -md -1 -bd -1 -dt 2")); + verify(mockNamespaces).setDispatchRate("myprop/ns1", DispatchRate.builder() .dispatchThrottlingRateInMsg(-1) .dispatchThrottlingRateInByte(-1) .ratePeriodInSecond(2) .build()); - namespaces.run(split("get-dispatch-rate myprop/clust/ns1")); - verify(mockNamespaces).getDispatchRate("myprop/clust/ns1"); + namespaces.run(split("get-dispatch-rate myprop/ns1")); + verify(mockNamespaces).getDispatchRate("myprop/ns1"); - namespaces.run(split("remove-dispatch-rate myprop/clust/ns1")); - verify(mockNamespaces).removeDispatchRate("myprop/clust/ns1"); + namespaces.run(split("remove-dispatch-rate myprop/ns1")); + verify(mockNamespaces).removeDispatchRate("myprop/ns1"); - namespaces.run(split("set-publish-rate myprop/clust/ns1 -m 10 -b 20")); - verify(mockNamespaces).setPublishRate("myprop/clust/ns1", new PublishRate(10, 20)); + namespaces.run(split("set-publish-rate myprop/ns1 -m 10 -b 20")); + verify(mockNamespaces).setPublishRate("myprop/ns1", new PublishRate(10, 20)); - namespaces.run(split("get-publish-rate myprop/clust/ns1")); - verify(mockNamespaces).getPublishRate("myprop/clust/ns1"); + namespaces.run(split("get-publish-rate myprop/ns1")); + verify(mockNamespaces).getPublishRate("myprop/ns1"); - namespaces.run(split("remove-publish-rate myprop/clust/ns1")); - verify(mockNamespaces).removePublishRate("myprop/clust/ns1"); + namespaces.run(split("remove-publish-rate myprop/ns1")); + verify(mockNamespaces).removePublishRate("myprop/ns1"); - namespaces.run(split("set-subscribe-rate myprop/clust/ns1 -sr 2 -st 60")); - verify(mockNamespaces).setSubscribeRate("myprop/clust/ns1", new SubscribeRate(2, 60)); + namespaces.run(split("set-subscribe-rate myprop/ns1 -sr 2 -st 60")); + verify(mockNamespaces).setSubscribeRate("myprop/ns1", new SubscribeRate(2, 60)); - namespaces.run(split("get-subscribe-rate myprop/clust/ns1")); - verify(mockNamespaces).getSubscribeRate("myprop/clust/ns1"); + namespaces.run(split("get-subscribe-rate myprop/ns1")); + verify(mockNamespaces).getSubscribeRate("myprop/ns1"); - namespaces.run(split("remove-subscribe-rate myprop/clust/ns1")); - verify(mockNamespaces).removeSubscribeRate("myprop/clust/ns1"); + namespaces.run(split("remove-subscribe-rate myprop/ns1")); + verify(mockNamespaces).removeSubscribeRate("myprop/ns1"); - namespaces.run(split("set-subscription-dispatch-rate myprop/clust/ns1 -md -1 -bd -1 -dt 2")); - verify(mockNamespaces).setSubscriptionDispatchRate("myprop/clust/ns1", DispatchRate.builder() + namespaces.run(split("set-subscription-dispatch-rate myprop/ns1 -md -1 -bd -1 -dt 2")); + verify(mockNamespaces).setSubscriptionDispatchRate("myprop/ns1", DispatchRate.builder() .dispatchThrottlingRateInMsg(-1) .dispatchThrottlingRateInByte(-1) .ratePeriodInSecond(2) .build()); - namespaces.run(split("get-subscription-dispatch-rate myprop/clust/ns1")); - verify(mockNamespaces).getSubscriptionDispatchRate("myprop/clust/ns1"); + namespaces.run(split("get-subscription-dispatch-rate myprop/ns1")); + verify(mockNamespaces).getSubscriptionDispatchRate("myprop/ns1"); - namespaces.run(split("remove-subscription-dispatch-rate myprop/clust/ns1")); - verify(mockNamespaces).removeSubscriptionDispatchRate("myprop/clust/ns1"); + namespaces.run(split("remove-subscription-dispatch-rate myprop/ns1")); + verify(mockNamespaces).removeSubscriptionDispatchRate("myprop/ns1"); - namespaces.run(split("get-compaction-threshold myprop/clust/ns1")); - verify(mockNamespaces).getCompactionThreshold("myprop/clust/ns1"); + namespaces.run(split("get-compaction-threshold myprop/ns1")); + verify(mockNamespaces).getCompactionThreshold("myprop/ns1"); - namespaces.run(split("remove-compaction-threshold myprop/clust/ns1")); - verify(mockNamespaces).removeCompactionThreshold("myprop/clust/ns1"); + namespaces.run(split("remove-compaction-threshold myprop/ns1")); + verify(mockNamespaces).removeCompactionThreshold("myprop/ns1"); - namespaces.run(split("set-compaction-threshold myprop/clust/ns1 -t 1G")); - verify(mockNamespaces).setCompactionThreshold("myprop/clust/ns1", 1024 * 1024 * 1024); + namespaces.run(split("set-compaction-threshold myprop/ns1 -t 1G")); + verify(mockNamespaces).setCompactionThreshold("myprop/ns1", 1024 * 1024 * 1024); - namespaces.run(split("get-offload-threshold myprop/clust/ns1")); - verify(mockNamespaces).getOffloadThreshold("myprop/clust/ns1"); + namespaces.run(split("get-offload-threshold myprop/ns1")); + verify(mockNamespaces).getOffloadThreshold("myprop/ns1"); - namespaces.run(split("set-offload-threshold myprop/clust/ns1 -s 1G")); - verify(mockNamespaces).setOffloadThreshold("myprop/clust/ns1", 1024 * 1024 * 1024); + namespaces.run(split("set-offload-threshold myprop/ns1 -s 1G")); + verify(mockNamespaces).setOffloadThreshold("myprop/ns1", 1024 * 1024 * 1024); - namespaces.run(split("get-offload-deletion-lag myprop/clust/ns1")); - verify(mockNamespaces).getOffloadDeleteLagMs("myprop/clust/ns1"); + namespaces.run(split("get-offload-deletion-lag myprop/ns1")); + verify(mockNamespaces).getOffloadDeleteLagMs("myprop/ns1"); - namespaces.run(split("set-offload-deletion-lag myprop/clust/ns1 -l 1d")); - verify(mockNamespaces).setOffloadDeleteLag("myprop/clust/ns1", 24 * 60 * 60, TimeUnit.SECONDS); + namespaces.run(split("set-offload-deletion-lag myprop/ns1 -l 1d")); + verify(mockNamespaces).setOffloadDeleteLag("myprop/ns1", 24 * 60 * 60, TimeUnit.SECONDS); - namespaces.run(split("clear-offload-deletion-lag myprop/clust/ns1")); - verify(mockNamespaces).clearOffloadDeleteLag("myprop/clust/ns1"); + namespaces.run(split("clear-offload-deletion-lag myprop/ns1")); + verify(mockNamespaces).clearOffloadDeleteLag("myprop/ns1"); - namespaces.run(split("set-offload-policies myprop/clust/ns1 -r test-region -d aws-s3 -b test-bucket " + namespaces.run(split("set-offload-policies myprop/ns1 -r test-region -d aws-s3 -b test-bucket " + "-e http://test.endpoint -mbs 32M -rbs 5M -oat 10M -oats 100 -oae 10s -orp tiered-storage-first")); - verify(mockNamespaces).setOffloadPolicies("myprop/clust/ns1", + verify(mockNamespaces).setOffloadPolicies("myprop/ns1", OffloadPoliciesImpl.create("aws-s3", "test-region", "test-bucket", "http://test.endpoint", null, null, null, null, 32 * 1024 * 1024, 5 * 1024 * 1024, 10 * 1024 * 1024L, 100L, 10000L, OffloadedReadPriority.TIERED_STORAGE_FIRST)); - namespaces.run(split("remove-offload-policies myprop/clust/ns1")); - verify(mockNamespaces).removeOffloadPolicies("myprop/clust/ns1"); - - namespaces.run(split("get-offload-policies myprop/clust/ns1")); - verify(mockNamespaces).getOffloadPolicies("myprop/clust/ns1"); + namespaces.run(split("remove-offload-policies myprop/ns1")); + verify(mockNamespaces).removeOffloadPolicies("myprop/ns1"); - namespaces.run(split("remove-message-ttl myprop/clust/ns1")); - verify(mockNamespaces).removeNamespaceMessageTTL("myprop/clust/ns1"); + namespaces.run(split("get-offload-policies myprop/ns1")); + verify(mockNamespaces).getOffloadPolicies("myprop/ns1"); - namespaces.run(split("set-deduplication-snapshot-interval myprop/clust/ns1 -i 1000")); - verify(mockNamespaces).setDeduplicationSnapshotInterval("myprop/clust/ns1", 1000); - namespaces.run(split("get-deduplication-snapshot-interval myprop/clust/ns1")); - verify(mockNamespaces).getDeduplicationSnapshotInterval("myprop/clust/ns1"); - namespaces.run(split("remove-deduplication-snapshot-interval myprop/clust/ns1")); - verify(mockNamespaces).removeDeduplicationSnapshotInterval("myprop/clust/ns1"); + namespaces.run(split("remove-message-ttl myprop/ns1")); + verify(mockNamespaces).removeNamespaceMessageTTL("myprop/ns1"); - namespaces.run(split("set-dispatcher-pause-on-ack-state-persistent myprop/clust/ns1")); - verify(mockNamespaces).setDispatcherPauseOnAckStatePersistent("myprop/clust/ns1"); + namespaces.run(split("set-deduplication-snapshot-interval myprop/ns1 -i 1000")); + verify(mockNamespaces).setDeduplicationSnapshotInterval("myprop/ns1", 1000); + namespaces.run(split("get-deduplication-snapshot-interval myprop/ns1")); + verify(mockNamespaces).getDeduplicationSnapshotInterval("myprop/ns1"); + namespaces.run(split("remove-deduplication-snapshot-interval myprop/ns1")); + verify(mockNamespaces).removeDeduplicationSnapshotInterval("myprop/ns1"); - namespaces.run(split("get-dispatcher-pause-on-ack-state-persistent myprop/clust/ns1")); - verify(mockNamespaces).getDispatcherPauseOnAckStatePersistent("myprop/clust/ns1"); + namespaces.run(split("set-dispatcher-pause-on-ack-state-persistent myprop/ns1")); + verify(mockNamespaces).setDispatcherPauseOnAckStatePersistent("myprop/ns1"); - namespaces.run(split("remove-dispatcher-pause-on-ack-state-persistent myprop/clust/ns1")); - verify(mockNamespaces).removeDispatcherPauseOnAckStatePersistent("myprop/clust/ns1"); + namespaces.run(split("get-dispatcher-pause-on-ack-state-persistent myprop/ns1")); + verify(mockNamespaces).getDispatcherPauseOnAckStatePersistent("myprop/ns1"); - } - - @Test - public void namespacesCreateV1() throws Exception { - PulsarAdmin admin = Mockito.mock(PulsarAdmin.class); - Namespaces mockNamespaces = mock(Namespaces.class); - when(admin.namespaces()).thenReturn(mockNamespaces); - CmdNamespaces namespaces = new CmdNamespaces(() -> admin); + namespaces.run(split("remove-dispatcher-pause-on-ack-state-persistent myprop/ns1")); + verify(mockNamespaces).removeDispatcherPauseOnAckStatePersistent("myprop/ns1"); - namespaces.run(split("create my-prop/my-cluster/my-namespace")); - verify(mockNamespaces).createNamespace("my-prop/my-cluster/my-namespace"); - } - - @Test - public void namespacesCreateV1WithBundlesAndClusters() throws Exception { - PulsarAdmin admin = Mockito.mock(PulsarAdmin.class); - Namespaces mockNamespaces = mock(Namespaces.class); - when(admin.namespaces()).thenReturn(mockNamespaces); - CmdNamespaces namespaces = new CmdNamespaces(() -> admin); - - namespaces.run(split("create my-prop/my-cluster/my-namespace --bundles 5 --clusters a,b,c")); - verify(mockNamespaces).createNamespace("my-prop/my-cluster/my-namespace", 5); - verify(mockNamespaces).setNamespaceReplicationClusters("my-prop/my-cluster/my-namespace", - Sets.newHashSet("a", "b", "c"), false); } @Test @@ -1008,17 +982,17 @@ public void resourceQuotas() throws Exception { when(admin.resourceQuotas()).thenReturn(mockResourceQuotas); cmdResourceQuotas = new CmdResourceQuotas(() -> admin); - cmdResourceQuotas.run(split("get --namespace myprop/clust/ns1 --bundle 0x80000000_0xffffffff")); - verify(mockResourceQuotas).getNamespaceBundleResourceQuota("myprop/clust/ns1", "0x80000000_0xffffffff"); + cmdResourceQuotas.run(split("get --namespace myprop/ns1 --bundle 0x80000000_0xffffffff")); + verify(mockResourceQuotas).getNamespaceBundleResourceQuota("myprop/ns1", "0x80000000_0xffffffff"); - cmdResourceQuotas.run(split("set --namespace myprop/clust/ns1 --bundle 0x80000000_0xffffffff -mi " + cmdResourceQuotas.run(split("set --namespace myprop/ns1 --bundle 0x80000000_0xffffffff -mi " + "10 -mo 20 -bi 10000 -bo 20000 -mem 100")); - verify(mockResourceQuotas).setNamespaceBundleResourceQuota("myprop/clust/ns1", + verify(mockResourceQuotas).setNamespaceBundleResourceQuota("myprop/ns1", "0x80000000_0xffffffff", quota); - cmdResourceQuotas.run(split("reset-namespace-bundle-quota --namespace myprop/clust/ns1 --bundle " + cmdResourceQuotas.run(split("reset-namespace-bundle-quota --namespace myprop/ns1 --bundle " + "0x80000000_0xffffffff")); - verify(mockResourceQuotas).resetNamespaceBundleResourceQuota("myprop/clust/ns1", + verify(mockResourceQuotas).resetNamespaceBundleResourceQuota("myprop/ns1", "0x80000000_0xffffffff"); } @@ -1052,272 +1026,272 @@ public void topicPolicies() throws Exception { CmdTopicPolicies cmdTopics = new CmdTopicPolicies(() -> admin); - cmdTopics.run(split("set-subscription-types-enabled persistent://myprop/clust/ns1/ds1 -t Shared,Failover")); - verify(mockTopicsPolicies).setSubscriptionTypesEnabled("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("set-subscription-types-enabled persistent://myprop/ns1/ds1 -t Shared,Failover")); + verify(mockTopicsPolicies).setSubscriptionTypesEnabled("persistent://myprop/ns1/ds1", Sets.newHashSet(SubscriptionType.Shared, SubscriptionType.Failover)); - cmdTopics.run(split("get-subscription-types-enabled persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getSubscriptionTypesEnabled("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("remove-subscription-types-enabled persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeSubscriptionTypesEnabled("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-subscription-types-enabled persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getSubscriptionTypesEnabled("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("remove-subscription-types-enabled persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeSubscriptionTypesEnabled("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-offload-policies persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getOffloadPolicies("persistent://myprop/clust/ns1/ds1", false); + cmdTopics.run(split("get-offload-policies persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getOffloadPolicies("persistent://myprop/ns1/ds1", false); - cmdTopics.run(split("remove-offload-policies persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeOffloadPolicies("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-offload-policies persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeOffloadPolicies("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("set-offload-policies persistent://myprop/clust/ns1/ds1 -d s3 -r" + cmdTopics.run(split("set-offload-policies persistent://myprop/ns1/ds1 -d s3 -r" + " region -b bucket -e endpoint -m 8 -rb 9 -t 10 -ts 10 -orp tiered-storage-first")); verify(mockTopicsPolicies) - .setOffloadPolicies("persistent://myprop/clust/ns1/ds1", OffloadPoliciesImpl.create( + .setOffloadPolicies("persistent://myprop/ns1/ds1", OffloadPoliciesImpl.create( "s3", "region", "bucket" , "endpoint", null, null, null, null, 8, 9, 10L, 10L, null, OffloadedReadPriority.TIERED_STORAGE_FIRST)); - cmdTopics.run(split("get-retention persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getRetention("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-retention persistent://myprop/clust/ns1/ds1 -t 10m -s 20M")); - verify(mockTopicsPolicies).setRetention("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-retention persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getRetention("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-retention persistent://myprop/ns1/ds1 -t 10m -s 20M")); + verify(mockTopicsPolicies).setRetention("persistent://myprop/ns1/ds1", new RetentionPolicies(10, 20)); // Test with default time unit (seconds) cmdTopics = new CmdTopicPolicies(() -> admin); reset(mockTopicsPolicies); - cmdTopics.run(split("set-retention persistent://myprop/clust/ns1/ds1 -t 180 -s 20M")); - verify(mockTopicsPolicies).setRetention("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("set-retention persistent://myprop/ns1/ds1 -t 180 -s 20M")); + verify(mockTopicsPolicies).setRetention("persistent://myprop/ns1/ds1", new RetentionPolicies(3, 20)); // Test with explicit time unit (seconds) cmdTopics = new CmdTopicPolicies(() -> admin); reset(mockTopicsPolicies); - cmdTopics.run(split("set-retention persistent://myprop/clust/ns1/ds1 -t 180s -s 20M")); - verify(mockTopicsPolicies).setRetention("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("set-retention persistent://myprop/ns1/ds1 -t 180s -s 20M")); + verify(mockTopicsPolicies).setRetention("persistent://myprop/ns1/ds1", new RetentionPolicies(3, 20)); // Test size with default size less than 1 mb cmdTopics = new CmdTopicPolicies(() -> admin); reset(mockTopicsPolicies); - cmdTopics.run(split("set-retention persistent://myprop/clust/ns1/ds1 -t 180 -s 4096")); - verify(mockTopicsPolicies).setRetention("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("set-retention persistent://myprop/ns1/ds1 -t 180 -s 4096")); + verify(mockTopicsPolicies).setRetention("persistent://myprop/ns1/ds1", new RetentionPolicies(3, 0)); // Test size with default size greater than 1mb cmdTopics = new CmdTopicPolicies(() -> admin); reset(mockTopicsPolicies); - cmdTopics.run(split("set-retention persistent://myprop/clust/ns1/ds1 -t 180 -s " + (2 * 1024 * 1024))); - verify(mockTopicsPolicies).setRetention("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("set-retention persistent://myprop/ns1/ds1 -t 180 -s " + (2 * 1024 * 1024))); + verify(mockTopicsPolicies).setRetention("persistent://myprop/ns1/ds1", new RetentionPolicies(3, 2)); - cmdTopics.run(split("remove-retention persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeRetention("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-retention persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeRetention("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-inactive-topic-policies persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getInactiveTopicPolicies("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-inactive-topic-policies persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeInactiveTopicPolicies("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-inactive-topic-policies persistent://myprop/clust/ns1/ds1" + cmdTopics.run(split("get-inactive-topic-policies persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getInactiveTopicPolicies("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-inactive-topic-policies persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeInactiveTopicPolicies("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-inactive-topic-policies persistent://myprop/ns1/ds1" + " -e -t 1s -m delete_when_no_subscriptions")); - verify(mockTopicsPolicies).setInactiveTopicPolicies("persistent://myprop/clust/ns1/ds1", + verify(mockTopicsPolicies).setInactiveTopicPolicies("persistent://myprop/ns1/ds1", new InactiveTopicPolicies( InactiveTopicDeleteMode.delete_when_no_subscriptions, 1, true)); - cmdTopics.run(split("get-compaction-threshold persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getCompactionThreshold("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-compaction-threshold persistent://myprop/clust/ns1/ds1 -t 10k")); - verify(mockTopicsPolicies).setCompactionThreshold("persistent://myprop/clust/ns1/ds1", 10 * 1024); - cmdTopics.run(split("remove-compaction-threshold persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeCompactionThreshold("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-max-producers persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getMaxProducers("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-max-producers persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeMaxProducers("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-producers persistent://myprop/clust/ns1/ds1 -p 99")); - verify(mockTopicsPolicies).setMaxProducers("persistent://myprop/clust/ns1/ds1", 99); - - cmdTopics.run(split("get-dispatch-rate persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopicsPolicies).getDispatchRate("persistent://myprop/clust/ns1/ds1", true); - cmdTopics.run(split("remove-dispatch-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeDispatchRate("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-dispatch-rate persistent://myprop/clust/ns1/ds1 -md -1 -bd -1 -dt 2")); - verify(mockTopicsPolicies).setDispatchRate("persistent://myprop/clust/ns1/ds1", DispatchRate.builder() + cmdTopics.run(split("get-compaction-threshold persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getCompactionThreshold("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-compaction-threshold persistent://myprop/ns1/ds1 -t 10k")); + verify(mockTopicsPolicies).setCompactionThreshold("persistent://myprop/ns1/ds1", 10 * 1024); + cmdTopics.run(split("remove-compaction-threshold persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeCompactionThreshold("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-max-producers persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getMaxProducers("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-max-producers persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeMaxProducers("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-producers persistent://myprop/ns1/ds1 -p 99")); + verify(mockTopicsPolicies).setMaxProducers("persistent://myprop/ns1/ds1", 99); + + cmdTopics.run(split("get-dispatch-rate persistent://myprop/ns1/ds1 -ap")); + verify(mockTopicsPolicies).getDispatchRate("persistent://myprop/ns1/ds1", true); + cmdTopics.run(split("remove-dispatch-rate persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeDispatchRate("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-dispatch-rate persistent://myprop/ns1/ds1 -md -1 -bd -1 -dt 2")); + verify(mockTopicsPolicies).setDispatchRate("persistent://myprop/ns1/ds1", DispatchRate.builder() .dispatchThrottlingRateInMsg(-1) .dispatchThrottlingRateInByte(-1) .ratePeriodInSecond(2) .build()); - cmdTopics.run(split("set-replicator-dispatch-rate persistent://myprop/clust/ns1/ds1 -md -1 -bd -1 -dt 2")); - verify(mockTopicsPolicies).setReplicatorDispatchRate("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("set-replicator-dispatch-rate persistent://myprop/ns1/ds1 -md -1 -bd -1 -dt 2")); + verify(mockTopicsPolicies).setReplicatorDispatchRate("persistent://myprop/ns1/ds1", DispatchRate.builder() .dispatchThrottlingRateInMsg(-1) .dispatchThrottlingRateInByte(-1) .ratePeriodInSecond(2) .build()); - cmdTopics.run(split("get-replicator-dispatch-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getReplicatorDispatchRate("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-replicator-dispatch-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeReplicatorDispatchRate("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-replicator-dispatch-rate persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getReplicatorDispatchRate("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-replicator-dispatch-rate persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeReplicatorDispatchRate("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("set-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1 -md -1 -bd -1 -dt 2")); - verify(mockTopicsPolicies).setSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("set-subscription-dispatch-rate persistent://myprop/ns1/ds1 -md -1 -bd -1 -dt 2")); + verify(mockTopicsPolicies).setSubscriptionDispatchRate("persistent://myprop/ns1/ds1", DispatchRate.builder() .dispatchThrottlingRateInMsg(-1) .dispatchThrottlingRateInByte(-1) .ratePeriodInSecond(2) .build()); - cmdTopics.run(split("get-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-subscription-dispatch-rate persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getSubscriptionDispatchRate("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-subscription-dispatch-rate persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeSubscriptionDispatchRate("persistent://myprop/ns1/ds1"); cmdTopics = new CmdTopicPolicies(() -> admin); cmdTopics.run(split( - "set-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1 -s sub -md -1 -bd -1 -dt 3")); - verify(mockTopicsPolicies).setSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1", "sub", + "set-subscription-dispatch-rate persistent://myprop/ns1/ds1 -s sub -md -1 -bd -1 -dt 3")); + verify(mockTopicsPolicies).setSubscriptionDispatchRate("persistent://myprop/ns1/ds1", "sub", DispatchRate.builder() .dispatchThrottlingRateInMsg(-1) .dispatchThrottlingRateInByte(-1) .ratePeriodInSecond(3) .build()); - cmdTopics.run(split("get-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1 -s sub")); - verify(mockTopicsPolicies).getSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-subscription-dispatch-rate persistent://myprop/ns1/ds1 -s sub")); + verify(mockTopicsPolicies).getSubscriptionDispatchRate("persistent://myprop/ns1/ds1", "sub", false); - cmdTopics.run(split("remove-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1 -s sub")); - verify(mockTopicsPolicies).removeSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("remove-subscription-dispatch-rate persistent://myprop/ns1/ds1 -s sub")); + verify(mockTopicsPolicies).removeSubscriptionDispatchRate("persistent://myprop/ns1/ds1", "sub"); - cmdTopics.run(split("get-persistence persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getPersistence("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-persistence persistent://myprop/clust/ns1/ds1 -e 2 -w 1 -a 1 -r 100.0")); - verify(mockTopicsPolicies).setPersistence("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-persistence persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getPersistence("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-persistence persistent://myprop/ns1/ds1 -e 2 -w 1 -a 1 -r 100.0")); + verify(mockTopicsPolicies).setPersistence("persistent://myprop/ns1/ds1", new PersistencePolicies(2, 1, 1, 100.0d)); - cmdTopics.run(split("remove-persistence persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removePersistence("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-publish-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getPublishRate("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-publish-rate persistent://myprop/clust/ns1/ds1 -m 10 -b 100")); - verify(mockTopicsPolicies).setPublishRate("persistent://myprop/clust/ns1/ds1", new PublishRate(10, 100)); - cmdTopics.run(split("remove-publish-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removePublishRate("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-subscribe-rate persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopicsPolicies).getSubscribeRate("persistent://myprop/clust/ns1/ds1", true); - cmdTopics.run(split("set-subscribe-rate persistent://myprop/clust/ns1/ds1 -sr 10 -st 100")); - verify(mockTopicsPolicies).setSubscribeRate("persistent://myprop/clust/ns1/ds1", new SubscribeRate(10, 100)); - cmdTopics.run(split("remove-subscribe-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeSubscribeRate("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-max-message-size persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getMaxMessageSize("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-message-size persistent://myprop/clust/ns1/ds1 -m 1000")); - verify(mockTopicsPolicies).setMaxMessageSize("persistent://myprop/clust/ns1/ds1", 1000); - cmdTopics.run(split("remove-max-message-size persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeMaxMessageSize("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-max-consumers persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getMaxConsumers("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-max-consumers persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeMaxConsumers("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-consumers persistent://myprop/clust/ns1/ds1 -c 99")); - verify(mockTopicsPolicies).setMaxConsumers("persistent://myprop/clust/ns1/ds1", 99); - - cmdTopics.run(split("remove-max-unacked-messages-per-consumer persistent://myprop/clust/ns1/ds1")); + cmdTopics.run(split("remove-persistence persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removePersistence("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-publish-rate persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getPublishRate("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-publish-rate persistent://myprop/ns1/ds1 -m 10 -b 100")); + verify(mockTopicsPolicies).setPublishRate("persistent://myprop/ns1/ds1", new PublishRate(10, 100)); + cmdTopics.run(split("remove-publish-rate persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removePublishRate("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-subscribe-rate persistent://myprop/ns1/ds1 -ap")); + verify(mockTopicsPolicies).getSubscribeRate("persistent://myprop/ns1/ds1", true); + cmdTopics.run(split("set-subscribe-rate persistent://myprop/ns1/ds1 -sr 10 -st 100")); + verify(mockTopicsPolicies).setSubscribeRate("persistent://myprop/ns1/ds1", new SubscribeRate(10, 100)); + cmdTopics.run(split("remove-subscribe-rate persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeSubscribeRate("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-max-message-size persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getMaxMessageSize("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-message-size persistent://myprop/ns1/ds1 -m 1000")); + verify(mockTopicsPolicies).setMaxMessageSize("persistent://myprop/ns1/ds1", 1000); + cmdTopics.run(split("remove-max-message-size persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeMaxMessageSize("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-max-consumers persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getMaxConsumers("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-max-consumers persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeMaxConsumers("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-consumers persistent://myprop/ns1/ds1 -c 99")); + verify(mockTopicsPolicies).setMaxConsumers("persistent://myprop/ns1/ds1", 99); + + cmdTopics.run(split("remove-max-unacked-messages-per-consumer persistent://myprop/ns1/ds1")); verify(mockTopicsPolicies, times(1)).removeMaxUnackedMessagesOnConsumer( - "persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("get-max-unacked-messages-per-consumer persistent://myprop/clust/ns1/ds1")); + "persistent://myprop/ns1/ds1"); + cmdTopics.run(split("get-max-unacked-messages-per-consumer persistent://myprop/ns1/ds1")); verify(mockTopicsPolicies, times(1)) - .getMaxUnackedMessagesOnConsumer("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-max-unacked-messages-per-consumer persistent://myprop/clust/ns1/ds1 -m 999")); + .getMaxUnackedMessagesOnConsumer("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-max-unacked-messages-per-consumer persistent://myprop/ns1/ds1 -m 999")); verify(mockTopicsPolicies, times(1)).setMaxUnackedMessagesOnConsumer( - "persistent://myprop/clust/ns1/ds1", 999); - - cmdTopics.run(split("get-message-ttl persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getMessageTTL("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-message-ttl persistent://myprop/clust/ns1/ds1 -t 10")); - verify(mockTopicsPolicies).setMessageTTL("persistent://myprop/clust/ns1/ds1", 10); - cmdTopics.run(split("remove-message-ttl persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeMessageTTL("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("get-subscription-expiration-time persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getSubscriptionExpirationTime("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-subscription-expiration-time persistent://myprop/clust/ns1/ds1 -t 10")); - verify(mockTopicsPolicies).setSubscriptionExpirationTime("persistent://myprop/clust/ns1/ds1", 10); - cmdTopics.run(split("remove-subscription-expiration-time persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeSubscriptionExpirationTime("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-max-consumers-per-subscription persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getMaxConsumersPerSubscription("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-consumers-per-subscription persistent://myprop/clust/ns1/ds1 -c 5")); - verify(mockTopicsPolicies).setMaxConsumersPerSubscription("persistent://myprop/clust/ns1/ds1", 5); - cmdTopics.run(split("remove-max-consumers-per-subscription persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeMaxConsumersPerSubscription("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-max-unacked-messages-per-subscription persistent://myprop/clust/ns1/ds1")); + "persistent://myprop/ns1/ds1", 999); + + cmdTopics.run(split("get-message-ttl persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getMessageTTL("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-message-ttl persistent://myprop/ns1/ds1 -t 10")); + verify(mockTopicsPolicies).setMessageTTL("persistent://myprop/ns1/ds1", 10); + cmdTopics.run(split("remove-message-ttl persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeMessageTTL("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("get-subscription-expiration-time persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getSubscriptionExpirationTime("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-subscription-expiration-time persistent://myprop/ns1/ds1 -t 10")); + verify(mockTopicsPolicies).setSubscriptionExpirationTime("persistent://myprop/ns1/ds1", 10); + cmdTopics.run(split("remove-subscription-expiration-time persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeSubscriptionExpirationTime("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-max-consumers-per-subscription persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getMaxConsumersPerSubscription("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-consumers-per-subscription persistent://myprop/ns1/ds1 -c 5")); + verify(mockTopicsPolicies).setMaxConsumersPerSubscription("persistent://myprop/ns1/ds1", 5); + cmdTopics.run(split("remove-max-consumers-per-subscription persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeMaxConsumersPerSubscription("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-max-unacked-messages-per-subscription persistent://myprop/ns1/ds1")); verify(mockTopicsPolicies, times(1)).getMaxUnackedMessagesOnSubscription( - "persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-max-unacked-messages-per-subscription persistent://myprop/clust/ns1/ds1")); + "persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-max-unacked-messages-per-subscription persistent://myprop/ns1/ds1")); verify(mockTopicsPolicies, times(1)).removeMaxUnackedMessagesOnSubscription( - "persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-unacked-messages-per-subscription persistent://myprop/clust/ns1/ds1 -m 99")); + "persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-unacked-messages-per-subscription persistent://myprop/ns1/ds1 -m 99")); verify(mockTopicsPolicies, times(1)).setMaxUnackedMessagesOnSubscription( - "persistent://myprop/clust/ns1/ds1", 99); + "persistent://myprop/ns1/ds1", 99); - cmdTopics.run(split("get-delayed-delivery persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getDelayedDeliveryPolicy("persistent://myprop/clust/ns1/ds1", false); + cmdTopics.run(split("get-delayed-delivery persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getDelayedDeliveryPolicy("persistent://myprop/ns1/ds1", false); cmdTopics.run(split( - "set-delayed-delivery persistent://myprop/clust/ns1/ds1 -t 10s --enable --maxDelay 5s")); - verify(mockTopicsPolicies).setDelayedDeliveryPolicy("persistent://myprop/clust/ns1/ds1", + "set-delayed-delivery persistent://myprop/ns1/ds1 -t 10s --enable --maxDelay 5s")); + verify(mockTopicsPolicies).setDelayedDeliveryPolicy("persistent://myprop/ns1/ds1", DelayedDeliveryPolicies.builder().tickTime(10000).active(true) .maxDeliveryDelayInMillis(5000).build()); - cmdTopics.run(split("remove-delayed-delivery persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeDelayedDeliveryPolicy("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-deduplication persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getDeduplicationStatus("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-deduplication persistent://myprop/clust/ns1/ds1 --disable")); - verify(mockTopicsPolicies).setDeduplicationStatus("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-deduplication persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeDeduplicationStatus("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-max-subscriptions-per-topic persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getMaxSubscriptionsPerTopic("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-subscriptions-per-topic persistent://myprop/clust/ns1/ds1 -s 1024")); - verify(mockTopicsPolicies).setMaxSubscriptionsPerTopic("persistent://myprop/clust/ns1/ds1", 1024); - cmdTopics.run(split("remove-max-subscriptions-per-topic persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeMaxSubscriptionsPerTopic("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-deduplication-snapshot-interval persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).getDeduplicationSnapshotInterval("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-deduplication-snapshot-interval persistent://myprop/clust/ns1/ds1 -i 100")); - verify(mockTopicsPolicies).setDeduplicationSnapshotInterval("persistent://myprop/clust/ns1/ds1", 100); - cmdTopics.run(split("remove-deduplication-snapshot-interval persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeDeduplicationSnapshotInterval("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-delayed-delivery persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeDelayedDeliveryPolicy("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-deduplication persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getDeduplicationStatus("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-deduplication persistent://myprop/ns1/ds1 --disable")); + verify(mockTopicsPolicies).setDeduplicationStatus("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-deduplication persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeDeduplicationStatus("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-max-subscriptions-per-topic persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getMaxSubscriptionsPerTopic("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-subscriptions-per-topic persistent://myprop/ns1/ds1 -s 1024")); + verify(mockTopicsPolicies).setMaxSubscriptionsPerTopic("persistent://myprop/ns1/ds1", 1024); + cmdTopics.run(split("remove-max-subscriptions-per-topic persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeMaxSubscriptionsPerTopic("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-deduplication-snapshot-interval persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).getDeduplicationSnapshotInterval("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-deduplication-snapshot-interval persistent://myprop/ns1/ds1 -i 100")); + verify(mockTopicsPolicies).setDeduplicationSnapshotInterval("persistent://myprop/ns1/ds1", 100); + cmdTopics.run(split("remove-deduplication-snapshot-interval persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeDeduplicationSnapshotInterval("persistent://myprop/ns1/ds1"); // Reset the cmd, and check global option cmdTopics = new CmdTopicPolicies(() -> admin); - cmdTopics.run(split("get-retention persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getRetention("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-retention persistent://myprop/clust/ns1/ds1 -t 10m -s 20M -g")); - verify(mockGlobalTopicsPolicies).setRetention("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-retention persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getRetention("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-retention persistent://myprop/ns1/ds1 -t 10m -s 20M -g")); + verify(mockGlobalTopicsPolicies).setRetention("persistent://myprop/ns1/ds1", new RetentionPolicies(10, 20)); cmdTopics = new CmdTopicPolicies(() -> admin); - cmdTopics.run(split("set-retention persistent://myprop/clust/ns1/ds1 -t 1440s -s 20M -g")); - verify(mockGlobalTopicsPolicies).setRetention("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("set-retention persistent://myprop/ns1/ds1 -t 1440s -s 20M -g")); + verify(mockGlobalTopicsPolicies).setRetention("persistent://myprop/ns1/ds1", new RetentionPolicies(24, 20)); cmdTopics = new CmdTopicPolicies(() -> admin); reset(mockGlobalTopicsPolicies); - cmdTopics.run(split("set-retention persistent://myprop/clust/ns1/ds1 -t 1440 -s 20M -g")); - verify(mockGlobalTopicsPolicies).setRetention("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("set-retention persistent://myprop/ns1/ds1 -t 1440 -s 20M -g")); + verify(mockGlobalTopicsPolicies).setRetention("persistent://myprop/ns1/ds1", new RetentionPolicies(24, 20)); - cmdTopics.run(split("remove-retention persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeRetention("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-retention persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeRetention("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-backlog-quota persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopicsPolicies).getBacklogQuotaMap("persistent://myprop/clust/ns1/ds1", true); - cmdTopics.run(split("set-backlog-quota persistent://myprop/clust/ns1/ds1 -l 10 -p producer_request_hold")); - verify(mockTopicsPolicies).setBacklogQuota("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-backlog-quota persistent://myprop/ns1/ds1 -ap")); + verify(mockTopicsPolicies).getBacklogQuotaMap("persistent://myprop/ns1/ds1", true); + cmdTopics.run(split("set-backlog-quota persistent://myprop/ns1/ds1 -l 10 -p producer_request_hold")); + verify(mockTopicsPolicies).setBacklogQuota("persistent://myprop/ns1/ds1", BacklogQuota.builder() .limitSize(10) .retentionPolicy(RetentionPolicy.producer_request_hold) @@ -1325,11 +1299,11 @@ public void topicPolicies() throws Exception { BacklogQuota.BacklogQuotaType.destination_storage); //cmd with option cannot be executed repeatedly. cmdTopics = new CmdTopicPolicies(() -> admin); - cmdTopics.run(split("set-message-ttl persistent://myprop/clust/ns1/ds1 -t 10h")); - verify(mockTopicsPolicies).setMessageTTL("persistent://myprop/clust/ns1/ds1", 10 * 60 * 60); - cmdTopics.run(split("set-backlog-quota persistent://myprop/clust/ns1/ds1 -lt 1w -p " + cmdTopics.run(split("set-message-ttl persistent://myprop/ns1/ds1 -t 10h")); + verify(mockTopicsPolicies).setMessageTTL("persistent://myprop/ns1/ds1", 10 * 60 * 60); + cmdTopics.run(split("set-backlog-quota persistent://myprop/ns1/ds1 -lt 1w -p " + "consumer_backlog_eviction -t message_age")); - verify(mockTopicsPolicies).setBacklogQuota("persistent://myprop/clust/ns1/ds1", + verify(mockTopicsPolicies).setBacklogQuota("persistent://myprop/ns1/ds1", BacklogQuota.builder() .limitTime(60 * 60 * 24 * 7) .retentionPolicy(RetentionPolicy.consumer_backlog_eviction) @@ -1337,9 +1311,9 @@ public void topicPolicies() throws Exception { BacklogQuota.BacklogQuotaType.message_age); //cmd with option cannot be executed repeatedly. cmdTopics = new CmdTopicPolicies(() -> admin); - cmdTopics.run(split("set-backlog-quota persistent://myprop/clust/ns1/ds1 -lt 1000 -p " + cmdTopics.run(split("set-backlog-quota persistent://myprop/ns1/ds1 -lt 1000 -p " + "producer_request_hold -t message_age")); - verify(mockTopicsPolicies).setBacklogQuota("persistent://myprop/clust/ns1/ds1", + verify(mockTopicsPolicies).setBacklogQuota("persistent://myprop/ns1/ds1", BacklogQuota.builder() .limitTime(1000) .retentionPolicy(RetentionPolicy.producer_request_hold) @@ -1347,240 +1321,240 @@ public void topicPolicies() throws Exception { BacklogQuota.BacklogQuotaType.message_age); //cmd with option cannot be executed repeatedly. cmdTopics = new CmdTopicPolicies(() -> admin); - Assert.assertFalse(cmdTopics.run(split("set-backlog-quota persistent://myprop/clust/ns1/ds1 " + Assert.assertFalse(cmdTopics.run(split("set-backlog-quota persistent://myprop/ns1/ds1 " + "-l 1000 -p producer_request_hold -t message_age"))); cmdTopics = new CmdTopicPolicies(() -> admin); - Assert.assertFalse(cmdTopics.run(split("set-backlog-quota persistent://myprop/clust/ns1/ds1 " + Assert.assertFalse(cmdTopics.run(split("set-backlog-quota persistent://myprop/ns1/ds1 " + "-lt 60 -p producer_request_hold -t destination_storage"))); //cmd with option cannot be executed repeatedly. cmdTopics = new CmdTopicPolicies(() -> admin); - cmdTopics.run(split("remove-backlog-quota persistent://myprop/clust/ns1/ds1")); - verify(mockTopicsPolicies).removeBacklogQuota("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("remove-backlog-quota persistent://myprop/ns1/ds1")); + verify(mockTopicsPolicies).removeBacklogQuota("persistent://myprop/ns1/ds1", BacklogQuota.BacklogQuotaType.destination_storage); //cmd with option cannot be executed repeatedly. cmdTopics = new CmdTopicPolicies(() -> admin); - cmdTopics.run(split("remove-backlog-quota persistent://myprop/clust/ns1/ds1 -t message_age")); - verify(mockTopicsPolicies).removeBacklogQuota("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("remove-backlog-quota persistent://myprop/ns1/ds1 -t message_age")); + verify(mockTopicsPolicies).removeBacklogQuota("persistent://myprop/ns1/ds1", BacklogQuota.BacklogQuotaType.message_age); - cmdTopics.run(split("get-max-producers persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getMaxProducers("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-max-producers persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeMaxProducers("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-producers persistent://myprop/clust/ns1/ds1 -p 99 -g")); - verify(mockGlobalTopicsPolicies).setMaxProducers("persistent://myprop/clust/ns1/ds1", 99); + cmdTopics.run(split("get-max-producers persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getMaxProducers("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-max-producers persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeMaxProducers("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-producers persistent://myprop/ns1/ds1 -p 99 -g")); + verify(mockGlobalTopicsPolicies).setMaxProducers("persistent://myprop/ns1/ds1", 99); - cmdTopics.run(split("remove-max-unacked-messages-per-consumer persistent://myprop/clust/ns1/ds1 -g")); + cmdTopics.run(split("remove-max-unacked-messages-per-consumer persistent://myprop/ns1/ds1 -g")); verify(mockGlobalTopicsPolicies, times(1)) - .removeMaxUnackedMessagesOnConsumer("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("get-max-unacked-messages-per-consumer persistent://myprop/clust/ns1/ds1 -g")); + .removeMaxUnackedMessagesOnConsumer("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("get-max-unacked-messages-per-consumer persistent://myprop/ns1/ds1 -g")); verify(mockGlobalTopicsPolicies, times(1)) - .getMaxUnackedMessagesOnConsumer("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-max-unacked-messages-per-consumer persistent://myprop/clust/ns1/ds1 -m 999 -g")); + .getMaxUnackedMessagesOnConsumer("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-max-unacked-messages-per-consumer persistent://myprop/ns1/ds1 -m 999 -g")); verify(mockGlobalTopicsPolicies, times(1)) - .setMaxUnackedMessagesOnConsumer("persistent://myprop/clust/ns1/ds1", 999); - - cmdTopics.run(split("get-message-ttl persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getMessageTTL("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-message-ttl persistent://myprop/clust/ns1/ds1 -t 10 -g")); - verify(mockGlobalTopicsPolicies).setMessageTTL("persistent://myprop/clust/ns1/ds1", 10); - cmdTopics.run(split("remove-message-ttl persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeMessageTTL("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("get-subscription-expiration-time persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getSubscriptionExpirationTime("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-subscription-expiration-time persistent://myprop/clust/ns1/ds1 -t 10 -g")); - verify(mockGlobalTopicsPolicies).setSubscriptionExpirationTime("persistent://myprop/clust/ns1/ds1", 10); - cmdTopics.run(split("remove-subscription-expiration-time persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeSubscriptionExpirationTime("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-persistence persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getPersistence("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-persistence persistent://myprop/clust/ns1/ds1 -e 2 -w 1 -a 1 -r 100.0 -g")); - verify(mockGlobalTopicsPolicies).setPersistence("persistent://myprop/clust/ns1/ds1", + .setMaxUnackedMessagesOnConsumer("persistent://myprop/ns1/ds1", 999); + + cmdTopics.run(split("get-message-ttl persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getMessageTTL("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-message-ttl persistent://myprop/ns1/ds1 -t 10 -g")); + verify(mockGlobalTopicsPolicies).setMessageTTL("persistent://myprop/ns1/ds1", 10); + cmdTopics.run(split("remove-message-ttl persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeMessageTTL("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("get-subscription-expiration-time persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getSubscriptionExpirationTime("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-subscription-expiration-time persistent://myprop/ns1/ds1 -t 10 -g")); + verify(mockGlobalTopicsPolicies).setSubscriptionExpirationTime("persistent://myprop/ns1/ds1", 10); + cmdTopics.run(split("remove-subscription-expiration-time persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeSubscriptionExpirationTime("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-persistence persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getPersistence("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-persistence persistent://myprop/ns1/ds1 -e 2 -w 1 -a 1 -r 100.0 -g")); + verify(mockGlobalTopicsPolicies).setPersistence("persistent://myprop/ns1/ds1", new PersistencePolicies(2, 1, 1, 100.0d)); - cmdTopics.run(split("remove-persistence persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removePersistence("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-persistence persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removePersistence("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-max-unacked-messages-per-subscription persistent://myprop/clust/ns1/ds1 -g")); + cmdTopics.run(split("get-max-unacked-messages-per-subscription persistent://myprop/ns1/ds1 -g")); verify(mockGlobalTopicsPolicies, times(1)) - .getMaxUnackedMessagesOnSubscription("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-max-unacked-messages-per-subscription persistent://myprop/clust/ns1/ds1 -g")); + .getMaxUnackedMessagesOnSubscription("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-max-unacked-messages-per-subscription persistent://myprop/ns1/ds1 -g")); verify(mockGlobalTopicsPolicies, times(1)) - .removeMaxUnackedMessagesOnSubscription("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-unacked-messages-per-subscription persistent://myprop/clust/ns1/ds1 -m 99 -g")); + .removeMaxUnackedMessagesOnSubscription("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-unacked-messages-per-subscription persistent://myprop/ns1/ds1 -m 99 -g")); verify(mockGlobalTopicsPolicies, times(1)) - .setMaxUnackedMessagesOnSubscription("persistent://myprop/clust/ns1/ds1", 99); + .setMaxUnackedMessagesOnSubscription("persistent://myprop/ns1/ds1", 99); - cmdTopics.run(split("get-inactive-topic-policies persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getInactiveTopicPolicies("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-inactive-topic-policies persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeInactiveTopicPolicies("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-inactive-topic-policies persistent://myprop/clust/ns1/ds1" + cmdTopics.run(split("get-inactive-topic-policies persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getInactiveTopicPolicies("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-inactive-topic-policies persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeInactiveTopicPolicies("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-inactive-topic-policies persistent://myprop/ns1/ds1" + " -e -t 1s -m delete_when_no_subscriptions -g")); - verify(mockGlobalTopicsPolicies).setInactiveTopicPolicies("persistent://myprop/clust/ns1/ds1", + verify(mockGlobalTopicsPolicies).setInactiveTopicPolicies("persistent://myprop/ns1/ds1", new InactiveTopicPolicies(InactiveTopicDeleteMode.delete_when_no_subscriptions, 1, true)); - cmdTopics.run(split("get-dispatch-rate persistent://myprop/clust/ns1/ds1 -ap -g")); - verify(mockGlobalTopicsPolicies).getDispatchRate("persistent://myprop/clust/ns1/ds1", true); - cmdTopics.run(split("remove-dispatch-rate persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeDispatchRate("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-dispatch-rate persistent://myprop/clust/ns1/ds1 -md -1 -bd -1 -dt 2 -g")); - verify(mockGlobalTopicsPolicies).setDispatchRate("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-dispatch-rate persistent://myprop/ns1/ds1 -ap -g")); + verify(mockGlobalTopicsPolicies).getDispatchRate("persistent://myprop/ns1/ds1", true); + cmdTopics.run(split("remove-dispatch-rate persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeDispatchRate("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-dispatch-rate persistent://myprop/ns1/ds1 -md -1 -bd -1 -dt 2 -g")); + verify(mockGlobalTopicsPolicies).setDispatchRate("persistent://myprop/ns1/ds1", DispatchRate.builder() .dispatchThrottlingRateInMsg(-1) .dispatchThrottlingRateInByte(-1) .ratePeriodInSecond(2) .build()); - cmdTopics.run(split("get-publish-rate persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getPublishRate("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-publish-rate persistent://myprop/clust/ns1/ds1 -m 10 -b 100 -g")); - verify(mockGlobalTopicsPolicies).setPublishRate("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-publish-rate persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getPublishRate("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-publish-rate persistent://myprop/ns1/ds1 -m 10 -b 100 -g")); + verify(mockGlobalTopicsPolicies).setPublishRate("persistent://myprop/ns1/ds1", new PublishRate(10, 100)); - cmdTopics.run(split("remove-publish-rate persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removePublishRate("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-publish-rate persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removePublishRate("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-subscribe-rate persistent://myprop/clust/ns1/ds1 -ap -g")); - verify(mockGlobalTopicsPolicies).getSubscribeRate("persistent://myprop/clust/ns1/ds1", true); - cmdTopics.run(split("set-subscribe-rate persistent://myprop/clust/ns1/ds1 -sr 10 -st 100 -g")); - verify(mockGlobalTopicsPolicies).setSubscribeRate("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-subscribe-rate persistent://myprop/ns1/ds1 -ap -g")); + verify(mockGlobalTopicsPolicies).getSubscribeRate("persistent://myprop/ns1/ds1", true); + cmdTopics.run(split("set-subscribe-rate persistent://myprop/ns1/ds1 -sr 10 -st 100 -g")); + verify(mockGlobalTopicsPolicies).setSubscribeRate("persistent://myprop/ns1/ds1", new SubscribeRate(10, 100)); - cmdTopics.run(split("remove-subscribe-rate persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeSubscribeRate("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-subscribe-rate persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeSubscribeRate("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-delayed-delivery persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getDelayedDeliveryPolicy("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-delayed-delivery persistent://myprop/clust/ns1/ds1 -t 10s --enable -md 5s -g")); - verify(mockGlobalTopicsPolicies).setDelayedDeliveryPolicy("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-delayed-delivery persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getDelayedDeliveryPolicy("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-delayed-delivery persistent://myprop/ns1/ds1 -t 10s --enable -md 5s -g")); + verify(mockGlobalTopicsPolicies).setDelayedDeliveryPolicy("persistent://myprop/ns1/ds1", DelayedDeliveryPolicies.builder().tickTime(10000).active(true) .maxDeliveryDelayInMillis(5000).build()); - cmdTopics.run(split("remove-delayed-delivery persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeDelayedDeliveryPolicy("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-max-message-size persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getMaxMessageSize("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-message-size persistent://myprop/clust/ns1/ds1 -m 1000 -g")); - verify(mockGlobalTopicsPolicies).setMaxMessageSize("persistent://myprop/clust/ns1/ds1", 1000); - cmdTopics.run(split("remove-max-message-size persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeMaxMessageSize("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-deduplication persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getDeduplicationStatus("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-deduplication persistent://myprop/clust/ns1/ds1 --disable -g")); - verify(mockGlobalTopicsPolicies).setDeduplicationStatus("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-deduplication persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeDeduplicationStatus("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-deduplication-snapshot-interval persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getDeduplicationSnapshotInterval("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-deduplication-snapshot-interval persistent://myprop/clust/ns1/ds1 -i 100 -g")); - verify(mockGlobalTopicsPolicies).setDeduplicationSnapshotInterval("persistent://myprop/clust/ns1/ds1", 100); - cmdTopics.run(split("remove-deduplication-snapshot-interval persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeDeduplicationSnapshotInterval("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-max-consumers-per-subscription persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getMaxConsumersPerSubscription("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-consumers-per-subscription persistent://myprop/clust/ns1/ds1 -c 5 -g")); - verify(mockGlobalTopicsPolicies).setMaxConsumersPerSubscription("persistent://myprop/clust/ns1/ds1", 5); - cmdTopics.run(split("remove-max-consumers-per-subscription persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeMaxConsumersPerSubscription("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("set-subscription-types-enabled persistent://myprop/clust/ns1/ds1 -t " + cmdTopics.run(split("remove-delayed-delivery persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeDelayedDeliveryPolicy("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-max-message-size persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getMaxMessageSize("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-message-size persistent://myprop/ns1/ds1 -m 1000 -g")); + verify(mockGlobalTopicsPolicies).setMaxMessageSize("persistent://myprop/ns1/ds1", 1000); + cmdTopics.run(split("remove-max-message-size persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeMaxMessageSize("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-deduplication persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getDeduplicationStatus("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-deduplication persistent://myprop/ns1/ds1 --disable -g")); + verify(mockGlobalTopicsPolicies).setDeduplicationStatus("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-deduplication persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeDeduplicationStatus("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-deduplication-snapshot-interval persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getDeduplicationSnapshotInterval("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-deduplication-snapshot-interval persistent://myprop/ns1/ds1 -i 100 -g")); + verify(mockGlobalTopicsPolicies).setDeduplicationSnapshotInterval("persistent://myprop/ns1/ds1", 100); + cmdTopics.run(split("remove-deduplication-snapshot-interval persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeDeduplicationSnapshotInterval("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-max-consumers-per-subscription persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getMaxConsumersPerSubscription("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-consumers-per-subscription persistent://myprop/ns1/ds1 -c 5 -g")); + verify(mockGlobalTopicsPolicies).setMaxConsumersPerSubscription("persistent://myprop/ns1/ds1", 5); + cmdTopics.run(split("remove-max-consumers-per-subscription persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeMaxConsumersPerSubscription("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("set-subscription-types-enabled persistent://myprop/ns1/ds1 -t " + "Shared,Failover -g")); - verify(mockGlobalTopicsPolicies).setSubscriptionTypesEnabled("persistent://myprop/clust/ns1/ds1", + verify(mockGlobalTopicsPolicies).setSubscriptionTypesEnabled("persistent://myprop/ns1/ds1", Sets.newHashSet(SubscriptionType.Shared, SubscriptionType.Failover)); - cmdTopics.run(split("get-subscription-types-enabled persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getSubscriptionTypesEnabled("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("remove-subscription-types-enabled persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeSubscriptionTypesEnabled("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-max-consumers persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getMaxConsumers("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-max-consumers persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeMaxConsumers("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-consumers persistent://myprop/clust/ns1/ds1 -c 99 -g")); - verify(mockGlobalTopicsPolicies).setMaxConsumers("persistent://myprop/clust/ns1/ds1", 99); - - cmdTopics.run(split("get-compaction-threshold persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getCompactionThreshold("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-compaction-threshold persistent://myprop/clust/ns1/ds1 -t 10k -g")); - verify(mockGlobalTopicsPolicies).setCompactionThreshold("persistent://myprop/clust/ns1/ds1", 10 * 1024); - cmdTopics.run(split("remove-compaction-threshold persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeCompactionThreshold("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("set-replicator-dispatch-rate persistent://myprop/clust/ns1/ds1 -md -1 -bd -1 " + cmdTopics.run(split("get-subscription-types-enabled persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getSubscriptionTypesEnabled("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("remove-subscription-types-enabled persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeSubscriptionTypesEnabled("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-max-consumers persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getMaxConsumers("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-max-consumers persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeMaxConsumers("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-consumers persistent://myprop/ns1/ds1 -c 99 -g")); + verify(mockGlobalTopicsPolicies).setMaxConsumers("persistent://myprop/ns1/ds1", 99); + + cmdTopics.run(split("get-compaction-threshold persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getCompactionThreshold("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-compaction-threshold persistent://myprop/ns1/ds1 -t 10k -g")); + verify(mockGlobalTopicsPolicies).setCompactionThreshold("persistent://myprop/ns1/ds1", 10 * 1024); + cmdTopics.run(split("remove-compaction-threshold persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeCompactionThreshold("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("set-replicator-dispatch-rate persistent://myprop/ns1/ds1 -md -1 -bd -1 " + "-dt 2 -g")); - verify(mockGlobalTopicsPolicies).setReplicatorDispatchRate("persistent://myprop/clust/ns1/ds1", + verify(mockGlobalTopicsPolicies).setReplicatorDispatchRate("persistent://myprop/ns1/ds1", DispatchRate.builder() .dispatchThrottlingRateInMsg(-1) .dispatchThrottlingRateInByte(-1) .ratePeriodInSecond(2) .build()); - cmdTopics.run(split("get-replicator-dispatch-rate persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getReplicatorDispatchRate("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-replicator-dispatch-rate persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeReplicatorDispatchRate("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-replicator-dispatch-rate persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getReplicatorDispatchRate("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-replicator-dispatch-rate persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeReplicatorDispatchRate("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("set-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1 -md -1 -bd -1 " + cmdTopics.run(split("set-subscription-dispatch-rate persistent://myprop/ns1/ds1 -md -1 -bd -1 " + "-dt 2 -g")); - verify(mockGlobalTopicsPolicies).setSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1", + verify(mockGlobalTopicsPolicies).setSubscriptionDispatchRate("persistent://myprop/ns1/ds1", DispatchRate.builder() .dispatchThrottlingRateInMsg(-1) .dispatchThrottlingRateInByte(-1) .ratePeriodInSecond(2) .build()); - cmdTopics.run(split("get-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-subscription-dispatch-rate persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getSubscriptionDispatchRate("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-subscription-dispatch-rate persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeSubscriptionDispatchRate("persistent://myprop/ns1/ds1"); cmdTopics = new CmdTopicPolicies(() -> admin); - cmdTopics.run(split("set-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1 -s sub -md -1 " + cmdTopics.run(split("set-subscription-dispatch-rate persistent://myprop/ns1/ds1 -s sub -md -1 " + "-bd -1 -dt 2 -g")); - verify(mockGlobalTopicsPolicies).setSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1", "sub", + verify(mockGlobalTopicsPolicies).setSubscriptionDispatchRate("persistent://myprop/ns1/ds1", "sub", DispatchRate.builder() .dispatchThrottlingRateInMsg(-1) .dispatchThrottlingRateInByte(-1) .ratePeriodInSecond(2) .build()); - cmdTopics.run(split("get-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1 -s sub -g")); - verify(mockGlobalTopicsPolicies).getSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-subscription-dispatch-rate persistent://myprop/ns1/ds1 -s sub -g")); + verify(mockGlobalTopicsPolicies).getSubscriptionDispatchRate("persistent://myprop/ns1/ds1", "sub", false); - cmdTopics.run(split("remove-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1 -s sub -g")); - verify(mockGlobalTopicsPolicies).removeSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("remove-subscription-dispatch-rate persistent://myprop/ns1/ds1 -s sub -g")); + verify(mockGlobalTopicsPolicies).removeSubscriptionDispatchRate("persistent://myprop/ns1/ds1", "sub"); - cmdTopics.run(split("get-max-subscriptions-per-topic persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getMaxSubscriptionsPerTopic("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-subscriptions-per-topic persistent://myprop/clust/ns1/ds1 -s 1024 -g")); - verify(mockGlobalTopicsPolicies).setMaxSubscriptionsPerTopic("persistent://myprop/clust/ns1/ds1", 1024); - cmdTopics.run(split("remove-max-subscriptions-per-topic persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeMaxSubscriptionsPerTopic("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-max-subscriptions-per-topic persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getMaxSubscriptionsPerTopic("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-subscriptions-per-topic persistent://myprop/ns1/ds1 -s 1024 -g")); + verify(mockGlobalTopicsPolicies).setMaxSubscriptionsPerTopic("persistent://myprop/ns1/ds1", 1024); + cmdTopics.run(split("remove-max-subscriptions-per-topic persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeMaxSubscriptionsPerTopic("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-offload-policies persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).getOffloadPolicies("persistent://myprop/clust/ns1/ds1", false); + cmdTopics.run(split("get-offload-policies persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).getOffloadPolicies("persistent://myprop/ns1/ds1", false); - cmdTopics.run(split("remove-offload-policies persistent://myprop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeOffloadPolicies("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-offload-policies persistent://myprop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeOffloadPolicies("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("set-offload-policies persistent://myprop/clust/ns1/ds1 -d s3 -r" + cmdTopics.run(split("set-offload-policies persistent://myprop/ns1/ds1 -d s3 -r" + " region -b bucket -e endpoint -m 8 -rb 9 -t 10 -ts 100 -orp tiered-storage-first -g")); verify(mockGlobalTopicsPolicies) - .setOffloadPolicies("persistent://myprop/clust/ns1/ds1", OffloadPoliciesImpl.create( + .setOffloadPolicies("persistent://myprop/ns1/ds1", OffloadPoliciesImpl.create( "s3", "region", "bucket" , "endpoint", null, null, null, null, 8, 9, 10L, 100L, null, OffloadedReadPriority.TIERED_STORAGE_FIRST)); - cmdTopics.run(split("set-auto-subscription-creation persistent://prop/clust/ns1/ds1 -e -g")); - verify(mockGlobalTopicsPolicies).setAutoSubscriptionCreation("persistent://prop/clust/ns1/ds1", + cmdTopics.run(split("set-auto-subscription-creation persistent://prop/ns1/ds1 -e -g")); + verify(mockGlobalTopicsPolicies).setAutoSubscriptionCreation("persistent://prop/ns1/ds1", AutoSubscriptionCreationOverride.builder() .allowAutoSubscriptionCreation(true) .build()); - cmdTopics.run(split("get-auto-subscription-creation persistent://prop/clust/ns1/ds1 -a -g")); - verify(mockGlobalTopicsPolicies).getAutoSubscriptionCreation("persistent://prop/clust/ns1/ds1", true); - cmdTopics.run(split("remove-auto-subscription-creation persistent://prop/clust/ns1/ds1 -g")); - verify(mockGlobalTopicsPolicies).removeAutoSubscriptionCreation("persistent://prop/clust/ns1/ds1"); + cmdTopics.run(split("get-auto-subscription-creation persistent://prop/ns1/ds1 -a -g")); + verify(mockGlobalTopicsPolicies).getAutoSubscriptionCreation("persistent://prop/ns1/ds1", true); + cmdTopics.run(split("remove-auto-subscription-creation persistent://prop/ns1/ds1 -g")); + verify(mockGlobalTopicsPolicies).removeAutoSubscriptionCreation("persistent://prop/ns1/ds1"); } @Test @@ -1595,22 +1569,22 @@ public void topicsSetOffloadPolicies() throws Exception { // filesystem offload CmdTopics cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("set-offload-policies persistent://myprop/clust/ns1/ds1 -d filesystem -oat 100M " + cmdTopics.run(split("set-offload-policies persistent://myprop/ns1/ds1 -d filesystem -oat 100M " + "-oats 1h -oae 1h -orp bookkeeper-first")); OffloadPoliciesImpl offloadPolicies = OffloadPoliciesImpl.create("filesystem", null, null, null, null, null, null, null, 64 * 1024 * 1024, 1024 * 1024, 100 * 1024 * 1024L, 3600L, 3600 * 1000L, OffloadedReadPriority.BOOKKEEPER_FIRST); - verify(mockTopics).setOffloadPolicies("persistent://myprop/clust/ns1/ds1", offloadPolicies); + verify(mockTopics).setOffloadPolicies("persistent://myprop/ns1/ds1", offloadPolicies); // S3 offload CmdTopics cmdTopics2 = new CmdTopics(() -> admin); - cmdTopics2.run(split("set-offload-policies persistent://myprop/clust/ns1/ds2 -d s3 -r region -b " + cmdTopics2.run(split("set-offload-policies persistent://myprop/ns1/ds2 -d s3 -r region -b " + "bucket -e endpoint -ts 50 -m 8 -rb 9 -t 10 -orp tiered-storage-first")); OffloadPoliciesImpl offloadPolicies2 = OffloadPoliciesImpl.create("s3", "region", "bucket", "endpoint", null, null, null, null, 8, 9, 10L, 50L, null, OffloadedReadPriority.TIERED_STORAGE_FIRST); - verify(mockTopics).setOffloadPolicies("persistent://myprop/clust/ns1/ds2", offloadPolicies2); + verify(mockTopics).setOffloadPolicies("persistent://myprop/ns1/ds2", offloadPolicies2); } @@ -1626,57 +1600,57 @@ public void topics() throws Exception { CmdTopics cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("truncate persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).truncate("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("truncate persistent://myprop/ns1/ds1")); + verify(mockTopics).truncate("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("delete persistent://myprop/clust/ns1/ds1 -f")); - verify(mockTopics).delete("persistent://myprop/clust/ns1/ds1", true); + cmdTopics.run(split("delete persistent://myprop/ns1/ds1 -f")); + verify(mockTopics).delete("persistent://myprop/ns1/ds1", true); - cmdTopics.run(split("unload persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).unload("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("unload persistent://myprop/ns1/ds1")); + verify(mockTopics).unload("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("permissions persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getPermissions("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("permissions persistent://myprop/ns1/ds1")); + verify(mockTopics).getPermissions("persistent://myprop/ns1/ds1"); cmdTopics.run(split( - "grant-permission persistent://myprop/clust/ns1/ds1 --role admin --actions produce,consume")); - verify(mockTopics).grantPermission("persistent://myprop/clust/ns1/ds1", "admin", + "grant-permission persistent://myprop/ns1/ds1 --role admin --actions produce,consume")); + verify(mockTopics).grantPermission("persistent://myprop/ns1/ds1", "admin", Sets.newHashSet(AuthAction.produce, AuthAction.consume)); - cmdTopics.run(split("revoke-permission persistent://myprop/clust/ns1/ds1 --role admin")); - verify(mockTopics).revokePermissions("persistent://myprop/clust/ns1/ds1", "admin"); + cmdTopics.run(split("revoke-permission persistent://myprop/ns1/ds1 --role admin")); + verify(mockTopics).revokePermissions("persistent://myprop/ns1/ds1", "admin"); - cmdTopics.run(split("list myprop/clust/ns1")); - verify(mockTopics).getList("myprop/clust/ns1", null, ListTopicsOptions.EMPTY); + cmdTopics.run(split("list myprop/ns1")); + verify(mockTopics).getList("myprop/ns1", null, ListTopicsOptions.EMPTY); - cmdTopics.run(split("lookup persistent://myprop/clust/ns1/ds1")); - verify(mockLookup).lookupTopic("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("lookup persistent://myprop/ns1/ds1")); + verify(mockLookup).lookupTopic("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("partitioned-lookup persistent://myprop/clust/ns1/ds1")); - verify(mockLookup).lookupPartitionedTopic("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("partitioned-lookup persistent://myprop/ns1/ds1")); + verify(mockLookup).lookupPartitionedTopic("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("partitioned-lookup persistent://myprop/clust/ns1/ds1 --sort-by-broker")); - verify(mockLookup, times(2)).lookupPartitionedTopic("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("partitioned-lookup persistent://myprop/ns1/ds1 --sort-by-broker")); + verify(mockLookup, times(2)).lookupPartitionedTopic("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("bundle-range persistent://myprop/clust/ns1/ds1")); - verify(mockLookup).getBundleRange("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("bundle-range persistent://myprop/ns1/ds1")); + verify(mockLookup).getBundleRange("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("subscriptions persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getSubscriptions("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("subscriptions persistent://myprop/ns1/ds1")); + verify(mockTopics).getSubscriptions("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("unsubscribe persistent://myprop/clust/ns1/ds1 -s sub1")); - verify(mockTopics).deleteSubscription("persistent://myprop/clust/ns1/ds1", "sub1", false); + cmdTopics.run(split("unsubscribe persistent://myprop/ns1/ds1 -s sub1")); + verify(mockTopics).deleteSubscription("persistent://myprop/ns1/ds1", "sub1", false); - cmdTopics.run(split("stats persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getStats("persistent://myprop/clust/ns1/ds1", false, true, false); + cmdTopics.run(split("stats persistent://myprop/ns1/ds1")); + verify(mockTopics).getStats("persistent://myprop/ns1/ds1", false, true, false); - cmdTopics.run(split("stats-internal persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getInternalStats("persistent://myprop/clust/ns1/ds1", false); + cmdTopics.run(split("stats-internal persistent://myprop/ns1/ds1")); + verify(mockTopics).getInternalStats("persistent://myprop/ns1/ds1", false); - cmdTopics.run(split("get-backlog-quotas persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopics).getBacklogQuotaMap("persistent://myprop/clust/ns1/ds1", true); - cmdTopics.run(split("set-backlog-quota persistent://myprop/clust/ns1/ds1 -l 10 -p producer_request_hold")); - verify(mockTopics).setBacklogQuota("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-backlog-quotas persistent://myprop/ns1/ds1 -ap")); + verify(mockTopics).getBacklogQuotaMap("persistent://myprop/ns1/ds1", true); + cmdTopics.run(split("set-backlog-quota persistent://myprop/ns1/ds1 -l 10 -p producer_request_hold")); + verify(mockTopics).setBacklogQuota("persistent://myprop/ns1/ds1", BacklogQuota.builder() .limitSize(10) .retentionPolicy(RetentionPolicy.producer_request_hold) @@ -1685,8 +1659,8 @@ public void topics() throws Exception { //cmd with option cannot be executed repeatedly. cmdTopics = new CmdTopics(() -> admin); cmdTopics.run(split( - "set-backlog-quota persistent://myprop/clust/ns1/ds1 -lt 5h -p consumer_backlog_eviction")); - verify(mockTopics).setBacklogQuota("persistent://myprop/clust/ns1/ds1", + "set-backlog-quota persistent://myprop/ns1/ds1 -lt 5h -p consumer_backlog_eviction")); + verify(mockTopics).setBacklogQuota("persistent://myprop/ns1/ds1", BacklogQuota.builder() .limitSize(-1) .limitTime(5 * 60 * 60) @@ -1695,9 +1669,9 @@ public void topics() throws Exception { BacklogQuota.BacklogQuotaType.destination_storage); //cmd with option cannot be executed repeatedly. cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("set-backlog-quota persistent://myprop/clust/ns1/ds1 -lt 1000 -p " + cmdTopics.run(split("set-backlog-quota persistent://myprop/ns1/ds1 -lt 1000 -p " + "producer_request_hold -t message_age")); - verify(mockTopics).setBacklogQuota("persistent://myprop/clust/ns1/ds1", + verify(mockTopics).setBacklogQuota("persistent://myprop/ns1/ds1", BacklogQuota.builder() .limitSize(-1) .limitTime(1000) @@ -1706,349 +1680,349 @@ public void topics() throws Exception { BacklogQuota.BacklogQuotaType.message_age); //cmd with option cannot be executed repeatedly. cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("remove-backlog-quota persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeBacklogQuota("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("remove-backlog-quota persistent://myprop/ns1/ds1")); + verify(mockTopics).removeBacklogQuota("persistent://myprop/ns1/ds1", BacklogQuota.BacklogQuotaType.destination_storage); //cmd with option cannot be executed repeatedly. cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("remove-backlog-quota persistent://myprop/clust/ns1/ds1 -t message_age")); - verify(mockTopics).removeBacklogQuota("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("remove-backlog-quota persistent://myprop/ns1/ds1 -t message_age")); + verify(mockTopics).removeBacklogQuota("persistent://myprop/ns1/ds1", BacklogQuota.BacklogQuotaType.message_age); - cmdTopics.run(split("info-internal persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getInternalInfo("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("info-internal persistent://myprop/ns1/ds1")); + verify(mockTopics).getInternalInfo("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("partitioned-stats persistent://myprop/clust/ns1/ds1 --per-partition")); - verify(mockTopics).getPartitionedStats("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("partitioned-stats persistent://myprop/ns1/ds1 --per-partition")); + verify(mockTopics).getPartitionedStats("persistent://myprop/ns1/ds1", true, false, true, false); - cmdTopics.run(split("partitioned-stats-internal persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getPartitionedInternalStats("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("partitioned-stats-internal persistent://myprop/ns1/ds1")); + verify(mockTopics).getPartitionedInternalStats("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("clear-backlog persistent://myprop/clust/ns1/ds1 -s sub1")); - verify(mockTopics).skipAllMessages("persistent://myprop/clust/ns1/ds1", "sub1"); + cmdTopics.run(split("clear-backlog persistent://myprop/ns1/ds1 -s sub1")); + verify(mockTopics).skipAllMessages("persistent://myprop/ns1/ds1", "sub1"); - cmdTopics.run(split("skip persistent://myprop/clust/ns1/ds1 -s sub1 -n 100")); - verify(mockTopics).skipMessages("persistent://myprop/clust/ns1/ds1", "sub1", 100); + cmdTopics.run(split("skip persistent://myprop/ns1/ds1 -s sub1 -n 100")); + verify(mockTopics).skipMessages("persistent://myprop/ns1/ds1", "sub1", 100); - cmdTopics.run(split("expire-messages persistent://myprop/clust/ns1/ds1 -s sub1 -t 100")); - verify(mockTopics).expireMessages("persistent://myprop/clust/ns1/ds1", "sub1", 100); + cmdTopics.run(split("expire-messages persistent://myprop/ns1/ds1 -s sub1 -t 100")); + verify(mockTopics).expireMessages("persistent://myprop/ns1/ds1", "sub1", 100); - cmdTopics.run(split("expire-messages-all-subscriptions persistent://myprop/clust/ns1/ds1 -t 100")); - verify(mockTopics).expireMessagesForAllSubscriptions("persistent://myprop/clust/ns1/ds1", 100); + cmdTopics.run(split("expire-messages-all-subscriptions persistent://myprop/ns1/ds1 -t 100")); + verify(mockTopics).expireMessagesForAllSubscriptions("persistent://myprop/ns1/ds1", 100); - cmdTopics.run(split("get-subscribe-rate persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopics).getSubscribeRate("persistent://myprop/clust/ns1/ds1", true); + cmdTopics.run(split("get-subscribe-rate persistent://myprop/ns1/ds1 -ap")); + verify(mockTopics).getSubscribeRate("persistent://myprop/ns1/ds1", true); - cmdTopics.run(split("set-subscribe-rate persistent://myprop/clust/ns1/ds1 -sr 2 -st 60")); - verify(mockTopics).setSubscribeRate("persistent://myprop/clust/ns1/ds1", new SubscribeRate(2, 60)); + cmdTopics.run(split("set-subscribe-rate persistent://myprop/ns1/ds1 -sr 2 -st 60")); + verify(mockTopics).setSubscribeRate("persistent://myprop/ns1/ds1", new SubscribeRate(2, 60)); - cmdTopics.run(split("remove-subscribe-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeSubscribeRate("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-subscribe-rate persistent://myprop/ns1/ds1")); + verify(mockTopics).removeSubscribeRate("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("set-replicated-subscription-status persistent://myprop/clust/ns1/ds1 -s sub1 -e")); - verify(mockTopics).setReplicatedSubscriptionStatus("persistent://myprop/clust/ns1/ds1", "sub1", true); + cmdTopics.run(split("set-replicated-subscription-status persistent://myprop/ns1/ds1 -s sub1 -e")); + verify(mockTopics).setReplicatedSubscriptionStatus("persistent://myprop/ns1/ds1", "sub1", true); //cmd with option cannot be executed repeatedly. cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("expire-messages persistent://myprop/clust/ns1/ds1 -s sub1 -p 1:1 -e")); - verify(mockTopics).expireMessages(eq("persistent://myprop/clust/ns1/ds1"), eq("sub1"), + cmdTopics.run(split("expire-messages persistent://myprop/ns1/ds1 -s sub1 -p 1:1 -e")); + verify(mockTopics).expireMessages(eq("persistent://myprop/ns1/ds1"), eq("sub1"), eq(new MessageIdImpl(1, 1, -1)), eq(true)); - cmdTopics.run(split("expire-messages-all-subscriptions persistent://myprop/clust/ns1/ds1 -t 1d")); - verify(mockTopics).expireMessagesForAllSubscriptions("persistent://myprop/clust/ns1/ds1", 60 * 60 * 24); + cmdTopics.run(split("expire-messages-all-subscriptions persistent://myprop/ns1/ds1 -t 1d")); + verify(mockTopics).expireMessagesForAllSubscriptions("persistent://myprop/ns1/ds1", 60 * 60 * 24); - cmdTopics.run(split("create-subscription persistent://myprop/clust/ns1/ds1 -s sub1 --messageId earliest")); - verify(mockTopics).createSubscription("persistent://myprop/clust/ns1/ds1", "sub1", + cmdTopics.run(split("create-subscription persistent://myprop/ns1/ds1 -s sub1 --messageId earliest")); + verify(mockTopics).createSubscription("persistent://myprop/ns1/ds1", "sub1", MessageId.earliest, false, null); - cmdTopics.run(split("analyze-backlog persistent://myprop/clust/ns1/ds1 -s sub1")); - verify(mockTopics).analyzeSubscriptionBacklog("persistent://myprop/clust/ns1/ds1", "sub1", + cmdTopics.run(split("analyze-backlog persistent://myprop/ns1/ds1 -s sub1")); + verify(mockTopics).analyzeSubscriptionBacklog("persistent://myprop/ns1/ds1", "sub1", Optional.empty()); - cmdTopics.run(split("trim-topic persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).trimTopic("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("trim-topic persistent://myprop/ns1/ds1")); + verify(mockTopics).trimTopic("persistent://myprop/ns1/ds1"); // jcommander is stateful, you cannot parse the same command twice cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("create-subscription persistent://myprop/clust/ns1/ds1 -s sub1 " + cmdTopics.run(split("create-subscription persistent://myprop/ns1/ds1 -s sub1 " + "--messageId earliest --property a=b -p x=y,z")); Map props = new HashMap<>(); props.put("a", "b"); props.put("x", "y,z"); - verify(mockTopics).createSubscription("persistent://myprop/clust/ns1/ds1", "sub1", + verify(mockTopics).createSubscription("persistent://myprop/ns1/ds1", "sub1", MessageId.earliest, false, props); cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("create-subscription persistent://myprop/clust/ns1/ds1 -s sub1 " + cmdTopics.run(split("create-subscription persistent://myprop/ns1/ds1 -s sub1 " + "--messageId earliest -r")); - verify(mockTopics).createSubscription("persistent://myprop/clust/ns1/ds1", "sub1", + verify(mockTopics).createSubscription("persistent://myprop/ns1/ds1", "sub1", MessageId.earliest, true, null); cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("update-subscription-properties persistent://myprop/clust/ns1/ds1 -s sub1 --clear")); - verify(mockTopics).updateSubscriptionProperties("persistent://myprop/clust/ns1/ds1", "sub1", + cmdTopics.run(split("update-subscription-properties persistent://myprop/ns1/ds1 -s sub1 --clear")); + verify(mockTopics).updateSubscriptionProperties("persistent://myprop/ns1/ds1", "sub1", new HashMap<>()); cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("update-properties persistent://myprop/clust/ns1/ds1 --property a=b -p x=y,z")); + cmdTopics.run(split("update-properties persistent://myprop/ns1/ds1 --property a=b -p x=y,z")); props = new HashMap<>(); props.put("a", "b"); props.put("x", "y,z"); - verify(mockTopics).updateProperties("persistent://myprop/clust/ns1/ds1", props); + verify(mockTopics).updateProperties("persistent://myprop/ns1/ds1", props); cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("remove-properties persistent://myprop/clust/ns1/ds1 --key a")); - verify(mockTopics).removeProperties("persistent://myprop/clust/ns1/ds1", "a"); + cmdTopics.run(split("remove-properties persistent://myprop/ns1/ds1 --key a")); + verify(mockTopics).removeProperties("persistent://myprop/ns1/ds1", "a"); cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("get-subscription-properties persistent://myprop/clust/ns1/ds1 -s sub1")); - verify(mockTopics).getSubscriptionProperties("persistent://myprop/clust/ns1/ds1", "sub1"); + cmdTopics.run(split("get-subscription-properties persistent://myprop/ns1/ds1 -s sub1")); + verify(mockTopics).getSubscriptionProperties("persistent://myprop/ns1/ds1", "sub1"); cmdTopics = new CmdTopics(() -> admin); props = new HashMap<>(); props.put("a", "b"); props.put("c", "d"); props.put("x", "y,z"); - cmdTopics.run(split("update-subscription-properties persistent://myprop/clust/ns1/ds1 -s " + cmdTopics.run(split("update-subscription-properties persistent://myprop/ns1/ds1 -s " + "sub1 -p a=b -p c=d -p x=y,z")); - verify(mockTopics).updateSubscriptionProperties("persistent://myprop/clust/ns1/ds1", "sub1", props); + verify(mockTopics).updateSubscriptionProperties("persistent://myprop/ns1/ds1", "sub1", props); - cmdTopics.run(split("create-partitioned-topic persistent://myprop/clust/ns1/ds1 --partitions 32")); - verify(mockTopics).createPartitionedTopic("persistent://myprop/clust/ns1/ds1", 32, null); + cmdTopics.run(split("create-partitioned-topic persistent://myprop/ns1/ds1 --partitions 32")); + verify(mockTopics).createPartitionedTopic("persistent://myprop/ns1/ds1", 32, null); - cmdTopics.run(split("create-missed-partitions persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).createMissedPartitions("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("create-missed-partitions persistent://myprop/ns1/ds1")); + verify(mockTopics).createMissedPartitions("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("create persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).createNonPartitionedTopic("persistent://myprop/clust/ns1/ds1", null); + cmdTopics.run(split("create persistent://myprop/ns1/ds1")); + verify(mockTopics).createNonPartitionedTopic("persistent://myprop/ns1/ds1", null); - cmdTopics.run(split("list-partitioned-topics myprop/clust/ns1")); - verify(mockTopics).getPartitionedTopicList("myprop/clust/ns1", ListTopicsOptions.EMPTY); + cmdTopics.run(split("list-partitioned-topics myprop/ns1")); + verify(mockTopics).getPartitionedTopicList("myprop/ns1", ListTopicsOptions.EMPTY); - cmdTopics.run(split("update-partitioned-topic persistent://myprop/clust/ns1/ds1 -p 6")); - verify(mockTopics).updatePartitionedTopic("persistent://myprop/clust/ns1/ds1", 6, false, false); + cmdTopics.run(split("update-partitioned-topic persistent://myprop/ns1/ds1 -p 6")); + verify(mockTopics).updatePartitionedTopic("persistent://myprop/ns1/ds1", 6, false, false); - cmdTopics.run(split("get-partitioned-topic-metadata persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getPartitionedTopicMetadata("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-partitioned-topic-metadata persistent://myprop/ns1/ds1")); + verify(mockTopics).getPartitionedTopicMetadata("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("delete-partitioned-topic persistent://myprop/clust/ns1/ds1 -f")); - verify(mockTopics).deletePartitionedTopic("persistent://myprop/clust/ns1/ds1", true); + cmdTopics.run(split("delete-partitioned-topic persistent://myprop/ns1/ds1 -f")); + verify(mockTopics).deletePartitionedTopic("persistent://myprop/ns1/ds1", true); - cmdTopics.run(split("peek-messages persistent://myprop/clust/ns1/ds1 -s sub1 -n 3")); - verify(mockTopics).peekMessages("persistent://myprop/clust/ns1/ds1", "sub1", 3, + cmdTopics.run(split("peek-messages persistent://myprop/ns1/ds1 -s sub1 -n 3")); + verify(mockTopics).peekMessages("persistent://myprop/ns1/ds1", "sub1", 3, false, TransactionIsolationLevel.READ_COMMITTED); MessageImpl message = mock(MessageImpl.class); when(message.getData()).thenReturn(new byte[]{}); when(message.getMessageId()).thenReturn(new MessageIdImpl(1L, 1L, 1)); - when(mockTopics.examineMessage("persistent://myprop/clust/ns1/ds1", "latest", + when(mockTopics.examineMessage("persistent://myprop/ns1/ds1", "latest", 1)).thenReturn(message); - cmdTopics.run(split("examine-messages persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).examineMessage("persistent://myprop/clust/ns1/ds1", "latest", 1); + cmdTopics.run(split("examine-messages persistent://myprop/ns1/ds1")); + verify(mockTopics).examineMessage("persistent://myprop/ns1/ds1", "latest", 1); - cmdTopics.run(split("enable-deduplication persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).enableDeduplication("persistent://myprop/clust/ns1/ds1", true); + cmdTopics.run(split("enable-deduplication persistent://myprop/ns1/ds1")); + verify(mockTopics).enableDeduplication("persistent://myprop/ns1/ds1", true); - cmdTopics.run(split("disable-deduplication persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).enableDeduplication("persistent://myprop/clust/ns1/ds1", false); + cmdTopics.run(split("disable-deduplication persistent://myprop/ns1/ds1")); + verify(mockTopics).enableDeduplication("persistent://myprop/ns1/ds1", false); - cmdTopics.run(split("set-deduplication persistent://myprop/clust/ns1/ds1 --disable")); - verify(mockTopics).setDeduplicationStatus("persistent://myprop/clust/ns1/ds1", false); + cmdTopics.run(split("set-deduplication persistent://myprop/ns1/ds1 --disable")); + verify(mockTopics).setDeduplicationStatus("persistent://myprop/ns1/ds1", false); - cmdTopics.run(split("set-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1 -md -1 " + cmdTopics.run(split("set-subscription-dispatch-rate persistent://myprop/ns1/ds1 -md -1 " + "-bd -1 -dt 2")); - verify(mockTopics).setSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1", + verify(mockTopics).setSubscriptionDispatchRate("persistent://myprop/ns1/ds1", DispatchRate.builder() .dispatchThrottlingRateInMsg(-1) .dispatchThrottlingRateInByte(-1) .ratePeriodInSecond(2) .build()); - cmdTopics.run(split("get-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-subscription-dispatch-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeSubscriptionDispatchRate("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-subscription-dispatch-rate persistent://myprop/ns1/ds1")); + verify(mockTopics).getSubscriptionDispatchRate("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-subscription-dispatch-rate persistent://myprop/ns1/ds1")); + verify(mockTopics).removeSubscriptionDispatchRate("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("remove-deduplication persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeDeduplicationStatus("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-deduplication persistent://myprop/ns1/ds1")); + verify(mockTopics).removeDeduplicationStatus("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-replicator-dispatch-rate persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopics).getReplicatorDispatchRate("persistent://myprop/clust/ns1/ds1", true); + cmdTopics.run(split("get-replicator-dispatch-rate persistent://myprop/ns1/ds1 -ap")); + verify(mockTopics).getReplicatorDispatchRate("persistent://myprop/ns1/ds1", true); - cmdTopics.run(split("set-subscription-types-enabled persistent://myprop/clust/ns1/ds1 -t " + cmdTopics.run(split("set-subscription-types-enabled persistent://myprop/ns1/ds1 -t " + "Shared,Failover")); - verify(mockTopics).setSubscriptionTypesEnabled("persistent://myprop/clust/ns1/ds1", + verify(mockTopics).setSubscriptionTypesEnabled("persistent://myprop/ns1/ds1", Sets.newHashSet(SubscriptionType.Shared, SubscriptionType.Failover)); - cmdTopics.run(split("get-subscription-types-enabled persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getSubscriptionTypesEnabled("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-subscription-types-enabled persistent://myprop/ns1/ds1")); + verify(mockTopics).getSubscriptionTypesEnabled("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("remove-subscription-types-enabled persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeSubscriptionTypesEnabled("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-subscription-types-enabled persistent://myprop/ns1/ds1")); + verify(mockTopics).removeSubscriptionTypesEnabled("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("set-replicator-dispatch-rate persistent://myprop/clust/ns1/ds1 -md 10 " + cmdTopics.run(split("set-replicator-dispatch-rate persistent://myprop/ns1/ds1 -md 10 " + "-bd 11 -dt 12")); - verify(mockTopics).setReplicatorDispatchRate("persistent://myprop/clust/ns1/ds1", + verify(mockTopics).setReplicatorDispatchRate("persistent://myprop/ns1/ds1", DispatchRate.builder() .dispatchThrottlingRateInMsg(10) .dispatchThrottlingRateInByte(11) .ratePeriodInSecond(12) .build()); - cmdTopics.run(split("remove-replicator-dispatch-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeReplicatorDispatchRate("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-replicator-dispatch-rate persistent://myprop/ns1/ds1")); + verify(mockTopics).removeReplicatorDispatchRate("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-deduplication-enabled persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getDeduplicationStatus("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("get-deduplication persistent://myprop/clust/ns1/ds1")); + cmdTopics.run(split("get-deduplication-enabled persistent://myprop/ns1/ds1")); + verify(mockTopics).getDeduplicationStatus("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("get-deduplication persistent://myprop/ns1/ds1")); verify(mockTopics, times(2)).getDeduplicationStatus( - "persistent://myprop/clust/ns1/ds1"); + "persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-offload-policies persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getOffloadPolicies("persistent://myprop/clust/ns1/ds1", false); + cmdTopics.run(split("get-offload-policies persistent://myprop/ns1/ds1")); + verify(mockTopics).getOffloadPolicies("persistent://myprop/ns1/ds1", false); - cmdTopics.run(split("remove-offload-policies persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeOffloadPolicies("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-offload-policies persistent://myprop/ns1/ds1")); + verify(mockTopics).removeOffloadPolicies("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-delayed-delivery persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getDelayedDeliveryPolicy("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-delayed-delivery persistent://myprop/clust/ns1/ds1 -t 10s -md 5s --enable")); - verify(mockTopics).setDelayedDeliveryPolicy("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-delayed-delivery persistent://myprop/ns1/ds1")); + verify(mockTopics).getDelayedDeliveryPolicy("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-delayed-delivery persistent://myprop/ns1/ds1 -t 10s -md 5s --enable")); + verify(mockTopics).setDelayedDeliveryPolicy("persistent://myprop/ns1/ds1", DelayedDeliveryPolicies.builder().tickTime(10000).active(true) .maxDeliveryDelayInMillis(5000).build()); - cmdTopics.run(split("remove-delayed-delivery persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeDelayedDeliveryPolicy("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-delayed-delivery persistent://myprop/ns1/ds1")); + verify(mockTopics).removeDelayedDeliveryPolicy("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("set-offload-policies persistent://myprop/clust/ns1/ds1 -d s3 -r region -b " + cmdTopics.run(split("set-offload-policies persistent://myprop/ns1/ds1 -d s3 -r region -b " + "bucket -e endpoint -ts 50 -m 8 -rb 9 -t 10 -orp tiered-storage-first")); OffloadPoliciesImpl offloadPolicies = OffloadPoliciesImpl.create("s3", "region", "bucket" , "endpoint", null, null, null, null, 8, 9, 10L, 50L, null, OffloadedReadPriority.TIERED_STORAGE_FIRST); - verify(mockTopics).setOffloadPolicies("persistent://myprop/clust/ns1/ds1", offloadPolicies); + verify(mockTopics).setOffloadPolicies("persistent://myprop/ns1/ds1", offloadPolicies); - cmdTopics.run(split("get-max-unacked-messages-on-consumer persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getMaxUnackedMessagesOnConsumer("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("get-max-unacked-messages-per-consumer persistent://myprop/clust/ns1/ds1")); + cmdTopics.run(split("get-max-unacked-messages-on-consumer persistent://myprop/ns1/ds1")); + verify(mockTopics).getMaxUnackedMessagesOnConsumer("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("get-max-unacked-messages-per-consumer persistent://myprop/ns1/ds1")); verify(mockTopics, times(2)) - .getMaxUnackedMessagesOnConsumer("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-max-unacked-messages-on-consumer persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeMaxUnackedMessagesOnConsumer("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("remove-max-unacked-messages-per-consumer persistent://myprop/clust/ns1/ds1")); + .getMaxUnackedMessagesOnConsumer("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-max-unacked-messages-on-consumer persistent://myprop/ns1/ds1")); + verify(mockTopics).removeMaxUnackedMessagesOnConsumer("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("remove-max-unacked-messages-per-consumer persistent://myprop/ns1/ds1")); verify(mockTopics, times(2)).removeMaxUnackedMessagesOnConsumer( - "persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-unacked-messages-on-consumer persistent://myprop/clust/ns1/ds1 -m 999")); - verify(mockTopics).setMaxUnackedMessagesOnConsumer("persistent://myprop/clust/ns1/ds1", 999); - cmdTopics.run(split("set-max-unacked-messages-per-consumer persistent://myprop/clust/ns1/ds1 -m 999")); + "persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-unacked-messages-on-consumer persistent://myprop/ns1/ds1 -m 999")); + verify(mockTopics).setMaxUnackedMessagesOnConsumer("persistent://myprop/ns1/ds1", 999); + cmdTopics.run(split("set-max-unacked-messages-per-consumer persistent://myprop/ns1/ds1 -m 999")); verify(mockTopics, times(2)).setMaxUnackedMessagesOnConsumer( - "persistent://myprop/clust/ns1/ds1", 999); + "persistent://myprop/ns1/ds1", 999); - cmdTopics.run(split("get-max-unacked-messages-on-subscription persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getMaxUnackedMessagesOnSubscription("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("get-max-unacked-messages-per-subscription persistent://myprop/clust/ns1/ds1")); + cmdTopics.run(split("get-max-unacked-messages-on-subscription persistent://myprop/ns1/ds1")); + verify(mockTopics).getMaxUnackedMessagesOnSubscription("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("get-max-unacked-messages-per-subscription persistent://myprop/ns1/ds1")); verify(mockTopics, times(2)).getMaxUnackedMessagesOnSubscription( - "persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-max-unacked-messages-on-subscription persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeMaxUnackedMessagesOnSubscription("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("remove-max-unacked-messages-per-subscription persistent://myprop/clust/ns1/ds1")); + "persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-max-unacked-messages-on-subscription persistent://myprop/ns1/ds1")); + verify(mockTopics).removeMaxUnackedMessagesOnSubscription("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("remove-max-unacked-messages-per-subscription persistent://myprop/ns1/ds1")); verify(mockTopics, times(2)).removeMaxUnackedMessagesOnSubscription( - "persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("get-publish-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getPublishRate("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-publish-rate persistent://myprop/clust/ns1/ds1 -m 100 -b 10240")); - verify(mockTopics).setPublishRate("persistent://myprop/clust/ns1/ds1", new PublishRate(100, 10240L)); - cmdTopics.run(split("remove-publish-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removePublishRate("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-unacked-messages-on-subscription persistent://myprop/clust/ns1/ds1 -m 99")); - verify(mockTopics).setMaxUnackedMessagesOnSubscription("persistent://myprop/clust/ns1/ds1", 99); - cmdTopics.run(split("set-max-unacked-messages-per-subscription persistent://myprop/clust/ns1/ds1 -m 99")); + "persistent://myprop/ns1/ds1"); + cmdTopics.run(split("get-publish-rate persistent://myprop/ns1/ds1")); + verify(mockTopics).getPublishRate("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-publish-rate persistent://myprop/ns1/ds1 -m 100 -b 10240")); + verify(mockTopics).setPublishRate("persistent://myprop/ns1/ds1", new PublishRate(100, 10240L)); + cmdTopics.run(split("remove-publish-rate persistent://myprop/ns1/ds1")); + verify(mockTopics).removePublishRate("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-unacked-messages-on-subscription persistent://myprop/ns1/ds1 -m 99")); + verify(mockTopics).setMaxUnackedMessagesOnSubscription("persistent://myprop/ns1/ds1", 99); + cmdTopics.run(split("set-max-unacked-messages-per-subscription persistent://myprop/ns1/ds1 -m 99")); verify(mockTopics, times(2)).setMaxUnackedMessagesOnSubscription( - "persistent://myprop/clust/ns1/ds1", 99); + "persistent://myprop/ns1/ds1", 99); - cmdTopics.run(split("get-compaction-threshold persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getCompactionThreshold("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("set-compaction-threshold persistent://myprop/clust/ns1/ds1 -t 10k")); - verify(mockTopics).setCompactionThreshold("persistent://myprop/clust/ns1/ds1", 10 * 1024); - cmdTopics.run(split("remove-compaction-threshold persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeCompactionThreshold("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-compaction-threshold persistent://myprop/ns1/ds1")); + verify(mockTopics).getCompactionThreshold("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("set-compaction-threshold persistent://myprop/ns1/ds1 -t 10k")); + verify(mockTopics).setCompactionThreshold("persistent://myprop/ns1/ds1", 10 * 1024); + cmdTopics.run(split("remove-compaction-threshold persistent://myprop/ns1/ds1")); + verify(mockTopics).removeCompactionThreshold("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-max-message-size persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getMaxMessageSize("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-max-message-size persistent://myprop/ns1/ds1")); + verify(mockTopics).getMaxMessageSize("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("remove-max-message-size persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeMaxMessageSize("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-max-message-size persistent://myprop/ns1/ds1")); + verify(mockTopics).removeMaxMessageSize("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-max-consumers-per-subscription persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getMaxConsumersPerSubscription("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-max-consumers-per-subscription persistent://myprop/ns1/ds1")); + verify(mockTopics).getMaxConsumersPerSubscription("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("set-max-consumers-per-subscription persistent://myprop/clust/ns1/ds1 -c 5")); - verify(mockTopics).setMaxConsumersPerSubscription("persistent://myprop/clust/ns1/ds1", 5); + cmdTopics.run(split("set-max-consumers-per-subscription persistent://myprop/ns1/ds1 -c 5")); + verify(mockTopics).setMaxConsumersPerSubscription("persistent://myprop/ns1/ds1", 5); - cmdTopics.run(split("remove-max-consumers-per-subscription persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeMaxConsumersPerSubscription("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-max-consumers-per-subscription persistent://myprop/ns1/ds1")); + verify(mockTopics).removeMaxConsumersPerSubscription("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("set-max-message-size persistent://myprop/clust/ns1/ds1 -m 99")); - verify(mockTopics).setMaxMessageSize("persistent://myprop/clust/ns1/ds1", 99); + cmdTopics.run(split("set-max-message-size persistent://myprop/ns1/ds1 -m 99")); + verify(mockTopics).setMaxMessageSize("persistent://myprop/ns1/ds1", 99); - cmdTopics.run(split("get-message-by-id persistent://myprop/clust/ns1/ds1 -l 10 -e 2")); - verify(mockTopics).getMessageById("persistent://myprop/clust/ns1/ds1", 10, 2); + cmdTopics.run(split("get-message-by-id persistent://myprop/ns1/ds1 -l 10 -e 2")); + verify(mockTopics).getMessageById("persistent://myprop/ns1/ds1", 10, 2); - cmdTopics.run(split("get-dispatch-rate persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopics).getDispatchRate("persistent://myprop/clust/ns1/ds1", true); - cmdTopics.run(split("remove-dispatch-rate persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeDispatchRate("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-dispatch-rate persistent://myprop/clust/ns1/ds1 -md -1 -bd -1 -dt 2")); - verify(mockTopics).setDispatchRate("persistent://myprop/clust/ns1/ds1", DispatchRate.builder() + cmdTopics.run(split("get-dispatch-rate persistent://myprop/ns1/ds1 -ap")); + verify(mockTopics).getDispatchRate("persistent://myprop/ns1/ds1", true); + cmdTopics.run(split("remove-dispatch-rate persistent://myprop/ns1/ds1")); + verify(mockTopics).removeDispatchRate("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-dispatch-rate persistent://myprop/ns1/ds1 -md -1 -bd -1 -dt 2")); + verify(mockTopics).setDispatchRate("persistent://myprop/ns1/ds1", DispatchRate.builder() .dispatchThrottlingRateInMsg(-1) .dispatchThrottlingRateInByte(-1) .ratePeriodInSecond(2) .build()); - cmdTopics.run(split("get-max-producers persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getMaxProducers("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-max-producers persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeMaxProducers("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-producers persistent://myprop/clust/ns1/ds1 -p 99")); - verify(mockTopics).setMaxProducers("persistent://myprop/clust/ns1/ds1", 99); - - cmdTopics.run(split("get-max-consumers persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getMaxConsumers("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-max-consumers persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeMaxConsumers("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-consumers persistent://myprop/clust/ns1/ds1 -c 99")); - verify(mockTopics).setMaxConsumers("persistent://myprop/clust/ns1/ds1", 99); - - cmdTopics.run(split("get-deduplication-snapshot-interval persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getDeduplicationSnapshotInterval("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("remove-deduplication-snapshot-interval persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeDeduplicationSnapshotInterval("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-deduplication-snapshot-interval persistent://myprop/clust/ns1/ds1 -i 99")); - verify(mockTopics).setDeduplicationSnapshotInterval("persistent://myprop/clust/ns1/ds1", 99); - - cmdTopics.run(split("get-inactive-topic-policies persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getInactiveTopicPolicies("persistent://myprop/clust/ns1/ds1", false); - cmdTopics.run(split("remove-inactive-topic-policies persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeInactiveTopicPolicies("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-inactive-topic-policies persistent://myprop/clust/ns1/ds1" + cmdTopics.run(split("get-max-producers persistent://myprop/ns1/ds1")); + verify(mockTopics).getMaxProducers("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-max-producers persistent://myprop/ns1/ds1")); + verify(mockTopics).removeMaxProducers("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-producers persistent://myprop/ns1/ds1 -p 99")); + verify(mockTopics).setMaxProducers("persistent://myprop/ns1/ds1", 99); + + cmdTopics.run(split("get-max-consumers persistent://myprop/ns1/ds1")); + verify(mockTopics).getMaxConsumers("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-max-consumers persistent://myprop/ns1/ds1")); + verify(mockTopics).removeMaxConsumers("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-consumers persistent://myprop/ns1/ds1 -c 99")); + verify(mockTopics).setMaxConsumers("persistent://myprop/ns1/ds1", 99); + + cmdTopics.run(split("get-deduplication-snapshot-interval persistent://myprop/ns1/ds1")); + verify(mockTopics).getDeduplicationSnapshotInterval("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("remove-deduplication-snapshot-interval persistent://myprop/ns1/ds1")); + verify(mockTopics).removeDeduplicationSnapshotInterval("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-deduplication-snapshot-interval persistent://myprop/ns1/ds1 -i 99")); + verify(mockTopics).setDeduplicationSnapshotInterval("persistent://myprop/ns1/ds1", 99); + + cmdTopics.run(split("get-inactive-topic-policies persistent://myprop/ns1/ds1")); + verify(mockTopics).getInactiveTopicPolicies("persistent://myprop/ns1/ds1", false); + cmdTopics.run(split("remove-inactive-topic-policies persistent://myprop/ns1/ds1")); + verify(mockTopics).removeInactiveTopicPolicies("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-inactive-topic-policies persistent://myprop/ns1/ds1" + " -e -t 1s -m delete_when_no_subscriptions")); - verify(mockTopics).setInactiveTopicPolicies("persistent://myprop/clust/ns1/ds1", + verify(mockTopics).setInactiveTopicPolicies("persistent://myprop/ns1/ds1", new InactiveTopicPolicies(InactiveTopicDeleteMode.delete_when_no_subscriptions, 1, true)); - cmdTopics.run(split("get-max-subscriptions persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getMaxSubscriptionsPerTopic("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-max-subscriptions persistent://myprop/clust/ns1/ds1 -m 100")); - verify(mockTopics).setMaxSubscriptionsPerTopic("persistent://myprop/clust/ns1/ds1", 100); - cmdTopics.run(split("remove-max-subscriptions persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeMaxSubscriptionsPerTopic("persistent://myprop/clust/ns1/ds1"); - - cmdTopics.run(split("get-persistence persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getPersistence("persistent://myprop/clust/ns1/ds1"); - cmdTopics.run(split("set-persistence persistent://myprop/clust/ns1/ds1 -e 2 -w 1 -a 1 -r 100.0")); - verify(mockTopics).setPersistence("persistent://myprop/clust/ns1/ds1", + cmdTopics.run(split("get-max-subscriptions persistent://myprop/ns1/ds1")); + verify(mockTopics).getMaxSubscriptionsPerTopic("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-max-subscriptions persistent://myprop/ns1/ds1 -m 100")); + verify(mockTopics).setMaxSubscriptionsPerTopic("persistent://myprop/ns1/ds1", 100); + cmdTopics.run(split("remove-max-subscriptions persistent://myprop/ns1/ds1")); + verify(mockTopics).removeMaxSubscriptionsPerTopic("persistent://myprop/ns1/ds1"); + + cmdTopics.run(split("get-persistence persistent://myprop/ns1/ds1")); + verify(mockTopics).getPersistence("persistent://myprop/ns1/ds1"); + cmdTopics.run(split("set-persistence persistent://myprop/ns1/ds1 -e 2 -w 1 -a 1 -r 100.0")); + verify(mockTopics).setPersistence("persistent://myprop/ns1/ds1", new PersistencePolicies(2, 1, 1, 100.0d)); - cmdTopics.run(split("remove-persistence persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removePersistence("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-persistence persistent://myprop/ns1/ds1")); + verify(mockTopics).removePersistence("persistent://myprop/ns1/ds1"); // argument matcher for the timestamp in reset cursor. Since we can't verify exact timestamp, we check for a // range of +/- 1 second of the expected timestamp @@ -2062,138 +2036,138 @@ public boolean matches(Long timestamp) { return false; } } - cmdTopics.run(split("reset-cursor persistent://myprop/clust/ns1/ds1 -s sub1 -t 1m")); - verify(mockTopics).resetCursor(eq("persistent://myprop/clust/ns1/ds1"), eq("sub1"), + cmdTopics.run(split("reset-cursor persistent://myprop/ns1/ds1 -s sub1 -t 1m")); + verify(mockTopics).resetCursor(eq("persistent://myprop/ns1/ds1"), eq("sub1"), longThat(new TimestampMatcher())); - when(mockTopics.terminateTopicAsync("persistent://myprop/clust/ns1/ds1")) + when(mockTopics.terminateTopicAsync("persistent://myprop/ns1/ds1")) .thenReturn(CompletableFuture.completedFuture(new MessageIdImpl(1L, 1L, 1))); - cmdTopics.run(split("terminate persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).terminateTopicAsync("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("terminate persistent://myprop/ns1/ds1")); + verify(mockTopics).terminateTopicAsync("persistent://myprop/ns1/ds1"); Map results = new HashMap<>(); results.put(0, new MessageIdImpl(1, 1, 0)); - when(mockTopics.terminatePartitionedTopic("persistent://myprop/clust/ns1/ds1")).thenReturn(results); - cmdTopics.run(split("partitioned-terminate persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).terminatePartitionedTopic("persistent://myprop/clust/ns1/ds1"); + when(mockTopics.terminatePartitionedTopic("persistent://myprop/ns1/ds1")).thenReturn(results); + cmdTopics.run(split("partitioned-terminate persistent://myprop/ns1/ds1")); + verify(mockTopics).terminatePartitionedTopic("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("compact persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).triggerCompaction("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("compact persistent://myprop/ns1/ds1")); + verify(mockTopics).triggerCompaction("persistent://myprop/ns1/ds1"); - when(mockTopics.compactionStatus("persistent://myprop/clust/ns1/ds1")) + when(mockTopics.compactionStatus("persistent://myprop/ns1/ds1")) .thenReturn(new LongRunningProcessStatus()); - cmdTopics.run(split("compaction-status persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).compactionStatus("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("compaction-status persistent://myprop/ns1/ds1")); + verify(mockTopics).compactionStatus("persistent://myprop/ns1/ds1"); PersistentTopicInternalStats stats = new PersistentTopicInternalStats(); stats.ledgers = new ArrayList<>(); stats.ledgers.add(newLedger(0, 10, 1000)); stats.ledgers.add(newLedger(1, 10, 2000)); stats.ledgers.add(newLedger(2, 10, 3000)); - when(mockTopics.getInternalStats("persistent://myprop/clust/ns1/ds1", false)) + when(mockTopics.getInternalStats("persistent://myprop/ns1/ds1", false)) .thenReturn(stats); - cmdTopics.run(split("offload persistent://myprop/clust/ns1/ds1 -s 1k")); - verify(mockTopics).triggerOffload("persistent://myprop/clust/ns1/ds1", new MessageIdImpl(2, 0, -1)); + cmdTopics.run(split("offload persistent://myprop/ns1/ds1 -s 1k")); + verify(mockTopics).triggerOffload("persistent://myprop/ns1/ds1", new MessageIdImpl(2, 0, -1)); - when(mockTopics.offloadStatus("persistent://myprop/clust/ns1/ds1")) + when(mockTopics.offloadStatus("persistent://myprop/ns1/ds1")) .thenReturn(new OffloadProcessStatusImpl()); - cmdTopics.run(split("offload-status persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).offloadStatus("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("offload-status persistent://myprop/ns1/ds1")); + verify(mockTopics).offloadStatus("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("last-message-id persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getLastMessageId(eq("persistent://myprop/clust/ns1/ds1")); + cmdTopics.run(split("last-message-id persistent://myprop/ns1/ds1")); + verify(mockTopics).getLastMessageId(eq("persistent://myprop/ns1/ds1")); - cmdTopics.run(split("get-message-ttl persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getMessageTTL("persistent://myprop/clust/ns1/ds1", false); + cmdTopics.run(split("get-message-ttl persistent://myprop/ns1/ds1")); + verify(mockTopics).getMessageTTL("persistent://myprop/ns1/ds1", false); - cmdTopics.run(split("set-message-ttl persistent://myprop/clust/ns1/ds1 -t 10")); - verify(mockTopics).setMessageTTL("persistent://myprop/clust/ns1/ds1", 10); + cmdTopics.run(split("set-message-ttl persistent://myprop/ns1/ds1 -t 10")); + verify(mockTopics).setMessageTTL("persistent://myprop/ns1/ds1", 10); - cmdTopics.run(split("remove-message-ttl persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeMessageTTL("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-message-ttl persistent://myprop/ns1/ds1")); + verify(mockTopics).removeMessageTTL("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("set-replicated-subscription-status persistent://myprop/clust/ns1/ds1 -s sub1 -d")); - verify(mockTopics).setReplicatedSubscriptionStatus("persistent://myprop/clust/ns1/ds1", "sub1", false); + cmdTopics.run(split("set-replicated-subscription-status persistent://myprop/ns1/ds1 -s sub1 -d")); + verify(mockTopics).setReplicatedSubscriptionStatus("persistent://myprop/ns1/ds1", "sub1", false); - cmdTopics.run(split("get-replicated-subscription-status persistent://myprop/clust/ns1/ds1 -s sub1")); - verify(mockTopics).getReplicatedSubscriptionStatus("persistent://myprop/clust/ns1/ds1", "sub1"); + cmdTopics.run(split("get-replicated-subscription-status persistent://myprop/ns1/ds1 -s sub1")); + verify(mockTopics).getReplicatedSubscriptionStatus("persistent://myprop/ns1/ds1", "sub1"); //cmd with option cannot be executed repeatedly. cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("get-max-unacked-messages-on-subscription persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopics).getMaxUnackedMessagesOnSubscription("persistent://myprop/clust/ns1/ds1", true); - cmdTopics.run(split("reset-cursor persistent://myprop/clust/ns1/ds2 -s sub1 -m 1:1 -e")); - verify(mockTopics).resetCursor(eq("persistent://myprop/clust/ns1/ds2"), eq("sub1") + cmdTopics.run(split("get-max-unacked-messages-on-subscription persistent://myprop/ns1/ds1 -ap")); + verify(mockTopics).getMaxUnackedMessagesOnSubscription("persistent://myprop/ns1/ds1", true); + cmdTopics.run(split("reset-cursor persistent://myprop/ns1/ds2 -s sub1 -m 1:1 -e")); + verify(mockTopics).resetCursor(eq("persistent://myprop/ns1/ds2"), eq("sub1") , eq(new MessageIdImpl(1, 1, -1)), eq(true)); - cmdTopics.run(split("get-maxProducers persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopics).getMaxProducers("persistent://myprop/clust/ns1/ds1", true); + cmdTopics.run(split("get-maxProducers persistent://myprop/ns1/ds1 -ap")); + verify(mockTopics).getMaxProducers("persistent://myprop/ns1/ds1", true); - cmdTopics.run(split("set-maxProducers persistent://myprop/clust/ns1/ds1 -p 3")); - verify(mockTopics).setMaxProducers("persistent://myprop/clust/ns1/ds1", 3); + cmdTopics.run(split("set-maxProducers persistent://myprop/ns1/ds1 -p 3")); + verify(mockTopics).setMaxProducers("persistent://myprop/ns1/ds1", 3); - cmdTopics.run(split("remove-maxProducers persistent://myprop/clust/ns1/ds2")); - verify(mockTopics).removeMaxProducers("persistent://myprop/clust/ns1/ds2"); + cmdTopics.run(split("remove-maxProducers persistent://myprop/ns1/ds2")); + verify(mockTopics).removeMaxProducers("persistent://myprop/ns1/ds2"); - cmdTopics.run(split("set-message-ttl persistent://myprop/clust/ns1/ds1 -t 30m")); - verify(mockTopics).setMessageTTL("persistent://myprop/clust/ns1/ds1", 30 * 60); + cmdTopics.run(split("set-message-ttl persistent://myprop/ns1/ds1 -t 30m")); + verify(mockTopics).setMessageTTL("persistent://myprop/ns1/ds1", 30 * 60); - cmdTopics.run(split("get-message-ttl persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopics).getMessageTTL("persistent://myprop/clust/ns1/ds1", true); + cmdTopics.run(split("get-message-ttl persistent://myprop/ns1/ds1 -ap")); + verify(mockTopics).getMessageTTL("persistent://myprop/ns1/ds1", true); - cmdTopics.run(split("get-offload-policies persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopics).getOffloadPolicies("persistent://myprop/clust/ns1/ds1", true); - cmdTopics.run(split("get-max-unacked-messages-on-consumer persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopics).getMaxUnackedMessagesOnConsumer("persistent://myprop/clust/ns1/ds1", true); + cmdTopics.run(split("get-offload-policies persistent://myprop/ns1/ds1 -ap")); + verify(mockTopics).getOffloadPolicies("persistent://myprop/ns1/ds1", true); + cmdTopics.run(split("get-max-unacked-messages-on-consumer persistent://myprop/ns1/ds1 -ap")); + verify(mockTopics).getMaxUnackedMessagesOnConsumer("persistent://myprop/ns1/ds1", true); - cmdTopics.run(split("get-inactive-topic-policies persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopics).getInactiveTopicPolicies("persistent://myprop/clust/ns1/ds1", true); + cmdTopics.run(split("get-inactive-topic-policies persistent://myprop/ns1/ds1 -ap")); + verify(mockTopics).getInactiveTopicPolicies("persistent://myprop/ns1/ds1", true); - cmdTopics.run(split("get-delayed-delivery persistent://myprop/clust/ns1/ds1 --applied")); - verify(mockTopics).getDelayedDeliveryPolicy("persistent://myprop/clust/ns1/ds1", true); + cmdTopics.run(split("get-delayed-delivery persistent://myprop/ns1/ds1 --applied")); + verify(mockTopics).getDelayedDeliveryPolicy("persistent://myprop/ns1/ds1", true); - cmdTopics.run(split("get-max-consumers persistent://myprop/clust/ns1/ds1 -ap")); - verify(mockTopics).getMaxConsumers("persistent://myprop/clust/ns1/ds1", true); + cmdTopics.run(split("get-max-consumers persistent://myprop/ns1/ds1 -ap")); + verify(mockTopics).getMaxConsumers("persistent://myprop/ns1/ds1", true); - cmdTopics.run(split("get-replication-clusters persistent://myprop/clust/ns1/ds1 --applied")); - verify(mockTopics).getReplicationClusters("persistent://myprop/clust/ns1/ds1", true); + cmdTopics.run(split("get-replication-clusters persistent://myprop/ns1/ds1 --applied")); + verify(mockTopics).getReplicationClusters("persistent://myprop/ns1/ds1", true); - cmdTopics.run(split("set-replication-clusters persistent://myprop/clust/ns1/ds1 -c test")); - verify(mockTopics).setReplicationClusters("persistent://myprop/clust/ns1/ds1", Lists.newArrayList("test")); + cmdTopics.run(split("set-replication-clusters persistent://myprop/ns1/ds1 -c test")); + verify(mockTopics).setReplicationClusters("persistent://myprop/ns1/ds1", Lists.newArrayList("test")); - cmdTopics.run(split("remove-replication-clusters persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeReplicationClusters("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-replication-clusters persistent://myprop/ns1/ds1")); + verify(mockTopics).removeReplicationClusters("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-shadow-topics persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getShadowTopics("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-shadow-topics persistent://myprop/ns1/ds1")); + verify(mockTopics).getShadowTopics("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("set-shadow-topics persistent://myprop/clust/ns1/ds1 -t test")); - verify(mockTopics).setShadowTopics("persistent://myprop/clust/ns1/ds1", Lists.newArrayList("test")); + cmdTopics.run(split("set-shadow-topics persistent://myprop/ns1/ds1 -t test")); + verify(mockTopics).setShadowTopics("persistent://myprop/ns1/ds1", Lists.newArrayList("test")); - cmdTopics.run(split("remove-shadow-topics persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).removeShadowTopics("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("remove-shadow-topics persistent://myprop/ns1/ds1")); + verify(mockTopics).removeShadowTopics("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("create-shadow-topic -s persistent://myprop/clust/ns1/source " - + "persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).createShadowTopic("persistent://myprop/clust/ns1/ds1", - "persistent://myprop/clust/ns1/source", null); + cmdTopics.run(split("create-shadow-topic -s persistent://myprop/ns1/source " + + "persistent://myprop/ns1/ds1")); + verify(mockTopics).createShadowTopic("persistent://myprop/ns1/ds1", + "persistent://myprop/ns1/source", null); cmdTopics = new CmdTopics(() -> admin); - cmdTopics.run(split("create-shadow-topic -p a=aa,b=bb,c=cc -s persistent://myprop/clust/ns1/source " - + "persistent://myprop/clust/ns1/ds1")); + cmdTopics.run(split("create-shadow-topic -p a=aa,b=bb,c=cc -s persistent://myprop/ns1/source " + + "persistent://myprop/ns1/ds1")); HashMap p = new HashMap<>(); p.put("a", "aa"); p.put("b", "bb"); p.put("c", "cc"); - verify(mockTopics).createShadowTopic("persistent://myprop/clust/ns1/ds1", - "persistent://myprop/clust/ns1/source", p); + verify(mockTopics).createShadowTopic("persistent://myprop/ns1/ds1", + "persistent://myprop/ns1/source", p); - cmdTopics.run(split("get-shadow-source persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getShadowSource("persistent://myprop/clust/ns1/ds1"); + cmdTopics.run(split("get-shadow-source persistent://myprop/ns1/ds1")); + verify(mockTopics).getShadowSource("persistent://myprop/ns1/ds1"); - cmdTopics.run(split("get-message-id-by-index persistent://myprop/clust/ns1/ds1 -i 0")); - verify(mockTopics).getMessageIdByIndex("persistent://myprop/clust/ns1/ds1", 0); + cmdTopics.run(split("get-message-id-by-index persistent://myprop/ns1/ds1 -i 0")); + verify(mockTopics).getMessageIdByIndex("persistent://myprop/ns1/ds1", 0); } @@ -2213,89 +2187,89 @@ public void persistentTopics() throws Exception { CmdPersistentTopics topics = new CmdPersistentTopics(() -> admin); - topics.run(split("truncate persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).truncate("persistent://myprop/clust/ns1/ds1"); + topics.run(split("truncate persistent://myprop/ns1/ds1")); + verify(mockTopics).truncate("persistent://myprop/ns1/ds1"); - topics.run(split("delete persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).delete("persistent://myprop/clust/ns1/ds1", false); + topics.run(split("delete persistent://myprop/ns1/ds1")); + verify(mockTopics).delete("persistent://myprop/ns1/ds1", false); - topics.run(split("unload persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).unload("persistent://myprop/clust/ns1/ds1"); + topics.run(split("unload persistent://myprop/ns1/ds1")); + verify(mockTopics).unload("persistent://myprop/ns1/ds1"); - topics.run(split("list myprop/clust/ns1")); - verify(mockTopics).getList("myprop/clust/ns1"); + topics.run(split("list myprop/ns1")); + verify(mockTopics).getList("myprop/ns1"); - topics.run(split("subscriptions persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getSubscriptions("persistent://myprop/clust/ns1/ds1"); + topics.run(split("subscriptions persistent://myprop/ns1/ds1")); + verify(mockTopics).getSubscriptions("persistent://myprop/ns1/ds1"); - topics.run(split("unsubscribe persistent://myprop/clust/ns1/ds1 -s sub1")); - verify(mockTopics).deleteSubscription("persistent://myprop/clust/ns1/ds1", "sub1", false); + topics.run(split("unsubscribe persistent://myprop/ns1/ds1 -s sub1")); + verify(mockTopics).deleteSubscription("persistent://myprop/ns1/ds1", "sub1", false); - topics.run(split("stats persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getStats("persistent://myprop/clust/ns1/ds1", false); + topics.run(split("stats persistent://myprop/ns1/ds1")); + verify(mockTopics).getStats("persistent://myprop/ns1/ds1", false); - topics.run(split("stats-internal persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getInternalStats("persistent://myprop/clust/ns1/ds1", false); + topics.run(split("stats-internal persistent://myprop/ns1/ds1")); + verify(mockTopics).getInternalStats("persistent://myprop/ns1/ds1", false); - topics.run(split("info-internal persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getInternalInfo("persistent://myprop/clust/ns1/ds1"); + topics.run(split("info-internal persistent://myprop/ns1/ds1")); + verify(mockTopics).getInternalInfo("persistent://myprop/ns1/ds1"); - topics.run(split("partitioned-stats persistent://myprop/clust/ns1/ds1 --per-partition")); - verify(mockTopics).getPartitionedStats("persistent://myprop/clust/ns1/ds1", true); + topics.run(split("partitioned-stats persistent://myprop/ns1/ds1 --per-partition")); + verify(mockTopics).getPartitionedStats("persistent://myprop/ns1/ds1", true); - topics.run(split("partitioned-stats-internal persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getPartitionedInternalStats("persistent://myprop/clust/ns1/ds1"); + topics.run(split("partitioned-stats-internal persistent://myprop/ns1/ds1")); + verify(mockTopics).getPartitionedInternalStats("persistent://myprop/ns1/ds1"); - topics.run(split("skip-all persistent://myprop/clust/ns1/ds1 -s sub1")); - verify(mockTopics).skipAllMessages("persistent://myprop/clust/ns1/ds1", "sub1"); + topics.run(split("skip-all persistent://myprop/ns1/ds1 -s sub1")); + verify(mockTopics).skipAllMessages("persistent://myprop/ns1/ds1", "sub1"); - topics.run(split("skip persistent://myprop/clust/ns1/ds1 -s sub1 -n 100")); - verify(mockTopics).skipMessages("persistent://myprop/clust/ns1/ds1", "sub1", 100); + topics.run(split("skip persistent://myprop/ns1/ds1 -s sub1 -n 100")); + verify(mockTopics).skipMessages("persistent://myprop/ns1/ds1", "sub1", 100); - topics.run(split("expire-messages persistent://myprop/clust/ns1/ds1 -s sub1 -t 100")); - verify(mockTopics).expireMessages("persistent://myprop/clust/ns1/ds1", "sub1", 100); + topics.run(split("expire-messages persistent://myprop/ns1/ds1 -s sub1 -t 100")); + verify(mockTopics).expireMessages("persistent://myprop/ns1/ds1", "sub1", 100); - topics.run(split("expire-messages-all-subscriptions persistent://myprop/clust/ns1/ds1 -t 100")); - verify(mockTopics).expireMessagesForAllSubscriptions("persistent://myprop/clust/ns1/ds1", 100); + topics.run(split("expire-messages-all-subscriptions persistent://myprop/ns1/ds1 -t 100")); + verify(mockTopics).expireMessagesForAllSubscriptions("persistent://myprop/ns1/ds1", 100); - topics.run(split("create-subscription persistent://myprop/clust/ns1/ds1 -s sub1 " + topics.run(split("create-subscription persistent://myprop/ns1/ds1 -s sub1 " + "--messageId earliest -p a=b --property c=d -p x=y,z")); Map props = new HashMap<>(); props.put("a", "b"); props.put("c", "d"); props.put("x", "y,z"); - verify(mockTopics).createSubscription("persistent://myprop/clust/ns1/ds1", "sub1", + verify(mockTopics).createSubscription("persistent://myprop/ns1/ds1", "sub1", MessageId.earliest, false, props); // jcommander is stateful, you cannot parse the same command twice topics = new CmdPersistentTopics(() -> admin); - topics.run(split("create-subscription persistent://myprop/clust/ns1/ds1 -s sub1 --messageId earliest")); - verify(mockTopics).createSubscription("persistent://myprop/clust/ns1/ds1", "sub1", + topics.run(split("create-subscription persistent://myprop/ns1/ds1 -s sub1 --messageId earliest")); + verify(mockTopics).createSubscription("persistent://myprop/ns1/ds1", "sub1", MessageId.earliest, false, null); - topics.run(split("create-partitioned-topic persistent://myprop/clust/ns1/ds1 --partitions 32")); - verify(mockTopics).createPartitionedTopic("persistent://myprop/clust/ns1/ds1", 32); + topics.run(split("create-partitioned-topic persistent://myprop/ns1/ds1 --partitions 32")); + verify(mockTopics).createPartitionedTopic("persistent://myprop/ns1/ds1", 32); - topics.run(split("list-partitioned-topics myprop/clust/ns1")); - verify(mockTopics).getPartitionedTopicList("myprop/clust/ns1"); + topics.run(split("list-partitioned-topics myprop/ns1")); + verify(mockTopics).getPartitionedTopicList("myprop/ns1"); - topics.run(split("get-partitioned-topic-metadata persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).getPartitionedTopicMetadata("persistent://myprop/clust/ns1/ds1"); + topics.run(split("get-partitioned-topic-metadata persistent://myprop/ns1/ds1")); + verify(mockTopics).getPartitionedTopicMetadata("persistent://myprop/ns1/ds1"); - topics.run(split("delete-partitioned-topic persistent://myprop/clust/ns1/ds1")); - verify(mockTopics).deletePartitionedTopic("persistent://myprop/clust/ns1/ds1", false); + topics.run(split("delete-partitioned-topic persistent://myprop/ns1/ds1")); + verify(mockTopics).deletePartitionedTopic("persistent://myprop/ns1/ds1", false); - topics.run(split("peek-messages persistent://myprop/clust/ns1/ds1 -s sub1 -n 3")); - verify(mockTopics).peekMessages("persistent://myprop/clust/ns1/ds1", "sub1", 3); + topics.run(split("peek-messages persistent://myprop/ns1/ds1 -s sub1 -n 3")); + verify(mockTopics).peekMessages("persistent://myprop/ns1/ds1", "sub1", 3); // cmd with option cannot be executed repeatedly topics = new CmdPersistentTopics(() -> admin); - topics.run(split("expire-messages persistent://myprop/clust/ns1/ds1 -s sub1 -t 2h")); - verify(mockTopics).expireMessages("persistent://myprop/clust/ns1/ds1", "sub1", 2 * 60 * 60); + topics.run(split("expire-messages persistent://myprop/ns1/ds1 -s sub1 -t 2h")); + verify(mockTopics).expireMessages("persistent://myprop/ns1/ds1", "sub1", 2 * 60 * 60); - topics.run(split("expire-messages-all-subscriptions persistent://myprop/clust/ns1/ds1 -t 3d")); - verify(mockTopics).expireMessagesForAllSubscriptions("persistent://myprop/clust/ns1/ds1", + topics.run(split("expire-messages-all-subscriptions persistent://myprop/ns1/ds1 -t 3d")); + verify(mockTopics).expireMessagesForAllSubscriptions("persistent://myprop/ns1/ds1", 3 * 60 * 60 * 24); // argument matcher for the timestamp in reset cursor. Since we can't verify exact timestamp, we check for a @@ -2310,8 +2284,8 @@ public boolean matches(Long timestamp) { return false; } } - topics.run(split("reset-cursor persistent://myprop/clust/ns1/ds1 -s sub1 -t 1m")); - verify(mockTopics).resetCursor(eq("persistent://myprop/clust/ns1/ds1"), eq("sub1"), + topics.run(split("reset-cursor persistent://myprop/ns1/ds1 -s sub1 -t 1m")); + verify(mockTopics).resetCursor(eq("persistent://myprop/ns1/ds1"), eq("sub1"), longThat(new TimestampMatcher())); } @@ -2339,8 +2313,8 @@ public void nonPersistentTopics() throws Exception { when(admin.nonPersistentTopics()).thenReturn(mockNonPersistentTopics); CmdNonPersistentTopics nonPersistentTopics = new CmdNonPersistentTopics(() -> admin); - nonPersistentTopics.run(split("list-in-bundle myprop/clust/ns1 --bundle 0x23d70a30_0x26666658")); - verify(mockNonPersistentTopics).getListInBundle("myprop/clust/ns1", "0x23d70a30_0x26666658"); + nonPersistentTopics.run(split("list-in-bundle myprop/ns1 --bundle 0x23d70a30_0x26666658")); + verify(mockNonPersistentTopics).getListInBundle("myprop/ns1", "0x23d70a30_0x26666658"); } @Test diff --git a/pulsar-client-tools-test/src/test/java/org/apache/pulsar/client/cli/PulsarClientToolTest.java b/pulsar-client-tools-test/src/test/java/org/apache/pulsar/client/cli/PulsarClientToolTest.java index fce91d5b2c290..27939e783ad05 100644 --- a/pulsar-client-tools-test/src/test/java/org/apache/pulsar/client/cli/PulsarClientToolTest.java +++ b/pulsar-client-tools-test/src/test/java/org/apache/pulsar/client/cli/PulsarClientToolTest.java @@ -58,7 +58,7 @@ public class PulsarClientToolTest extends BrokerTestBase { @BeforeMethod @Override public void setup() throws Exception { - super.internalSetup(); + super.baseSetup(); } @AfterMethod(alwaysRun = true) @@ -79,8 +79,9 @@ public void testInitialization() throws InterruptedException, ExecutionException TenantInfoImpl tenantInfo = createDefaultTenantInfo(); admin.tenants().createTenant(tenantName, tenantInfo); + admin.namespaces().createNamespace(tenantName + "/ns"); - String topicName = String.format("persistent://%s/ns/topic-scale-ns-0/topic", tenantName); + String topicName = String.format("persistent://%s/ns/topic", tenantName); int numberOfMessages = 10; @@ -433,7 +434,7 @@ public void testSendMultipleMessage() throws Exception { } private static String getTopicWithRandomSuffix(String localNameBase) { - return String.format("persistent://prop/ns-abc/test/%s-%s", localNameBase, UUID.randomUUID().toString()); + return String.format("persistent://prop/ns-abc/%s-%s", localNameBase, UUID.randomUUID().toString()); } diff --git a/pulsar-client-tools-test/src/test/java/org/apache/pulsar/client/cli/PulsarClientToolWsTest.java b/pulsar-client-tools-test/src/test/java/org/apache/pulsar/client/cli/PulsarClientToolWsTest.java index 7668ba749f0fa..60a37fe4c3b0b 100644 --- a/pulsar-client-tools-test/src/test/java/org/apache/pulsar/client/cli/PulsarClientToolWsTest.java +++ b/pulsar-client-tools-test/src/test/java/org/apache/pulsar/client/cli/PulsarClientToolWsTest.java @@ -38,7 +38,7 @@ public class PulsarClientToolWsTest extends BrokerTestBase { @BeforeMethod @Override protected void setup() throws Exception { - super.internalSetup(); + super.baseSetup(); } @AfterMethod(alwaysRun = true) @@ -53,7 +53,7 @@ public void testWebSocketNonDurableSubscriptionMode() throws Exception { properties.setProperty("serviceUrl", brokerUrl.toString()); properties.setProperty("useTls", "false"); - final String topicName = "persistent://my-property/my-ns/test/topic-" + UUID.randomUUID(); + final String topicName = "persistent://my-property/my-ns/topic-" + UUID.randomUUID(); int numberOfMessages = 10; { @@ -100,7 +100,7 @@ public void testWebSocketDurableSubscriptionMode() throws Exception { properties.setProperty("serviceUrl", brokerUrl.toString()); properties.setProperty("useTls", "false"); - final String topicName = "persistent://my-property/my-ns/test/topic-" + UUID.randomUUID(); + final String topicName = "persistent://my-property/my-ns/topic-" + UUID.randomUUID(); int numberOfMessages = 10; { @@ -148,7 +148,7 @@ public void testWebSocketReader() throws Exception { properties.setProperty("serviceUrl", brokerUrl.toString()); properties.setProperty("useTls", "false"); - final String topicName = "persistent://my-property/my-ns/test/topic-" + UUID.randomUUID(); + final String topicName = "persistent://my-property/my-ns/topic-" + UUID.randomUUID(); int numberOfMessages = 10; { diff --git a/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CliCommand.java b/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CliCommand.java index 8a8019cbe8ccc..41593eb9e236e 100644 --- a/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CliCommand.java +++ b/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CliCommand.java @@ -42,14 +42,6 @@ public abstract class CliCommand implements Callable { @Spec private CommandSpec commandSpec; - static String[] validatePropertyCluster(String params) { - String[] parts = params.split("/"); - if (parts.length != 2) { - throw new IllegalArgumentException("Parameter format is incorrect"); - } - return parts; - } - static String validateNamespace(String namespace) { return NamespaceName.get(namespace).toString(); } diff --git a/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdBrokers.java b/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdBrokers.java index b85a784c3c2b8..206403360263a 100644 --- a/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdBrokers.java +++ b/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdBrokers.java @@ -20,7 +20,6 @@ import java.util.function.Supplier; import org.apache.pulsar.client.admin.PulsarAdmin; -import org.apache.pulsar.common.naming.TopicVersion; import picocli.CommandLine.Command; import picocli.CommandLine.Option; import picocli.CommandLine.Parameters; @@ -126,12 +125,9 @@ void run() throws Exception { @Command(description = "Run a health check against the broker") private class HealthcheckCmd extends CliCommand { - @Option(names = {"-tv", "--topic-version"}, description = "topic version V1 is default") - private TopicVersion topicVersion; - @Override void run() throws Exception { - getAdmin().brokers().healthcheck(topicVersion); + getAdmin().brokers().healthcheck(); System.out.println("ok"); } diff --git a/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdNamespaces.java b/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdNamespaces.java index 4158dd34528ba..8913bc382994f 100644 --- a/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdNamespaces.java +++ b/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdNamespaces.java @@ -41,7 +41,6 @@ import org.apache.pulsar.client.admin.PulsarAdmin; import org.apache.pulsar.client.admin.PulsarAdminException; import org.apache.pulsar.client.api.SubscriptionType; -import org.apache.pulsar.common.naming.NamespaceName; import org.apache.pulsar.common.policies.data.AutoSubscriptionCreationOverride; import org.apache.pulsar.common.policies.data.AutoTopicCreationOverride; import org.apache.pulsar.common.policies.data.BacklogQuota; @@ -82,17 +81,6 @@ void run() throws PulsarAdminException { } } - @Command(description = "Get the namespaces for a tenant in a cluster", hidden = true) - private class GetNamespacesPerCluster extends CliCommand { - @Parameters(description = "tenant/cluster", arity = "1") - private String params; - - @Override - void run() throws PulsarAdminException { - String[] parts = validatePropertyCluster(params); - print(getAdmin().namespaces().getNamespaces(parts[0], parts[1])); - } - } @Command(description = "Get the list of topics for a namespace") private class GetTopics extends CliCommand { @@ -176,28 +164,15 @@ void run() throws PulsarAdminException { "Invalid number of bundles. Number of bundles has to be in the range of (0, 2^32]."); } - NamespaceName namespaceName = NamespaceName.get(namespace); - if (namespaceName.isV2()) { - Policies policies = new Policies(); - policies.bundles = numBundles > 0 ? BundlesData.builder() - .numBundles(numBundles).build() : null; - - if (clusters != null) { - policies.replication_clusters = new HashSet<>(clusters); - } - - getAdmin().namespaces().createNamespace(namespace, policies); - } else { - if (numBundles == 0) { - getAdmin().namespaces().createNamespace(namespace); - } else { - getAdmin().namespaces().createNamespace(namespace, numBundles); - } + Policies policies = new Policies(); + policies.bundles = numBundles > 0 ? BundlesData.builder() + .numBundles(numBundles).build() : null; - if (clusters != null && !clusters.isEmpty()) { - getAdmin().namespaces().setNamespaceReplicationClusters(namespace, new HashSet<>(clusters), false); - } + if (clusters != null) { + policies.replication_clusters = new HashSet<>(clusters); } + + getAdmin().namespaces().createNamespace(namespace, policies); } } @@ -2718,7 +2693,6 @@ void run() throws PulsarAdminException { public CmdNamespaces(Supplier admin) { super("namespaces", admin); addCommand("list", new GetNamespacesPerProperty()); - addCommand("list-cluster", new GetNamespacesPerCluster()); addCommand("topics", new GetTopics()); addCommand("bundles", new GetBundles()); diff --git a/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdPersistentTopics.java b/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdPersistentTopics.java index 7b86e2af7f523..e92e48fcbd7a5 100644 --- a/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdPersistentTopics.java +++ b/pulsar-client-tools/src/main/java/org/apache/pulsar/admin/cli/CmdPersistentTopics.java @@ -594,7 +594,7 @@ void run() throws PulsarAdminException { @Command(description = "Get message by its ledgerId and entryId") private class GetMessageById extends CliCommand { - @Parameters(description = "persistent://property/cluster/namespace/topic", arity = "1") + @Parameters(description = "persistent://tenant/namespace/topic", arity = "1") private String topicName; @Option(names = { "-l", "--ledgerId" }, @@ -621,7 +621,7 @@ void run() throws PulsarAdminException { @Command(description = "Get last message Id of the topic") private class GetLastMessageId extends CliCommand { - @Parameters(description = "persistent://property/cluster/namespace/topic", arity = "1") + @Parameters(description = "persistent://tenant/namespace/topic", arity = "1") private String topicName; @Override diff --git a/pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdConsume.java b/pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdConsume.java index 06a15eb181c37..4a5254cd9c0b4 100644 --- a/pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdConsume.java +++ b/pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdConsume.java @@ -250,25 +250,17 @@ private int consume(String topic) { } - @SuppressWarnings("deprecation") @VisibleForTesting public String getWebSocketConsumeUri(String topic) { String serviceURLWithoutTrailingSlash = serviceURL.substring(0, serviceURL.endsWith("/") ? serviceURL.length() - 1 : serviceURL.length()); TopicName topicName = TopicName.get(topic); - String wsTopic; - if (topicName.isV2()) { - wsTopic = String.format("%s/%s/%s/%s", topicName.getDomain(), topicName.getTenant(), - topicName.getNamespacePortion(), topicName.getLocalName()); - } else { - wsTopic = String.format("%s/%s/%s/%s/%s", topicName.getDomain(), topicName.getTenant(), - topicName.getCluster(), topicName.getNamespacePortion(), topicName.getLocalName()); - } + String wsTopic = String.format("%s/%s/%s/%s", topicName.getDomain(), topicName.getTenant(), + topicName.getNamespacePortion(), topicName.getLocalName()); - String uriFormat = "%s/ws" + (topicName.isV2() ? "/v2/" : "/") - + "consumer/%s/%s?subscriptionType=%s&subscriptionMode=%s"; - return String.format(uriFormat, serviceURLWithoutTrailingSlash, wsTopic, subscriptionName, + return String.format("%s/ws/v2/consumer/%s/%s?subscriptionType=%s&subscriptionMode=%s", + serviceURLWithoutTrailingSlash, wsTopic, subscriptionName, subscriptionType.toString(), subscriptionMode.toString()); } diff --git a/pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdProduce.java b/pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdProduce.java index b166cd9372874..9c72cd474ccb7 100644 --- a/pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdProduce.java +++ b/pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdProduce.java @@ -438,24 +438,16 @@ private static Schema buildGenericSchema(SchemaType type, String definition) } - @SuppressWarnings("deprecation") @VisibleForTesting public String getWebSocketProduceUri(String topic) { String serviceURLWithoutTrailingSlash = serviceURL.substring(0, serviceURL.endsWith("/") ? serviceURL.length() - 1 : serviceURL.length()); TopicName topicName = TopicName.get(topic); - String wsTopic; - if (topicName.isV2()) { - wsTopic = String.format("%s/%s/%s/%s", topicName.getDomain(), topicName.getTenant(), - topicName.getNamespacePortion(), topicName.getLocalName()); - } else { - wsTopic = String.format("%s/%s/%s/%s/%s", topicName.getDomain(), topicName.getTenant(), - topicName.getCluster(), topicName.getNamespacePortion(), topicName.getLocalName()); - } + String wsTopic = String.format("%s/%s/%s/%s", topicName.getDomain(), topicName.getTenant(), + topicName.getNamespacePortion(), topicName.getLocalName()); - String uriFormat = "%s/ws" + (topicName.isV2() ? "/v2/" : "/") + "producer/%s"; - return String.format(uriFormat, serviceURLWithoutTrailingSlash, wsTopic); + return String.format("%s/ws/v2/producer/%s", serviceURLWithoutTrailingSlash, wsTopic); } @SuppressWarnings("deprecation") diff --git a/pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdRead.java b/pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdRead.java index 72f6bacbb88d5..e5421ffa6acb9 100644 --- a/pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdRead.java +++ b/pulsar-client-tools/src/main/java/org/apache/pulsar/client/cli/CmdRead.java @@ -205,21 +205,14 @@ private int read(String topic) { } - @SuppressWarnings("deprecation") @VisibleForTesting public String getWebSocketReadUri(String topic) { String serviceURLWithoutTrailingSlash = serviceURL.substring(0, serviceURL.endsWith("/") ? serviceURL.length() - 1 : serviceURL.length()); TopicName topicName = TopicName.get(topic); - String wsTopic; - if (topicName.isV2()) { - wsTopic = String.format("%s/%s/%s/%s", topicName.getDomain(), topicName.getTenant(), - topicName.getNamespacePortion(), topicName.getLocalName()); - } else { - wsTopic = String.format("%s/%s/%s/%s/%s", topicName.getDomain(), topicName.getTenant(), - topicName.getCluster(), topicName.getNamespacePortion(), topicName.getLocalName()); - } + String wsTopic = String.format("%s/%s/%s/%s", topicName.getDomain(), topicName.getTenant(), + topicName.getNamespacePortion(), topicName.getLocalName()); String msgIdQueryParam; if ("latest".equals(startMessageId) || "earliest".equals(startMessageId)) { @@ -229,8 +222,8 @@ public String getWebSocketReadUri(String topic) { msgIdQueryParam = Base64.getEncoder().encodeToString(msgId.toByteArray()); } - String uriFormat = "%s/ws" + (topicName.isV2() ? "/v2/" : "/") + "reader/%s?messageId=%s"; - return String.format(uriFormat, serviceURLWithoutTrailingSlash, wsTopic, msgIdQueryParam); + return String.format("%s/ws/v2/reader/%s?messageId=%s", serviceURLWithoutTrailingSlash, wsTopic, + msgIdQueryParam); } @SuppressWarnings("deprecation") diff --git a/pulsar-client-tools/src/test/java/org/apache/pulsar/admin/cli/TestRunMain.java b/pulsar-client-tools/src/test/java/org/apache/pulsar/admin/cli/TestRunMain.java index c3dbd1cdc7c85..17b4fde011c29 100644 --- a/pulsar-client-tools/src/test/java/org/apache/pulsar/admin/cli/TestRunMain.java +++ b/pulsar-client-tools/src/test/java/org/apache/pulsar/admin/cli/TestRunMain.java @@ -98,7 +98,7 @@ public void testMainArgs() throws Exception { printWriter.close(); testConfigFile.deleteOnExit(); - String argStrTemp = "%s %s --admin-url https://url:4443 " + "topics stats persistent://prop/cluster/ns/t1"; + String argStrTemp = "%s %s --admin-url https://url:4443 " + "topics stats persistent://prop/ns/t1"; boolean prevValue = PulsarAdminTool.allowSystemExit; PulsarAdminTool.allowSystemExit = false; diff --git a/pulsar-client-tools/src/test/java/org/apache/pulsar/client/cli/TestCmdConsume.java b/pulsar-client-tools/src/test/java/org/apache/pulsar/client/cli/TestCmdConsume.java index c5d9d721d8a66..9834c49f2480a 100644 --- a/pulsar-client-tools/src/test/java/org/apache/pulsar/client/cli/TestCmdConsume.java +++ b/pulsar-client-tools/src/test/java/org/apache/pulsar/client/cli/TestCmdConsume.java @@ -38,10 +38,6 @@ public void setUp() throws Exception { @Test public void testGetWebSocketConsumeUri() { - String topicNameV1 = "persistent://public/cluster/default/issue-11067"; - assertEquals(cmdConsume.getWebSocketConsumeUri(topicNameV1), - "ws://localhost:8080/ws/consumer/persistent/public/cluster/default/issue-11067/my-sub" - + "?subscriptionType=Exclusive&subscriptionMode=Durable"); String topicNameV2 = "persistent://public/default/issue-11067"; assertEquals(cmdConsume.getWebSocketConsumeUri(topicNameV2), "ws://localhost:8080/ws/v2/consumer/persistent/public/default/issue-11067/my-sub" diff --git a/pulsar-client-tools/src/test/java/org/apache/pulsar/client/cli/TestCmdProduce.java b/pulsar-client-tools/src/test/java/org/apache/pulsar/client/cli/TestCmdProduce.java index eb3f94db26459..1b918fbe8dd46 100644 --- a/pulsar-client-tools/src/test/java/org/apache/pulsar/client/cli/TestCmdProduce.java +++ b/pulsar-client-tools/src/test/java/org/apache/pulsar/client/cli/TestCmdProduce.java @@ -45,9 +45,6 @@ public void setUp() { @Test public void testGetWebSocketProduceUri() { - String topicNameV1 = "persistent://public/cluster/default/issue-11067"; - assertEquals(cmdProduce.getWebSocketProduceUri(topicNameV1), - "ws://localhost:8080/ws/producer/persistent/public/cluster/default/issue-11067"); String topicNameV2 = "persistent://public/default/issue-11067"; assertEquals(cmdProduce.getWebSocketProduceUri(topicNameV2), "ws://localhost:8080/ws/v2/producer/persistent/public/default/issue-11067"); diff --git a/pulsar-client-tools/src/test/java/org/apache/pulsar/client/cli/TestCmdRead.java b/pulsar-client-tools/src/test/java/org/apache/pulsar/client/cli/TestCmdRead.java index bb33b4dd058aa..45f508f25cb9d 100644 --- a/pulsar-client-tools/src/test/java/org/apache/pulsar/client/cli/TestCmdRead.java +++ b/pulsar-client-tools/src/test/java/org/apache/pulsar/client/cli/TestCmdRead.java @@ -47,10 +47,6 @@ public void testGetWebSocketReadUri(String msgId, String msgIdQueryParam) throws startMessageIdField.setAccessible(true); startMessageIdField.set(cmdRead, msgId); - String topicNameV1 = "persistent://public/cluster/default/t1"; - assertEquals(cmdRead.getWebSocketReadUri(topicNameV1), - "ws://localhost:8080/ws/reader/persistent/public/cluster/default/t1?messageId=" + msgIdQueryParam); - String topicNameV2 = "persistent://public/default/t2"; assertEquals(cmdRead.getWebSocketReadUri(topicNameV2), "ws://localhost:8080/ws/v2/reader/persistent/public/default/t2?messageId=" + msgIdQueryParam); diff --git a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/HttpLookupService.java b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/HttpLookupService.java index c364a79453765..22ae64da1045c 100644 --- a/pulsar-client/src/main/java/org/apache/pulsar/client/impl/HttpLookupService.java +++ b/pulsar-client/src/main/java/org/apache/pulsar/client/impl/HttpLookupService.java @@ -61,8 +61,7 @@ public class HttpLookupService implements LookupService { private final boolean useTls; private final String listenerName; - private static final String BasePathV1 = "lookup/v2/destination/"; - private static final String BasePathV2 = "lookup/v2/topic/"; + private static final String BasePath = "lookup/v2/topic/"; private final LatencyHistogram histoGetBroker; private final LatencyHistogram histoGetTopicMetadata; @@ -105,7 +104,6 @@ public void updateServiceUrl(String serviceUrl) throws PulsarClientException { * @return broker-socket-address that serves given topic */ @Override - @SuppressWarnings("deprecation") public CompletableFuture getBroker(TopicName topicName, Map lookupProperties) { if (lookupProperties == null) { lookupProperties = httpClient.clientConf.getLookupProperties(); @@ -114,8 +112,7 @@ public CompletableFuture getBroker(TopicName topicName, Map httpFuture = httpClient.get( String.format(format, topicName.getLookupName()) + "?checkAllowAutoCreation=" + metadataAutoCreationEnabled, @@ -196,8 +193,7 @@ public CompletableFuture getTopicsUnderNamespace(NamespaceName CompletableFuture future = new CompletableFuture<>(); - String format = namespace.isV2() - ? "admin/v2/namespaces/%s/topics?mode=%s" : "admin/namespaces/%s/destinations?mode=%s"; + String format = "admin/v2/namespaces/%s/topics?mode=%s"; httpClient .get(String.format(format, namespace, mode.toString()), String[].class) .thenAccept(topics -> { diff --git a/pulsar-client/src/test/java/org/apache/pulsar/client/tutorial/SampleAsyncProducerWithSchema.java b/pulsar-client/src/test/java/org/apache/pulsar/client/tutorial/SampleAsyncProducerWithSchema.java index 3520d03e0c5d8..8c9017ea18373 100644 --- a/pulsar-client/src/test/java/org/apache/pulsar/client/tutorial/SampleAsyncProducerWithSchema.java +++ b/pulsar-client/src/test/java/org/apache/pulsar/client/tutorial/SampleAsyncProducerWithSchema.java @@ -37,7 +37,7 @@ public static void main(String[] args) throws IOException { PulsarClient pulsarClient = PulsarClient.builder().serviceUrl("http://localhost:8080").build(); Producer producer = pulsarClient.newProducer(JSONSchema.of(SchemaDefinition.builder() - .withPojo(JsonPojo.class).build())).topic("persistent://my-property/use/my-ns/my-topic") + .withPojo(JsonPojo.class).build())).topic("persistent://my-property/my-ns/my-topic") .sendTimeout(3, TimeUnit.SECONDS).create(); List> futures = new ArrayList<>(); diff --git a/pulsar-client/src/test/java/org/apache/pulsar/client/tutorial/SampleConsumerWithSchema.java b/pulsar-client/src/test/java/org/apache/pulsar/client/tutorial/SampleConsumerWithSchema.java index 8a3a2885afc97..e468acde121c0 100644 --- a/pulsar-client/src/test/java/org/apache/pulsar/client/tutorial/SampleConsumerWithSchema.java +++ b/pulsar-client/src/test/java/org/apache/pulsar/client/tutorial/SampleConsumerWithSchema.java @@ -33,7 +33,7 @@ public static void main(String[] args) throws PulsarClientException, JsonProcess Consumer consumer = pulsarClient.newConsumer(JSONSchema.of (SchemaDefinition.builder().withPojo(JsonPojo.class).build())) // - .topic("persistent://my-property/use/my-ns/my-topic") // + .topic("persistent://my-property/my-ns/my-topic") // .subscriptionName("my-subscription-name").subscribe(); Message msg = null; diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/naming/Constants.java b/pulsar-common/src/main/java/org/apache/pulsar/common/naming/Constants.java index 7970b395fb326..fbe94369a0464 100644 --- a/pulsar-common/src/main/java/org/apache/pulsar/common/naming/Constants.java +++ b/pulsar-common/src/main/java/org/apache/pulsar/common/naming/Constants.java @@ -23,8 +23,6 @@ */ public class Constants { - public static final String GLOBAL_CLUSTER = "global"; - public static final String WEBSOCKET_DUMMY_ORIGINAL_PRINCIPLE = "__websocket_dummy_original_principle"; private Constants() {} diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java b/pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java index a804e7b6506ad..a2e13125a9626 100644 --- a/pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java +++ b/pulsar-common/src/main/java/org/apache/pulsar/common/naming/NamespaceName.java @@ -36,7 +36,6 @@ public class NamespaceName implements ServiceUnitId { private final String namespace; private final String tenant; - private final String cluster; private final String localName; private static final LoadingCache cache = CacheBuilder.newBuilder().maximumSize(100000) @@ -54,11 +53,6 @@ public static NamespaceName get(String tenant, String namespace) { return get(tenant + '/' + namespace); } - public static NamespaceName get(String tenant, String cluster, String namespace) { - validateNamespaceName(tenant, cluster, namespace); - return get(tenant + '/' + cluster + '/' + namespace); - } - public static NamespaceName get(String namespace) { if (namespace == null || namespace.isEmpty()) { throw new IllegalArgumentException("Invalid null namespace: " + namespace); @@ -94,32 +88,25 @@ public static Optional getIfValid(String namespace) { private NamespaceName(String namespace) { // Verify it's a proper namespace // The namespace name is composed of / - // or in the legacy format with the cluster name: - // // try { String[] parts = namespace.split("/"); if (parts.length == 2) { - // New style namespace : / validateNamespaceName(parts[0], parts[1]); tenant = parts[0]; - cluster = null; localName = parts[1]; } else if (parts.length == 3) { - // Old style namespace: // - validateNamespaceName(parts[0], parts[1], parts[2]); - - tenant = parts[0]; - cluster = parts[1]; - localName = parts[2]; + throw new IllegalArgumentException( + "V1 namespace names (with cluster component) are no longer supported. " + + "Please use the V2 format: '/'. Got: " + namespace); } else { throw new IllegalArgumentException("Invalid namespace format. namespace: " + namespace); } } catch (IllegalArgumentException | NullPointerException e) { throw new IllegalArgumentException("Invalid namespace format." - + " expected / or // " - + "but got: " + namespace, e); + + " expected /" + + " but got: " + namespace, e); } this.namespace = namespace; } @@ -128,17 +115,12 @@ public String getTenant() { return tenant; } - @Deprecated - public String getCluster() { - return cluster; - } - public String getLocalName() { return localName; } public boolean isGlobal() { - return cluster == null || Constants.GLOBAL_CLUSTER.equalsIgnoreCase(cluster); + return true; } public String getPersistentTopicName(String localTopic) { @@ -189,17 +171,6 @@ public static void validateNamespaceName(String tenant, String namespace) { NamedEntity.checkName(namespace); } - public static void validateNamespaceName(String tenant, String cluster, String namespace) { - if ((tenant == null || tenant.isEmpty()) || (cluster == null || cluster.isEmpty()) - || (namespace == null || namespace.isEmpty())) { - throw new IllegalArgumentException( - String.format("Invalid namespace format. namespace: %s/%s/%s", tenant, cluster, namespace)); - } - NamedEntity.checkName(tenant); - NamedEntity.checkName(cluster); - NamedEntity.checkName(namespace); - } - @Override public NamespaceName getNamespaceObject() { return this; @@ -209,12 +180,4 @@ public NamespaceName getNamespaceObject() { public boolean includes(TopicName topicName) { return this.equals(topicName.getNamespaceObject()); } - - /** - * Returns true if this is a V2 namespace prop/namespace-name. - * @return true if v2 - */ - public boolean isV2() { - return cluster == null; - } } diff --git a/pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java b/pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java index 4d9b28df91be1..ad14edabde0bf 100644 --- a/pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java +++ b/pulsar-common/src/main/java/org/apache/pulsar/common/naming/TopicName.java @@ -42,7 +42,6 @@ public class TopicName implements ServiceUnitId { private final TopicDomain domain; private final String tenant; - private final String cluster; private final String namespacePortion; private final String localName; @@ -72,12 +71,6 @@ public static TopicName get(String domain, String tenant, String namespace, Stri return TopicName.get(name); } - public static TopicName get(String domain, String tenant, String cluster, String namespace, - String topic) { - String name = domain + "://" + tenant + '/' + cluster + '/' + namespace + '/' + topic; - return TopicName.get(name); - } - public static TopicName get(String topic) { TopicName tp = cache.get(topic); if (tp != null) { @@ -119,7 +112,7 @@ private TopicName(String completeTopicName) { if (!completeTopicName.contains("://")) { // The short topic name can be: // - - // - // + // - // String[] parts = StringUtils.split(completeTopicName, '/'); if (parts.length == 3) { completeTopicName = TopicDomain.persistent.name() + "://" + completeTopicName; @@ -133,40 +126,25 @@ private TopicName(String completeTopicName) { } } - // The fully qualified topic name can be in two different forms: - // new: persistent://tenant/namespace/topic - // legacy: persistent://tenant/cluster/namespace/topic - + // Expected format: persistent://tenant/namespace/topic List parts = Splitter.on("://").limit(2).splitToList(completeTopicName); this.domain = TopicDomain.getEnum(parts.get(0)); String rest = parts.get(1); - // The rest of the name can be in different forms: - // new: tenant/namespace/ - // legacy: tenant/cluster/namespace/ - // Examples of localName: - // 1. some, name, xyz - // 2. xyz-123, feeder-2 - - + // Expected format: tenant/namespace/ parts = Splitter.on("/").limit(4).splitToList(rest); - if (parts.size() == 3) { - // New topic name without cluster name + if (parts.size() == 4) { + throw new IllegalArgumentException( + "V1 topic names (with cluster component) are no longer supported. " + + "Please use the V2 format: '://tenant/namespace/topic'. Got: " + + completeTopicName); + } else if (parts.size() == 3) { this.tenant = parts.get(0); - this.cluster = null; this.namespacePortion = parts.get(1); this.localName = parts.get(2); this.partitionIndex = getPartitionIndex(completeTopicName); this.namespaceName = NamespaceName.get(tenant, namespacePortion); - } else if (parts.size() == 4) { - // Legacy topic name that includes cluster name - this.tenant = parts.get(0); - this.cluster = parts.get(1); - this.namespacePortion = parts.get(2); - this.localName = parts.get(3); - this.partitionIndex = getPartitionIndex(completeTopicName); - this.namespaceName = NamespaceName.get(tenant, cluster, namespacePortion); } else { throw new IllegalArgumentException("Invalid topic name: " + completeTopicName); } @@ -179,14 +157,8 @@ private TopicName(String completeTopicName) { } catch (NullPointerException e) { throw new IllegalArgumentException("Invalid topic name: " + completeTopicName, e); } - if (isV2()) { - this.completeTopicName = String.format("%s://%s/%s/%s", - domain, tenant, namespacePortion, localName); - } else { - this.completeTopicName = String.format("%s://%s/%s/%s/%s", - domain, tenant, cluster, - namespacePortion, localName); - } + this.completeTopicName = String.format("%s://%s/%s/%s", + domain, tenant, namespacePortion, localName); } public boolean isPersistent() { @@ -196,8 +168,6 @@ public boolean isPersistent() { /** * Extract the namespace portion out of a completeTopicName name. * - *

Works both with old & new convention. - * * @return the namespace */ public String getNamespace() { @@ -222,11 +192,6 @@ public String getTenant() { return tenant; } - @Deprecated - public String getCluster() { - return cluster; - } - public String getNamespacePortion() { return namespacePortion; } @@ -263,9 +228,9 @@ public boolean isPartitioned() { * For partitions in a topic, return the base partitioned topic name. * Eg: *

    - *
  • persistent://prop/cluster/ns/my-topic-partition-1 --> - * persistent://prop/cluster/ns/my-topic - *
  • persistent://prop/cluster/ns/my-topic --> persistent://prop/cluster/ns/my-topic + *
  • persistent://prop/ns/my-topic-partition-1 --> + * persistent://prop/ns/my-topic + *
  • persistent://prop/ns/my-topic --> persistent://prop/ns/my-topic *
*/ public String getPartitionedTopicName() { @@ -323,11 +288,7 @@ public String getRestPath() { public String getRestPath(boolean includeDomain) { String domainName = includeDomain ? domain + "/" : ""; - if (isV2()) { - return String.format("%s%s/%s/%s", domainName, tenant, namespacePortion, getEncodedLocalName()); - } else { - return String.format("%s%s/%s/%s/%s", domainName, tenant, cluster, namespacePortion, getEncodedLocalName()); - } + return String.format("%s%s/%s/%s", domainName, tenant, namespacePortion, getEncodedLocalName()); } /** @@ -338,18 +299,11 @@ public String getRestPath(boolean includeDomain) { public String getPersistenceNamingEncoding() { // The convention is: domain://tenant/namespace/topic // We want to persist in the order: tenant/namespace/domain/topic - - // For legacy naming scheme, the convention is: domain://tenant/cluster/namespace/topic - // We want to persist in the order: tenant/cluster/namespace/domain/topic - if (isV2()) { - return String.format("%s/%s/%s/%s", tenant, namespacePortion, domain, getEncodedLocalName()); - } else { - return String.format("%s/%s/%s/%s/%s", tenant, cluster, namespacePortion, domain, getEncodedLocalName()); - } + return String.format("%s/%s/%s/%s", tenant, namespacePortion, domain, getEncodedLocalName()); } /** - * get topic full name from managedLedgerName. + * Get topic full name from managedLedgerName. * * @return the topic full name, format -> domain://tenant/namespace/topic */ @@ -361,7 +315,6 @@ public static String fromPersistenceNamingEncoding(String mlName) { } List parts = Splitter.on("/").splitToList(mlName); String tenant; - String cluster; String namespacePortion; String domain; String localName; @@ -372,12 +325,14 @@ public static String fromPersistenceNamingEncoding(String mlName) { localName = Codec.decode(parts.get(3)); return String.format("%s://%s/%s/%s", domain, tenant, namespacePortion, localName); } else if (parts.size() == 5) { + // Legacy V1 managed ledger name: tenant/cluster/namespace/domain/topic + // Convert to V2 format, dropping the cluster component tenant = parts.get(0); - cluster = parts.get(1); + // parts.get(1) is the cluster, which we drop namespacePortion = parts.get(2); domain = parts.get(3); localName = Codec.decode(parts.get(4)); - return String.format("%s://%s/%s/%s/%s", domain, tenant, cluster, namespacePortion, localName); + return String.format("%s://%s/%s/%s", domain, tenant, namespacePortion, localName); } else { throw new IllegalArgumentException("Invalid managedLedger name: " + mlName); } @@ -388,21 +343,17 @@ public static String fromPersistenceNamingEncoding(String mlName) { * *

Example: * - *

persistent://tenant/cluster/namespace/completeTopicName -> - * persistent/tenant/cluster/namespace/completeTopicName + *

persistent://tenant/namespace/completeTopicName -> + * persistent/tenant/namespace/completeTopicName * * @return */ public String getLookupName() { - if (isV2()) { - return String.format("%s/%s/%s/%s", domain, tenant, namespacePortion, getEncodedLocalName()); - } else { - return String.format("%s/%s/%s/%s/%s", domain, tenant, cluster, namespacePortion, getEncodedLocalName()); - } + return String.format("%s/%s/%s/%s", domain, tenant, namespacePortion, getEncodedLocalName()); } public boolean isGlobal() { - return cluster == null || Constants.GLOBAL_CLUSTER.equalsIgnoreCase(cluster); + return namespaceName.isGlobal(); } public String getSchemaName() { @@ -436,21 +387,12 @@ public boolean includes(TopicName otherTopicName) { return this.equals(otherTopicName); } - /** - * Returns true if this a V2 topic name prop/ns/topic-name. - * @return true if V2 - */ - public boolean isV2() { - return cluster == null; - } - /** * Convert a topic name to a full topic name. - * In Pulsar, a full topic name is ":////" (v2) or - * "://///" (v1). However, for convenient, it's allowed for clients - * to pass a short topic name with v2 format: + * In Pulsar, a full topic name is ":////". + * For convenience, clients can pass a short topic name: * - "", which represents "persistent://public/default/" - * - "//, which represents "persistent:////" + * - "//", which represents "persistent:////" * * @param topic the topic name from client * @return the full topic name. @@ -460,19 +402,18 @@ public static String toFullTopicName(String topic) { if (index >= 0) { TopicDomain.getEnum(topic.substring(0, index)); final List parts = splitBySlash(topic.substring(index + "://".length()), 4); - if (parts.size() != 3 && parts.size() != 4) { - throw new IllegalArgumentException(topic + " is invalid"); + if (parts.size() == 4) { + throw new IllegalArgumentException( + "V1 topic names (with cluster component) are no longer supported. " + + "Please use the V2 format: '://tenant/namespace/topic'. Got: " + topic); } - if (parts.size() == 3) { - NamespaceName.validateNamespaceName(parts.get(0), parts.get(1)); - if (StringUtils.isBlank(parts.get(2))) { - throw new IllegalArgumentException(topic + " has blank local topic"); - } - } else { - NamespaceName.validateNamespaceName(parts.get(0), parts.get(1), parts.get(2)); - if (StringUtils.isBlank(parts.get(3))) { - throw new IllegalArgumentException(topic + " has blank local topic"); - } + if (parts.size() != 3) { + throw new IllegalArgumentException(topic + " is invalid. " + + "Expected format: '://tenant/namespace/topic'"); + } + NamespaceName.validateNamespaceName(parts.get(0), parts.get(1)); + if (StringUtils.isBlank(parts.get(2))) { + throw new IllegalArgumentException(topic + " has blank local topic"); } return topic; // it's a valid full topic name } else { diff --git a/pulsar-common/src/test/java/org/apache/pulsar/common/naming/NamespaceNameTest.java b/pulsar-common/src/test/java/org/apache/pulsar/common/naming/NamespaceNameTest.java index 337a5ea1f6b0a..5d2579ce4f0c8 100644 --- a/pulsar-common/src/test/java/org/apache/pulsar/common/naming/NamespaceNameTest.java +++ b/pulsar-common/src/test/java/org/apache/pulsar/common/naming/NamespaceNameTest.java @@ -20,7 +20,6 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; @@ -46,66 +45,53 @@ public void namespace_propertyNamespaceTopic() { NamespaceName.get("property.namespace:topic"); } + // 3-part V1 namespace names are no longer supported @Test(expectedExceptions = IllegalArgumentException.class) - public void namespace_propertyClusterNamespaceTopic() { - NamespaceName.get("property/cluster/namespace/topic"); + public void namespace_threePartNameRejected() { + NamespaceName.get("property/cluster/namespace"); } @Test(expectedExceptions = IllegalArgumentException.class) - public void namespace_null() { - NamespaceName.get(null); + public void namespace_fourPartNameRejected() { + NamespaceName.get("property/cluster/namespace/topic"); } @Test(expectedExceptions = IllegalArgumentException.class) - public void namespace_nullTenant() { - NamespaceName.get(null, "use", "ns1"); + public void namespace_null() { + NamespaceName.get(null); } @Test public void namespace_persistentTopic() { - assertEquals(NamespaceName.get("prop/cluster/ns").getPersistentTopicName("ds"), - "persistent://prop/cluster/ns/ds"); + assertEquals(NamespaceName.get("prop/ns").getPersistentTopicName("ds"), + "persistent://prop/ns/ds"); } @Test(expectedExceptions = IllegalArgumentException.class) public void namespace_topicNameNullDomain() { - NamespaceName.get("prop/cluster/ns").getTopicName(null, "ds"); + NamespaceName.get("prop/ns").getTopicName(null, "ds"); } @Test public void namespace_persistentTopicExplicitDomain() { - assertEquals(NamespaceName.get("prop/cluster/ns").getTopicName(TopicDomain.persistent, "ds"), - "persistent://prop/cluster/ns/ds"); + assertEquals(NamespaceName.get("prop/ns").getTopicName(TopicDomain.persistent, "ds"), + "persistent://prop/ns/ds"); } @Test public void namespace_equals() { - assertEquals(NamespaceName.get("prop/cluster/ns"), NamespaceName.get("prop/cluster/ns")); + assertEquals(NamespaceName.get("prop/ns"), NamespaceName.get("prop/ns")); } @Test public void namespace_toString() { - assertEquals(NamespaceName.get("prop/cluster/ns").toString(), "prop/cluster/ns"); + assertEquals(NamespaceName.get("prop/ns").toString(), "prop/ns"); } @SuppressWarnings("AssertBetweenInconvertibleTypes") @Test public void namespace_equalsCheckType() { - assertNotEquals(NamespaceName.get("prop/cluster/ns"), "prop/cluster/ns"); - } - - @Test - public void namespace_vargEquivalentToParse() { - assertEquals(NamespaceName.get("prop", "cluster", "ns"), NamespaceName.get("prop/cluster/ns")); - } - - // Deprecation warning suppressed as this test targets deprecated methods - @SuppressWarnings("deprecation") - @Test - public void namespace_members() { - assertEquals(NamespaceName.get("prop/cluster/ns").getTenant(), "prop"); - assertEquals(NamespaceName.get("prop/cluster/ns").getCluster(), "cluster"); - assertEquals(NamespaceName.get("prop/cluster/ns").getLocalName(), "ns"); + assertNotEquals(NamespaceName.get("prop/ns"), "prop/ns"); } @Test(expectedExceptions = IllegalArgumentException.class) @@ -113,77 +99,22 @@ public void namespace_oldStyleNamespaceTenant() { NamespaceName.get("ns").getTenant(); } - // Deprecation warning suppressed as this test targets deprecated methods - @SuppressWarnings("deprecation") - @Test(expectedExceptions = IllegalArgumentException.class) - public void namespace_oldStyleNamespaceCluster() { - NamespaceName.get("ns").getCluster(); - } - @Test(expectedExceptions = IllegalArgumentException.class) public void namespace_oldStyleNamespaceLocalName() { NamespaceName.get("ns").getLocalName(); } - @Test(expectedExceptions = IllegalArgumentException.class) - public void namespace_nullTenant2() { - NamespaceName.get(null, "cluster", "namespace"); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void namespace_emptyTenant() { - NamespaceName.get("", "cluster", "namespace"); - } - @Test(expectedExceptions = IllegalArgumentException.class) public void namespace_emptyTenantElement() { - NamespaceName.get("/cluster/namespace"); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void namespace_missingCluster() { - NamespaceName.get("pulsar//namespace"); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void namespace_nullCluster() { - NamespaceName.get("pulsar", null, "namespace"); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void namespace_emptyCluster() { - NamespaceName.get("pulsar", "", "namespace"); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void namespace_nullNamespace() { - NamespaceName.get("pulsar", "cluster", null); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void namespace_emptyNamespace() { - NamespaceName.get("pulsar", "cluster", ""); - } - - // Deprecation warning suppressed as this test targets deprecated methods - @SuppressWarnings("deprecation") - @Test - public void namespace_v2Namespace() { - NamespaceName v2Namespace = NamespaceName.get("pulsar/colo1/testns-1"); - assertEquals(v2Namespace.getTenant(), "pulsar"); - assertEquals(v2Namespace.getCluster(), "colo1"); - assertEquals(v2Namespace.getLocalName(), "testns-1"); + NamespaceName.get("/namespace"); } - // Deprecation warning suppressed as this test targets deprecated methods - @SuppressWarnings("deprecation") @Test - void testNewScheme() { + void testNamespaceProperties() { NamespaceName ns = NamespaceName.get("my-tenant/my-namespace"); assertEquals(ns.getTenant(), "my-tenant"); assertEquals(ns.getLocalName(), "my-namespace"); assertTrue(ns.isGlobal()); - assertNull(ns.getCluster()); assertEquals(ns.getPersistentTopicName("my-topic"), "persistent://my-tenant/my-namespace/my-topic"); } } diff --git a/pulsar-common/src/test/java/org/apache/pulsar/common/naming/TopicNameTest.java b/pulsar-common/src/test/java/org/apache/pulsar/common/naming/TopicNameTest.java index 62fd5feb481d0..f19053da29ace 100644 --- a/pulsar-common/src/test/java/org/apache/pulsar/common/naming/TopicNameTest.java +++ b/pulsar-common/src/test/java/org/apache/pulsar/common/naming/TopicNameTest.java @@ -21,7 +21,6 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertNull; import static org.testng.Assert.assertThrows; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; @@ -30,7 +29,6 @@ public class TopicNameTest { - @SuppressWarnings("deprecation") @Test public void topic() { try { @@ -40,33 +38,30 @@ public void topic() { // Expected } - assertEquals(TopicName.get("persistent://tenant/cluster/namespace/topic").getNamespace(), - "tenant/cluster/namespace"); - assertEquals(TopicName.get("persistent://tenant/cluster/namespace/topic").getNamespace(), - "tenant/cluster/namespace"); + // V2 format: persistent://tenant/namespace/topic + assertEquals(TopicName.get("persistent://tenant/namespace/topic").getNamespace(), + "tenant/namespace"); - assertEquals(TopicName.get("persistent://tenant/cluster/namespace/topic"), - TopicName.get("persistent", "tenant", "cluster", "namespace", "topic")); + assertEquals(TopicName.get("persistent://tenant/namespace/topic"), + TopicName.get("persistent", "tenant", "namespace", "topic")); - assertEquals(TopicName.get("persistent://tenant/cluster/namespace/topic").hashCode(), - TopicName.get("persistent", "tenant", "cluster", "namespace", "topic").hashCode()); + assertEquals(TopicName.get("persistent://tenant/namespace/topic").hashCode(), + TopicName.get("persistent", "tenant", "namespace", "topic").hashCode()); - assertEquals(TopicName.get("persistent://tenant/cluster/namespace/topic").toString(), - "persistent://tenant/cluster/namespace/topic"); - assertEquals(TopicName.toFullTopicName("persistent://tenant/cluster/namespace/topic"), - "persistent://tenant/cluster/namespace/topic"); + assertEquals(TopicName.get("persistent://tenant/namespace/topic").toString(), + "persistent://tenant/namespace/topic"); + assertEquals(TopicName.toFullTopicName("persistent://tenant/namespace/topic"), + "persistent://tenant/namespace/topic"); - assertEquals(TopicName.get("persistent://tenant/cluster/namespace/topic").getDomain(), + assertEquals(TopicName.get("persistent://tenant/namespace/topic").getDomain(), TopicDomain.persistent); - assertEquals(TopicName.get("persistent://tenant/cluster/namespace/topic").getTenant(), + assertEquals(TopicName.get("persistent://tenant/namespace/topic").getTenant(), "tenant"); - assertEquals(TopicName.get("persistent://tenant/cluster/namespace/topic").getCluster(), - "cluster"); - assertEquals(TopicName.get("persistent://tenant/cluster/namespace/topic").getNamespacePortion(), + assertEquals(TopicName.get("persistent://tenant/namespace/topic").getNamespacePortion(), "namespace"); - assertEquals(TopicName.get("persistent://tenant/cluster/namespace/topic").getNamespace(), - "tenant/cluster/namespace"); - assertEquals(TopicName.get("persistent://tenant/cluster/namespace/topic").getLocalName(), + assertEquals(TopicName.get("persistent://tenant/namespace/topic").getNamespace(), + "tenant/namespace"); + assertEquals(TopicName.get("persistent://tenant/namespace/topic").getLocalName(), "topic"); try { @@ -83,13 +78,6 @@ public void topic() { // Ok } - try { - TopicName.get("://tenant.namespace:my-topic").getCluster(); - fail("Should have raised exception"); - } catch (IllegalArgumentException e) { - // Ok - } - try { TopicName.get("://tenant.namespace:my-topic").getNamespacePortion(); fail("Should have raised exception"); @@ -114,68 +102,42 @@ public void topic() { assertThrows(IllegalArgumentException.class, () -> TopicName.toFullTopicName("://tenant.namespace")); try { - TopicName.get("invalid://tenant/cluster/namespace/topic"); + TopicName.get("invalid://tenant/namespace/topic"); fail("Should have raied exception"); } catch (IllegalArgumentException e) { // Ok } assertThrows(IllegalArgumentException.class, - () -> TopicName.toFullTopicName("invalid://tenant/cluster/namespace/topic")); + () -> TopicName.toFullTopicName("invalid://tenant/namespace/topic")); - try { - TopicName.get("tenant/cluster/namespace/topic"); - fail("Should have raised exception"); - } catch (IllegalArgumentException e) { - // Ok - } - assertThrows(IllegalArgumentException.class, () -> TopicName.toFullTopicName("tenant/cluster/namespace/topic")); - - try { - TopicName.get("persistent:///cluster/namespace/mydest-1"); - fail("Should have raised exception"); - } catch (IllegalArgumentException e) { - // Ok - } + // V1 topic names (with cluster component) are no longer supported assertThrows(IllegalArgumentException.class, - () -> TopicName.toFullTopicName("persistent:///cluster/namespace/mydest-1")); - - try { - TopicName.get("persistent://pulsar//namespace/mydest-1"); - fail("Should have raised exception"); - } catch (IllegalArgumentException e) { - // Ok - } + () -> TopicName.get("persistent://tenant/cluster/namespace/topic")); assertThrows(IllegalArgumentException.class, - () -> TopicName.toFullTopicName("persistent://pulsar//namespace/mydest-1")); + () -> TopicName.get("non-persistent://tenant/cluster/namespace/topic")); - try { - TopicName.get("persistent://pulsar/cluster//mydest-1"); - fail("Should have raised exception"); - } catch (IllegalArgumentException e) { - // Ok - } + // 4-part short topic names (without domain) are not supported assertThrows(IllegalArgumentException.class, - () -> TopicName.toFullTopicName("persistent://pulsar/cluster//mydest-1")); + () -> TopicName.get("tenant/cluster/namespace/topic")); + assertThrows(IllegalArgumentException.class, () -> TopicName.toFullTopicName("tenant/cluster/namespace/topic")); try { - TopicName.get("persistent://pulsar/cluster/namespace/"); + TopicName.get("persistent:///namespace/mydest-1"); fail("Should have raised exception"); } catch (IllegalArgumentException e) { // Ok } assertThrows(IllegalArgumentException.class, - () -> TopicName.toFullTopicName("persistent://pulsar/cluster/namespace/")); + () -> TopicName.toFullTopicName("persistent:///namespace/mydest-1")); try { - TopicName.get("://pulsar/cluster/namespace/"); + TopicName.get("persistent://pulsar//mydest-1"); fail("Should have raised exception"); } catch (IllegalArgumentException e) { // Ok } - assertThrows(IllegalArgumentException.class, () -> TopicName.toFullTopicName("://pulsar/cluster/namespace/")); - - assertEquals(TopicName.get("persistent://tenant/cluster/namespace/topic") - .getPersistenceNamingEncoding(), "tenant/cluster/namespace/persistent/topic"); + assertThrows(IllegalArgumentException.class, + () -> TopicName.toFullTopicName("persistent://pulsar//mydest-1")); try { TopicName.get("://tenant.namespace"); @@ -185,14 +147,6 @@ public void topic() { } assertThrows(IllegalArgumentException.class, () -> TopicName.toFullTopicName("://tenant.namespace")); - try { - TopicName.get("://tenant/cluster/namespace"); - fail("Should have raied exception"); - } catch (IllegalArgumentException e) { - // Ok - } - assertThrows(IllegalArgumentException.class, () -> TopicName.toFullTopicName("://tenant//cluster/namespace")); - try { TopicName.get(" "); fail("Should have raised exception"); @@ -201,29 +155,22 @@ public void topic() { } assertThrows(IllegalArgumentException.class, () -> TopicName.toFullTopicName(" ")); - TopicName nameWithSlash = TopicName.get("persistent://tenant/cluster/namespace/ns-abc/table/1"); - assertEquals(nameWithSlash.getEncodedLocalName(), Codec.encode("ns-abc/table/1")); - - TopicName nameEndingInSlash = TopicName - .get("persistent://tenant/cluster/namespace/ns-abc/table/1/"); - assertEquals(nameEndingInSlash.getEncodedLocalName(), Codec.encode("ns-abc/table/1/")); - - TopicName nameWithTwoSlashes = TopicName - .get("persistent://tenant/cluster/namespace//ns-abc//table//1//"); - assertEquals(nameWithTwoSlashes.getEncodedLocalName(), Codec.encode("/ns-abc//table//1//")); - - TopicName nameWithRandomCharacters = TopicName - .get("persistent://tenant/cluster/namespace/$#3rpa/table/1"); - assertEquals(nameWithRandomCharacters.getEncodedLocalName(), Codec.encode("$#3rpa/table/1")); + // V2 topic names do not allow '/' in local names (V1 did) + assertThrows(IllegalArgumentException.class, + () -> TopicName.get("persistent://tenant/namespace/ns-abc/table/1")); + assertThrows(IllegalArgumentException.class, + () -> TopicName.get("persistent://tenant/namespace/ns-abc/table/1/")); + assertThrows(IllegalArgumentException.class, + () -> TopicName.get("persistent://tenant/namespace/$#3rpa/table/1")); - TopicName topicName = TopicName.get("persistent://myprop/mycolo/myns/mytopic"); - assertEquals(topicName.getPartition(0).toString(), "persistent://myprop/mycolo/myns/mytopic-partition-0"); + TopicName topicName = TopicName.get("persistent://myprop/myns/mytopic"); + assertEquals(topicName.getPartition(0).toString(), "persistent://myprop/myns/mytopic-partition-0"); - TopicName partitionedDn = TopicName.get("persistent://myprop/mycolo/myns/mytopic").getPartition(2); + TopicName partitionedDn = TopicName.get("persistent://myprop/myns/mytopic").getPartition(2); assertEquals(partitionedDn.getPartitionIndex(), 2); assertEquals(topicName.getPartitionIndex(), -1); - assertEquals(TopicName.getPartitionIndex("persistent://myprop/mycolo/myns/mytopic-partition-4"), 4); + assertEquals(TopicName.getPartitionIndex("persistent://myprop/myns/mytopic-partition-4"), 4); // Following behavior is not right actually, none partitioned topic, partition index is -1 assertEquals(TopicName.getPartitionIndex("mytopic-partition--1"), -1); @@ -247,23 +194,22 @@ public void topic() { @Test public void testDecodeEncode() throws Exception { - String encodedName = - "a%3Aen-in_in_business_content_item_20150312173022_https%5C%3A%2F%2Fin.news.example.com%2Fr"; - String rawName = "a:en-in_in_business_content_item_20150312173022_https\\://in.news.example.com/r"; + String encodedName = "a%3Aen-in_in_business_content_item_20150312173022_https%5C%3A"; + String rawName = "a:en-in_in_business_content_item_20150312173022_https\\:"; assertEquals(Codec.decode(encodedName), rawName); assertEquals(Codec.encode(rawName), encodedName); - String topicName = "persistent://prop/colo/ns/" + rawName; + String topicName = "persistent://prop/ns/" + rawName; TopicName name = TopicName.get(topicName); assertEquals(name.getLocalName(), rawName); assertEquals(name.getEncodedLocalName(), encodedName); - assertEquals(name.getPersistenceNamingEncoding(), "prop/colo/ns/persistent/" + encodedName); + assertEquals(name.getPersistenceNamingEncoding(), "prop/ns/persistent/" + encodedName); } @Test public void testFromPersistenceNamingEncoding() { - // case1: V2 + // case1: V2 (4-part ML name: tenant/namespace/persistent/topic) String mlName1 = "public_tenant/default_namespace/persistent/test_topic"; String expectedTopicName1 = "persistent://public_tenant/default_namespace/test_topic"; @@ -271,20 +217,18 @@ public void testFromPersistenceNamingEncoding() { assertEquals(name1.getPersistenceNamingEncoding(), mlName1); assertEquals(TopicName.fromPersistenceNamingEncoding(mlName1), expectedTopicName1); - // case2: V1 + // case2: 5-part ML name (legacy V1 format: tenant/cluster/namespace/persistent/topic) + // Now produces V2 output with cluster dropped String mlName2 = "public_tenant/my_cluster/default_namespace/persistent/test_topic"; - String expectedTopicName2 = "persistent://public_tenant/my_cluster/default_namespace/test_topic"; - - TopicName name2 = TopicName.get(expectedTopicName2); - assertEquals(name2.getPersistenceNamingEncoding(), mlName2); + String expectedTopicName2 = "persistent://public_tenant/default_namespace/test_topic"; assertEquals(TopicName.fromPersistenceNamingEncoding(mlName2), expectedTopicName2); - // case3: null + // case3: empty String mlName3 = ""; String expectedTopicName3 = ""; assertEquals(expectedTopicName3, TopicName.fromPersistenceNamingEncoding(mlName3)); - // case4: Invalid name + // case4: Invalid name (6-part) try { String mlName4 = "public_tenant/my_cluster/default_namespace/persistent/test_topic/sub_topic"; TopicName.fromPersistenceNamingEncoding(mlName4); @@ -301,9 +245,8 @@ public void testFromPersistenceNamingEncoding() { } - @SuppressWarnings("deprecation") @Test - public void testTopicNameWithoutCluster() throws Exception { + public void testTopicNameProperties() throws Exception { TopicName topicName = TopicName.get("persistent://tenant/namespace/topic"); assertEquals(topicName.getNamespace(), "tenant/namespace"); @@ -316,7 +259,6 @@ public void testTopicNameWithoutCluster() throws Exception { assertEquals(topicName.toString(), "persistent://tenant/namespace/topic"); assertEquals(topicName.getDomain(), TopicDomain.persistent); assertEquals(topicName.getTenant(), "tenant"); - assertNull(topicName.getCluster()); assertEquals(topicName.getNamespacePortion(), "namespace"); assertEquals(topicName.getNamespace(), "tenant/namespace"); assertEquals(topicName.getLocalName(), "topic"); @@ -340,19 +282,12 @@ public void testShortTopicName() throws Exception { assertEquals("test-namespace", tn.getNamespacePortion()); assertEquals("test-short-topic", tn.getLocalName()); - try { - TopicName.get("pulsar/cluster/namespace/test"); - fail("Should have raised exception"); - } catch (IllegalArgumentException e) { - // Ok - } + // 4-part V1 names are no longer supported + assertThrows(IllegalArgumentException.class, + () -> TopicName.get("pulsar/cluster/namespace/test")); - try { - TopicName.get("pulsar/cluster"); - fail("Should have raised exception"); - } catch (IllegalArgumentException e) { - // Ok - } + assertThrows(IllegalArgumentException.class, + () -> TopicName.get("pulsar/cluster")); } @Test @@ -370,7 +305,11 @@ public void testToFullTopicName() { assertEquals("persistent://tenant/ns/tp???xx=", TopicName.toFullTopicName("tenant/ns/tp???xx=")); assertEquals("persistent://tenant/ns/test", TopicName.toFullTopicName("persistent://tenant/ns/test")); assertThrows(IllegalArgumentException.class, () -> TopicName.toFullTopicName("ns/topic")); - // v1 format is not supported when the domain is not included + // v1 format is not supported assertThrows(IllegalArgumentException.class, () -> TopicName.toFullTopicName("tenant/cluster/ns/topic")); + assertThrows(IllegalArgumentException.class, + () -> TopicName.toFullTopicName("persistent://tenant/cluster/ns/topic")); + assertThrows(IllegalArgumentException.class, + () -> TopicName.toFullTopicName("non-persistent://tenant/cluster/ns/topic")); } } diff --git a/pulsar-common/src/test/java/org/apache/pulsar/common/policies/impl/NamespaceIsolationPoliciesTest.java b/pulsar-common/src/test/java/org/apache/pulsar/common/policies/impl/NamespaceIsolationPoliciesTest.java index e2f187d24a4e7..af73752e3c91f 100644 --- a/pulsar-common/src/test/java/org/apache/pulsar/common/policies/impl/NamespaceIsolationPoliciesTest.java +++ b/pulsar-common/src/test/java/org/apache/pulsar/common/policies/impl/NamespaceIsolationPoliciesTest.java @@ -46,7 +46,7 @@ public class NamespaceIsolationPoliciesTest { - private final String defaultJson = "{\"policy1\":{\"namespaces\":[\"pulsar/use/test.*\"]," + private final String defaultJson = "{\"policy1\":{\"namespaces\":[\"pulsar/test.*\"]," + "\"primary\":[\"prod1-broker[1-3].messaging.use.example.com\"]," + "\"secondary\":[\"prod1-broker.*.use.example.com\"]," + "\"auto_failover_policy\":{\"parameters\":{\"min_limit\":\"3\",\"usage_threshold\":\"100\"}," @@ -80,7 +80,7 @@ public void testJsonSerialization() throws Exception { parameters.put("usage_threshold", "100"); NamespaceIsolationData nsPolicyData = NamespaceIsolationData.builder() - .namespaces(Collections.singletonList("pulsar/use/other.*")) + .namespaces(Collections.singletonList("pulsar/other.*")) .primary(Collections.singletonList("prod1-broker[4-6].messaging.use.example.com")) .secondary(Collections.singletonList("prod1-broker.*.messaging.use.example.com")) .autoFailoverPolicy(AutoFailoverPolicyData.builder() @@ -129,9 +129,9 @@ public void testGetNamespaceIsolationPolicyByName() throws Exception { @Test public void testGetNamespaceIsolationPolicyByNamespace() throws Exception { NamespaceIsolationPolicies policies = this.getDefaultTestPolicies(); - NamespaceIsolationPolicy nsPolicy = policies.getPolicyByNamespace(NamespaceName.get("no/such/namespace")); + NamespaceIsolationPolicy nsPolicy = policies.getPolicyByNamespace(NamespaceName.get("no/namespace")); assertNull(nsPolicy); - nsPolicy = policies.getPolicyByNamespace(NamespaceName.get("pulsar/use/testns-1")); + nsPolicy = policies.getPolicyByNamespace(NamespaceName.get("pulsar/testns-1")); assertNotNull(nsPolicy); assertEquals(new NamespaceIsolationPolicyImpl(policies.getPolicies().get("policy1")), nsPolicy); } @@ -140,7 +140,7 @@ public void testGetNamespaceIsolationPolicyByNamespace() throws Exception { public void testSetPolicy() throws Exception { NamespaceIsolationPolicies policies = this.getDefaultTestPolicies(); // set a new policy - String newPolicyJson = "{\"namespaces\":[\"pulsar/use/TESTNS.*\"]," + String newPolicyJson = "{\"namespaces\":[\"pulsar/TESTNS.*\"]," + "\"primary\":[\"prod1-broker[45].messaging.use.example.com\"]," + "\"secondary\":[\"prod1-broker.*.use.example.com\"]," + "\"auto_failover_policy\":{\"policy_type\":\"min_available\",\"parameters\":{\"min_limit\":2," @@ -154,7 +154,7 @@ public void testSetPolicy() throws Exception { assertEquals(policies.getPolicies().size(), 2); assertEquals(policies.getPolicyByName(newPolicyName), new NamespaceIsolationPolicyImpl(nsPolicyData)); assertNotEquals(policies.getPolicyByName("policy1"), policies.getPolicyByName(newPolicyName)); - assertEquals(policies.getPolicyByNamespace(NamespaceName.get("pulsar/use/TESTNS.1")), + assertEquals(policies.getPolicyByNamespace(NamespaceName.get("pulsar/TESTNS.1")), new NamespaceIsolationPolicyImpl(nsPolicyData)); } @@ -169,7 +169,7 @@ private NamespaceIsolationPolicies getDefaultTestPolicies() throws Exception { @Test public void testBrokerAssignment() throws Exception { NamespaceIsolationPolicies policies = this.getDefaultTestPolicies(); - NamespaceName ns = NamespaceName.get("pulsar/use/testns-1"); + NamespaceName ns = NamespaceName.get("pulsar/testns-1"); SortedSet primaryCandidates = new TreeSet<>(); BrokerStatus primary = BrokerStatus.builder() .brokerAddress("prod1-broker1.messaging.use.example.com") @@ -198,7 +198,7 @@ public void testBrokerAssignment() throws Exception { assertEquals(secondaryCandidates.size(), 1); assertEquals(sharedCandidates.size(), 0); assertEquals(secondary, secondaryCandidates.first()); - policies.assignBroker(NamespaceName.get("pulsar/use1/testns-1"), shared, primaryCandidates, secondaryCandidates, + policies.assignBroker(NamespaceName.get("pulsar/other-ns"), shared, primaryCandidates, secondaryCandidates, sharedCandidates); assertEquals(primaryCandidates.size(), 1); assertEquals(secondaryCandidates.size(), 1); diff --git a/pulsar-common/src/test/java/org/apache/pulsar/common/policies/impl/NamespaceIsolationPolicyImplTest.java b/pulsar-common/src/test/java/org/apache/pulsar/common/policies/impl/NamespaceIsolationPolicyImplTest.java index 4c2f788886795..15910b4eb8960 100644 --- a/pulsar-common/src/test/java/org/apache/pulsar/common/policies/impl/NamespaceIsolationPolicyImplTest.java +++ b/pulsar-common/src/test/java/org/apache/pulsar/common/policies/impl/NamespaceIsolationPolicyImplTest.java @@ -42,7 +42,7 @@ import org.testng.annotations.Test; public class NamespaceIsolationPolicyImplTest { - private final String defaultPolicyJson = "{\"namespaces\":[\"pulsar/use/test.*\"]," + private final String defaultPolicyJson = "{\"namespaces\":[\"pulsar/test.*\"]," + "\"primary\":[\"prod1-broker[1-3].messaging.use.example.com\"]," + "\"secondary\":[\"prod1-broker.*.use.example.com\"]," + "\"auto_failover_policy\":{\"policy_type\":\"min_available\",\"parameters\":{\"min_limit\":\"3\"," @@ -63,7 +63,7 @@ public void testConstructor() throws Exception { parameters.put("usage_threshold", "90"); NamespaceIsolationData policyData = NamespaceIsolationData.builder() - .namespaces(Collections.singletonList("pulsar/use/test.*")) + .namespaces(Collections.singletonList("pulsar/test.*")) .primary(Collections.singletonList("prod1-broker[1-3].messaging.use.example.com")) .secondary(Collections.singletonList("prod1-broker.*.use.example.com")) .autoFailoverPolicy(AutoFailoverPolicyData.builder() @@ -116,28 +116,28 @@ public void testFindBrokers() throws Exception { String broker = String.format("prod1-broker%d.messaging.usw.example.com", i); brokers.add(new URL(String.format("http://%s:8080", broker))); } - List primaryBrokers = defaultPolicy.findPrimaryBrokers(brokers, NamespaceName.get("pulsar/use/testns-1")); + List primaryBrokers = defaultPolicy.findPrimaryBrokers(brokers, NamespaceName.get("pulsar/testns-1")); assertEquals(primaryBrokers.size(), 3); for (URL primaryBroker : primaryBrokers) { assertTrue(primaryBroker.getHost().matches("prod1-broker[1-3].messaging.use.example.com")); } - primaryBrokers = defaultPolicy.findPrimaryBrokers(otherBrokers, NamespaceName.get("pulsar/use/testns-1")); + primaryBrokers = defaultPolicy.findPrimaryBrokers(otherBrokers, NamespaceName.get("pulsar/testns-1")); assertTrue(primaryBrokers.isEmpty()); try { - primaryBrokers = defaultPolicy.findPrimaryBrokers(brokers, NamespaceName.get("no/such/namespace")); + primaryBrokers = defaultPolicy.findPrimaryBrokers(brokers, NamespaceName.get("no/namespace")); } catch (IllegalArgumentException iae) { // OK } List secondaryBrokers = defaultPolicy.findSecondaryBrokers(brokers, - NamespaceName.get("pulsar/use/testns-1")); + NamespaceName.get("pulsar/testns-1")); assertEquals(secondaryBrokers.size(), 10); for (URL secondaryBroker : secondaryBrokers) { assertTrue(secondaryBroker.getHost().matches("prod1-broker.*.messaging.use.example.com")); } - secondaryBrokers = defaultPolicy.findSecondaryBrokers(otherBrokers, NamespaceName.get("pulsar/use/testns-1")); + secondaryBrokers = defaultPolicy.findSecondaryBrokers(otherBrokers, NamespaceName.get("pulsar/testns-1")); assertTrue(secondaryBrokers.isEmpty()); try { - secondaryBrokers = defaultPolicy.findSecondaryBrokers(brokers, NamespaceName.get("no/such/namespace")); + secondaryBrokers = defaultPolicy.findSecondaryBrokers(brokers, NamespaceName.get("no/namespace")); } catch (IllegalArgumentException iae) { // OK } diff --git a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyServiceStarter.java b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyServiceStarter.java index 7b66831cec7cd..144e953ac4db5 100644 --- a/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyServiceStarter.java +++ b/pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/ProxyServiceStarter.java @@ -450,15 +450,12 @@ public static void addWebServerHandlers(WebServer server, } final JettyWebSocketServlet producerWebSocketServlet = new WebSocketProducerServlet(webSocketService); addWebSocketServlet(server, WebSocketProducerServlet.SERVLET_PATH, producerWebSocketServlet); - addWebSocketServlet(server, WebSocketProducerServlet.SERVLET_PATH_V2, producerWebSocketServlet); final JettyWebSocketServlet consumerWebSocketServlet = new WebSocketConsumerServlet(webSocketService); addWebSocketServlet(server, WebSocketConsumerServlet.SERVLET_PATH, consumerWebSocketServlet); - addWebSocketServlet(server, WebSocketConsumerServlet.SERVLET_PATH_V2, consumerWebSocketServlet); final JettyWebSocketServlet readerWebSocketServlet = new WebSocketReaderServlet(webSocketService); addWebSocketServlet(server, WebSocketReaderServlet.SERVLET_PATH, readerWebSocketServlet); - addWebSocketServlet(server, WebSocketReaderServlet.SERVLET_PATH_V2, readerWebSocketServlet); final WebSocketMultiTopicConsumerServlet multiTopicConsumerWebSocketServlet = new WebSocketMultiTopicConsumerServlet(webSocketService); diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyConnectionThrottlingTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyConnectionThrottlingTest.java index f2a57a0d86199..6bd343093a10f 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyConnectionThrottlingTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyConnectionThrottlingTest.java @@ -54,6 +54,7 @@ public class ProxyConnectionThrottlingTest extends MockedPulsarServiceBaseTest { @BeforeClass protected void setup() throws Exception { internalSetup(); + setupDefaultTenantAndNamespace(); proxyConfig.setServicePort(Optional.of(0)); proxyConfig.setBrokerProxyAllowedTargetPorts("*"); @@ -94,7 +95,7 @@ public void testInboundConnection() throws Exception { .build(); Producer producer1 = client1.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/producer-topic-1").create(); + .topic("persistent://public/default/producer-topic-1").create(); log.info("Creating producer 2"); PulsarClient client2 = PulsarClient.builder() @@ -103,7 +104,7 @@ public void testInboundConnection() throws Exception { .build(); Producer producer2 = client2.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/producer-topic-1").create(); + .topic("persistent://public/default/producer-topic-1").create(); log.info("Creating producer 3"); @Cleanup @@ -113,7 +114,7 @@ public void testInboundConnection() throws Exception { .build(); try { Producer producer3 = client3.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/producer-topic-1").create(); + .topic("persistent://public/default/producer-topic-1").create(); producer3.send("Message 1".getBytes()); Assert.fail("Should have failed since max num of connections is 2 and the first" + " producer used them all up - one for discovery and other for producing."); diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyEnableHAProxyProtocolTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyEnableHAProxyProtocolTest.java index 359df30b76f00..5d4d8324953ed 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyEnableHAProxyProtocolTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyEnableHAProxyProtocolTest.java @@ -55,6 +55,7 @@ public class ProxyEnableHAProxyProtocolTest extends MockedPulsarServiceBaseTest protected void setup() throws Exception { conf.setHaProxyProtocolEnabled(true); internalSetup(); + setupDefaultTenantAndNamespace(); proxyConfig.setServicePort(Optional.ofNullable(0)); proxyConfig.setBrokerProxyAllowedTargetPorts("*"); @@ -93,7 +94,7 @@ public void testSimpleProduceAndConsume() throws PulsarClientException, PulsarAd PulsarClient client = PulsarClient.builder().serviceUrl(proxyService.getServiceUrl()) .build(); - final String topicName = "persistent://sample/test/local/testSimpleProduceAndConsume"; + final String topicName = "persistent://public/default/testSimpleProduceAndConsume"; final String subName = "my-subscriber-name"; final int messages = 100; diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyKeyStoreTlsTransportTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyKeyStoreTlsTransportTest.java index 09ec1b1889313..c3b6f10eb1946 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyKeyStoreTlsTransportTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyKeyStoreTlsTransportTest.java @@ -61,6 +61,7 @@ protected void setup() throws Exception { conf.setTlsRequireTrustedClientCertOnConnect(true); internalSetup(); + setupDefaultTenantAndNamespace(); // proxy with JKS proxyConfig.setServicePort(Optional.of(0)); @@ -133,7 +134,7 @@ public void testProducer() throws Exception { PulsarClient client = newClient(); @Cleanup Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/topic" + System.currentTimeMillis()) + .topic("persistent://public/default/topic" + System.currentTimeMillis()) .create(); for (int i = 0; i < 10; i++) { diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyKeyStoreTlsWithAuthTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyKeyStoreTlsWithAuthTest.java index c8cc6a7aa6ad4..8877395633aab 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyKeyStoreTlsWithAuthTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyKeyStoreTlsWithAuthTest.java @@ -43,7 +43,6 @@ import org.apache.pulsar.client.api.Schema; import org.apache.pulsar.client.impl.auth.AuthenticationKeyStoreTls; import org.apache.pulsar.common.configuration.PulsarConfigurationLoader; -import org.apache.pulsar.common.policies.data.TenantInfoImpl; import org.apache.pulsar.metadata.impl.ZKMetadataStore; import org.mockito.Mockito; import org.testng.Assert; @@ -61,6 +60,7 @@ public class ProxyKeyStoreTlsWithAuthTest extends MockedPulsarServiceBaseTest { @BeforeMethod protected void setup() throws Exception { internalSetup(); + setupDefaultTenantAndNamespace(); proxyConfig.setServicePort(Optional.of(0)); proxyConfig.setBrokerProxyAllowedTargetPorts("*"); @@ -140,7 +140,7 @@ public void testProducer() throws Exception { PulsarClient client = internalSetUpForClient(true, proxyService.getServiceUrlTls()); @Cleanup Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/topic" + System.currentTimeMillis()) + .topic("persistent://public/default/topic" + System.currentTimeMillis()) .create(); for (int i = 0; i < 10; i++) { @@ -155,7 +155,7 @@ public void testProducerFailed() throws Exception { try { @Cleanup Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/topic" + System.currentTimeMillis()) + .topic("persistent://public/default/topic" + System.currentTimeMillis()) .create(); Assert.fail("Should failed since broker setTlsRequireTrustedClientCertOnConnect, " + "while client not set keystore"); @@ -170,9 +170,7 @@ public void testProducerFailed() throws Exception { public void testPartitions() throws Exception { @Cleanup PulsarClient client = internalSetUpForClient(true, proxyService.getServiceUrlTls()); - String topicName = "persistent://sample/test/local/partitioned-topic" + System.currentTimeMillis(); - TenantInfoImpl tenantInfo = createDefaultTenantInfo(); - admin.tenants().createTenant("sample", tenantInfo); + String topicName = "persistent://public/default/partitioned-topic" + System.currentTimeMillis(); admin.topics().createPartitionedTopic(topicName, 2); @Cleanup diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyKeyStoreTlsWithoutAuthTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyKeyStoreTlsWithoutAuthTest.java index 235672020328b..397f05affe9bc 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyKeyStoreTlsWithoutAuthTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyKeyStoreTlsWithoutAuthTest.java @@ -39,7 +39,6 @@ import org.apache.pulsar.client.api.Schema; import org.apache.pulsar.client.impl.auth.AuthenticationKeyStoreTls; import org.apache.pulsar.common.configuration.PulsarConfigurationLoader; -import org.apache.pulsar.common.policies.data.TenantInfoImpl; import org.apache.pulsar.metadata.impl.ZKMetadataStore; import org.mockito.Mockito; import org.testng.Assert; @@ -57,6 +56,7 @@ public class ProxyKeyStoreTlsWithoutAuthTest extends MockedPulsarServiceBaseTest @BeforeMethod protected void setup() throws Exception { internalSetup(); + setupDefaultTenantAndNamespace(); proxyConfig.setServicePort(Optional.of(0)); proxyConfig.setBrokerProxyAllowedTargetPorts("*"); @@ -127,7 +127,7 @@ public void testProducer() throws Exception { PulsarClient client = internalSetUpForClient(true, proxyService.getServiceUrlTls()); @Cleanup Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/topic" + System.currentTimeMillis()) + .topic("persistent://public/default/topic" + System.currentTimeMillis()) .create(); for (int i = 0; i < 10; i++) { @@ -142,7 +142,7 @@ public void testProducerFailed() throws Exception { try { @Cleanup Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/topic" + System.currentTimeMillis()) + .topic("persistent://public/default/topic" + System.currentTimeMillis()) .create(); Assert.fail("Should failed since broker setTlsRequireTrustedClientCertOnConnect, " + "while client not set keystore"); @@ -157,9 +157,7 @@ public void testProducerFailed() throws Exception { public void testPartitions() throws Exception { @Cleanup PulsarClient client = internalSetUpForClient(true, proxyService.getServiceUrlTls()); - String topicName = "persistent://sample/test/local/partitioned-topic" + System.currentTimeMillis(); - TenantInfoImpl tenantInfo = createDefaultTenantInfo(); - admin.tenants().createTenant("sample", tenantInfo); + String topicName = "persistent://public/default/partitioned-topic" + System.currentTimeMillis(); admin.topics().createPartitionedTopic(topicName, 2); @Cleanup diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyLookupThrottlingTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyLookupThrottlingTest.java index 83321d0f776a5..ece4873dc3147 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyLookupThrottlingTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyLookupThrottlingTest.java @@ -57,6 +57,7 @@ public class ProxyLookupThrottlingTest extends MockedPulsarServiceBaseTest { @BeforeMethod(alwaysRun = true) protected void setup() throws Exception { internalSetup(); + setupDefaultTenantAndNamespace(); proxyConfig.setServicePort(Optional.of(0)); proxyConfig.setBrokerProxyAllowedTargetPorts("*"); @@ -105,12 +106,12 @@ public void testLookup() throws Exception { @Cleanup Producer producer1 = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/producer-topic").create(); + .topic("persistent://public/default/producer-topic").create(); assertTrue(proxyService.getLookupRequestSemaphore().tryAcquire()); try { @Cleanup Producer producer2 = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/producer-topic").create(); + .topic("persistent://public/default/producer-topic").create(); Assert.fail("Should have failed since can't acquire LookupRequestSemaphore"); } catch (Exception ex) { // Ignore @@ -120,7 +121,7 @@ public void testLookup() throws Exception { try { @Cleanup Producer producer3 = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/producer-topic").create(); + .topic("persistent://public/default/producer-topic").create(); } catch (Exception ex) { Assert.fail("Should not have failed since can acquire LookupRequestSemaphore"); } diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyMutualTlsTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyMutualTlsTest.java index d3b68bbd0c304..229da188daa5f 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyMutualTlsTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyMutualTlsTest.java @@ -56,6 +56,7 @@ public class ProxyMutualTlsTest extends MockedPulsarServiceBaseTest { @BeforeClass protected void setup() throws Exception { internalSetup(); + setupDefaultTenantAndNamespace(); proxyConfig.setServicePort(Optional.of(0)); proxyConfig.setBrokerProxyAllowedTargetPorts("*"); @@ -109,7 +110,7 @@ public void testProducerByTlsTransport() throws Exception { .build(); @Cleanup Producer producer = - client.newProducer(Schema.BYTES).topic("persistent://sample/test/local/" + UUID.randomUUID()).create(); + client.newProducer(Schema.BYTES).topic("persistent://public/default/" + UUID.randomUUID()).create(); for (int i = 0; i < 10; i++) { producer.send("test".getBytes()); @@ -128,7 +129,7 @@ public void testProducerByAuthenticationTls() throws Exception { .build(); @Cleanup Producer producer = - client.newProducer(Schema.BYTES).topic("persistent://sample/test/local/" + UUID.randomUUID()).create(); + client.newProducer(Schema.BYTES).topic("persistent://public/default/" + UUID.randomUUID()).create(); for (int i = 0; i < 10; i++) { producer.send("test".getBytes()); @@ -147,6 +148,6 @@ public void testProducerNegative() throws Exception { assertThrows(PulsarClientException.class, () -> client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/" + UUID.randomUUID()).create()); + .topic("persistent://public/default/" + UUID.randomUUID()).create()); } } diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyParserTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyParserTest.java index ee0f8010b7d79..4269bcf66c502 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyParserTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyParserTest.java @@ -48,7 +48,6 @@ import org.apache.pulsar.common.api.proto.CommandActiveConsumerChange; import org.apache.pulsar.common.api.proto.ProtocolVersion; import org.apache.pulsar.common.configuration.PulsarConfigurationLoader; -import org.apache.pulsar.common.policies.data.TenantInfoImpl; import org.apache.pulsar.common.util.netty.EventLoopUtil; import org.apache.pulsar.metadata.impl.ZKMetadataStore; import org.mockito.Mockito; @@ -70,6 +69,7 @@ public class ProxyParserTest extends MockedPulsarServiceBaseTest { @BeforeClass protected void setup() throws Exception { internalSetup(); + setupDefaultTenantAndNamespace(); proxyConfig.setServicePort(Optional.of(0)); proxyConfig.setBrokerProxyAllowedTargetPorts("*"); @@ -110,7 +110,7 @@ public void testProducer() throws Exception { PulsarClient client = PulsarClient.builder().serviceUrl(proxyService.getServiceUrl()) .build(); Producer producer = - client.newProducer(Schema.BYTES).topic("persistent://sample/test/local/producer-topic") + client.newProducer(Schema.BYTES).topic("persistent://public/default/producer-topic") .create(); for (int i = 0; i < 10; i++) { @@ -124,14 +124,14 @@ public void testProducerConsumer() throws Exception { PulsarClient client = PulsarClient.builder().serviceUrl(proxyService.getServiceUrl()) .build(); Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/producer-consumer-topic") + .topic("persistent://public/default/producer-consumer-topic") .enableBatching(false) .messageRoutingMode(MessageRoutingMode.SinglePartition) .create(); // Create a consumer directly attached to broker Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://sample/test/local/producer-consumer-topic").subscriptionName("my-sub").subscribe(); + .topic("persistent://public/default/producer-consumer-topic").subscriptionName("my-sub").subscribe(); for (int i = 0; i < 10; i++) { producer.send("test".getBytes()); @@ -151,20 +151,18 @@ public void testProducerConsumer() throws Exception { @Test public void testPartitions() throws Exception { - TenantInfoImpl tenantInfo = createDefaultTenantInfo(); - admin.tenants().createTenant("sample", tenantInfo); @Cleanup PulsarClient client = PulsarClient.builder().serviceUrl(proxyService.getServiceUrl()) .build(); - admin.topics().createPartitionedTopic("persistent://sample/test/local/partitioned-topic", 2); + admin.topics().createPartitionedTopic("persistent://public/default/partitioned-topic", 2); Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/partitioned-topic") + .topic("persistent://public/default/partitioned-topic") .enableBatching(false) .messageRoutingMode(MessageRoutingMode.RoundRobinPartition).create(); // Create a consumer directly attached to broker - Consumer consumer = pulsarClient.newConsumer().topic("persistent://sample/test/local/partitioned-topic") + Consumer consumer = pulsarClient.newConsumer().topic("persistent://public/default/partitioned-topic") .subscriptionName("my-sub").subscribe(); for (int i = 0; i < 10; i++) { @@ -185,19 +183,19 @@ public void testRegexSubscription() throws Exception { // create two topics by subscribing to a topic and closing it try (Consumer ignored = client.newConsumer() - .topic("persistent://sample/test/local/topic1") + .topic("persistent://public/default/topic1") .subscriptionName("ignored") .subscribe()) { } try (Consumer ignored = client.newConsumer() - .topic("persistent://sample/test/local/topic2") + .topic("persistent://public/default/topic2") .subscriptionName("ignored") .subscribe()) { } String subName = "regex-sub-proxy-parser-test-" + System.currentTimeMillis(); // make sure regex subscription - String regexSubscriptionPattern = "persistent://sample/test/local/topic.*"; + String regexSubscriptionPattern = "persistent://public/default/topic.*"; log.info("Regex subscribe to topics {}", regexSubscriptionPattern); try (Consumer consumer = client.newConsumer() .topicsPattern(regexSubscriptionPattern) @@ -208,7 +206,7 @@ public void testRegexSubscription() throws Exception { final int numMessages = 20; try (Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/topic1") + .topic("persistent://public/default/topic1") .create()) { for (int i = 0; i < numMessages; i++) { producer.send(("message-" + i).getBytes(UTF_8)); @@ -224,7 +222,7 @@ public void testRegexSubscription() throws Exception { @Test public void testProtocolVersionAdvertisement() throws Exception { - final String topic = "persistent://sample/test/local/protocol-version-advertisement"; + final String topic = "persistent://public/default/protocol-version-advertisement"; final String sub = "my-sub"; ClientConfigurationData conf = new ClientConfigurationData(); diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyServiceStarterDisableZeroCopyTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyServiceStarterDisableZeroCopyTest.java index b645c47242546..240115461ad5d 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyServiceStarterDisableZeroCopyTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyServiceStarterDisableZeroCopyTest.java @@ -27,6 +27,7 @@ public class ProxyServiceStarterDisableZeroCopyTest extends ProxyServiceStarterT @BeforeClass protected void setup() throws Exception { internalSetup(); + setupDefaultTenantAndNamespace(); serviceStarter = new ProxyServiceStarter(getArgs(), null, true); serviceStarter.getConfig().setBrokerServiceURL(pulsar.getBrokerServiceUrl()); serviceStarter.getConfig().setBrokerWebServiceURL(pulsar.getWebServiceAddress()); diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyServiceStarterTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyServiceStarterTest.java index a6ca8ee5bffc9..9b6d7968703cc 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyServiceStarterTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyServiceStarterTest.java @@ -88,6 +88,7 @@ public static String[] getArgs() { @BeforeClass protected void setup() throws Exception { internalSetup(); + setupDefaultTenantAndNamespace(); serviceStarter = new ProxyServiceStarter(getArgs(), null, true); serviceStarter.getConfig().setBrokerServiceURL(pulsar.getBrokerServiceUrl()); serviceStarter.getConfig().setBrokerWebServiceURL(pulsar.getWebServiceAddress()); @@ -120,7 +121,7 @@ public void testProducer() throws Exception { @Cleanup Producer producer = client.newProducer() - .topic("persistent://sample/test/local/websocket-topic") + .topic("persistent://public/default/websocket-topic") .create(); for (int i = 0; i < 10; i++) { @@ -141,7 +142,7 @@ public void testProduceAndConsumeMessageWithWebsocket() throws Exception { WebSocketClient producerWebSocketClient = new WebSocketClient(producerClient); producerWebSocketClient.start(); MyWebSocket producerSocket = new MyWebSocket(); - String produceUri = computeWsBasePath() + "/producer/persistent/sample/test/local/websocket-topic"; + String produceUri = computeWsBasePath() + "/v2/producer/persistent/public/default/websocket-topic"; CompletableFuture producerSession = producerWebSocketClient.connect(producerSocket, URI.create(produceUri)); @@ -155,7 +156,7 @@ public void testProduceAndConsumeMessageWithWebsocket() throws Exception { WebSocketClient consumerWebSocketClient = new WebSocketClient(consumerClient); consumerWebSocketClient.start(); MyWebSocket consumerSocket = new MyWebSocket(); - String consumeUri = computeWsBasePath() + "/consumer/persistent/sample/test/local/websocket-topic/my-sub"; + String consumeUri = computeWsBasePath() + "/v2/consumer/persistent/public/default/websocket-topic/my-sub"; CompletableFuture consumerSession = consumerWebSocketClient.connect(consumerSocket, URI.create(consumeUri)); consumerSession.get().sendPing(ByteBuffer.wrap("ping".getBytes()), Callback.NOOP); diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyServiceTlsStarterTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyServiceTlsStarterTest.java index d09301514fe55..ee52d2ac52d02 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyServiceTlsStarterTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyServiceTlsStarterTest.java @@ -58,6 +58,7 @@ public class ProxyServiceTlsStarterTest extends MockedPulsarServiceBaseTest { @BeforeClass protected void setup() throws Exception { internalSetup(); + setupDefaultTenantAndNamespace(); serviceStarter = new ProxyServiceStarter(getArgs(), null, true); serviceStarter.getConfig().setBrokerServiceURL(pulsar.getBrokerServiceUrl()); serviceStarter.getConfig().setBrokerServiceURLTLS(pulsar.getBrokerServiceUrlTls()); @@ -104,7 +105,7 @@ public void testProducer() throws Exception { @Cleanup Producer producer = client.newProducer() - .topic("persistent://sample/test/local/websocket-topic") + .topic("persistent://public/default/websocket-topic") .create(); for (int i = 0; i < 10; i++) { @@ -120,7 +121,7 @@ public void testProduceAndConsumeMessageWithWebsocket() throws Exception { WebSocketClient producerWebSocketClient = new WebSocketClient(producerClient); producerWebSocketClient.start(); MyWebSocket producerSocket = new MyWebSocket(); - String produceUri = "ws://localhost:" + webPort + "/ws/producer/persistent/sample/test/local/websocket-topic"; + String produceUri = "ws://localhost:" + webPort + "/ws/v2/producer/persistent/public/default/websocket-topic"; CompletableFuture producerSession = producerWebSocketClient.connect(producerSocket, URI.create(produceUri)); @@ -135,7 +136,7 @@ public void testProduceAndConsumeMessageWithWebsocket() throws Exception { consumerWebSocketClient.start(); MyWebSocket consumerSocket = new MyWebSocket(); String consumeUri = "ws://localhost:" + webPort - + "/ws/consumer/persistent/sample/test/local/websocket-topic/my-sub"; + + "/ws/v2/consumer/persistent/public/default/websocket-topic/my-sub"; CompletableFuture consumerSession = consumerWebSocketClient.connect(consumerSocket, URI.create(consumeUri)); consumerSession.get().sendPing(ByteBuffer.wrap("ping".getBytes()), Callback.NOOP); diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyStatsTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyStatsTest.java index b6a0758b528e6..5f9ea70a5e52e 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyStatsTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyStatsTest.java @@ -70,6 +70,7 @@ public class ProxyStatsTest extends MockedPulsarServiceBaseTest { @BeforeClass protected void setup() throws Exception { internalSetup(); + setupDefaultTenantAndNamespace(); proxyConfig.setServicePort(Optional.of(0)); proxyConfig.setBrokerProxyAllowedTargetPorts("*"); @@ -132,7 +133,7 @@ protected void cleanup() throws Exception { */ @Test public void testConnectionsStats() throws Exception { - final String topicName1 = "persistent://sample/test/local/connections-stats"; + final String topicName1 = "persistent://public/default/connections-stats"; @Cleanup PulsarClient client = PulsarClient.builder().serviceUrl(proxyService.getServiceUrl()).build(); Producer producer = client.newProducer(Schema.BYTES).topic(topicName1).enableBatching(false) @@ -174,8 +175,8 @@ public void testConnectionsStats() throws Exception { @Test public void testTopicStats() throws Exception { proxyService.setProxyLogLevel(2); - final String topicName = "persistent://sample/test/local/topic-stats"; - final String topicName2 = "persistent://sample/test/local/topic-stats-2"; + final String topicName = "persistent://public/default/topic-stats"; + final String topicName2 = "persistent://public/default/topic-stats-2"; @Cleanup PulsarClient client = PulsarClient.builder().serviceUrl(proxyService.getServiceUrl()).build(); @@ -226,8 +227,8 @@ public void testTopicStats() throws Exception { @Test public void testMemoryLeakFixed() throws Exception { proxyService.setProxyLogLevel(2); - final String topicName = "persistent://sample/test/local/topic-stats"; - final String topicName2 = "persistent://sample/test/local/topic-stats-2"; + final String topicName = "persistent://public/default/topic-stats"; + final String topicName2 = "persistent://public/default/topic-stats-2"; @Cleanup PulsarClient client = PulsarClient.builder().serviceUrl(proxyService.getServiceUrl()).build(); diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyStuckConnectionTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyStuckConnectionTest.java index 30c6e45654ba0..325dcbeb7124d 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyStuckConnectionTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyStuckConnectionTest.java @@ -69,6 +69,7 @@ public class ProxyStuckConnectionTest extends MockedPulsarServiceBaseTest { protected void setup() throws Exception { useBrokerSocatProxy = true; internalSetup(); + setupDefaultTenantAndNamespace(); int brokerPort = pulsar.getBrokerService().getListenPort().get(); Testcontainers.exposeHostPorts(brokerPort); @@ -143,7 +144,7 @@ public void testKeySharedStickyWithStuckConnection() throws Exception { // such as hash range conflicts .keepAliveInterval(2, TimeUnit.SECONDS) .build(); - String topicName = BrokerTestUtil.newUniqueName("persistent://sample/test/local/test-topic"); + String topicName = BrokerTestUtil.newUniqueName("persistent://public/default/test-topic"); @Cleanup Consumer consumer = client.newConsumer() diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyTest.java index 64ea589e023a6..4a00314bb0e8c 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyTest.java @@ -30,7 +30,6 @@ import io.netty.channel.EventLoopGroup; import io.netty.util.concurrent.DefaultThreadFactory; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -74,10 +73,7 @@ import org.apache.pulsar.common.configuration.PulsarConfigurationLoader; import org.apache.pulsar.common.naming.TopicName; import org.apache.pulsar.common.partition.PartitionedTopicMetadata; -import org.apache.pulsar.common.policies.data.ClusterData; import org.apache.pulsar.common.policies.data.RetentionPolicies; -import org.apache.pulsar.common.policies.data.TenantInfo; -import org.apache.pulsar.common.policies.data.TenantInfoImpl; import org.apache.pulsar.common.policies.data.TopicType; import org.apache.pulsar.common.protocol.Commands; import org.apache.pulsar.common.schema.SchemaInfo; @@ -127,13 +123,7 @@ protected void setup() throws Exception { proxyService.start(); - // create default resources. - admin.clusters().createCluster(conf.getClusterName(), - ClusterData.builder().serviceUrl(pulsar.getWebServiceAddress()).build()); - TenantInfo tenantInfo = new TenantInfoImpl(Collections.emptySet(), - Collections.singleton(conf.getClusterName())); - admin.tenants().createTenant("public", tenantInfo); - admin.namespaces().createNamespace("public/default"); + setupDefaultTenantAndNamespace(); } protected void initializeProxyConfig() throws Exception { @@ -174,7 +164,7 @@ public void testProducer() throws Exception { @Cleanup Producer producer = client.newProducer() - .topic("persistent://sample/test/local/producer-topic") + .topic("persistent://public/default/producer-topic") .create(); for (int i = 0; i < 10; i++) { @@ -190,7 +180,7 @@ public void testProxyConnectionClientConfig() throws Exception { @Cleanup Producer producer = client.newProducer() - .topic("persistent://sample/test/local/producer-topic2") + .topic("persistent://public/default/producer-topic2") .create(); MutableBoolean found = new MutableBoolean(false); @@ -218,7 +208,7 @@ public void testProducerConsumer() throws Exception { @Cleanup Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/producer-consumer-topic") + .topic("persistent://public/default/producer-consumer-topic") .enableBatching(false) .messageRoutingMode(MessageRoutingMode.SinglePartition) .create(); @@ -226,7 +216,7 @@ public void testProducerConsumer() throws Exception { // Create a consumer directly attached to broker @Cleanup Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://sample/test/local/producer-consumer-topic").subscriptionName("my-sub").subscribe(); + .topic("persistent://public/default/producer-consumer-topic").subscriptionName("my-sub").subscribe(); for (int i = 0; i < 10; i++) { producer.send("test".getBytes()); @@ -244,22 +234,20 @@ public void testProducerConsumer() throws Exception { @Test public void testPartitions() throws Exception { - TenantInfoImpl tenantInfo = createDefaultTenantInfo(); - admin.tenants().createTenant("sample", tenantInfo); @Cleanup PulsarClient client = PulsarClient.builder().serviceUrl(proxyService.getServiceUrl()) .build(); - admin.topics().createPartitionedTopic("persistent://sample/test/local/partitioned-topic", 2); + admin.topics().createPartitionedTopic("persistent://public/default/partitioned-topic", 2); @Cleanup Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/partitioned-topic") + .topic("persistent://public/default/partitioned-topic") .enableBatching(false) .messageRoutingMode(MessageRoutingMode.RoundRobinPartition).create(); // Create a consumer directly attached to broker @Cleanup - Consumer consumer = pulsarClient.newConsumer().topic("persistent://sample/test/local/partitioned-topic") + Consumer consumer = pulsarClient.newConsumer().topic("persistent://public/default/partitioned-topic") .subscriptionName("my-sub").subscribe(); for (int i = 0; i < 10; i++) { @@ -287,7 +275,7 @@ public void testAutoCreateTopic() throws Exception{ @Cleanup PulsarClient client = PulsarClient.builder().serviceUrl(proxyService.getServiceUrl()) .build(); - String topic = "persistent://sample/test/local/partitioned-proxy-topic"; + String topic = "persistent://public/default/partitioned-proxy-topic"; CompletableFuture> partitionNamesFuture = client.getPartitionsForTopic(topic); List partitionNames = partitionNamesFuture.get(30000, TimeUnit.MILLISECONDS); assertEquals(partitionNames.size(), defaultPartition); @@ -305,12 +293,12 @@ public void testRegexSubscription() throws Exception { // create two topics by subscribing to a topic and closing it try (Consumer ignored = client.newConsumer() - .topic("persistent://sample/test/local/regex-sub-topic1") + .topic("persistent://public/default/regex-sub-topic1") .subscriptionName("proxy-ignored") .subscribe()) { } try (Consumer ignored = client.newConsumer() - .topic("persistent://sample/test/local/regex-sub-topic2") + .topic("persistent://public/default/regex-sub-topic2") .subscriptionName("proxy-ignored") .subscribe()) { } @@ -318,7 +306,7 @@ public void testRegexSubscription() throws Exception { String subName = "regex-sub-proxy-test-" + System.currentTimeMillis(); // make sure regex subscription - String regexSubscriptionPattern = "persistent://sample/test/local/regex-sub-topic.*"; + String regexSubscriptionPattern = "persistent://public/default/regex-sub-topic.*"; log.info("Regex subscribe to topics {}", regexSubscriptionPattern); try (Consumer consumer = client.newConsumer() .topicsPattern(regexSubscriptionPattern) @@ -330,7 +318,7 @@ public void testRegexSubscription() throws Exception { final int numMessages = 20; try (Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/regex-sub-topic1") + .topic("persistent://public/default/regex-sub-topic1") .create()) { for (int i = 0; i < numMessages; i++) { producer.send(("message-" + i).getBytes(UTF_8)); @@ -415,7 +403,7 @@ public void testGetSchema() throws Exception { .build(); Schema schema = Schema.AVRO(Foo.class); try { - try (Producer ignored = client.newProducer(schema).topic("persistent://sample/test/local/get-schema") + try (Producer ignored = client.newProducer(schema).topic("persistent://public/default/get-schema") .create()) { } } catch (Exception ex) { @@ -427,14 +415,14 @@ public void testGetSchema() throws Exception { schemaVersion[i] = b; } SchemaInfo schemaInfo = ((PulsarClientImpl) client).getLookup() - .getSchema(TopicName.get("persistent://sample/test/local/get-schema"), schemaVersion) + .getSchema(TopicName.get("persistent://public/default/get-schema"), schemaVersion) .get().orElse(null); assertEquals(new String(schemaInfo.getSchema()), new String(schema.getSchemaInfo().getSchema())); } @Test public void testProtocolVersionAdvertisement() throws Exception { - final String topic = "persistent://sample/test/local/protocol-version-advertisement"; + final String topic = "persistent://public/default/protocol-version-advertisement"; final String sub = "my-sub"; ClientConfigurationData conf = new ClientConfigurationData(); @@ -497,7 +485,7 @@ public void testGetClientVersion() throws Exception { PulsarClient client = PulsarClient.builder().serviceUrl(proxyService.getServiceUrl()) .build(); - String topic = BrokerTestUtil.newUniqueName("persistent://sample/test/local/testGetClientVersion"); + String topic = BrokerTestUtil.newUniqueName("persistent://public/default/testGetClientVersion"); String subName = "test-sub"; @Cleanup diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyTlsTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyTlsTest.java index f299dbe39ea10..f5bb0aa9223f9 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyTlsTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyTlsTest.java @@ -34,7 +34,6 @@ import org.apache.pulsar.client.api.PulsarClient; import org.apache.pulsar.client.api.Schema; import org.apache.pulsar.common.configuration.PulsarConfigurationLoader; -import org.apache.pulsar.common.policies.data.TenantInfoImpl; import org.apache.pulsar.metadata.impl.ZKMetadataStore; import org.mockito.Mockito; import org.testng.annotations.AfterClass; @@ -51,6 +50,7 @@ public class ProxyTlsTest extends MockedPulsarServiceBaseTest { @BeforeClass protected void setup() throws Exception { internalSetup(); + setupDefaultTenantAndNamespace(); proxyConfig.setServicePort(Optional.of(0)); proxyConfig.setBrokerProxyAllowedTargetPorts("*"); @@ -97,7 +97,7 @@ public void testProducer() throws Exception { .allowTlsInsecureConnection(false) .tlsTrustCertsFilePath(CA_CERT_FILE_PATH).build(); Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/topic").create(); + .topic("persistent://public/default/topic").create(); for (int i = 0; i < 10; i++) { producer.send("test".getBytes()); @@ -110,16 +110,14 @@ public void testPartitions() throws Exception { PulsarClient client = PulsarClient.builder() .serviceUrl(proxyService.getServiceUrlTls()) .allowTlsInsecureConnection(false).tlsTrustCertsFilePath(CA_CERT_FILE_PATH).build(); - TenantInfoImpl tenantInfo = createDefaultTenantInfo(); - admin.tenants().createTenant("sample", tenantInfo); - admin.topics().createPartitionedTopic("persistent://sample/test/local/partitioned-topic", 2); + admin.topics().createPartitionedTopic("persistent://public/default/partitioned-topic", 2); Producer producer = client.newProducer(Schema.BYTES) - .topic("persistent://sample/test/local/partitioned-topic") + .topic("persistent://public/default/partitioned-topic") .messageRoutingMode(MessageRoutingMode.RoundRobinPartition).create(); // Create a consumer directly attached to broker - Consumer consumer = pulsarClient.newConsumer().topic("persistent://sample/test/local/partitioned-topic") + Consumer consumer = pulsarClient.newConsumer().topic("persistent://public/default/partitioned-topic") .subscriptionName("my-sub").subscribe(); for (int i = 0; i < 10; i++) { diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyWithAuthorizationNegTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyWithAuthorizationNegTest.java index 04813e1ad15b6..962833bc2984b 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyWithAuthorizationNegTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyWithAuthorizationNegTest.java @@ -190,7 +190,7 @@ public void testProxyAuthorization() throws Exception { PulsarClient proxyClient = createPulsarClient("pulsar+ssl://localhost:" + proxyService.getListenPortTls().get()); - String namespaceName = "my-property/proxy-authorization-neg/my-ns"; + String namespaceName = "my-property/my-ns"; admin.clusters().createCluster("proxy-authorization-neg", ClusterData.builder().serviceUrl(brokerUrl.toString()).build()); @@ -208,7 +208,7 @@ public void testProxyAuthorization() throws Exception { Consumer consumer; try { consumer = proxyClient.newConsumer() - .topic("persistent://my-property/proxy-authorization-neg/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscribe(); } catch (Exception ex) { // expected @@ -216,19 +216,19 @@ public void testProxyAuthorization() throws Exception { Sets.newHashSet(AuthAction.consume)); log.info("-- Admin permissions {} ---", admin.namespaces().getPermissions(namespaceName)); consumer = proxyClient.newConsumer() - .topic("persistent://my-property/proxy-authorization-neg/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscribe(); } Producer producer; try { producer = proxyClient.newProducer(Schema.BYTES) - .topic("persistent://my-property/proxy-authorization-neg/my-ns/my-topic1").create(); + .topic("persistent://my-property/my-ns/my-topic1").create(); } catch (Exception ex) { // expected admin.namespaces().grantPermissionOnNamespace(namespaceName, "Proxy", Sets.newHashSet(AuthAction.produce, AuthAction.consume)); producer = proxyClient.newProducer(Schema.BYTES) - .topic("persistent://my-property/proxy-authorization-neg/my-ns/my-topic1").create(); + .topic("persistent://my-property/my-ns/my-topic1").create(); } final int msgs = 10; for (int i = 0; i < msgs; i++) { diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyWithJwtAuthorizationTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyWithJwtAuthorizationTest.java index 9015c651c2cf0..38cb254dc4dfd 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyWithJwtAuthorizationTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyWithJwtAuthorizationTest.java @@ -177,7 +177,7 @@ public void testProxyAuthorization() throws Exception { @Cleanup PulsarClient proxyClient = createPulsarClient(proxyService.getServiceUrl(), PulsarClient.builder()); - String namespaceName = "my-property/proxy-authorization/my-ns"; + String namespaceName = "my-property/my-ns"; admin.clusters().createCluster("proxy-authorization", ClusterData.builder() .serviceUrl(brokerUrl.toString()).build()); @@ -189,7 +189,7 @@ public void testProxyAuthorization() throws Exception { Consumer consumer; try { consumer = proxyClient.newConsumer() - .topic("persistent://my-property/proxy-authorization/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscribe(); Assert.fail("should have failed with authorization error"); } catch (Exception ex) { @@ -198,14 +198,14 @@ public void testProxyAuthorization() throws Exception { Sets.newHashSet(AuthAction.consume)); log.info("-- Admin permissions {} ---", admin.namespaces().getPermissions(namespaceName)); consumer = proxyClient.newConsumer() - .topic("persistent://my-property/proxy-authorization/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscribe(); } Producer producer; try { producer = proxyClient.newProducer(Schema.BYTES) - .topic("persistent://my-property/proxy-authorization/my-ns/my-topic1").create(); + .topic("persistent://my-property/my-ns/my-topic1").create(); Assert.fail("should have failed with authorization error"); } catch (Exception ex) { // excepted @@ -213,7 +213,7 @@ public void testProxyAuthorization() throws Exception { Sets.newHashSet(AuthAction.produce, AuthAction.consume)); log.info("-- Admin permissions {} ---", admin.namespaces().getPermissions(namespaceName)); producer = proxyClient.newProducer(Schema.BYTES) - .topic("persistent://my-property/proxy-authorization/my-ns/my-topic1").create(); + .topic("persistent://my-property/my-ns/my-topic1").create(); } final int msgs = 10; for (int i = 0; i < msgs; i++) { @@ -375,7 +375,7 @@ public void testProxyAuthorizationWithPrefixSubscriptionAuthMode() throws Except @Cleanup PulsarClient proxyClient = createPulsarClient(proxyService.getServiceUrl(), PulsarClient.builder()); - String namespaceName = "my-property/proxy-authorization/my-ns"; + String namespaceName = "my-property/my-ns"; admin.clusters().createCluster("proxy-authorization", ClusterData.builder() .serviceUrl(brokerUrl.toString()).build()); @@ -390,18 +390,18 @@ public void testProxyAuthorizationWithPrefixSubscriptionAuthMode() throws Except Consumer consumer; try { consumer = proxyClient.newConsumer() - .topic("persistent://my-property/proxy-authorization/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscribe(); Assert.fail("should have failed with authorization error"); } catch (Exception ex) { // excepted consumer = proxyClient.newConsumer() - .topic("persistent://my-property/proxy-authorization/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName(CLIENT_ROLE + "-sub1").subscribe(); } Producer producer = proxyClient.newProducer(Schema.BYTES) - .topic("persistent://my-property/proxy-authorization/my-ns/my-topic1").create(); + .topic("persistent://my-property/my-ns/my-topic1").create(); final int msgs = 10; for (int i = 0; i < msgs; i++) { String message = "my-message-" + i; diff --git a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyWithoutServiceDiscoveryTest.java b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyWithoutServiceDiscoveryTest.java index e4d7eaa74d273..8f187cbe47b7d 100644 --- a/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyWithoutServiceDiscoveryTest.java +++ b/pulsar-proxy/src/test/java/org/apache/pulsar/proxy/server/ProxyWithoutServiceDiscoveryTest.java @@ -173,13 +173,13 @@ public void testDiscoveryService() throws Exception { admin.tenants().createTenant("my-property", new TenantInfoImpl(Sets.newHashSet("appid1", "appid2"), Sets.newHashSet("without-service-discovery"))); - admin.namespaces().createNamespace("my-property/without-service-discovery/my-ns"); + admin.namespaces().createNamespace("my-property/my-ns"); Consumer consumer = proxyClient.newConsumer() - .topic("persistent://my-property/without-service-discovery/my-ns/my-topic1") + .topic("persistent://my-property/my-ns/my-topic1") .subscriptionName("my-subscriber-name").subscribe(); Producer producer = proxyClient.newProducer(Schema.BYTES) - .topic("persistent://my-property/without-service-discovery/my-ns/my-topic1").create(); + .topic("persistent://my-property/my-ns/my-topic1").create(); final int msgs = 10; for (int i = 0; i < msgs; i++) { String message = "my-message-" + i; diff --git a/pulsar-testclient/src/main/java/org/apache/pulsar/proxy/socket/client/PerformanceClient.java b/pulsar-testclient/src/main/java/org/apache/pulsar/proxy/socket/client/PerformanceClient.java index 19b7792f8226c..53d588e3ba7c6 100644 --- a/pulsar-testclient/src/main/java/org/apache/pulsar/proxy/socket/client/PerformanceClient.java +++ b/pulsar-testclient/src/main/java/org/apache/pulsar/proxy/socket/client/PerformanceClient.java @@ -238,8 +238,7 @@ public void runPerformanceTest() throws InterruptedException, IOException { HashMap producersMap = new HashMap<>(); String topicName = this.topics.get(0); String restPath = TopicName.get(topicName).getRestPath(); - String produceBaseEndPoint = TopicName.get(topicName).isV2() - ? this.proxyURL + "ws/v2/producer/" + restPath : this.proxyURL + "ws/producer/" + restPath; + String produceBaseEndPoint = this.proxyURL + "ws/v2/producer/" + restPath; HttpClient httpClient = new HttpClient(); httpClient.setSslContextFactory(new SslContextFactory.Client(true)); for (int i = 0; i < this.numTopics; i++) { diff --git a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/AbstractWebSocketHandler.java b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/AbstractWebSocketHandler.java index ecb78d17c7033..7fc3c169dbd3d 100644 --- a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/AbstractWebSocketHandler.java +++ b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/AbstractWebSocketHandler.java @@ -35,7 +35,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.Getter; -import org.apache.commons.lang3.StringUtils; import org.apache.pulsar.broker.authentication.AuthenticationDataHttps; import org.apache.pulsar.broker.authentication.AuthenticationDataSource; import org.apache.pulsar.broker.authentication.AuthenticationState; @@ -255,14 +254,7 @@ protected void extractTopicName(HttpServletRequest request) { String uri = request.getRequestURI(); List parts = Splitter.on("/").splitToList(uri); - // V1 Format must be like : - // /ws/producer/persistent/my-property/my-cluster/my-ns/my-topic - // or - // /ws/consumer/persistent/my-property/my-cluster/my-ns/my-topic/my-subscription - // or - // /ws/reader/persistent/my-property/my-cluster/my-ns/my-topic - - // V2 Format must be like : + // Format must be like : // /ws/v2/producer/persistent/my-property/my-ns/my-topic // or // /ws/v2/consumer/persistent/my-property/my-ns/my-topic/my-subscription @@ -271,28 +263,15 @@ protected void extractTopicName(HttpServletRequest request) { checkArgument(parts.size() >= 8, "Invalid topic name format"); checkArgument(parts.get(1).equals("ws")); + checkArgument(parts.get(2).equals("v2")); - final boolean isV2Format = parts.get(2).equals("v2"); - final int domainIndex = isV2Format ? 4 : 3; - checkArgument(parts.get(domainIndex).equals("persistent") - || parts.get(domainIndex).equals("non-persistent")); + checkArgument(parts.get(4).equals("persistent") + || parts.get(4).equals("non-persistent")); - final String domain = parts.get(domainIndex); - final NamespaceName namespace = isV2Format ? NamespaceName.get(parts.get(5), parts.get(6)) : - NamespaceName.get(parts.get(4), parts.get(5), parts.get(6)); + final String domain = parts.get(4); + final NamespaceName namespace = NamespaceName.get(parts.get(5), parts.get(6)); - // The topic name which contains slashes is also split, so it needs to be jointed - int startPosition = 7; - boolean isConsumer = "consumer".equals(parts.get(2)) || "consumer".equals(parts.get(3)); - int endPosition = isConsumer ? parts.size() - 1 : parts.size(); - StringBuilder topicName = new StringBuilder(parts.get(startPosition)); - while (++startPosition < endPosition) { - if (StringUtils.isEmpty(parts.get(startPosition))) { - continue; - } - topicName.append("/").append(parts.get(startPosition)); - } - final String name = Codec.decode(topicName.toString()); + final String name = Codec.decode(parts.get(7)); topic = TopicName.get(domain, namespace, name); } diff --git a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketConsumerServlet.java b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketConsumerServlet.java index f97a11fd164c1..4e6079b15a958 100644 --- a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketConsumerServlet.java +++ b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketConsumerServlet.java @@ -25,8 +25,7 @@ public class WebSocketConsumerServlet extends JettyWebSocketServlet { private static final long serialVersionUID = 1L; - public static final String SERVLET_PATH = "/ws/consumer"; - public static final String SERVLET_PATH_V2 = "/ws/v2/consumer"; + public static final String SERVLET_PATH = "/ws/v2/consumer"; private final transient WebSocketService service; diff --git a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketProducerServlet.java b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketProducerServlet.java index 2dd75071e83b7..8f87cf822864b 100644 --- a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketProducerServlet.java +++ b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketProducerServlet.java @@ -25,8 +25,7 @@ public class WebSocketProducerServlet extends JettyWebSocketServlet { private static final long serialVersionUID = 1L; - public static final String SERVLET_PATH = "/ws/producer"; - public static final String SERVLET_PATH_V2 = "/ws/v2/producer"; + public static final String SERVLET_PATH = "/ws/v2/producer"; private final transient WebSocketService service; diff --git a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketReaderServlet.java b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketReaderServlet.java index f04effc0c5259..b0a399497bf5f 100644 --- a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketReaderServlet.java +++ b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/WebSocketReaderServlet.java @@ -25,8 +25,7 @@ public class WebSocketReaderServlet extends JettyWebSocketServlet { private static final transient long serialVersionUID = 1L; - public static final String SERVLET_PATH = "/ws/reader"; - public static final String SERVLET_PATH_V2 = "/ws/v2/reader"; + public static final String SERVLET_PATH = "/ws/v2/reader"; private final transient WebSocketService service; diff --git a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/admin/WebSocketWebResource.java b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/admin/WebSocketWebResource.java index 6515a01c477b9..41fef328c2fd5 100644 --- a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/admin/WebSocketWebResource.java +++ b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/admin/WebSocketWebResource.java @@ -37,7 +37,6 @@ public class WebSocketWebResource { public static final String ATTRIBUTE_PROXY_SERVICE_NAME = "webProxyService"; - public static final String ADMIN_PATH_V1 = "/admin"; public static final String ADMIN_PATH_V2 = "/admin/v2"; @Context diff --git a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/admin/v1/WebSocketProxyStatsV1.java b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/admin/v1/WebSocketProxyStatsV1.java deleted file mode 100644 index 66dc1d4942c29..0000000000000 --- a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/admin/v1/WebSocketProxyStatsV1.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.websocket.admin.v1; - -import static org.apache.pulsar.common.util.Codec.decode; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import java.util.Collection; -import java.util.Map; -import javax.ws.rs.Encoded; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import org.apache.pulsar.common.naming.TopicName; -import org.apache.pulsar.common.stats.Metrics; -import org.apache.pulsar.websocket.admin.WebSocketProxyStatsBase; -import org.apache.pulsar.websocket.stats.ProxyTopicStat; - -@Path("/proxy-stats") -@Api(value = "/proxy", description = "Stats for web-socket proxy", tags = "proxy-stats") -@Produces(MediaType.APPLICATION_JSON) -public class WebSocketProxyStatsV1 extends WebSocketProxyStatsBase { - - @GET - @Path("/metrics") - @ApiOperation(value = "Gets the metrics for Monitoring", - notes = "Requested should be executed by Monitoring agent on each proxy to fetch the metrics", - response = Metrics.class, responseContainer = "List") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission") }) - public Collection internalGetMetrics() throws Exception { - return super.internalGetMetrics(); - } - - @GET - @Path("/{tenant}/{cluster}/{namespace}/{topic}/stats") - @ApiOperation(value = "Get the stats for the topic.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), - @ApiResponse(code = 404, message = "Topic does not exist") }) - public ProxyTopicStat getStats(@PathParam("tenant") String tenant, @PathParam("cluster") String cluster, - @PathParam("namespace") String namespace, @PathParam("topic") @Encoded String encodedTopic) { - return super.internalGetStats( - TopicName.get("persistent", tenant, cluster, namespace, decode(encodedTopic))); - } - - @GET - @Path("/stats") - @ApiOperation(value = "Get the stats for the topic.") - @ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission") }) - public Map internalGetProxyStats() { - return super.internalGetProxyStats(); - } -} diff --git a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/admin/v1/package-info.java b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/admin/v1/package-info.java deleted file mode 100644 index 25b6612ce38e4..0000000000000 --- a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/admin/v1/package-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.pulsar.websocket.admin.v1; diff --git a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/service/WebSocketServiceStarter.java b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/service/WebSocketServiceStarter.java index 0a445aebe3a00..6136ff4490517 100644 --- a/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/service/WebSocketServiceStarter.java +++ b/pulsar-websocket/src/main/java/org/apache/pulsar/websocket/service/WebSocketServiceStarter.java @@ -19,7 +19,6 @@ package org.apache.pulsar.websocket.service; import static com.google.common.base.Preconditions.checkArgument; -import static org.apache.pulsar.websocket.admin.WebSocketWebResource.ADMIN_PATH_V1; import static org.apache.pulsar.websocket.admin.WebSocketWebResource.ADMIN_PATH_V2; import static org.apache.pulsar.websocket.admin.WebSocketWebResource.ATTRIBUTE_PROXY_SERVICE_NAME; import org.apache.pulsar.common.configuration.PulsarConfigurationLoader; @@ -31,7 +30,6 @@ import org.apache.pulsar.websocket.WebSocketProducerServlet; import org.apache.pulsar.websocket.WebSocketReaderServlet; import org.apache.pulsar.websocket.WebSocketService; -import org.apache.pulsar.websocket.admin.v1.WebSocketProxyStatsV1; import org.apache.pulsar.websocket.admin.v2.WebSocketProxyStatsV2; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -92,17 +90,9 @@ public static void start(ProxyServer proxyServer, WebSocketService service) thro proxyServer.addWebSocketServlet(WebSocketProducerServlet.SERVLET_PATH, new WebSocketProducerServlet(service)); proxyServer.addWebSocketServlet(WebSocketConsumerServlet.SERVLET_PATH, new WebSocketConsumerServlet(service)); proxyServer.addWebSocketServlet(WebSocketReaderServlet.SERVLET_PATH, new WebSocketReaderServlet(service)); - - proxyServer.addWebSocketServlet(WebSocketProducerServlet.SERVLET_PATH_V2, - new WebSocketProducerServlet(service)); - proxyServer.addWebSocketServlet(WebSocketConsumerServlet.SERVLET_PATH_V2, - new WebSocketConsumerServlet(service)); proxyServer.addWebSocketServlet(WebSocketMultiTopicConsumerServlet.SERVLET_PATH, new WebSocketMultiTopicConsumerServlet(service)); - proxyServer.addWebSocketServlet(WebSocketReaderServlet.SERVLET_PATH_V2, - new WebSocketReaderServlet(service)); - proxyServer.addRestResource(ADMIN_PATH_V1, ATTRIBUTE_PROXY_SERVICE_NAME, service, WebSocketProxyStatsV1.class); proxyServer.addRestResource(ADMIN_PATH_V2, ATTRIBUTE_PROXY_SERVICE_NAME, service, WebSocketProxyStatsV2.class); proxyServer.addRestResource("/", VipStatus.ATTRIBUTE_STATUS_FILE_PATH, service.getConfig().getStatusFilePath(), VipStatus.class); diff --git a/pulsar-websocket/src/test/java/org/apache/pulsar/websocket/AbstractWebSocketHandlerTest.java b/pulsar-websocket/src/test/java/org/apache/pulsar/websocket/AbstractWebSocketHandlerTest.java index efae1931f5760..2d75bc187b8cd 100644 --- a/pulsar-websocket/src/test/java/org/apache/pulsar/websocket/AbstractWebSocketHandlerTest.java +++ b/pulsar-websocket/src/test/java/org/apache/pulsar/websocket/AbstractWebSocketHandlerTest.java @@ -84,48 +84,20 @@ final void cleanupCreatedClients() { @Test public void topicNameUrlEncodingTest() throws Exception { - String producerV1 = "/ws/producer/persistent/my-property/my-cluster/my-ns/"; - String producerV1Topic = "my-topic[]<>"; - String consumerV1 = "/ws/consumer/persistent/my-property/my-cluster/my-ns/"; - String consumerV1Topic = "my-topic!@#!@@!#"; - String consumerV1Sub = "my-subscription[]<>!@#$%^&*( )"; - - String readerV1 = "/ws/reader/persistent/my-property/my-cluster/my-ns/"; - String readerV1Topic = "my-topic[]!) (*&^%$#@"; - String producerV2 = "/ws/v2/producer/persistent/my-property/my-ns/"; String producerV2Topic = "my-topic[]<>"; String consumerV2 = "/ws/v2/consumer/persistent/my-property/my-ns/"; String consumerV2Topic = "my-topic"; String consumerV2Sub = "my-subscription[][]<>"; String readerV2 = "/ws/v2/reader/persistent/my-property/my-ns/"; - String readerV2Topic = "my-topic/ / /@!$#^&*( /)1 /_、`,《》[]"; + String readerV2Topic = "my-topic @!$#^&*()-_、`,《》<>[]"; httpServletRequest = mock(HttpServletRequest.class); - when(httpServletRequest.getRequestURI()).thenReturn(producerV1 - + URLEncoder.encode(producerV1Topic, StandardCharsets.UTF_8.name())); - WebSocketHandlerImpl webSocketHandler = new WebSocketHandlerImpl(null, httpServletRequest, null); - TopicName topicName = webSocketHandler.getTopic(); - assertEquals(topicName.toString(), "persistent://my-property/my-cluster/my-ns/" + producerV1Topic); - - when(httpServletRequest.getRequestURI()).thenReturn(consumerV1 - + URLEncoder.encode(consumerV1Topic, StandardCharsets.UTF_8.name()) + "/" - + URLEncoder.encode(consumerV1Sub, StandardCharsets.UTF_8.name())); - webSocketHandler = new WebSocketHandlerImpl(null, httpServletRequest, null); - topicName = webSocketHandler.getTopic(); - assertEquals(topicName.toString(), "persistent://my-property/my-cluster/my-ns/" + consumerV1Topic); - - when(httpServletRequest.getRequestURI()).thenReturn(readerV1 - + URLEncoder.encode(readerV1Topic, StandardCharsets.UTF_8.name())); - webSocketHandler = new WebSocketHandlerImpl(null, httpServletRequest, null); - topicName = webSocketHandler.getTopic(); - assertEquals(topicName.toString(), "persistent://my-property/my-cluster/my-ns/" + readerV1Topic); - when(httpServletRequest.getRequestURI()).thenReturn(producerV2 + URLEncoder.encode(producerV2Topic, StandardCharsets.UTF_8.name())); - webSocketHandler = new WebSocketHandlerImpl(null, httpServletRequest, null); - topicName = webSocketHandler.getTopic(); + WebSocketHandlerImpl webSocketHandler = new WebSocketHandlerImpl(null, httpServletRequest, null); + TopicName topicName = webSocketHandler.getTopic(); assertEquals(topicName.toString(), "persistent://my-property/my-ns/" + producerV2Topic); when(httpServletRequest.getRequestURI()).thenReturn(consumerV2 @@ -148,18 +120,14 @@ public String extractSubscription(HttpServletRequest request) { String uri = request.getRequestURI(); List parts = Splitter.on("/").splitToList(uri); - // v1 Format must be like : - // /ws/consumer/persistent/my-property/my-cluster/my-ns/my-topic/my-subscription - - // v2 Format must be like : + // Format must be like : // /ws/v2/consumer/persistent/my-property/my-ns/my-topic/my-subscription checkArgument(parts.size() == 9, "Invalid topic name format"); checkArgument(parts.get(1).equals("ws")); + checkArgument(parts.get(2).equals("v2")); - final boolean isV2Format = parts.get(2).equals("v2"); - final int domainIndex = isV2Format ? 4 : 3; - checkArgument(parts.get(domainIndex).equals("persistent") - || parts.get(domainIndex).equals("non-persistent")); + checkArgument(parts.get(4).equals("persistent") + || parts.get(4).equals("non-persistent")); checkArgument(parts.get(8).length() > 0, "Empty subscription name"); return Codec.decode(parts.get(8)); @@ -167,35 +135,15 @@ public String extractSubscription(HttpServletRequest request) { @Test public void parseTopicNameTest() { - String producerV1 = "/ws/producer/persistent/my-property/my-cluster/my-ns/my-topic"; - String consumerV1 = "/ws/consumer/persistent/my-property/my-cluster/my-ns/my-topic/my-subscription"; - String readerV1 = "/ws/reader/persistent/my-property/my-cluster/my-ns/my-topic"; - String producerV2 = "/ws/v2/producer/persistent/my-property/my-ns/my-topic"; String consumerV2 = "/ws/v2/consumer/persistent/my-property/my-ns/my-topic/my-subscription"; - String consumerLongTopicNameV2 = "/ws/v2/consumer/persistent/my-tenant/my-ns/some/topic/with/slashes/my-sub"; - String readerV2 = "/ws/v2/reader/persistent/my-property/my-ns/my-topic/ / /@!$#^&*( /)1 /_、`,《》"; + String readerV2 = "/ws/v2/reader/persistent/my-property/my-ns/my-topic"; httpServletRequest = mock(HttpServletRequest.class); - when(httpServletRequest.getRequestURI()).thenReturn(producerV1); + when(httpServletRequest.getRequestURI()).thenReturn(producerV2); WebSocketHandlerImpl webSocketHandler = new WebSocketHandlerImpl(null, httpServletRequest, null); TopicName topicName = webSocketHandler.getTopic(); - assertEquals(topicName.toString(), "persistent://my-property/my-cluster/my-ns/my-topic"); - - when(httpServletRequest.getRequestURI()).thenReturn(consumerV1); - webSocketHandler = new WebSocketHandlerImpl(null, httpServletRequest, null); - topicName = webSocketHandler.getTopic(); - assertEquals(topicName.toString(), "persistent://my-property/my-cluster/my-ns/my-topic"); - - when(httpServletRequest.getRequestURI()).thenReturn(readerV1); - webSocketHandler = new WebSocketHandlerImpl(null, httpServletRequest, null); - topicName = webSocketHandler.getTopic(); - assertEquals(topicName.toString(), "persistent://my-property/my-cluster/my-ns/my-topic"); - - when(httpServletRequest.getRequestURI()).thenReturn(producerV2); - webSocketHandler = new WebSocketHandlerImpl(null, httpServletRequest, null); - topicName = webSocketHandler.getTopic(); assertEquals(topicName.toString(), "persistent://my-property/my-ns/my-topic"); when(httpServletRequest.getRequestURI()).thenReturn(consumerV2); @@ -203,15 +151,10 @@ public void parseTopicNameTest() { topicName = webSocketHandler.getTopic(); assertEquals(topicName.toString(), "persistent://my-property/my-ns/my-topic"); - when(httpServletRequest.getRequestURI()).thenReturn(consumerLongTopicNameV2); - webSocketHandler = new WebSocketHandlerImpl(null, httpServletRequest, null); - topicName = webSocketHandler.getTopic(); - assertEquals(topicName.toString(), "persistent://my-tenant/my-ns/some/topic/with/slashes"); - when(httpServletRequest.getRequestURI()).thenReturn(readerV2); webSocketHandler = new WebSocketHandlerImpl(null, httpServletRequest, null); topicName = webSocketHandler.getTopic(); - assertEquals(topicName.toString(), "persistent://my-property/my-ns/my-topic/ / /@!$#^&*( /)1 /_、`,《》"); + assertEquals(topicName.toString(), "persistent://my-property/my-ns/my-topic"); } diff --git a/pulsar-websocket/src/test/java/org/apache/pulsar/websocket/admin/WebSocketWebResourceTest.java b/pulsar-websocket/src/test/java/org/apache/pulsar/websocket/admin/WebSocketWebResourceTest.java index 1e127e5c9c4dc..acf60309b239e 100644 --- a/pulsar-websocket/src/test/java/org/apache/pulsar/websocket/admin/WebSocketWebResourceTest.java +++ b/pulsar-websocket/src/test/java/org/apache/pulsar/websocket/admin/WebSocketWebResourceTest.java @@ -123,7 +123,7 @@ public void setup(Method method) throws Exception { // Mock UriInfo when(uri.getRequestUri()).thenReturn(null); - topicName = TopicName.get("persistent://tenant/cluster/ns/dest"); + topicName = TopicName.get("persistent://tenant/ns/dest"); } @AfterMethod(alwaysRun = true) diff --git a/tests/integration/src/test/java/org/apache/pulsar/tests/integration/cli/AdminMultiHostTest.java b/tests/integration/src/test/java/org/apache/pulsar/tests/integration/cli/AdminMultiHostTest.java index c9c32e689b61b..e4e0d0f6baa3c 100644 --- a/tests/integration/src/test/java/org/apache/pulsar/tests/integration/cli/AdminMultiHostTest.java +++ b/tests/integration/src/test/java/org/apache/pulsar/tests/integration/cli/AdminMultiHostTest.java @@ -25,7 +25,6 @@ import java.util.concurrent.TimeoutException; import lombok.Cleanup; import org.apache.pulsar.client.admin.PulsarAdmin; -import org.apache.pulsar.common.naming.TopicVersion; import org.apache.pulsar.tests.TestRetrySupport; import org.apache.pulsar.tests.integration.containers.BrokerContainer; import org.apache.pulsar.tests.integration.topologies.PulsarCluster; @@ -87,7 +86,7 @@ private void waitBrokerDown(PulsarAdmin admin, int expectBrokers, int timeout) throws InterruptedException, ExecutionException, TimeoutException { FutureTask futureTask = new FutureTask<>(() -> { while (admin.brokers().getActiveBrokers(clusterName).size() != expectBrokers) { - admin.brokers().healthcheck(TopicVersion.V1); + admin.brokers().healthcheck(); TimeUnit.MILLISECONDS.sleep(1000); } return true; diff --git a/tests/integration/src/test/java/org/apache/pulsar/tests/integration/cli/SchemaUpdateStrategyTest.java b/tests/integration/src/test/java/org/apache/pulsar/tests/integration/cli/SchemaUpdateStrategyTest.java index dbbe4c5dc41a5..062c241778f06 100644 --- a/tests/integration/src/test/java/org/apache/pulsar/tests/integration/cli/SchemaUpdateStrategyTest.java +++ b/tests/integration/src/test/java/org/apache/pulsar/tests/integration/cli/SchemaUpdateStrategyTest.java @@ -440,63 +440,4 @@ public void testDisabledV2() throws Exception { testAutoUpdateDisabled("public/dis-np-v2", "non-persistent://public/dis-np-v2/topic1"); } - @Test - public void testBackwardV1() throws Exception { - pulsarCluster.runAdminCommandOnAnyBroker("namespaces", "create", - "public/" + pulsarCluster.getClusterName() + "/b-p-v1"); - pulsarCluster.runAdminCommandOnAnyBroker("namespaces", "create", - "public/" + pulsarCluster.getClusterName() + "/b-np-v1"); - testAutoUpdateBackward("public/" + pulsarCluster.getClusterName() + "/b-p-v1", - "persistent://public/" + pulsarCluster.getClusterName() + "/b-p-v1/topic1"); - testAutoUpdateBackward("public/" + pulsarCluster.getClusterName() + "/b-np-v1", - "persistent://public/" + pulsarCluster.getClusterName() + "/b-np-v1/topic1"); - } - - @Test - public void testForwardV1() throws Exception { - pulsarCluster.runAdminCommandOnAnyBroker("namespaces", "create", - "public/" + pulsarCluster.getClusterName() + "/f-p-v1"); - pulsarCluster.runAdminCommandOnAnyBroker("namespaces", "create", - "public/" + pulsarCluster.getClusterName() + "/f-np-v1"); - testAutoUpdateForward("public/" + pulsarCluster.getClusterName() + "/f-p-v1", - "persistent://public/" + pulsarCluster.getClusterName() + "/f-p-v1/topic1"); - testAutoUpdateForward("public/" + pulsarCluster.getClusterName() + "/f-np-v1", - "persistent://public/" + pulsarCluster.getClusterName() + "/f-np-v1/topic1"); - } - - @Test - public void testFullV1() throws Exception { - pulsarCluster.runAdminCommandOnAnyBroker("namespaces", "create", - "public/" + pulsarCluster.getClusterName() + "/full-p-v1"); - pulsarCluster.runAdminCommandOnAnyBroker("namespaces", "create", - "public/" + pulsarCluster.getClusterName() + "/full-np-v1"); - testAutoUpdateFull("public/" + pulsarCluster.getClusterName() + "/full-p-v1", - "persistent://public/" + pulsarCluster.getClusterName() + "/full-p-v1/topic1"); - testAutoUpdateFull("public/" + pulsarCluster.getClusterName() + "/full-np-v1", - "persistent://public/" + pulsarCluster.getClusterName() + "/full-np-v1/topic1"); - } - - @Test - public void testNoneV1() throws Exception { - pulsarCluster.runAdminCommandOnAnyBroker("namespaces", "create", - "public/" + pulsarCluster.getClusterName() + "/none-p-v1"); - pulsarCluster.runAdminCommandOnAnyBroker("namespaces", "create", - "public/" + pulsarCluster.getClusterName() + "/none-np-v1"); - testNone("public/" + pulsarCluster.getClusterName() + "/none-p-v1", - "persistent://public/" + pulsarCluster.getClusterName() + "/none-p-v1/topic1"); - testNone("public/" + pulsarCluster.getClusterName() + "/none-np-v1", - "persistent://public/" + pulsarCluster.getClusterName() + "/none-np-v1/topic1"); - } - - @Test - public void testDisabledV1() throws Exception { - pulsarCluster.runAdminCommandOnAnyBroker("namespaces", "create", - "public/" + pulsarCluster.getClusterName() + "/dis-p-v1"); - pulsarCluster.runAdminCommandOnAnyBroker("namespaces", "create", - "public/" + pulsarCluster.getClusterName() + "/dis-np-v1"); - testAutoUpdateDisabled("public/" + pulsarCluster.getClusterName() + "/dis-p-v1", - "persistent://public/" + pulsarCluster.getClusterName() + "/dis-p-v1/topic1"); - testAutoUpdateDisabled("public/" + pulsarCluster.getClusterName() + "/dis-np-v1", - "persistent://public/" + pulsarCluster.getClusterName() + "/dis-np-v1/topic1"); - } } diff --git a/tests/pulsar-client-admin-shade-test/src/test/java/org/apache/pulsar/tests/integration/SimpleProducerConsumerTest.java b/tests/pulsar-client-admin-shade-test/src/test/java/org/apache/pulsar/tests/integration/SimpleProducerConsumerTest.java index ea586ec6bed49..2c5d1d57518a3 100644 --- a/tests/pulsar-client-admin-shade-test/src/test/java/org/apache/pulsar/tests/integration/SimpleProducerConsumerTest.java +++ b/tests/pulsar-client-admin-shade-test/src/test/java/org/apache/pulsar/tests/integration/SimpleProducerConsumerTest.java @@ -95,6 +95,7 @@ public void setup() throws Exception { admin.namespaces().createNamespace("my-property/my-ns"); admin.namespaces().setNamespaceReplicationClusters("my-property/my-ns", Collections.singleton("standalone"), false); + admin.namespaces().createNamespace("my-property/myenc-ns", Collections.singleton("standalone")); } @Override @@ -400,12 +401,12 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe MessageImpl msg = null; Set messageSet = new HashSet<>(); Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/myenc-ns/myenc-topic1").subscriptionName("my-subscriber-name") + .topic("persistent://my-property/myenc-ns/myenc-topic1").subscriptionName("my-subscriber-name") .acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); // 1. Invalid key name try { - pulsarClient.newProducer().topic("persistent://my-property/use/myenc-ns/myenc-topic1") + pulsarClient.newProducer().topic("persistent://my-property/myenc-ns/myenc-topic1") .addEncryptionKey("client-non-existant-rsa.pem").cryptoKeyReader(new EncKeyReader()).create(); Assert.fail("Producer creation should not suceed if failing to read key"); } catch (Exception e) { @@ -414,7 +415,7 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe // 2. Producer with valid key name Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/myenc-ns/myenc-topic1") + .topic("persistent://my-property/myenc-ns/myenc-topic1") .addEncryptionKey("client-rsa.pem") .cryptoKeyReader(new EncKeyReader()) .enableBatching(false) @@ -433,7 +434,7 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe // 4. Set consumer config to consume even if decryption fails consumer.close(); - consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/myenc-ns/myenc-topic1") + consumer = pulsarClient.newConsumer().topic("persistent://my-property/myenc-ns/myenc-topic1") .subscriptionName("my-subscriber-name").cryptoFailureAction(ConsumerCryptoFailureAction.CONSUME) .acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); @@ -454,7 +455,7 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe // 5. Set keyreader and failure action consumer.close(); // Set keyreader - consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/myenc-ns/myenc-topic1") + consumer = pulsarClient.newConsumer().topic("persistent://my-property/myenc-ns/myenc-topic1") .subscriptionName("my-subscriber-name").cryptoFailureAction(ConsumerCryptoFailureAction.FAIL) .cryptoKeyReader(new EncKeyReader()).acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); @@ -474,7 +475,7 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe // 6. Set consumer config to discard if decryption fails consumer.close(); - consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/myenc-ns/myenc-topic1") + consumer = pulsarClient.newConsumer().topic("persistent://my-property/myenc-ns/myenc-topic1") .subscriptionName("my-subscriber-name").cryptoFailureAction(ConsumerCryptoFailureAction.DISCARD) .acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); diff --git a/tests/pulsar-client-all-shade-test/src/test/java/org/apache/pulsar/tests/integration/SimpleProducerConsumerTest.java b/tests/pulsar-client-all-shade-test/src/test/java/org/apache/pulsar/tests/integration/SimpleProducerConsumerTest.java index b9d7f255359a1..51a14558c9337 100644 --- a/tests/pulsar-client-all-shade-test/src/test/java/org/apache/pulsar/tests/integration/SimpleProducerConsumerTest.java +++ b/tests/pulsar-client-all-shade-test/src/test/java/org/apache/pulsar/tests/integration/SimpleProducerConsumerTest.java @@ -97,6 +97,7 @@ public void setup() throws Exception { admin.namespaces().createNamespace("my-property/my-ns"); admin.namespaces().setNamespaceReplicationClusters("my-property/my-ns", Collections.singleton("standalone"), false); + admin.namespaces().createNamespace("my-property/myenc-ns", Collections.singleton("standalone")); } @Override @@ -399,12 +400,12 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe MessageImpl msg = null; Set messageSet = new HashSet<>(); Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/myenc-ns/myenc-topic1").subscriptionName("my-subscriber-name") + .topic("persistent://my-property/myenc-ns/myenc-topic1").subscriptionName("my-subscriber-name") .acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); // 1. Invalid key name try { - pulsarClient.newProducer().topic("persistent://my-property/use/myenc-ns/myenc-topic1") + pulsarClient.newProducer().topic("persistent://my-property/myenc-ns/myenc-topic1") .addEncryptionKey("client-non-existant-rsa.pem").cryptoKeyReader(new EncKeyReader()).create(); Assert.fail("Producer creation should not suceed if failing to read key"); } catch (Exception e) { @@ -413,7 +414,7 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe // 2. Producer with valid key name Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/myenc-ns/myenc-topic1") + .topic("persistent://my-property/myenc-ns/myenc-topic1") .addEncryptionKey("client-rsa.pem") .cryptoKeyReader(new EncKeyReader()) .enableBatching(false) @@ -432,7 +433,7 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe // 4. Set consumer config to consume even if decryption fails consumer.close(); - consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/myenc-ns/myenc-topic1") + consumer = pulsarClient.newConsumer().topic("persistent://my-property/myenc-ns/myenc-topic1") .subscriptionName("my-subscriber-name").cryptoFailureAction(ConsumerCryptoFailureAction.CONSUME) .acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); @@ -453,7 +454,7 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe // 5. Set keyreader and failure action consumer.close(); // Set keyreader - consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/myenc-ns/myenc-topic1") + consumer = pulsarClient.newConsumer().topic("persistent://my-property/myenc-ns/myenc-topic1") .subscriptionName("my-subscriber-name").cryptoFailureAction(ConsumerCryptoFailureAction.FAIL) .cryptoKeyReader(new EncKeyReader()).acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); @@ -473,7 +474,7 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe // 6. Set consumer config to discard if decryption fails consumer.close(); - consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/myenc-ns/myenc-topic1") + consumer = pulsarClient.newConsumer().topic("persistent://my-property/myenc-ns/myenc-topic1") .subscriptionName("my-subscriber-name").cryptoFailureAction(ConsumerCryptoFailureAction.DISCARD) .acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); diff --git a/tests/pulsar-client-shade-test/src/test/java/org/apache/pulsar/tests/integration/SimpleProducerConsumerTest.java b/tests/pulsar-client-shade-test/src/test/java/org/apache/pulsar/tests/integration/SimpleProducerConsumerTest.java index 7f1b3a2de01dc..e245d81c9fe85 100644 --- a/tests/pulsar-client-shade-test/src/test/java/org/apache/pulsar/tests/integration/SimpleProducerConsumerTest.java +++ b/tests/pulsar-client-shade-test/src/test/java/org/apache/pulsar/tests/integration/SimpleProducerConsumerTest.java @@ -92,9 +92,8 @@ public void setup() throws Exception { admin.tenants().createTenant("my-property", TenantInfo.builder().adminRoles(new HashSet<>(Arrays.asList("appid1", "appid2"))) .allowedClusters(Collections.singleton("standalone")).build()); - admin.namespaces().createNamespace("my-property/my-ns"); - admin.namespaces().setNamespaceReplicationClusters("my-property/my-ns", - Collections.singleton("standalone"), false); + admin.namespaces().createNamespace("my-property/my-ns", Collections.singleton("standalone")); + admin.namespaces().createNamespace("my-property/myenc-ns", Collections.singleton("standalone")); } @Override @@ -397,12 +396,12 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe MessageImpl msg = null; Set messageSet = new HashSet<>(); Consumer consumer = pulsarClient.newConsumer() - .topic("persistent://my-property/use/myenc-ns/myenc-topic1").subscriptionName("my-subscriber-name") + .topic("persistent://my-property/myenc-ns/myenc-topic1").subscriptionName("my-subscriber-name") .acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); // 1. Invalid key name try { - pulsarClient.newProducer().topic("persistent://my-property/use/myenc-ns/myenc-topic1") + pulsarClient.newProducer().topic("persistent://my-property/myenc-ns/myenc-topic1") .addEncryptionKey("client-non-existant-rsa.pem").cryptoKeyReader(new EncKeyReader()).create(); Assert.fail("Producer creation should not suceed if failing to read key"); } catch (Exception e) { @@ -411,7 +410,7 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe // 2. Producer with valid key name Producer producer = pulsarClient.newProducer() - .topic("persistent://my-property/use/myenc-ns/myenc-topic1") + .topic("persistent://my-property/myenc-ns/myenc-topic1") .addEncryptionKey("client-rsa.pem") .cryptoKeyReader(new EncKeyReader()) .enableBatching(false) @@ -430,7 +429,7 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe // 4. Set consumer config to consume even if decryption fails consumer.close(); - consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/myenc-ns/myenc-topic1") + consumer = pulsarClient.newConsumer().topic("persistent://my-property/myenc-ns/myenc-topic1") .subscriptionName("my-subscriber-name").cryptoFailureAction(ConsumerCryptoFailureAction.CONSUME) .acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); @@ -451,7 +450,7 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe // 5. Set keyreader and failure action consumer.close(); // Set keyreader - consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/myenc-ns/myenc-topic1") + consumer = pulsarClient.newConsumer().topic("persistent://my-property/myenc-ns/myenc-topic1") .subscriptionName("my-subscriber-name").cryptoFailureAction(ConsumerCryptoFailureAction.FAIL) .cryptoKeyReader(new EncKeyReader()).acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe(); @@ -471,7 +470,7 @@ public EncryptionKeyInfo getPrivateKey(String keyName, Map keyMe // 6. Set consumer config to discard if decryption fails consumer.close(); - consumer = pulsarClient.newConsumer().topic("persistent://my-property/use/myenc-ns/myenc-topic1") + consumer = pulsarClient.newConsumer().topic("persistent://my-property/myenc-ns/myenc-topic1") .subscriptionName("my-subscriber-name").cryptoFailureAction(ConsumerCryptoFailureAction.DISCARD) .acknowledgmentGroupTime(0, TimeUnit.SECONDS).subscribe();