This is an automated email from the ASF dual-hosted git repository. xyz pushed a commit to branch branch-2.8 in repository https://gitbox.apache.org/repos/asf/pulsar.git
commit 428f453fc285a2da3178bd82ba7456832ffb1678 Author: Ruguo Yu <[email protected]> AuthorDate: Mon Nov 8 19:13:02 2021 +0800 [pulsar-admin] Add corresponding get command for namespace (#12322) ### Motivation CLI `./bin/pulsar-admin` provides many `set` commands for namespace and also provides corresponding `get` commands, but I found that the following `set` commands lack corresponding `get` commands. - [grant-subscription-permission](https://pulsar.apache.org/tools/pulsar-admin/2.9.0-SNAPSHOT/#-em-grant-subscription-permission-em-) - [set-auto-topic-creation](https://pulsar.apache.org/tools/pulsar-admin/2.9.0-SNAPSHOT/#-em-set-auto-topic-creation-em-) - [set-auto-subscription-creation](https://pulsar.apache.org/tools/pulsar-admin/2.9.0-SNAPSHOT/#-em-set-auto-subscription-creation-em-) - [set-encryption-required](https://pulsar.apache.org/tools/pulsar-admin/2.9.0-SNAPSHOT/#-em-set-encryption-required-em-) - [set-subscription-auth-mode](https://pulsar.apache.org/tools/pulsar-admin/2.9.0-SNAPSHOT/#-em-set-subscription-auth-mode-em-) The purpose of this PR is to supplement these `get` commands, as follow: - subscription-permission - get-auto-topic-creation - get-auto-subscription-creation - get-encryption-required - get-subscription-auth-mode (cherry picked from commit d055ebd1186ffae2d2af1382e05b21c60e9f9574) --- .../pulsar/broker/admin/impl/NamespacesBase.java | 24 +++ .../apache/pulsar/broker/admin/v1/Namespaces.java | 65 ++++++++ .../apache/pulsar/broker/admin/v2/Namespaces.java | 59 +++++++ .../pulsar/broker/auth/AuthorizationTest.java | 6 + .../BrokerServiceAutoSubscriptionCreationTest.java | 19 ++- .../BrokerServiceAutoTopicCreationTest.java | 37 +++-- .../api/AuthorizationProducerConsumerTest.java | 7 + .../org/apache/pulsar/client/admin/Namespaces.java | 81 ++++++++++ .../client/admin/internal/NamespacesImpl.java | 170 +++++++++++++++++++++ .../pulsar/admin/cli/PulsarAdminToolTest.java | 6 + .../org/apache/pulsar/admin/cli/CmdNamespaces.java | 65 ++++++++ 11 files changed, 518 insertions(+), 21 deletions(-) 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 e04b5bc0069..7c581b2cf83 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 @@ -814,6 +814,12 @@ public abstract class NamespacesBase extends AdminResource { }); } + protected AutoTopicCreationOverride internalGetAutoTopicCreation() { + validateNamespacePolicyOperation(namespaceName, PolicyName.AUTO_TOPIC_CREATION, PolicyOperation.READ); + Policies policies = getNamespacePolicies(namespaceName); + return policies.autoTopicCreationOverride; + } + protected void internalSetAutoTopicCreation(AsyncResponse asyncResponse, AutoTopicCreationOverride autoTopicCreationOverride) { final int maxPartitions = pulsar().getConfig().getMaxNumPartitionsPerPartitionedTopic(); @@ -888,6 +894,12 @@ public abstract class NamespacesBase extends AdminResource { }); } + protected AutoSubscriptionCreationOverride internalGetAutoSubscriptionCreation() { + validateNamespacePolicyOperation(namespaceName, PolicyName.AUTO_SUBSCRIPTION_CREATION, PolicyOperation.READ); + Policies policies = getNamespacePolicies(namespaceName); + return policies.autoSubscriptionCreationOverride; + } + protected void internalRemoveAutoSubscriptionCreation(AsyncResponse asyncResponse) { internalSetAutoSubscriptionCreation(asyncResponse, null); } @@ -1715,6 +1727,12 @@ public abstract class NamespacesBase extends AdminResource { } } + protected SubscriptionAuthMode internalGetSubscriptionAuthMode() { + validateNamespacePolicyOperation(namespaceName, PolicyName.SUBSCRIPTION_AUTH_MODE, PolicyOperation.READ); + Policies policies = getNamespacePolicies(namespaceName); + return policies.subscription_auth_mode; + } + protected void internalModifyEncryptionRequired(boolean encryptionRequired) { validateNamespacePolicyOperation(namespaceName, PolicyName.ENCRYPTION, PolicyOperation.WRITE); validatePoliciesReadOnlyAccess(); @@ -1733,6 +1751,12 @@ public abstract class NamespacesBase extends AdminResource { } } + protected Boolean internalGetEncryptionRequired() { + validateNamespacePolicyOperation(namespaceName, PolicyName.ENCRYPTION, PolicyOperation.READ); + Policies policies = getNamespacePolicies(namespaceName); + return policies.encryption_required; + } + protected DelayedDeliveryPolicies internalGetDelayedDelivery() { validateNamespacePolicyOperation(namespaceName, PolicyName.DELAYED_DELIVERY, PolicyOperation.READ); return getNamespacePolicies(namespaceName).delayed_delivery_policies; 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 index 9fec59cd4b6..9130245a23f 100644 --- 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 @@ -245,6 +245,22 @@ public class Namespaces extends NamespacesBase { return policies.auth_policies.getNamespaceAuthentication(); } + @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 Map<String, Set<String>> getPermissionOnSubscription(@PathParam("property") String property, + @PathParam("cluster") String cluster, + @PathParam("namespace") String namespace) { + validateNamespaceName(property, cluster, namespace); + validateNamespaceOperation(NamespaceName.get(property, namespace), NamespaceOperation.GET_PERMISSION); + + Policies policies = getNamespacePolicies(namespaceName); + return policies.auth_policies.getSubscriptionAuthentication(); + } + @POST @Path("/{property}/{cluster}/{namespace}/permissions/{role}") @ApiOperation(hidden = true, value = "Grant a new permission to a role on a namespace.") @@ -449,6 +465,18 @@ public class Namespaces extends NamespacesBase { internalModifyDeduplication(enableDeduplication); } + @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 AutoTopicCreationOverride getAutoTopicCreation(@PathParam("property") String property, + @PathParam("cluster") String cluster, + @PathParam("namespace") String namespace) { + validateNamespaceName(property, cluster, namespace); + return internalGetAutoTopicCreation(); + } + @POST @Path("/{property}/{cluster}/{namespace}/autoTopicCreation") @ApiOperation(value = "Override broker's allowAutoTopicCreation setting for a namespace") @@ -510,6 +538,18 @@ public class Namespaces extends NamespacesBase { } } + @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 AutoSubscriptionCreationOverride getAutoSubscriptionCreation(@PathParam("property") String property, + @PathParam("cluster") String cluster, + @PathParam("namespace") String namespace) { + validateNamespaceName(property, cluster, namespace); + return internalGetAutoSubscriptionCreation(); + } + @DELETE @Path("/{property}/{cluster}/{namespace}/autoSubscriptionCreation") @ApiOperation(value = "Remove override of broker's allowAutoSubscriptionCreation in a namespace") @@ -958,6 +998,18 @@ public class Namespaces extends NamespacesBase { 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 SubscriptionAuthMode getSubscriptionAuthMode(@PathParam("property") String property, + @PathParam("cluster") String cluster, + @PathParam("namespace") String namespace) { + validateNamespaceName(property, cluster, namespace); + return internalGetSubscriptionAuthMode(); + } + @POST @Path("/{property}/{cluster}/{namespace}/encryptionRequired") @ApiOperation(hidden = true, value = "Message encryption is required or not for all topics in a namespace") @@ -970,6 +1022,19 @@ public class Namespaces extends NamespacesBase { 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.") 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 76e543001f2..ef16d1ca640 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 @@ -192,6 +192,21 @@ public class Namespaces extends NamespacesBase { return policies.auth_policies.getNamespaceAuthentication(); } + @GET + @Path("/{tenant}/{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 = "Tenant or cluster or namespace doesn't exist"), + @ApiResponse(code = 409, message = "Namespace is not empty")}) + public Map<String, Set<String>> getPermissionOnSubscription(@PathParam("tenant") String tenant, + @PathParam("namespace") String namespace) { + validateNamespaceName(tenant, namespace); + validateNamespaceOperation(NamespaceName.get(tenant, namespace), NamespaceOperation.GET_PERMISSION); + + Policies policies = getNamespacePolicies(namespaceName); + return policies.auth_policies.getSubscriptionAuthentication(); + } + @POST @Path("/{tenant}/{namespace}/permissions/{role}") @ApiOperation(value = "Grant a new permission to a role on a namespace.") @@ -382,6 +397,17 @@ public class Namespaces extends NamespacesBase { internalModifyDeduplication(null); } + @GET + @Path("/{tenant}/{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 namespace doesn't exist")}) + public AutoTopicCreationOverride getAutoTopicCreation(@PathParam("tenant") String tenant, + @PathParam("namespace") String namespace) { + validateNamespaceName(tenant, namespace); + return internalGetAutoTopicCreation(); + } + @POST @Path("/{tenant}/{namespace}/autoTopicCreation") @ApiOperation(value = "Override broker's allowAutoTopicCreation setting for a namespace") @@ -443,6 +469,17 @@ public class Namespaces extends NamespacesBase { } } + @GET + @Path("/{tenant}/{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 = "Tenant or namespace doesn't exist")}) + public AutoSubscriptionCreationOverride getAutoSubscriptionCreation(@PathParam("tenant") String tenant, + @PathParam("namespace") String namespace) { + validateNamespaceName(tenant, namespace); + return internalGetAutoSubscriptionCreation(); + } + @DELETE @Path("/{tenant}/{namespace}/autoSubscriptionCreation") @ApiOperation(value = "Remove override of broker's allowAutoSubscriptionCreation in a namespace") @@ -977,6 +1014,17 @@ public class Namespaces extends NamespacesBase { internalSetSubscriptionAuthMode(subscriptionAuthMode); } + @GET + @Path("/{tenant}/{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 = "Tenant or namespace doesn't exist")}) + public SubscriptionAuthMode getSubscriptionAuthMode(@PathParam("tenant") String tenant, + @PathParam("namespace") String namespace) { + validateNamespaceName(tenant, namespace); + return internalGetSubscriptionAuthMode(); + } + @POST @Path("/{tenant}/{namespace}/encryptionRequired") @ApiOperation(value = "Message encryption is required or not for all topics in a namespace") @@ -992,6 +1040,17 @@ public class Namespaces extends NamespacesBase { internalModifyEncryptionRequired(encryptionRequired); } + @GET + @Path("/{tenant}/{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 = "Tenant or namespace doesn't exist")}) + public Boolean getEncryptionRequired(@PathParam("tenant") String tenant, + @PathParam("namespace") String namespace) { + validateNamespaceName(tenant, namespace); + return internalGetEncryptionRequired(); + } + @GET @Path("/{tenant}/{namespace}/delayedDelivery") @ApiOperation(value = "Get delayed delivery messages config on a namespace.") 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 7bbbc9072f3..4b18791fce0 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 @@ -35,6 +35,7 @@ import org.apache.pulsar.common.policies.data.ClusterData; import org.apache.pulsar.common.policies.data.ClusterDataImpl; import org.apache.pulsar.common.policies.data.TenantInfoImpl; import org.apache.pulsar.common.policies.data.SubscriptionAuthMode; +import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -203,7 +204,12 @@ public class AuthorizationTest extends MockedPulsarServiceBaseTest { // 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"), + SubscriptionAuthMode.None); admin.namespaces().setSubscriptionAuthMode("p1/c1/ns1", SubscriptionAuthMode.Prefix); + Assert.assertEquals(admin.namespaces().getSubscriptionAuthMode("p1/c1/ns1"), + SubscriptionAuthMode.Prefix); waitForChange(); assertTrue(auth.canLookup(TopicName.get("persistent://p1/c1/ns1/ds1"), "role1", null)); diff --git a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerServiceAutoSubscriptionCreationTest.java b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerServiceAutoSubscriptionCreationTest.java index 81f9521bbff..dc4b3d9d51d 100644 --- a/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerServiceAutoSubscriptionCreationTest.java +++ b/pulsar-broker/src/test/java/org/apache/pulsar/broker/service/BrokerServiceAutoSubscriptionCreationTest.java @@ -26,6 +26,7 @@ import org.apache.pulsar.client.api.MessageId; import org.apache.pulsar.client.api.PulsarClientException; import org.apache.pulsar.common.naming.TopicName; import org.apache.pulsar.common.policies.data.AutoSubscriptionCreationOverride; +import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; @@ -98,10 +99,13 @@ public class BrokerServiceAutoSubscriptionCreationTest extends BrokerTestBase { admin.topics().createNonPartitionedTopic(topicName.toString()); pulsar.getConfiguration().setAllowAutoSubscriptionCreation(false); + AutoSubscriptionCreationOverride autoSubscriptionCreationOverride = AutoSubscriptionCreationOverride.builder() + .allowAutoSubscriptionCreation(true) + .build(); pulsar.getAdminClient().namespaces().setAutoSubscriptionCreation(topicName.getNamespace(), - AutoSubscriptionCreationOverride.builder() - .allowAutoSubscriptionCreation(true) - .build()); + autoSubscriptionCreationOverride); + Assert.assertEquals(pulsar.getAdminClient().namespaces().getAutoSubscriptionCreation(topicName.getNamespace()), + autoSubscriptionCreationOverride); // Subscribe operation should be successful pulsarClient.newConsumer().topic(topicName.toString()).subscriptionName(subscriptionName).subscribe(); @@ -117,10 +121,13 @@ public class BrokerServiceAutoSubscriptionCreationTest extends BrokerTestBase { admin.topics().createNonPartitionedTopic(topicName.toString()); pulsar.getConfiguration().setAllowAutoSubscriptionCreation(true); + AutoSubscriptionCreationOverride autoSubscriptionCreationOverride = AutoSubscriptionCreationOverride.builder() + .allowAutoSubscriptionCreation(false) + .build(); pulsar.getAdminClient().namespaces().setAutoSubscriptionCreation(topicName.getNamespace(), - AutoSubscriptionCreationOverride.builder() - .allowAutoSubscriptionCreation(false) - .build()); + autoSubscriptionCreationOverride); + Assert.assertEquals(pulsar.getAdminClient().namespaces().getAutoSubscriptionCreation(topicName.getNamespace()), + autoSubscriptionCreationOverride); try { pulsarClient.newConsumer().topic(topicName.toString()).subscriptionName(subscriptionName).subscribe(); 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 33ed35636db..1b3ca1616fa 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 @@ -29,6 +29,7 @@ import org.apache.pulsar.common.events.EventsTopicNames; import org.apache.pulsar.common.naming.TopicName; import org.apache.pulsar.common.policies.data.AutoTopicCreationOverride; import org.apache.pulsar.common.policies.data.TopicType; +import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; @@ -168,11 +169,13 @@ public class BrokerServiceAutoTopicCreationTest extends BrokerTestBase{ final String subscriptionName = "test-topic-sub-4"; final TopicName topicName = TopicName.get(topicString); pulsar.getConfiguration().setAllowAutoTopicCreation(false); - pulsar.getAdminClient().namespaces().setAutoTopicCreation(topicName.getNamespace(), - AutoTopicCreationOverride.builder() - .allowAutoTopicCreation(true) - .topicType(TopicType.NON_PARTITIONED.toString()) - .build()); + AutoTopicCreationOverride autoTopicCreationOverride = AutoTopicCreationOverride.builder() + .allowAutoTopicCreation(true) + .topicType(TopicType.NON_PARTITIONED.toString()) + .build(); + pulsar.getAdminClient().namespaces().setAutoTopicCreation(topicName.getNamespace(), autoTopicCreationOverride); + Assert.assertEquals(pulsar.getAdminClient().namespaces().getAutoTopicCreation(topicName.getNamespace()), + autoTopicCreationOverride); pulsarClient.newConsumer().topic(topicString).subscriptionName(subscriptionName).subscribe(); assertTrue(admin.namespaces().getTopics("prop/ns-abc").contains(topicString)); @@ -185,10 +188,12 @@ public class BrokerServiceAutoTopicCreationTest extends BrokerTestBase{ final String subscriptionName = "test-topic-sub-5"; final TopicName topicName = TopicName.get(topicString); pulsar.getConfiguration().setAllowAutoTopicCreation(true); - pulsar.getAdminClient().namespaces().setAutoTopicCreation(topicName.getNamespace(), - AutoTopicCreationOverride.builder() - .allowAutoTopicCreation(false) - .build()); + AutoTopicCreationOverride autoTopicCreationOverride = AutoTopicCreationOverride.builder() + .allowAutoTopicCreation(false) + .build(); + pulsar.getAdminClient().namespaces().setAutoTopicCreation(topicName.getNamespace(), autoTopicCreationOverride); + Assert.assertEquals(pulsar.getAdminClient().namespaces().getAutoTopicCreation(topicName.getNamespace()), + autoTopicCreationOverride); try { pulsarClient.newConsumer().topic(topicString).subscriptionName(subscriptionName).subscribe(); @@ -205,12 +210,14 @@ public class BrokerServiceAutoTopicCreationTest extends BrokerTestBase{ final TopicName topicName = TopicName.get(topicString); pulsar.getConfiguration().setAllowAutoTopicCreation(false); - pulsar.getAdminClient().namespaces().setAutoTopicCreation(topicName.getNamespace(), - AutoTopicCreationOverride.builder() - .allowAutoTopicCreation(true) - .topicType(TopicType.PARTITIONED.toString()) - .defaultNumPartitions(4) - .build()); + AutoTopicCreationOverride autoTopicCreationOverride = AutoTopicCreationOverride.builder() + .allowAutoTopicCreation(true) + .topicType(TopicType.PARTITIONED.toString()) + .defaultNumPartitions(4) + .build(); + pulsar.getAdminClient().namespaces().setAutoTopicCreation(topicName.getNamespace(), autoTopicCreationOverride); + Assert.assertEquals(pulsar.getAdminClient().namespaces().getAutoTopicCreation(topicName.getNamespace()), + autoTopicCreationOverride); final String subscriptionName = "test-topic-sub-6"; pulsarClient.newConsumer().topic(topicString).subscriptionName(subscriptionName).subscribe(); 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 31b2451575d..a899b314357 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 @@ -34,6 +34,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeMap; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -281,6 +282,9 @@ public class AuthorizationProducerConsumerTest extends ProducerConsumerBase { String otherPrincipal = "Principal-1-to-access-sub"; tenantAdmin.namespaces().grantPermissionOnSubscription(namespace, subscriptionName, Collections.singleton(otherPrincipal)); + TreeMap<String, Set<String>> permissionOnSubscription = new TreeMap<>(); + permissionOnSubscription.put(subscriptionName, Collections.singleton(otherPrincipal)); + Assert.assertEquals(tenantAdmin.namespaces().getPermissionOnSubscription(namespace), permissionOnSubscription); // now, subscriptionRole doesn't have subscription level access so, it will fail to access subscription try { @@ -301,6 +305,9 @@ public class AuthorizationProducerConsumerTest extends ProducerConsumerBase { // now, grant subscription-access to subscriptionRole as well superAdmin.namespaces().grantPermissionOnSubscription(namespace, subscriptionName, Sets.newHashSet(otherPrincipal, subscriptionRole)); + TreeMap<String, Set<String>> permissionOnSubscription1 = new TreeMap<>(); + permissionOnSubscription1.put(subscriptionName, Sets.newHashSet(otherPrincipal, subscriptionRole)); + Assert.assertEquals(tenantAdmin.namespaces().getPermissionOnSubscription(namespace), permissionOnSubscription1); sub1Admin.topics().skipAllMessages(topicName, subscriptionName); sub1Admin.topics().skipMessages(topicName, subscriptionName, 1); 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 6ea4bab025c..fb1b67e7f1d 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 @@ -687,6 +687,19 @@ public interface Namespaces { */ CompletableFuture<Void> revokePermissionsOnNamespaceAsync(String namespace, String role); + /** + * Get permission to role to access subscription's admin-api. + * @param namespace + * @throws PulsarAdminException + */ + Map<String, Set<String>> getPermissionOnSubscription(String namespace) throws PulsarAdminException; + + /** + * Get permission to role to access subscription's admin-api asynchronously. + * @param namespace + */ + CompletableFuture<Map<String, Set<String>>> getPermissionOnSubscriptionAsync(String namespace); + /** * Grant permission to role to access subscription's admin-api. * @param namespace @@ -1237,6 +1250,23 @@ public interface Namespaces { CompletableFuture<Void> setAutoTopicCreationAsync( String namespace, AutoTopicCreationOverride autoTopicCreationOverride); + /** + * Get the autoTopicCreation info within a namespace. + * + * @param namespace + * @return + * @throws PulsarAdminException + */ + AutoTopicCreationOverride getAutoTopicCreation(String namespace) throws PulsarAdminException; + + /** + * Get the autoTopicCreation info within a namespace asynchronously. + * + * @param namespace + * @return + */ + CompletableFuture<AutoTopicCreationOverride> getAutoTopicCreationAsync(String namespace); + /** * Removes the autoTopicCreation policy for a given namespace. * <p/> @@ -1322,6 +1352,23 @@ public interface Namespaces { CompletableFuture<Void> setAutoSubscriptionCreationAsync( String namespace, AutoSubscriptionCreationOverride autoSubscriptionCreationOverride); + /** + * Get the autoSubscriptionCreation info within a namespace. + * + * @param namespace + * @return + * @throws PulsarAdminException + */ + AutoSubscriptionCreationOverride getAutoSubscriptionCreation(String namespace) throws PulsarAdminException; + + /** + * Get the autoSubscriptionCreation info within a namespace asynchronously. + * + * @param namespace + * @return + */ + CompletableFuture<AutoSubscriptionCreationOverride> getAutoSubscriptionCreationAsync(String namespace); + /** * Sets the subscriptionTypesEnabled policy for a given namespace, overriding broker settings. * @@ -2438,6 +2485,23 @@ public interface Namespaces { */ void setEncryptionRequiredStatus(String namespace, boolean encryptionRequired) throws PulsarAdminException; + /** + * Get the encryption required status within a namespace. + * + * @param namespace + * @return + * @throws PulsarAdminException + */ + Boolean getEncryptionRequiredStatus(String namespace) throws PulsarAdminException; + + /** + * Get the encryption required status within a namespace asynchronously. + * + * @param namespace + * @return + */ + CompletableFuture<Boolean> getEncryptionRequiredStatusAsync(String namespace); + /** * Set the encryption required status for all topics within a namespace asynchronously. * <p/> @@ -2646,6 +2710,23 @@ public interface Namespaces { */ CompletableFuture<Void> setSubscriptionAuthModeAsync(String namespace, SubscriptionAuthMode subscriptionAuthMode); + /** + * Get the subscriptionAuthMode within a namespace. + * + * @param namespace + * @return + * @throws PulsarAdminException + */ + SubscriptionAuthMode getSubscriptionAuthMode(String namespace) throws PulsarAdminException; + + /** + * Get the subscriptionAuthMode within a namespace asynchronously. + * + * @param namespace + * @return + */ + CompletableFuture<SubscriptionAuthMode> getSubscriptionAuthModeAsync(String namespace); + /** * Get the deduplicationSnapshotInterval for a namespace. * 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 6a489f9bcd3..1d59d4c9c20 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 @@ -513,6 +513,39 @@ public class NamespacesImpl extends BaseResource implements Namespaces { return asyncDeleteRequest(path); } + @Override + public Map<String, Set<String>> getPermissionOnSubscription(String namespace) throws PulsarAdminException { + try { + return getPermissionOnSubscriptionAsync(namespace).get(this.readTimeoutMs, TimeUnit.MILLISECONDS); + } catch (ExecutionException e) { + throw (PulsarAdminException) e.getCause(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new PulsarAdminException(e); + } catch (TimeoutException e) { + throw new PulsarAdminException.TimeoutException(e); + } + } + + @Override + public CompletableFuture<Map<String, Set<String>>> getPermissionOnSubscriptionAsync(String namespace) { + NamespaceName ns = NamespaceName.get(namespace); + WebTarget path = namespacePath(ns, "permissions", "subscription"); + final CompletableFuture<Map<String, Set<String>>> future = new CompletableFuture<>(); + asyncGetRequest(path, + new InvocationCallback<Map<String, Set<String>>>() { + @Override + public void completed(Map<String, Set<String>> permissions) { + future.complete(permissions); + } + + @Override + public void failed(Throwable throwable) { + future.completeExceptionally(getApiException(throwable.getCause())); + } + }); + return future; + } @Override public void grantPermissionOnSubscription(String namespace, String subscription, Set<String> roles) @@ -995,6 +1028,40 @@ public class NamespacesImpl extends BaseResource implements Namespaces { return asyncPostRequest(path, Entity.entity(autoTopicCreationOverride, MediaType.APPLICATION_JSON)); } + @Override + public AutoTopicCreationOverride getAutoTopicCreation(String namespace) throws PulsarAdminException { + try { + return getAutoTopicCreationAsync(namespace).get(this.readTimeoutMs, TimeUnit.MILLISECONDS); + } catch (ExecutionException e) { + throw (PulsarAdminException) e.getCause(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new PulsarAdminException(e); + } catch (TimeoutException e) { + throw new PulsarAdminException.TimeoutException(e); + } + } + + @Override + public CompletableFuture<AutoTopicCreationOverride> getAutoTopicCreationAsync(String namespace) { + NamespaceName ns = NamespaceName.get(namespace); + WebTarget path = namespacePath(ns, "autoTopicCreation"); + final CompletableFuture<AutoTopicCreationOverride> future = new CompletableFuture<>(); + asyncGetRequest(path, + new InvocationCallback<AutoTopicCreationOverride>() { + @Override + public void completed(AutoTopicCreationOverride autoTopicCreationOverride) { + future.complete(autoTopicCreationOverride); + } + + @Override + public void failed(Throwable throwable) { + future.completeExceptionally(getApiException(throwable.getCause())); + } + }); + return future; + } + @Override public void removeAutoTopicCreation(String namespace) throws PulsarAdminException { try { @@ -1040,6 +1107,41 @@ public class NamespacesImpl extends BaseResource implements Namespaces { return asyncPostRequest(path, Entity.entity(autoSubscriptionCreationOverride, MediaType.APPLICATION_JSON)); } + @Override + public AutoSubscriptionCreationOverride getAutoSubscriptionCreation(String namespace) throws PulsarAdminException { + try { + return getAutoSubscriptionCreationAsync(namespace).get(this.readTimeoutMs, TimeUnit.MILLISECONDS); + } catch (ExecutionException e) { + throw (PulsarAdminException) e.getCause(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new PulsarAdminException(e); + } catch (TimeoutException e) { + throw new PulsarAdminException.TimeoutException(e); + } + } + + @Override + public CompletableFuture<AutoSubscriptionCreationOverride> getAutoSubscriptionCreationAsync(String namespace) { + NamespaceName ns = NamespaceName.get(namespace); + WebTarget path = namespacePath(ns, "autoSubscriptionCreation"); + final CompletableFuture<AutoSubscriptionCreationOverride> future = new CompletableFuture<>(); + asyncGetRequest(path, + new InvocationCallback<AutoSubscriptionCreationOverride>() { + @Override + public void completed(AutoSubscriptionCreationOverride autoSubscriptionCreation) { + future.complete(autoSubscriptionCreation); + } + + @Override + public void failed(Throwable throwable) { + future.completeExceptionally(getApiException(throwable.getCause())); + } + }); + return future; + } + + @Override public void setSubscriptionTypesEnabled( String namespace, Set<SubscriptionType> subscriptionTypesEnabled) throws PulsarAdminException { @@ -2105,6 +2207,40 @@ public class NamespacesImpl extends BaseResource implements Namespaces { return asyncPostRequest(path, Entity.entity(subscriptionAuthMode, MediaType.APPLICATION_JSON)); } + @Override + public SubscriptionAuthMode getSubscriptionAuthMode(String namespace) throws PulsarAdminException { + try { + return getSubscriptionAuthModeAsync(namespace).get(this.readTimeoutMs, TimeUnit.MILLISECONDS); + } catch (ExecutionException e) { + throw (PulsarAdminException) e.getCause(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new PulsarAdminException(e); + } catch (TimeoutException e) { + throw new PulsarAdminException.TimeoutException(e); + } + } + + @Override + public CompletableFuture<SubscriptionAuthMode> getSubscriptionAuthModeAsync(String namespace) { + NamespaceName ns = NamespaceName.get(namespace); + WebTarget path = namespacePath(ns, "subscriptionAuthMode"); + final CompletableFuture<SubscriptionAuthMode> future = new CompletableFuture<>(); + asyncGetRequest(path, + new InvocationCallback<SubscriptionAuthMode>() { + @Override + public void completed(SubscriptionAuthMode subscriptionAuthMode) { + future.complete(subscriptionAuthMode); + } + + @Override + public void failed(Throwable throwable) { + future.completeExceptionally(getApiException(throwable.getCause())); + } + }); + return future; + } + @Override public void setEncryptionRequiredStatus(String namespace, boolean encryptionRequired) throws PulsarAdminException { try { @@ -2127,6 +2263,40 @@ public class NamespacesImpl extends BaseResource implements Namespaces { return asyncPostRequest(path, Entity.entity(encryptionRequired, MediaType.APPLICATION_JSON)); } + @Override + public Boolean getEncryptionRequiredStatus(String namespace) throws PulsarAdminException { + try { + return getEncryptionRequiredStatusAsync(namespace).get(this.readTimeoutMs, TimeUnit.MILLISECONDS); + } catch (ExecutionException e) { + throw (PulsarAdminException) e.getCause(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new PulsarAdminException(e); + } catch (TimeoutException e) { + throw new PulsarAdminException.TimeoutException(e); + } + } + + @Override + public CompletableFuture<Boolean> getEncryptionRequiredStatusAsync(String namespace) { + NamespaceName ns = NamespaceName.get(namespace); + WebTarget path = namespacePath(ns, "encryptionRequired"); + final CompletableFuture<Boolean> future = new CompletableFuture<>(); + asyncGetRequest(path, + new InvocationCallback<Boolean>() { + @Override + public void completed(Boolean enabled) { + future.complete(enabled); + } + + @Override + public void failed(Throwable throwable) { + future.completeExceptionally(getApiException(throwable.getCause())); + } + }); + return future; + } + @Override public DelayedDeliveryPolicies getDelayedDelivery(String namespace) throws PulsarAdminException { try { 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 362e2308a60..792a85bb3d0 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 @@ -509,6 +509,9 @@ public class PulsarAdminToolTest { .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("remove-auto-topic-creation myprop/clust/ns1")); verify(mockNamespaces).removeAutoTopicCreation("myprop/clust/ns1"); @@ -516,6 +519,9 @@ public class PulsarAdminToolTest { verify(mockNamespaces).setAutoSubscriptionCreation("myprop/clust/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("remove-auto-subscription-creation myprop/clust/ns1")); verify(mockNamespaces).removeAutoSubscriptionCreation("myprop/clust/ns1"); 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 4c08bce9c04..25087cfb25e 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 @@ -235,6 +235,18 @@ public class CmdNamespaces extends CmdBase { } } + @Parameters(commandDescription = "Get permissions to access subscription admin-api") + private class SubscriptionPermissions extends CliCommand { + @Parameter(description = "tenant/namespace", required = true) + private java.util.List<String> params; + + @Override + void run() throws PulsarAdminException { + String namespace = validateNamespace(params); + print(getAdmin().namespaces().getPermissionOnSubscription(namespace)); + } + } + @Parameters(commandDescription = "Grant permissions to access subscription admin-api") private class GrantSubscriptionPermissions extends CliCommand { @Parameter(description = "tenant/namespace", required = true) @@ -586,6 +598,18 @@ public class CmdNamespaces extends CmdBase { } } + @Parameters(commandDescription = "Get autoTopicCreation info for a namespace") + private class GetAutoTopicCreation extends CliCommand { + @Parameter(description = "tenant/namespace", required = true) + private java.util.List<String> params; + + @Override + void run() throws PulsarAdminException { + String namespace = validateNamespace(params); + print(getAdmin().namespaces().getAutoTopicCreation(namespace)); + } + } + @Parameters(commandDescription = "Remove override of autoTopicCreation for a namespace") private class RemoveAutoTopicCreation extends CliCommand { @Parameter(description = "tenant/namespace", required = true) @@ -617,6 +641,18 @@ public class CmdNamespaces extends CmdBase { } } + @Parameters(commandDescription = "Get the autoSubscriptionCreation for a namespace") + private class GetAutoSubscriptionCreation extends CliCommand { + @Parameter(description = "tenant/namespace", required = true) + private java.util.List<String> params; + + @Override + void run() throws PulsarAdminException { + String namespace = validateNamespace(params); + print(getAdmin().namespaces().getAutoSubscriptionCreation(namespace)); + } + } + @Parameters(commandDescription = "Remove override of autoSubscriptionCreation for a namespace") private class RemoveAutoSubscriptionCreation extends CliCommand { @Parameter(description = "tenant/namespace", required = true) @@ -1271,6 +1307,18 @@ public class CmdNamespaces extends CmdBase { } } + @Parameters(commandDescription = "Get encryption required for a namespace") + private class GetEncryptionRequired extends CliCommand { + @Parameter(description = "tenant/namespace", required = true) + private java.util.List<String> params; + + @Override + void run() throws PulsarAdminException { + String namespace = validateNamespace(params); + print(getAdmin().namespaces().getEncryptionRequiredStatus(namespace)); + } + } + @Parameters(commandDescription = "Get the delayed delivery policy for a namespace") private class GetDelayedDelivery extends CliCommand { @Parameter(description = "tenant/namespace", required = true) @@ -1403,6 +1451,18 @@ public class CmdNamespaces extends CmdBase { } } + @Parameters(commandDescription = "Get subscriptionAuthMod for a namespace") + private class GetSubscriptionAuthMode extends CliCommand { + @Parameter(description = "tenant/namespace", required = true) + private java.util.List<String> params; + + @Override + void run() throws PulsarAdminException { + String namespace = validateNamespace(params); + print(getAdmin().namespaces().getSubscriptionAuthMode(namespace)); + } + } + @Parameters(commandDescription = "Get deduplicationSnapshotInterval for a namespace") private class GetDeduplicationSnapshotInterval extends CliCommand { @Parameter(description = "tenant/namespace", required = true) @@ -2328,6 +2388,7 @@ public class CmdNamespaces extends CmdBase { jcommander.addCommand("grant-permission", new GrantPermissions()); jcommander.addCommand("revoke-permission", new RevokePermissions()); + jcommander.addCommand("subscription-permission", new SubscriptionPermissions()); jcommander.addCommand("grant-subscription-permission", new GrantSubscriptionPermissions()); jcommander.addCommand("revoke-subscription-permission", new RevokeSubscriptionPermissions()); @@ -2367,9 +2428,11 @@ public class CmdNamespaces extends CmdBase { jcommander.addCommand("remove-deduplication", new RemoveDeduplication()); jcommander.addCommand("set-auto-topic-creation", new SetAutoTopicCreation()); + jcommander.addCommand("get-auto-topic-creation", new GetAutoTopicCreation()); jcommander.addCommand("remove-auto-topic-creation", new RemoveAutoTopicCreation()); jcommander.addCommand("set-auto-subscription-creation", new SetAutoSubscriptionCreation()); + jcommander.addCommand("get-auto-subscription-creation", new GetAutoSubscriptionCreation()); jcommander.addCommand("remove-auto-subscription-creation", new RemoveAutoSubscriptionCreation()); jcommander.addCommand("get-retention", new GetRetention()); @@ -2409,7 +2472,9 @@ public class CmdNamespaces extends CmdBase { jcommander.addCommand("unsubscribe", new Unsubscribe()); jcommander.addCommand("set-encryption-required", new SetEncryptionRequired()); + jcommander.addCommand("get-encryption-required", new GetEncryptionRequired()); jcommander.addCommand("set-subscription-auth-mode", new SetSubscriptionAuthMode()); + jcommander.addCommand("get-subscription-auth-mode", new GetSubscriptionAuthMode()); jcommander.addCommand("set-delayed-delivery", new SetDelayedDelivery()); jcommander.addCommand("get-delayed-delivery", new GetDelayedDelivery());
