mirror of https://github.com/apache/druid.git
endpoint to delete lookup tier and remove tier on last lookup deletion (#7852)
This commit is contained in:
parent
f603498e11
commit
b3328b2785
|
@ -292,7 +292,10 @@ Using the prior example, a `GET` to `/druid/coordinator/v1/lookups/config/realti
|
|||
```
|
||||
|
||||
## Delete Lookup
|
||||
A `DELETE` to `/druid/coordinator/v1/lookups/config/{tier}/{id}` will remove that lookup from the cluster.
|
||||
A `DELETE` to `/druid/coordinator/v1/lookups/config/{tier}/{id}` will remove that lookup from the cluster. If it was last lookup in the tier, then tier is deleted as well.
|
||||
|
||||
## Delete Tier
|
||||
A `DELETE` to `/druid/coordinator/v1/lookups/config/{tier}` will remove that tier from the cluster.
|
||||
|
||||
## List tier names
|
||||
A `GET` to `/druid/coordinator/v1/lookups/config` will return a list of known tier names in the dynamic configuration.
|
||||
|
|
|
@ -176,6 +176,35 @@ public class LookupCoordinatorResource
|
|||
}
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Produces({MediaType.APPLICATION_JSON, SmileMediaTypes.APPLICATION_JACKSON_SMILE})
|
||||
@Path("/config/{tier}")
|
||||
public Response deleteTier(
|
||||
@PathParam("tier") String tier,
|
||||
@HeaderParam(AuditManager.X_DRUID_AUTHOR) @DefaultValue("") final String author,
|
||||
@HeaderParam(AuditManager.X_DRUID_COMMENT) @DefaultValue("") final String comment,
|
||||
@Context HttpServletRequest req
|
||||
)
|
||||
{
|
||||
try {
|
||||
if (Strings.isNullOrEmpty(tier)) {
|
||||
return Response.status(Response.Status.BAD_REQUEST)
|
||||
.entity(ServletResourceUtils.sanitizeException(new NullPointerException("`tier` required")))
|
||||
.build();
|
||||
}
|
||||
|
||||
if (lookupCoordinatorManager.deleteTier(tier, new AuditInfo(author, comment, req.getRemoteAddr()))) {
|
||||
return Response.status(Response.Status.ACCEPTED).build();
|
||||
} else {
|
||||
return Response.status(Response.Status.NOT_FOUND).build();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e, "Error deleting tier [%s]", tier);
|
||||
return Response.serverError().entity(ServletResourceUtils.sanitizeException(e)).build();
|
||||
}
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Produces({MediaType.APPLICATION_JSON, SmileMediaTypes.APPLICATION_JACKSON_SMILE})
|
||||
@Path("/config/{tier}/{lookup}")
|
||||
|
|
|
@ -255,6 +255,27 @@ public class LookupCoordinatorManager
|
|||
return lookupMapConfigRef.get();
|
||||
}
|
||||
|
||||
public boolean deleteTier(final String tier, AuditInfo auditInfo)
|
||||
{
|
||||
Preconditions.checkState(lifecycleLock.awaitStarted(5, TimeUnit.SECONDS), "not started");
|
||||
|
||||
synchronized (this) {
|
||||
final Map<String, Map<String, LookupExtractorFactoryMapContainer>> priorSpec = getKnownLookups();
|
||||
if (priorSpec == null) {
|
||||
LOG.warn("Requested delete tier [%s]. But no lookups exist!", tier);
|
||||
return false;
|
||||
}
|
||||
final Map<String, Map<String, LookupExtractorFactoryMapContainer>> updateSpec = new HashMap<>(priorSpec);
|
||||
|
||||
if (updateSpec.remove(tier) == null) {
|
||||
LOG.warn("Requested delete of tier [%s] that does not exist!", tier);
|
||||
return false;
|
||||
}
|
||||
|
||||
return configManager.set(LOOKUP_CONFIG_KEY, updateSpec, auditInfo).isOk();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean deleteLookup(final String tier, final String lookup, AuditInfo auditInfo)
|
||||
{
|
||||
Preconditions.checkState(lifecycleLock.awaitStarted(5, TimeUnit.SECONDS), "not started");
|
||||
|
@ -279,7 +300,12 @@ public class LookupCoordinatorManager
|
|||
|
||||
final Map<String, LookupExtractorFactoryMapContainer> updateTierSpec = new HashMap<>(priorTierSpec);
|
||||
updateTierSpec.remove(lookup);
|
||||
updateSpec.put(tier, updateTierSpec);
|
||||
|
||||
if (updateTierSpec.isEmpty()) {
|
||||
updateSpec.remove(tier);
|
||||
} else {
|
||||
updateSpec.put(tier, updateTierSpec);
|
||||
}
|
||||
return configManager.set(LOOKUP_CONFIG_KEY, updateSpec, auditInfo).isOk();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -286,6 +286,48 @@ public class LookupCoordinatorResourceTest
|
|||
EasyMock.verify(lookupCoordinatorManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleDeleteTier()
|
||||
{
|
||||
final String author = "some author";
|
||||
final String comment = "some comment";
|
||||
final String ip = "127.0.0.1";
|
||||
|
||||
final HttpServletRequest request = EasyMock.createStrictMock(HttpServletRequest.class);
|
||||
EasyMock.expect(request.getRemoteAddr()).andReturn(ip).once();
|
||||
|
||||
final Capture<AuditInfo> auditInfoCapture = Capture.newInstance();
|
||||
final LookupCoordinatorManager lookupCoordinatorManager = EasyMock.createStrictMock(
|
||||
LookupCoordinatorManager.class);
|
||||
EasyMock.expect(lookupCoordinatorManager.deleteTier(
|
||||
EasyMock.eq(LOOKUP_TIER),
|
||||
EasyMock.capture(auditInfoCapture)
|
||||
)).andReturn(true).once();
|
||||
|
||||
EasyMock.replay(lookupCoordinatorManager, request);
|
||||
|
||||
final LookupCoordinatorResource lookupCoordinatorResource = new LookupCoordinatorResource(
|
||||
lookupCoordinatorManager,
|
||||
mapper,
|
||||
mapper
|
||||
);
|
||||
final Response response = lookupCoordinatorResource.deleteTier(
|
||||
LOOKUP_TIER,
|
||||
author,
|
||||
comment,
|
||||
request
|
||||
);
|
||||
|
||||
Assert.assertEquals(202, response.getStatus());
|
||||
Assert.assertTrue(auditInfoCapture.hasCaptured());
|
||||
final AuditInfo auditInfo = auditInfoCapture.getValue();
|
||||
Assert.assertEquals(author, auditInfo.getAuthor());
|
||||
Assert.assertEquals(comment, auditInfo.getComment());
|
||||
Assert.assertEquals(ip, auditInfo.getIp());
|
||||
|
||||
EasyMock.verify(lookupCoordinatorManager, request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleDelete()
|
||||
{
|
||||
|
|
|
@ -846,6 +846,52 @@ public class LookupCoordinatorManagerTest
|
|||
EasyMock.verify(configManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteTier()
|
||||
{
|
||||
final LookupExtractorFactoryMapContainer foo1 = new LookupExtractorFactoryMapContainer(
|
||||
"v0",
|
||||
ImmutableMap.of("lookup", "foo1")
|
||||
);
|
||||
|
||||
final LookupExtractorFactoryMapContainer foo2 = new LookupExtractorFactoryMapContainer(
|
||||
"v0",
|
||||
ImmutableMap.of("lookup", "foo2")
|
||||
);
|
||||
final LookupCoordinatorManager manager = new LookupCoordinatorManager(
|
||||
client,
|
||||
druidNodeDiscoveryProvider,
|
||||
mapper,
|
||||
configManager,
|
||||
lookupCoordinatorManagerConfig
|
||||
)
|
||||
{
|
||||
@Override
|
||||
public Map<String, Map<String, LookupExtractorFactoryMapContainer>> getKnownLookups()
|
||||
{
|
||||
return ImmutableMap.of(LOOKUP_TIER, ImmutableMap.of(
|
||||
"foo1", foo1,
|
||||
"foo2", foo2
|
||||
));
|
||||
}
|
||||
};
|
||||
manager.start();
|
||||
final AuditInfo auditInfo = new AuditInfo("author", "comment", "localhost");
|
||||
EasyMock.reset(configManager);
|
||||
EasyMock.expect(
|
||||
configManager.set(
|
||||
EasyMock.eq(LookupCoordinatorManager.LOOKUP_CONFIG_KEY),
|
||||
EasyMock.eq(
|
||||
ImmutableMap.<String, Map<String, LookupExtractorFactoryMapContainer>>of()
|
||||
),
|
||||
EasyMock.eq(auditInfo)
|
||||
)
|
||||
).andReturn(SetResult.ok()).once();
|
||||
EasyMock.replay(configManager);
|
||||
Assert.assertTrue(manager.deleteTier(LOOKUP_TIER, auditInfo));
|
||||
EasyMock.verify(configManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteLookup()
|
||||
{
|
||||
|
@ -896,6 +942,47 @@ public class LookupCoordinatorManagerTest
|
|||
EasyMock.verify(configManager);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeleteLastLookup()
|
||||
{
|
||||
final LookupExtractorFactoryMapContainer lookup = new LookupExtractorFactoryMapContainer(
|
||||
"v0",
|
||||
ImmutableMap.of("lookup", "foo")
|
||||
);
|
||||
final LookupCoordinatorManager manager = new LookupCoordinatorManager(
|
||||
client,
|
||||
druidNodeDiscoveryProvider,
|
||||
mapper,
|
||||
configManager,
|
||||
lookupCoordinatorManagerConfig
|
||||
)
|
||||
{
|
||||
@Override
|
||||
public Map<String, Map<String, LookupExtractorFactoryMapContainer>> getKnownLookups()
|
||||
{
|
||||
return ImmutableMap.of(LOOKUP_TIER, ImmutableMap.of(
|
||||
"foo", lookup
|
||||
));
|
||||
}
|
||||
};
|
||||
manager.start();
|
||||
final AuditInfo auditInfo = new AuditInfo("author", "comment", "localhost");
|
||||
EasyMock.reset(configManager);
|
||||
EasyMock.expect(
|
||||
configManager.set(
|
||||
EasyMock.eq(LookupCoordinatorManager.LOOKUP_CONFIG_KEY),
|
||||
EasyMock.eq(
|
||||
ImmutableMap.<String, Map<String, LookupExtractorFactoryMapContainer>>of()
|
||||
),
|
||||
EasyMock.eq(auditInfo)
|
||||
)
|
||||
).andReturn(SetResult.ok()).once();
|
||||
EasyMock.replay(configManager);
|
||||
Assert.assertTrue(manager.deleteLookup(LOOKUP_TIER, "foo", auditInfo));
|
||||
EasyMock.verify(configManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteLookupIgnoresMissing()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue