This is an automated email from the ASF dual-hosted git repository.
sijie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar.git
The following commit(s) were added to refs/heads/master by this push:
new 682ceb4 Support limits the max tenants of the Pulsar cluster (#8261)
682ceb4 is described below
commit 682ceb44e7cde5ed8fa5bb79dd13ba05d66f27e7
Author: feynmanlin <[email protected]>
AuthorDate: Sat Oct 17 00:54:07 2020 +0800
Support limits the max tenants of the Pulsar cluster (#8261)
Fixes #8223
### Motivation
Support limits the max tenants of the Pulsar cluster. When the tenants
reach the max tenants of the cluster, the broker should reject the new tenant
request.
### Modifications
Add maxTenants=0 in the broker.conf and don't limit by default.
### Verifying this change
TenantTest#testMaxTenant
---
conf/broker.conf | 4 ++
deployment/terraform-ansible/templates/broker.conf | 4 ++
.../apache/pulsar/broker/ServiceConfiguration.java | 7 +++
.../pulsar/broker/admin/impl/TenantsBase.java | 10 ++++
.../org/apache/pulsar/client/api/TenantTest.java | 69 ++++++++++++++++++++++
5 files changed, 94 insertions(+)
diff --git a/conf/broker.conf b/conf/broker.conf
index f1b6cf4..bf5eb72 100644
--- a/conf/broker.conf
+++ b/conf/broker.conf
@@ -82,6 +82,10 @@ isRunningStandalone=
# Name of the cluster to which this broker belongs to
clusterName=
+# The maximum number of tenants that each pulsar cluster can create
+# This configuration is not precise control, in a concurrent scenario, the
threshold will be exceeded
+maxTenants=0
+
# Enable cluster's failure-domain which can distribute brokers into logical
region
failureDomainsEnabled=false
diff --git a/deployment/terraform-ansible/templates/broker.conf
b/deployment/terraform-ansible/templates/broker.conf
index c430426..d5dc441 100644
--- a/deployment/terraform-ansible/templates/broker.conf
+++ b/deployment/terraform-ansible/templates/broker.conf
@@ -67,6 +67,10 @@ isRunningStandalone=
# Name of the cluster to which this broker belongs to
clusterName={{ cluster_name }}
+# The maximum number of tenants that each pulsar cluster can create
+# This configuration is not precise control, in a concurrent scenario, the
threshold will be exceeded
+maxTenants=0
+
# Enable cluster's failure-domain which can distribute brokers into logical
region
failureDomainsEnabled=false
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 bac8da7..8b13ca5 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
@@ -239,6 +239,13 @@ public class ServiceConfiguration implements
PulsarConfiguration {
@FieldContext(
category = CATEGORY_SERVER,
dynamic = true,
+ doc = "The maximum number of tenants that each pulsar cluster can
create."
+ + "This configuration is not precise control, in a concurrent
scenario, the threshold will be exceeded."
+ )
+ private int maxTenants = 0;
+ @FieldContext(
+ category = CATEGORY_SERVER,
+ dynamic = true,
doc = "Enable cluster's failure-domain which can distribute brokers
into logical region"
)
private boolean failureDomainsEnabled = false;
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 b7b64dd..bce1e83 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
@@ -105,6 +105,16 @@ public class TenantsBase extends AdminResource {
try {
NamedEntity.checkName(tenant);
+
+ int maxTenants = pulsar().getConfiguration().getMaxTenants();
+ //Due to the cost of distributed locks, no locks are added here.
+ //In a concurrent scenario, the threshold will be exceeded.
+ if (maxTenants > 0) {
+ List<String> tenants = globalZk().getChildren(path(POLICIES),
false);
+ if (tenants != null && tenants.size() >= maxTenants) {
+ throw new RestException(Status.PRECONDITION_FAILED,
"Exceed the maximum number of tenants");
+ }
+ }
zkCreate(path(POLICIES, tenant),
jsonMapper().writeValueAsBytes(config));
log.info("[{}] Created tenant {}", clientAppId(), tenant);
} catch (KeeperException.NodeExistsException e) {
diff --git
a/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TenantTest.java
b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TenantTest.java
new file mode 100644
index 0000000..0b84a7a
--- /dev/null
+++ b/pulsar-broker/src/test/java/org/apache/pulsar/client/api/TenantTest.java
@@ -0,0 +1,69 @@
+/**
+ * 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;
+
+import com.google.common.collect.Sets;
+import org.apache.pulsar.broker.auth.MockedPulsarServiceBaseTest;
+import org.apache.pulsar.client.admin.PulsarAdminException;
+import org.apache.pulsar.common.policies.data.ClusterData;
+import org.apache.pulsar.common.policies.data.TenantInfo;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class TenantTest extends MockedPulsarServiceBaseTest {
+
+ @BeforeMethod
+ @Override
+ protected void setup() throws Exception {
+
+ }
+
+ @AfterMethod
+ @Override
+ protected void cleanup() throws Exception {
+ super.internalCleanup();
+ }
+
+ @Test
+ public void testMaxTenant() throws Exception {
+ conf.setMaxTenants(2);
+ super.internalSetup();
+ admin.clusters().createCluster("test", new
ClusterData(brokerUrl.toString()));
+ TenantInfo tenantInfo = new TenantInfo(Sets.newHashSet("role1",
"role2"), Sets.newHashSet("test"));
+ admin.tenants().createTenant("testTenant1", tenantInfo);
+ admin.tenants().createTenant("testTenant2", tenantInfo);
+ try {
+ admin.tenants().createTenant("testTenant3", tenantInfo);
+ } catch (PulsarAdminException e) {
+ Assert.assertEquals(e.getStatusCode(), 412);
+ Assert.assertEquals(e.getHttpError(), "Exceed the maximum number
of tenants");
+ }
+ //unlimited
+ super.internalCleanup();
+ conf.setMaxTenants(0);
+ super.internalSetup();
+ admin.clusters().createCluster("test", new
ClusterData(brokerUrl.toString()));
+ for (int i = 0; i < 10; i++) {
+ admin.tenants().createTenant("testTenant-unlimited" + i,
tenantInfo);
+ }
+ }
+
+}