Merge "Add REST endpoint to kill a task"
This commit is contained in:
@@ -731,6 +731,39 @@ As result a link:#task-info[TaskInfo] entity is returned.
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
[[delete-task]]
|
||||||
|
=== Delete Task
|
||||||
|
--
|
||||||
|
'DELETE /config/server/tasks/link:#task-id[\{task-id\}]'
|
||||||
|
--
|
||||||
|
|
||||||
|
Kills a task from the background work queue that the Gerrit daemon
|
||||||
|
is currently performing, or will perform in the near future.
|
||||||
|
|
||||||
|
The caller must be a member of a group that is granted the
|
||||||
|
link:access-control.html#capability_kill[Kill Task] capability
|
||||||
|
or the link:access-control.html#capability_administrateServer[
|
||||||
|
Administrate Server] capability.
|
||||||
|
|
||||||
|
End-users may see a task only if they can also see the project the task
|
||||||
|
is associated with. Tasks operating on other projects, or that do not
|
||||||
|
have a specific project, are hidden.
|
||||||
|
|
||||||
|
Members of a group that is granted the
|
||||||
|
link:access-control.html#capability_viewQueue[View Queue] capability or
|
||||||
|
the link:access-control.html#capability_administrateServer[Administrate
|
||||||
|
Server] capability can see all tasks.
|
||||||
|
|
||||||
|
.Request
|
||||||
|
----
|
||||||
|
DELETE /config/server/tasks/1e688bea HTTP/1.0
|
||||||
|
----
|
||||||
|
|
||||||
|
.Response
|
||||||
|
----
|
||||||
|
HTTP/1.1 204 No Content
|
||||||
|
----
|
||||||
|
|
||||||
[[get-top-menus]]
|
[[get-top-menus]]
|
||||||
=== Get Top Menus
|
=== Get Top Menus
|
||||||
--
|
--
|
||||||
|
@@ -0,0 +1,64 @@
|
|||||||
|
// Copyright (C) 2014 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.acceptance.rest.config;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||||
|
import com.google.gerrit.acceptance.RestResponse;
|
||||||
|
import com.google.gerrit.server.config.ListTasks.TaskInfo;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class KillTaskIT extends AbstractDaemonTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void killTask() throws IOException {
|
||||||
|
RestResponse r = adminSession.get("/config/server/tasks/");
|
||||||
|
List<TaskInfo> result = newGson().fromJson(r.getReader(),
|
||||||
|
new TypeToken<List<TaskInfo>>() {}.getType());
|
||||||
|
r.consume();
|
||||||
|
int taskCount = result.size();
|
||||||
|
assertTrue(taskCount > 0);
|
||||||
|
|
||||||
|
r = adminSession.delete("/config/server/tasks/" + result.get(0).id);
|
||||||
|
assertEquals(HttpStatus.SC_NO_CONTENT, r.getStatusCode());
|
||||||
|
r.consume();
|
||||||
|
|
||||||
|
r = adminSession.get("/config/server/tasks/");
|
||||||
|
result = newGson().fromJson(r.getReader(),
|
||||||
|
new TypeToken<List<TaskInfo>>() {}.getType());
|
||||||
|
r.consume();
|
||||||
|
assertEquals(taskCount - 1, result.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void killTask_NotFound() throws IOException {
|
||||||
|
RestResponse r = adminSession.get("/config/server/tasks/");
|
||||||
|
List<TaskInfo> result = newGson().fromJson(r.getReader(),
|
||||||
|
new TypeToken<List<TaskInfo>>() {}.getType());
|
||||||
|
r.consume();
|
||||||
|
assertTrue(result.size() > 0);
|
||||||
|
|
||||||
|
r = userSession.delete("/config/server/tasks/" + result.get(0).id);
|
||||||
|
assertEquals(HttpStatus.SC_NOT_FOUND, r.getStatusCode());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (C) 2014 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package com.google.gerrit.server.config;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
|
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||||
|
import com.google.gerrit.extensions.restapi.Response;
|
||||||
|
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||||
|
import com.google.gerrit.server.config.DeleteTask.Input;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@RequiresCapability(GlobalCapability.KILL_TASK)
|
||||||
|
public class DeleteTask implements RestModifyView<TaskResource, Input> {
|
||||||
|
public static class Input {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<?> apply(TaskResource rsrc, Input input) {
|
||||||
|
rsrc.getTask().cancel(true);
|
||||||
|
return Response.none();
|
||||||
|
}
|
||||||
|
}
|
@@ -32,6 +32,7 @@ public class Module extends RestApiModule {
|
|||||||
child(CONFIG_KIND, "capabilities").to(CapabilitiesCollection.class);
|
child(CONFIG_KIND, "capabilities").to(CapabilitiesCollection.class);
|
||||||
child(CONFIG_KIND, "tasks").to(TasksCollection.class);
|
child(CONFIG_KIND, "tasks").to(TasksCollection.class);
|
||||||
get(TASK_KIND).to(GetTask.class);
|
get(TASK_KIND).to(GetTask.class);
|
||||||
|
delete(TASK_KIND).to(DeleteTask.class);
|
||||||
child(CONFIG_KIND, "top-menus").to(TopMenuCollection.class);
|
child(CONFIG_KIND, "top-menus").to(TopMenuCollection.class);
|
||||||
get(CONFIG_KIND, "version").to(GetVersion.class);
|
get(CONFIG_KIND, "version").to(GetVersion.class);
|
||||||
get(CONFIG_KIND, "preferences").to(GetPreferences.class);
|
get(CONFIG_KIND, "preferences").to(GetPreferences.class);
|
||||||
|
@@ -16,17 +16,18 @@ package com.google.gerrit.sshd.commands;
|
|||||||
|
|
||||||
import com.google.gerrit.common.data.GlobalCapability;
|
import com.google.gerrit.common.data.GlobalCapability;
|
||||||
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
import com.google.gerrit.extensions.annotations.RequiresCapability;
|
||||||
|
import com.google.gerrit.server.config.DeleteTask;
|
||||||
|
import com.google.gerrit.server.config.TaskResource;
|
||||||
import com.google.gerrit.server.git.WorkQueue;
|
import com.google.gerrit.server.git.WorkQueue;
|
||||||
import com.google.gerrit.server.git.WorkQueue.Task;
|
import com.google.gerrit.server.git.WorkQueue.Task;
|
||||||
import com.google.gerrit.server.util.IdGenerator;
|
|
||||||
import com.google.gerrit.sshd.AdminHighPriorityCommand;
|
import com.google.gerrit.sshd.AdminHighPriorityCommand;
|
||||||
import com.google.gerrit.sshd.SshCommand;
|
import com.google.gerrit.sshd.SshCommand;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import org.kohsuke.args4j.Argument;
|
import org.kohsuke.args4j.Argument;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.ArrayList;
|
||||||
import java.util.Set;
|
import java.util.List;
|
||||||
|
|
||||||
/** Kill a task in the work queue. */
|
/** Kill a task in the work queue. */
|
||||||
@AdminHighPriorityCommand
|
@AdminHighPriorityCommand
|
||||||
@@ -35,25 +36,20 @@ final class KillCommand extends SshCommand {
|
|||||||
@Inject
|
@Inject
|
||||||
private WorkQueue workQueue;
|
private WorkQueue workQueue;
|
||||||
|
|
||||||
private final Set<Integer> taskIds = new HashSet<>();
|
@Inject
|
||||||
|
private DeleteTask deleteTask;
|
||||||
|
|
||||||
@Argument(index = 0, multiValued = true, required = true, metaVar = "ID")
|
@Argument(index = 0, multiValued = true, required = true, metaVar = "ID")
|
||||||
void addTaskId(final String taskId) {
|
private final List<String> taskIds = new ArrayList<>();
|
||||||
int p = 0;
|
|
||||||
while (p < taskId.length() - 1 && taskId.charAt(p) == '0') {
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
taskIds.add((int) Long.parseLong(taskId.substring(p), 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run() {
|
protected void run() {
|
||||||
for (final Integer id : taskIds) {
|
for (String id : taskIds) {
|
||||||
final Task<?> task = workQueue.getTask(id);
|
try {
|
||||||
if (task != null) {
|
Task<?> task = workQueue.getTask((int) Long.parseLong(id, 16));
|
||||||
task.cancel(true);
|
deleteTask.apply(new TaskResource(task), null);
|
||||||
} else {
|
} catch (NumberFormatException e) {
|
||||||
stderr.print("kill: " + IdGenerator.format(id) + ": No such task\n");
|
stderr.print("kill: " + id + ": No such task\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user