Repository: aurora Updated Branches: refs/heads/master 767563ec7 -> 1fbf7732d
Add cluster state debug endpoint to Scheduler HTTP servlet. Reviewed at https://reviews.apache.org/r/59539/ Project: http://git-wip-us.apache.org/repos/asf/aurora/repo Commit: http://git-wip-us.apache.org/repos/asf/aurora/commit/1fbf7732 Tree: http://git-wip-us.apache.org/repos/asf/aurora/tree/1fbf7732 Diff: http://git-wip-us.apache.org/repos/asf/aurora/diff/1fbf7732 Branch: refs/heads/master Commit: 1fbf7732dc543b539ca9b41a0455615d540c9e86 Parents: 767563e Author: David McLaughlin <[email protected]> Authored: Wed May 24 15:07:33 2017 -0700 Committer: David McLaughlin <[email protected]> Committed: Wed May 24 15:07:33 2017 -0700 ---------------------------------------------------------------------- .../scheduler/http/JettyServerModule.java | 2 + .../org/apache/aurora/scheduler/http/State.java | 51 ++++++++++++ src/main/resources/scheduler/assets/index.html | 1 + .../apache/aurora/scheduler/http/StateTest.java | 81 ++++++++++++++++++++ 4 files changed, 135 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/aurora/blob/1fbf7732/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java b/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java index 53ebc0b..f7e72e7 100644 --- a/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java +++ b/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java @@ -206,6 +206,7 @@ public class JettyServerModule extends AbstractModule { "pendingtasks", "quotas", "slaves", + "state", "tiers", "utilization" ); @@ -227,6 +228,7 @@ public class JettyServerModule extends AbstractModule { .put(Quotas.class, "quotas") .put(Services.class, "services") .put(StructDump.class, "structdump") + .put(State.class, "state") .put(ThreadStackPrinter.class, "threads") .put(Tiers.class, "tiers") .put(TimeSeriesDataSource.class, "graphdata") http://git-wip-us.apache.org/repos/asf/aurora/blob/1fbf7732/src/main/java/org/apache/aurora/scheduler/http/State.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/aurora/scheduler/http/State.java b/src/main/java/org/apache/aurora/scheduler/http/State.java new file mode 100644 index 0000000..dc356b7 --- /dev/null +++ b/src/main/java/org/apache/aurora/scheduler/http/State.java @@ -0,0 +1,51 @@ +/** + * 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 org.apache.aurora.scheduler.http; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import com.google.common.collect.Multimap; + +import org.apache.aurora.scheduler.preemptor.ClusterState; +import org.apache.aurora.scheduler.preemptor.ClusterStateImpl; +import org.apache.aurora.scheduler.preemptor.PreemptionVictim; + +import static java.util.Objects.requireNonNull; + +import static org.apache.aurora.scheduler.http.api.GsonMessageBodyHandler.GSON; + +/** + * Servlet that exposes cluster state as JSON. + */ +@Path("/state") +public class State { + private final ClusterState clusterState; + + @Inject + State(ClusterStateImpl clusterState) { + this.clusterState = requireNonNull(clusterState); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getState() { + Multimap<String, PreemptionVictim> state = clusterState.getSlavesToActiveTasks(); + return Response.ok(GSON.toJson(state.asMap())).build(); + } +} http://git-wip-us.apache.org/repos/asf/aurora/blob/1fbf7732/src/main/resources/scheduler/assets/index.html ---------------------------------------------------------------------- diff --git a/src/main/resources/scheduler/assets/index.html b/src/main/resources/scheduler/assets/index.html index 9bd22a8..5330913 100644 --- a/src/main/resources/scheduler/assets/index.html +++ b/src/main/resources/scheduler/assets/index.html @@ -64,6 +64,7 @@ <li><a href='/offers'>/offers</a></li> <li><a href='/pendingtasks'>/pendingtasks</a></li> <li><a href='/quotas'>/quotas</a></li> + <li><a href='/state'>/state</a></li> <li><a href='/tiers'>/tiers</a></li> <li><a href='/utilization'>/utilization</a></li> </ul> http://git-wip-us.apache.org/repos/asf/aurora/blob/1fbf7732/src/test/java/org/apache/aurora/scheduler/http/StateTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/aurora/scheduler/http/StateTest.java b/src/test/java/org/apache/aurora/scheduler/http/StateTest.java new file mode 100644 index 0000000..0af8b0d --- /dev/null +++ b/src/test/java/org/apache/aurora/scheduler/http/StateTest.java @@ -0,0 +1,81 @@ +/** + * 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 org.apache.aurora.scheduler.http; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Multimap; + +import org.apache.aurora.common.testing.easymock.EasyMockTest; +import org.apache.aurora.gen.AssignedTask; +import org.apache.aurora.gen.JobKey; +import org.apache.aurora.gen.TaskConfig; +import org.apache.aurora.scheduler.preemptor.ClusterStateImpl; +import org.apache.aurora.scheduler.preemptor.PreemptionVictim; +import org.apache.aurora.scheduler.storage.entities.IAssignedTask; +import org.junit.Before; +import org.junit.Test; + +import static org.easymock.EasyMock.expect; +import static org.junit.Assert.assertEquals; + +public class StateTest extends EasyMockTest { + + private ClusterStateImpl clusterState; + private State state; + + @Before + public void setUp() { + clusterState = createMock(ClusterStateImpl.class); + state = new State(clusterState); + } + + private Multimap<String, PreemptionVictim> createState(IAssignedTask... tasks) { + ImmutableMultimap.Builder<String, PreemptionVictim> victims = ImmutableSetMultimap.builder(); + for (IAssignedTask task : tasks) { + victims.put(task.getSlaveId(), PreemptionVictim.fromTask(task)); + } + return victims.build(); + } + + private IAssignedTask makeTask(String taskId, String agentId) { + return IAssignedTask.build(new AssignedTask() + .setSlaveId(agentId) + .setSlaveHost(agentId + "-host") + .setTaskId(taskId) + .setTask(new TaskConfig().setJob(new JobKey("role", "env", "job")))); + } + + @Test + public void testJson() throws Exception { + Multimap<String, PreemptionVictim> expected = createState( + makeTask("task1", "agent1"), + makeTask("task2", "agent1"), + makeTask("task3", "agent2"), + makeTask("task4", "agent3")); + expect(clusterState.getSlavesToActiveTasks()).andReturn(expected); + control.replay(); + + JsonNode result = new ObjectMapper().readTree((String) state.getState().getEntity()); + assertEquals(ImmutableList.of("agent1", "agent2", "agent3"), + ImmutableList.copyOf(result.fieldNames())); + assertEquals(2, ((ArrayNode) result.get("agent1")).size()); + assertEquals(1, ((ArrayNode) result.get("agent2")).size()); + assertEquals(1, ((ArrayNode) result.get("agent3")).size()); + } +}
