use of com.yahoo.pulsar.common.policies.data.Policies in project pulsar by yahoo.
the class Namespaces method clearNamespaceBundleBacklog.
@POST
@Path("/{property}/{cluster}/{namespace}/{bundle}/clearBacklog")
@ApiOperation(value = "Clear backlog for all destinations on a namespace bundle.")
@ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @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) {
validateAdminAccessOnProperty(property);
Policies policies = getNamespacePolicies(property, cluster, namespace);
if (!cluster.equals(Namespaces.GLOBAL_CLUSTER)) {
validateClusterOwnership(cluster);
validateClusterForProperty(property, cluster);
}
NamespaceName nsName = new NamespaceName(property, cluster, namespace);
validateNamespaceBundleOwnership(nsName, policies.bundles, bundleRange, authoritative, true);
clearBacklog(nsName, bundleRange, null);
log.info("[{}] Successfully cleared backlog on namespace bundle {}/{}", clientAppId(), nsName.toString(), bundleRange);
}
use of com.yahoo.pulsar.common.policies.data.Policies in project pulsar by yahoo.
the class Namespaces method createNamespace.
@PUT
@Path("/{property}/{cluster}/{namespace}")
@ApiOperation(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(@PathParam("property") String property, @PathParam("cluster") String cluster, @PathParam("namespace") String namespace, BundlesData initialBundles) {
validateAdminAccessOnProperty(property);
validatePoliciesReadOnlyAccess();
// check is made at the time of setting replication.
if (!cluster.equals(GLOBAL_CLUSTER)) {
validateClusterForProperty(property, cluster);
}
if (!clusters().contains(cluster)) {
log.warn("[{}] Failed to create namespace. Cluster {} does not exist", clientAppId(), cluster);
throw new RestException(Status.NOT_FOUND, "Cluster does not exist");
}
try {
checkNotNull(propertiesCache().get(path("policies", property)));
} catch (NoNodeException nne) {
log.warn("[{}] Failed to create namespace. Property {} does not exist", clientAppId(), property);
throw new RestException(Status.NOT_FOUND, "Property does not exist");
} catch (RestException e) {
throw e;
} catch (Exception e) {
throw new RestException(e);
}
try {
NamedEntity.checkName(namespace);
policiesCache().invalidate(path("policies", property, cluster, namespace));
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);
}
}
zkCreateOptimistic(path("policies", property, cluster, namespace), jsonMapper().writeValueAsBytes(policies));
log.info("[{}] Created namespace {}/{}/{}", clientAppId(), property, cluster, namespace);
} catch (KeeperException.NodeExistsException e) {
log.warn("[{}] Failed to create namespace {}/{}/{} - already exists", clientAppId(), property, cluster, namespace);
throw new RestException(Status.CONFLICT, "Namespace already exists");
} catch (IllegalArgumentException e) {
log.warn("[{}] Failed to create namespace with invalid name {}", clientAppId(), property, e);
throw new RestException(Status.PRECONDITION_FAILED, "Namespace name is not valid");
} catch (Exception e) {
log.error("[{}] Failed to create namespace {}/{}/{}", clientAppId(), property, cluster, namespace, e);
throw new RestException(e);
}
}
use of com.yahoo.pulsar.common.policies.data.Policies in project pulsar by yahoo.
the class Namespaces method clearNamespaceBundleBacklogForSubscription.
@POST
@Path("/{property}/{cluster}/{namespace}/{bundle}/clearBacklog/{subscription}")
@ApiOperation(value = "Clear backlog for a given subscription on all destinations on a namespace bundle.")
@ApiResponses(value = { @ApiResponse(code = 403, message = "Don't have admin permission"), @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) {
validateAdminAccessOnProperty(property);
Policies policies = getNamespacePolicies(property, cluster, namespace);
if (!cluster.equals(Namespaces.GLOBAL_CLUSTER)) {
validateClusterOwnership(cluster);
validateClusterForProperty(property, cluster);
}
NamespaceName nsName = new NamespaceName(property, cluster, namespace);
validateNamespaceBundleOwnership(nsName, policies.bundles, bundleRange, authoritative, true);
clearBacklog(nsName, bundleRange, subscription);
log.info("[{}] Successfully cleared backlog for subscription {} on namespace bundle {}/{}", clientAppId(), subscription, nsName.toString(), bundleRange);
}
use of com.yahoo.pulsar.common.policies.data.Policies in project pulsar by yahoo.
the class AdminApiTest method namespaces.
@Test(invocationCount = 1)
public void namespaces() throws PulsarAdminException, PulsarServerException, Exception {
admin.clusters().createCluster("usw", new ClusterData());
PropertyAdmin propertyAdmin = new PropertyAdmin(Lists.newArrayList("role1", "role2"), Sets.newHashSet("use", "usw"));
admin.properties().updateProperty("prop-xyz", propertyAdmin);
assertEquals(admin.namespaces().getPolicies("prop-xyz/use/ns1").bundles, Policies.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.numBundles, 4);
assertEquals(admin.namespaces().getPolicies("prop-xyz/use/ns3").bundles.boundaries.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"), Lists.newArrayList("prop-xyz/use/ns1", "prop-xyz/use/ns2"));
assertEquals(admin.namespaces().getNamespaces("prop-xyz", "use"), Lists.newArrayList("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.
}
admin.namespaces().grantPermissionOnNamespace("prop-xyz/use/ns1", "my-role", EnumSet.allOf(AuthAction.class));
Policies policies = new Policies();
policies.auth_policies.namespace_auth.put("my-role", EnumSet.allOf(AuthAction.class));
assertEquals(admin.namespaces().getPolicies("prop-xyz/use/ns1"), policies);
assertEquals(admin.namespaces().getPermissions("prop-xyz/use/ns1"), policies.auth_policies.namespace_auth);
assertEquals(admin.namespaces().getDestinations("prop-xyz/use/ns1"), Lists.newArrayList());
admin.namespaces().revokePermissionsOnNamespace("prop-xyz/use/ns1", "my-role");
policies.auth_policies.namespace_auth.remove("my-role");
assertEquals(admin.namespaces().getPolicies("prop-xyz/use/ns1"), policies);
assertEquals(admin.namespaces().getPersistence("prop-xyz/use/ns1"), new PersistencePolicies(1, 1, 1, 0.0));
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.createProducer("persistent://prop-xyz/use/ns1/my-topic");
producer.close();
admin.persistentTopics().delete("persistent://prop-xyz/use/ns1/my-topic");
admin.namespaces().unloadNamespaceBundle("prop-xyz/use/ns1", "0x00000000_0xffffffff");
NamespaceName ns = new NamespaceName("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<NamespaceEphemeralData> 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"), Lists.newArrayList("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.createProducer("persistent://prop-xyz/use/ns2/my-topic");
producer.close();
admin.persistentTopics().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");
}
use of com.yahoo.pulsar.common.policies.data.Policies in project pulsar by yahoo.
the class PersistentTopicTest method testAtomicReplicationRemoval.
/**
* {@link PersistentReplicator.removeReplicator} doesn't remove replicator in atomic way and does in multiple step:
* 1. disconnect replicator producer
* <p>
* 2. close cursor
* <p>
* 3. remove from replicator-list.
* <p>
*
* If we try to startReplicationProducer before step-c finish then it should not avoid restarting repl-producer.
*
* @throws Exception
*/
@Test
public void testAtomicReplicationRemoval() throws Exception {
final String globalTopicName = "persistent://prop/global/ns-abc/successTopic";
String localCluster = "local";
String remoteCluster = "remote";
final ManagedLedger ledgerMock = mock(ManagedLedger.class);
doNothing().when(ledgerMock).asyncDeleteCursor(anyObject(), anyObject(), anyObject());
doReturn(new ArrayList<Object>()).when(ledgerMock).getCursors();
PersistentTopic topic = new PersistentTopic(globalTopicName, ledgerMock, brokerService);
String remoteReplicatorName = topic.replicatorPrefix + "." + remoteCluster;
ConcurrentOpenHashMap<String, PersistentReplicator> replicatorMap = topic.getReplicators();
final URL brokerUrl = new URL("http://" + pulsar.getAdvertisedAddress() + ":" + pulsar.getConfiguration().getBrokerServicePort());
PulsarClient client = PulsarClient.create(brokerUrl.toString());
ManagedCursor cursor = mock(ManagedCursorImpl.class);
doReturn(remoteCluster).when(cursor).getName();
brokerService.getReplicationClients().put(remoteCluster, client);
PersistentReplicator replicator = spy(new PersistentReplicator(topic, cursor, localCluster, remoteCluster, brokerService));
replicatorMap.put(remoteReplicatorName, replicator);
// step-1 remove replicator : it will disconnect the producer but it will wait for callback to be completed
Method removeMethod = PersistentTopic.class.getDeclaredMethod("removeReplicator", String.class);
removeMethod.setAccessible(true);
removeMethod.invoke(topic, remoteReplicatorName);
// step-2 now, policies doesn't have removed replication cluster so, it should not invoke "startProducer" of the
// replicator
when(pulsar.getConfigurationCache().policiesCache().get(AdminResource.path("policies", DestinationName.get(globalTopicName).getNamespace()))).thenReturn(Optional.of(new Policies()));
// try to start replicator again
topic.startReplProducers();
// verify: replicator.startProducer is not invoked
verify(replicator, Mockito.times(0)).startProducer();
// step-3 : complete the callback to remove replicator from the list
ArgumentCaptor<DeleteCursorCallback> captor = ArgumentCaptor.forClass(DeleteCursorCallback.class);
Mockito.verify(ledgerMock).asyncDeleteCursor(anyObject(), captor.capture(), anyObject());
DeleteCursorCallback callback = captor.getValue();
callback.deleteCursorComplete(null);
}
Aggregations