Skip to content

Commit

Permalink
Closes #980 - Extending the alerting API to reload kapacitor tasks du…
Browse files Browse the repository at this point in the history
…e to changed alerting rules (#982)
  • Loading branch information
Patrick-Eichhorn authored Feb 2, 2021
1 parent 48aa5cb commit f2bf2d0
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 125 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ public KapacitorTaskController(InspectitServerSettings settings) {
@ApiOperation(value = "Provides a list with basic information about each kapacitor task. Only tasks based on templates will be listed.")
@GetMapping("/alert/kapacitor/tasks")
public List<Task> getAllTasks() {
ObjectNode response = kapacitor()
.getForEntity("/kapacitor/v1/tasks", ObjectNode.class)
.getBody();
ObjectNode response = kapacitor().getForEntity("/kapacitor/v1/tasks", ObjectNode.class).getBody();

return StreamSupport.stream(response.path("tasks").spliterator(), false)
.map(Task::fromKapacitorResponse)
Expand All @@ -39,8 +37,7 @@ public List<Task> getAllTasks() {

@GetMapping("/alert/kapacitor/tasks/{taskId}")
public Task getTask(@PathVariable @ApiParam("The id of the task to query") String taskId) {
ObjectNode response = kapacitor()
.getForEntity("/kapacitor/v1/tasks/{taskId}", ObjectNode.class, taskId)
ObjectNode response = kapacitor().getForEntity("/kapacitor/v1/tasks/{taskId}", ObjectNode.class, taskId)
.getBody();

return Task.fromKapacitorResponse(response);
Expand All @@ -50,8 +47,7 @@ public Task getTask(@PathVariable @ApiParam("The id of the task to query") Strin
@ApiOperation(value = "Inserts a new Kapacitor task")
@PostMapping("/alert/kapacitor/tasks")
public Task addTask(@RequestBody Task task) {
ObjectNode response = kapacitor()
.postForEntity("/kapacitor/v1/tasks", task.toKapacitorRequest(), ObjectNode.class)
ObjectNode response = kapacitor().postForEntity("/kapacitor/v1/tasks", task.toKapacitorRequest(), ObjectNode.class)
.getBody();

return Task.fromKapacitorResponse(response);
Expand All @@ -60,10 +56,9 @@ public Task addTask(@RequestBody Task task) {
@Secured(UserRoleConfiguration.WRITE_ACCESS_ROLE)
@ApiOperation(value = "Updates one or more settings of a kapacitor task")
@PatchMapping("/alert/kapacitor/tasks/{taskId}")
public Task updateTask(@PathVariable @ApiParam("The id of the task to update") String taskId,
@RequestBody Task task) {
ObjectNode response = kapacitor()
.patchForObject("/kapacitor/v1/tasks/{taskId}", task.toKapacitorRequest(), ObjectNode.class, taskId);
public Task updateTask(@PathVariable @ApiParam("The id of the task to update") String taskId, @RequestBody Task task) {
ObjectNode response = kapacitor().patchForObject("/kapacitor/v1/tasks/{taskId}", task.toKapacitorRequest(), ObjectNode.class, taskId);
triggerTaskReload(task);

return Task.fromKapacitorResponse(response);
}
Expand All @@ -75,4 +70,17 @@ public void removeTask(@PathVariable @ApiParam("The id of the task to delete") S
kapacitorRestTemplate.delete("/kapacitor/v1/tasks/{taskId}", taskId);
}

/**
* Required to reload kapacitor tasks during runtime.
* A task cannot be reloaded and just doing patch request against the template API - without changing it -
* triggers kapacitor to reload the previously changed task.
* Note that all tasks created from this template will be reloaded.
*
* @param task kapacitor task
*/
private void triggerTaskReload(Task task) {
String taskTemplateId = task.getTemplate();
kapacitor().patchForObject("/kapacitor/v1/templates/{templateID}", task.toKapacitorRequestTemplateUpdate(), ObjectNode.class, taskTemplateId);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
@NoArgsConstructor
public class Task {

private static final ObjectMapper mapper = new ObjectMapper();

String id;

/**
Expand Down Expand Up @@ -64,7 +66,6 @@ public class Task {
* @return a JSON-Object which can be used for adding or updating this task in POST/PATCH request to kapacitor
*/
public ObjectNode toKapacitorRequest() {
ObjectMapper mapper = new ObjectMapper();
ObjectNode result = mapper.createObjectNode();
ObjectNode varsNode = mapper.createObjectNode();
if (id != null) {
Expand Down Expand Up @@ -108,6 +109,17 @@ public ObjectNode toKapacitorRequest() {

}

/**
* @return a JSON-Object which can be used for updating the template in PATCH request to kapacitor
*/
public ObjectNode toKapacitorRequestTemplateUpdate() {
ObjectNode result = mapper.createObjectNode();
result.put("id", template);

return result;

}

public static Task fromKapacitorResponse(JsonNode task) {
Task.TaskBuilder builder = Task.builder()
.id(task.path("id").asText())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,32 +47,27 @@ void tasksListedCorrectly() {
assertThat(task.getTemplate()).isEqualTo("my_template");
assertThat(task.getDescription()).isNull();
assertThat(task.getTopic()).isNull();
assertThat(task.getVars()).containsExactlyInAnyOrder(
TemplateVariable.builder()
.name("some_string")
.type("string")
.value("test")
.description("")
.build(),
TemplateVariable.builder()
.name("some_float")
.type("float")
.value(4242.0)
.description("")
.build(),
TemplateVariable.builder()
.name("some_int")
.type("int")
.value(42.0)
.description("")
.build(),
TemplateVariable.builder()
.name("some_dur")
.type("duration")
.value("2h")
.description("")
.build()
);
assertThat(task.getVars()).containsExactlyInAnyOrder(TemplateVariable.builder()
.name("some_string")
.type("string")
.value("test")
.description("")
.build(), TemplateVariable.builder()
.name("some_float")
.type("float")
.value(4242.0)
.description("")
.build(), TemplateVariable.builder()
.name("some_int")
.type("int")
.value(42.0)
.description("")
.build(), TemplateVariable.builder()
.name("some_dur")
.type("duration")
.value("2h")
.description("")
.build());

});
assertThat(result).anySatisfy(task -> {
Expand All @@ -86,14 +81,12 @@ void tasksListedCorrectly() {
assertThat(task.getTemplate()).isEqualTo("some_template");
assertThat(task.getDescription()).isEqualTo("My task description");
assertThat(task.getTopic()).isEqualTo("my_topic");
assertThat(task.getVars()).containsExactlyInAnyOrder(
TemplateVariable.builder()
.name("some_string")
.type("string")
.value("test")
.description("")
.build()
);
assertThat(task.getVars()).containsExactlyInAnyOrder(TemplateVariable.builder()
.name("some_string")
.type("string")
.value("test")
.description("")
.build());

});

Expand Down Expand Up @@ -122,14 +115,12 @@ void conflictingTemplateDefinitions() {
assertThat(task.getTemplate()).isEqualTo("other_template");
assertThat(task.getDescription()).isEqualTo("My task description");
assertThat(task.getTopic()).isEqualTo("my_topic");
assertThat(task.getVars()).containsExactlyInAnyOrder(
TemplateVariable.builder()
.name("some_string")
.type("string")
.value("test")
.description("")
.build()
);
assertThat(task.getVars()).containsExactlyInAnyOrder(TemplateVariable.builder()
.name("some_string")
.type("string")
.value("test")
.description("")
.build());

mockKapacitor.verify();
}
Expand All @@ -140,20 +131,11 @@ class AddTasks {

@Test
void addWithTemplate() {
Task toAdd = Task.builder()
.id("my_task")
.template("blub")
.build();
Task toAdd = Task.builder().id("my_task").template("blub").build();

mockKapacitor.expect(requestTo("/kapacitor/v1/tasks"))
.andExpect(method(HttpMethod.POST))
.andExpect(content().json(
"{" +
"\"id\" : \"my_task\"," +
"\"template-id\" : \"blub\"," +
"\"vars\" : { \"inspectit_template_reference\" : {\"type\" : \"string\", \"value\" : \"blub\"} }" +
"}"
, true))
.andExpect(content().json("{" + "\"id\" : \"my_task\"," + "\"template-id\" : \"blub\"," + "\"vars\" : { \"inspectit_template_reference\" : {\"type\" : \"string\", \"value\" : \"blub\"} }" + "}", true))
.andRespond(withSuccess(getTestJson("tasks_conflicting_template.json"), MediaType.APPLICATION_JSON));

Task result = controller.addTask(toAdd);
Expand All @@ -177,15 +159,7 @@ void addWithDescriptionAndVariable() {

mockKapacitor.expect(requestTo("/kapacitor/v1/tasks"))
.andExpect(method(HttpMethod.POST))
.andExpect(content().json(
"{" +
"\"id\" : \"my_task\"," +
"\"vars\" : { " +
"\"inspectit_template_description\" : {\"type\" : \"string\", \"value\" : \"blub\"}, " +
"\"my_dur\" : {\"type\" : \"duration\", \"value\" : 7000000000} " +
"}" +
"}"
, true))
.andExpect(content().json("{" + "\"id\" : \"my_task\"," + "\"vars\" : { " + "\"inspectit_template_description\" : {\"type\" : \"string\", \"value\" : \"blub\"}, " + "\"my_dur\" : {\"type\" : \"duration\", \"value\" : 7000000000} " + "}" + "}", true))
.andRespond(withSuccess(getTestJson("tasks_conflicting_template.json"), MediaType.APPLICATION_JSON));

Task result = controller.addTask(toAdd);
Expand All @@ -197,23 +171,11 @@ void addWithDescriptionAndVariable() {

@Test
void addWithTopicAndStatus() {
Task toAdd = Task.builder()
.id("my_task")
.topic("blub")
.status("disabled")
.build();
Task toAdd = Task.builder().id("my_task").topic("blub").status("disabled").build();

mockKapacitor.expect(requestTo("/kapacitor/v1/tasks"))
.andExpect(method(HttpMethod.POST))
.andExpect(content().json(
"{" +
"\"id\" : \"my_task\"," +
"\"status\" : \"disabled\"," +
"\"vars\" : { " +
"\"topic\" : {\"type\" : \"string\", \"value\" : \"blub\"} " +
"}" +
"}"
, true))
.andExpect(content().json("{" + "\"id\" : \"my_task\"," + "\"status\" : \"disabled\"," + "\"vars\" : { " + "\"topic\" : {\"type\" : \"string\", \"value\" : \"blub\"} " + "}" + "}", true))
.andRespond(withSuccess(getTestJson("tasks_conflicting_template.json"), MediaType.APPLICATION_JSON));

Task result = controller.addTask(toAdd);
Expand All @@ -228,17 +190,16 @@ class UpdateTasks {

@Test
void changeId() {
Task toAdd = Task.builder()
.id("new_id")
.build();
Task toAdd = Task.builder().id("new_id").build();

mockKapacitor.expect(requestTo("/kapacitor/v1/tasks/my_task"))
.andExpect(method(HttpMethod.PATCH))
.andExpect(content().json(
"{" +
"\"id\" : \"new_id\"" +
"}"
, true))
.andExpect(content().json("{" + "\"id\" : \"new_id\"" + "}", true))
.andRespond(withSuccess(getTestJson("tasks_conflicting_template.json"), MediaType.APPLICATION_JSON));

mockKapacitor.expect(requestTo("/kapacitor/v1/templates/"))
.andExpect(content().json("{}"))
.andExpect(method(HttpMethod.PATCH))
.andRespond(withSuccess(getTestJson("tasks_conflicting_template.json"), MediaType.APPLICATION_JSON));

Task result = controller.updateTask("my_task", toAdd);
Expand All @@ -249,18 +210,16 @@ void changeId() {

@Test
void changeTemplate() {
Task toAdd = Task.builder()
.template("blub")
.build();
Task toAdd = Task.builder().template("blub").build();

mockKapacitor.expect(requestTo("/kapacitor/v1/tasks/my_task"))
.andExpect(method(HttpMethod.PATCH))
.andExpect(content().json(
"{" +
"\"template-id\" : \"blub\"," +
"\"vars\" : { \"inspectit_template_reference\" : {\"type\" : \"string\", \"value\" : \"blub\"} }" +
"}"
, true))
.andExpect(content().json("{" + "\"template-id\" : \"blub\"," + "\"vars\" : { \"inspectit_template_reference\" : {\"type\" : \"string\", \"value\" : \"blub\"} }" + "}", true))
.andRespond(withSuccess(getTestJson("tasks_conflicting_template.json"), MediaType.APPLICATION_JSON));

mockKapacitor.expect(requestTo("/kapacitor/v1/templates/blub"))
.andExpect(content().json("{" + "\"id\" : \"blub\"}"))
.andExpect(method(HttpMethod.PATCH))
.andRespond(withSuccess(getTestJson("tasks_conflicting_template.json"), MediaType.APPLICATION_JSON));

Task result = controller.updateTask("my_task", toAdd);
Expand All @@ -282,14 +241,12 @@ void changeDescriptionAndVariable() {

mockKapacitor.expect(requestTo("/kapacitor/v1/tasks/my_task"))
.andExpect(method(HttpMethod.PATCH))
.andExpect(content().json(
"{" +
"\"vars\" : { " +
"\"inspectit_template_description\" : {\"type\" : \"string\", \"value\" : \"blub\"}, " +
"\"my_dur\" : {\"type\" : \"duration\", \"value\" : 7000000000} " +
"}" +
"}"
, true))
.andExpect(content().json("{" + "\"vars\" : { " + "\"inspectit_template_description\" : {\"type\" : \"string\", \"value\" : \"blub\"}, " + "\"my_dur\" : {\"type\" : \"duration\", \"value\" : 7000000000} " + "}" + "}", true))
.andRespond(withSuccess(getTestJson("tasks_conflicting_template.json"), MediaType.APPLICATION_JSON));

mockKapacitor.expect(requestTo("/kapacitor/v1/templates/"))
.andExpect(content().json("{}"))
.andExpect(method(HttpMethod.PATCH))
.andRespond(withSuccess(getTestJson("tasks_conflicting_template.json"), MediaType.APPLICATION_JSON));

Task result = controller.updateTask("my_task", toAdd);
Expand All @@ -300,21 +257,16 @@ void changeDescriptionAndVariable() {

@Test
void changeTopicAndStatus() {
Task toAdd = Task.builder()
.topic("blub")
.status("disabled")
.build();
Task toAdd = Task.builder().topic("blub").status("disabled").build();

mockKapacitor.expect(requestTo("/kapacitor/v1/tasks/my_task"))
.andExpect(method(HttpMethod.PATCH))
.andExpect(content().json(
"{" +
"\"status\" : \"disabled\"," +
"\"vars\" : { " +
"\"topic\" : {\"type\" : \"string\", \"value\" : \"blub\"} " +
"}" +
"}"
, true))
.andExpect(content().json("{" + "\"status\" : \"disabled\"," + "\"vars\" : { " + "\"topic\" : {\"type\" : \"string\", \"value\" : \"blub\"} " + "}" + "}", true))
.andRespond(withSuccess(getTestJson("tasks_conflicting_template.json"), MediaType.APPLICATION_JSON));

mockKapacitor.expect(requestTo("/kapacitor/v1/templates/"))
.andExpect(content().json("{}"))
.andExpect(method(HttpMethod.PATCH))
.andRespond(withSuccess(getTestJson("tasks_conflicting_template.json"), MediaType.APPLICATION_JSON));

Task result = controller.updateTask("my_task", toAdd);
Expand Down

0 comments on commit f2bf2d0

Please sign in to comment.