This is an automated email from the ASF dual-hosted git repository.

penghui pushed a commit to branch branch-2.7
in repository https://gitbox.apache.org/repos/asf/pulsar.git


The following commit(s) were added to refs/heads/branch-2.7 by this push:
     new 801c286665e Validate rack name (#16850)
801c286665e is described below

commit 801c286665efa6fac80829f20a0c8423b85c1a52
Author: JiangHaiting <[email protected]>
AuthorDate: Wed Aug 3 09:28:38 2022 +0800

    Validate rack name (#16850)
---
 .../org/apache/pulsar/broker/admin/v2/Bookies.java | 18 +++++++--
 .../apache/pulsar/broker/admin/BookiesApiTest.java | 46 +++++++++++++++++++++-
 2 files changed, 60 insertions(+), 4 deletions(-)

diff --git 
a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Bookies.java 
b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Bookies.java
index 164cb0175c0..4f626599c5f 100644
--- a/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Bookies.java
+++ b/pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Bookies.java
@@ -22,10 +22,8 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
 import io.swagger.annotations.ApiResponses;
-
 import java.util.Map.Entry;
 import java.util.Optional;
-
 import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
@@ -35,7 +33,7 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response.Status;
-
+import org.apache.commons.lang3.StringUtils;
 import org.apache.pulsar.broker.admin.AdminResource;
 import org.apache.pulsar.broker.web.RestException;
 import org.apache.pulsar.common.policies.data.BookieInfo;
@@ -51,6 +49,7 @@ import org.slf4j.LoggerFactory;
 @Api(value = "/bookies", description = "Configure bookies rack placement", 
tags = "bookies")
 @Produces(MediaType.APPLICATION_JSON)
 public class Bookies extends AdminResource {
+    private static final String PATH_SEPARATOR = "/";
 
     @GET
     @Path("/racks-info")
@@ -126,6 +125,19 @@ public class Bookies extends AdminResource {
             throw new RestException(Status.PRECONDITION_FAILED, "Bookie 
'group' parameters is missing");
         }
 
+        // validate rack name
+        int separatorCnt = StringUtils.countMatches(
+                StringUtils.strip(bookieInfo.getRack(), PATH_SEPARATOR), 
PATH_SEPARATOR);
+        boolean isRackEnabled = 
pulsar().getConfiguration().isBookkeeperClientRackawarePolicyEnabled();
+        boolean isRegionEnabled = 
pulsar().getConfiguration().isBookkeeperClientRegionawarePolicyEnabled();
+        if (isRackEnabled && ((isRegionEnabled && separatorCnt != 1) || 
(!isRegionEnabled && separatorCnt != 0))) {
+            throw new RestException(Status.PRECONDITION_FAILED, "Bookie 'rack' 
parameter is invalid, "
+                    + "When `RackawareEnsemblePlacementPolicy` is enabled, the 
rack name is not allowed to contain "
+                    + "slash (`/`) except for the beginning and end of the 
rack name string. "
+                    + "When `RegionawareEnsemblePlacementPolicy` is enabled, 
the rack name can only contain "
+                    + "one slash (`/`) except for the beginning and end of the 
rack name string.");
+        }
+
         Optional<Entry<BookiesRackConfiguration, Stat>> entry = localZkCache()
                 .getEntry(ZkBookieRackAffinityMapping.BOOKIE_INFO_ROOT_PATH, 
(key, content) -> ObjectMapperFactory
                         .getThreadLocal().readValue(content, 
BookiesRackConfiguration.class));
diff --git 
a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/BookiesApiTest.java
 
b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/BookiesApiTest.java
index 3160b328130..4684431edc1 100644
--- 
a/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/BookiesApiTest.java
+++ 
b/pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/BookiesApiTest.java
@@ -18,12 +18,13 @@
  */
 package org.apache.pulsar.broker.admin;
 
+import static org.mockito.Mockito.doReturn;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
-
 import java.util.Optional;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.pulsar.broker.ServiceConfiguration;
 import org.apache.pulsar.broker.auth.MockedPulsarServiceBaseTest;
 import org.apache.pulsar.client.admin.PulsarAdminException;
 import org.apache.pulsar.common.policies.data.BookieInfo;
@@ -109,6 +110,49 @@ public class BookiesApiTest extends 
MockedPulsarServiceBaseTest {
 
         conf = admin.bookies().getBookiesRackInfo();
         assertTrue(conf.isEmpty());
+
+        // test invalid rack name
+        // use rack aware placement policy
+        String errorMsg = "Bookie 'rack' parameter is invalid, When 
`RackawareEnsemblePlacementPolicy` is enabled, "
+                + "the rack name is not allowed to contain slash (`/`) except 
for the beginning and end of the rack name "
+                + "string. When `RegionawareEnsemblePlacementPolicy` is 
enabled, the rack name can only contain "
+                + "one slash (`/`) except for the beginning and end of the 
rack name string.";
+
+        BookieInfo newInfo3 = new BookieInfo("/rack/a","127.0.0.2");
+        try {
+            admin.bookies().updateBookieRackInfo(bookie0, "default", newInfo3);
+            fail();
+        } catch (PulsarAdminException e) {
+            assertEquals(412, e.getStatusCode());
+            assertEquals(errorMsg, e.getMessage());
+        }
+
+        BookieInfo newInfo4 = new BookieInfo("/rack","127.0.0.2");
+        try {
+            admin.bookies().updateBookieRackInfo(bookie0, "default", newInfo4);
+        } catch (PulsarAdminException e) {
+            fail();
+        }
+
+        // enable region aware placement policy
+        ServiceConfiguration configuration = new ServiceConfiguration();
+        configuration.setBookkeeperClientRegionawarePolicyEnabled(true);
+        doReturn(configuration).when(pulsar).getConfiguration();
+        BookieInfo newInfo5 = new BookieInfo("/region/rack/a", "127.0.0.2");
+        try {
+            admin.bookies().updateBookieRackInfo(bookie0, "default", newInfo5);
+            fail();
+        } catch (PulsarAdminException e) {
+            assertEquals(412, e.getStatusCode());
+            assertEquals(errorMsg, e.getMessage());
+        }
+
+        BookieInfo newInfo6 = new BookieInfo("/region/rack/", "127.0.0.2");
+        try {
+            admin.bookies().updateBookieRackInfo(bookie0, "default", newInfo6);
+        } catch (PulsarAdminException e) {
+            fail();
+        }
     }
 
 }

Reply via email to