From 5ecb222711c639e862a9fc410e90697c1d9853b3 Mon Sep 17 00:00:00 2001 From: Chimdumebi Nebolisa Date: Sun, 18 Jan 2026 19:32:29 -0600 Subject: [PATCH 1/3] Relax validation for defaultNumPartitions on non-partitioned autoTopicCreation override --- .../policies/data/impl/AutoTopicCreationOverrideImpl.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/policies/data/impl/AutoTopicCreationOverrideImpl.java b/pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/policies/data/impl/AutoTopicCreationOverrideImpl.java index 52cf1f1829b8d..3e87795bccddd 100644 --- a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/policies/data/impl/AutoTopicCreationOverrideImpl.java +++ b/pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/policies/data/impl/AutoTopicCreationOverrideImpl.java @@ -51,11 +51,6 @@ public static ValidateResult validateOverride(AutoTopicCreationOverride override if (override.getDefaultNumPartitions() <= 0) { return ValidateResult.fail("[defaultNumPartitions] cannot be less than 1 for partition type."); } - } else if (TopicType.NON_PARTITIONED.toString().equals(override.getTopicType())) { - if (override.getDefaultNumPartitions() != null) { - return ValidateResult.fail("[defaultNumPartitions] is not allowed to be" - + " set when the type is non-partition."); - } } } return ValidateResult.success(); From 7a13f4245b6dc134a946b6c9d925a9b48caacf56 Mon Sep 17 00:00:00 2001 From: Chimdumebi Nebolisa Date: Sun, 18 Jan 2026 19:32:44 -0600 Subject: [PATCH 2/3] Add broker test: accept but ignore defaultNumPartitions for non-partitioned autoTopicCreation override --- .../pulsar/broker/admin/AdminApi2Test.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) 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 eeac3e1c5e24d..5b115bc74988c 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 @@ -2458,6 +2458,32 @@ public void testAutoTopicCreationOverrideWithMaxNumPartitionsLimit() throws Exce assertTrue(ex.getCause() instanceof NotAcceptableException); } } + + @Test + public void testAutoTopicCreationOverrideNonPartitionedDefaultNumPartitionsIgnored() throws Exception { + String tenantName = newUniqueName("prop-xyz2"); + String namespaceName = tenantName + "/ns-" + System.currentTimeMillis(); + TenantInfoImpl tenantInfo = new TenantInfoImpl(Set.of("role1", "role2"), Set.of("test")); + admin.tenants().createTenant(tenantName, tenantInfo); + admin.namespaces().createNamespace(namespaceName, Set.of("test")); + + AutoTopicCreationOverride overridePolicy = AutoTopicCreationOverride.builder() + .allowAutoTopicCreation(true) + .topicType(TopicType.NON_PARTITIONED.toString()) + .defaultNumPartitions(5) + .build(); + admin.namespaces().setAutoTopicCreation(namespaceName, overridePolicy); + + AutoTopicCreationOverride storedPolicy = admin.namespaces().getAutoTopicCreation(namespaceName); + assertTrue(storedPolicy.isAllowAutoTopicCreation()); + assertEquals(storedPolicy.getTopicType(), TopicType.NON_PARTITIONED.toString()); + assertEquals(storedPolicy.getDefaultNumPartitions(), Integer.valueOf(5)); + + String topicName = "persistent://" + namespaceName + "/auto-topic-" + UUID.randomUUID(); + pulsarClient.newProducer().topic(topicName).create().close(); + + assertEquals(admin.topics().getPartitionedTopicMetadata(topicName).partitions, 0); + } @Test public void testMaxTopicsPerNamespace() throws Exception { restartClusterAfterTest(); From 505efbe01183b80a8ddd3283b8bd0aa6b4590dec Mon Sep 17 00:00:00 2001 From: Chimdumebi Nebolisa Date: Mon, 19 Jan 2026 07:38:01 -0600 Subject: [PATCH 3/3] Fix validation for defaultNumPartitions on non-partitioned override --- .../impl/AutoTopicCreationOverrideImpl.java | 7 ++++++ .../data/AutoTopicCreationOverrideTest.java | 24 ++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/policies/data/impl/AutoTopicCreationOverrideImpl.java b/pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/policies/data/impl/AutoTopicCreationOverrideImpl.java index 3e87795bccddd..79410b01fd5a3 100644 --- a/pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/policies/data/impl/AutoTopicCreationOverrideImpl.java +++ b/pulsar-client-admin-api/src/main/java/org/apache/pulsar/common/policies/data/impl/AutoTopicCreationOverrideImpl.java @@ -44,6 +44,7 @@ public static ValidateResult validateOverride(AutoTopicCreationOverride override if (!TopicType.isValidTopicType(override.getTopicType())) { return ValidateResult.fail(String.format("Unknown topic type [%s]", override.getTopicType())); } + if (TopicType.PARTITIONED.toString().equals(override.getTopicType())) { if (override.getDefaultNumPartitions() == null) { return ValidateResult.fail("[defaultNumPartitions] cannot be null when the type is partitioned."); @@ -51,6 +52,12 @@ public static ValidateResult validateOverride(AutoTopicCreationOverride override if (override.getDefaultNumPartitions() <= 0) { return ValidateResult.fail("[defaultNumPartitions] cannot be less than 1 for partition type."); } + } else if (TopicType.NON_PARTITIONED.toString().equals(override.getTopicType())) { + Integer p = override.getDefaultNumPartitions(); + if (p != null && p != 0 && p != 1) { + return ValidateResult.fail( + "[defaultNumPartitions] must be null, 0 or 1 when the type is non-partitioned."); + } } } return ValidateResult.success(); diff --git a/pulsar-common/src/test/java/org/apache/pulsar/common/policies/data/AutoTopicCreationOverrideTest.java b/pulsar-common/src/test/java/org/apache/pulsar/common/policies/data/AutoTopicCreationOverrideTest.java index 89d41547ba967..e7a34cf4505ad 100644 --- a/pulsar-common/src/test/java/org/apache/pulsar/common/policies/data/AutoTopicCreationOverrideTest.java +++ b/pulsar-common/src/test/java/org/apache/pulsar/common/policies/data/AutoTopicCreationOverrideTest.java @@ -73,7 +73,28 @@ public void testNumPartitionsNotSet() { } @Test - public void testNumPartitionsOnNonPartitioned() { + public void testNumPartitionsOnNonPartitionedZeroAllowed() { + AutoTopicCreationOverride override = AutoTopicCreationOverride.builder() + .allowAutoTopicCreation(true) + .topicType(TopicType.NON_PARTITIONED.toString()) + .defaultNumPartitions(0) + .build(); + assertTrue(AutoTopicCreationOverrideImpl.validateOverride(override).isSuccess()); + } + + @Test + public void testNumPartitionsOnNonPartitionedOneAllowed() { + AutoTopicCreationOverride override = AutoTopicCreationOverride.builder() + .allowAutoTopicCreation(true) + .topicType(TopicType.NON_PARTITIONED.toString()) + .defaultNumPartitions(1) + .build(); + assertTrue(AutoTopicCreationOverrideImpl.validateOverride(override).isSuccess()); + } + + + @Test + public void testNumPartitionsOnNonPartitionedTooHighRejected() { AutoTopicCreationOverride override = AutoTopicCreationOverride.builder() .allowAutoTopicCreation(true) .topicType(TopicType.NON_PARTITIONED.toString()) @@ -81,4 +102,5 @@ public void testNumPartitionsOnNonPartitioned() { .build(); assertFalse(AutoTopicCreationOverrideImpl.validateOverride(override).isSuccess()); } + }