Repository: metron Updated Branches: refs/heads/master ae50723a5 -> ba46fa734
METRON-982 REST STORM Support for supervisor summary (ottobackwards) closes apache/metron#607 Project: http://git-wip-us.apache.org/repos/asf/metron/repo Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/ba46fa73 Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/ba46fa73 Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/ba46fa73 Branch: refs/heads/master Commit: ba46fa734d868c78b3e75c86210d947ed7621f0e Parents: ae50723 Author: ottobackwards <ottobackwa...@gmail.com> Authored: Fri Jul 28 11:24:32 2017 -0400 Committer: otto <o...@apache.org> Committed: Fri Jul 28 11:24:32 2017 -0400 ---------------------------------------------------------------------- .../metron/rest/model/SupervisorStatus.java | 144 +++++++++++++++++++ .../metron/rest/model/SupervisorSummary.java | 53 +++++++ metron-interface/metron-rest/README.md | 6 + .../apache/metron/rest/MetronRestConstants.java | 1 + .../metron/rest/controller/StormController.java | 8 ++ .../metron/rest/service/StormStatusService.java | 3 + .../service/impl/StormStatusServiceImpl.java | 63 ++++---- .../StormControllerIntegrationTest.java | 13 ++ .../metron/rest/mock/MockStormRestTemplate.java | 11 +- 9 files changed, 274 insertions(+), 28 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metron/blob/ba46fa73/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/SupervisorStatus.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/SupervisorStatus.java b/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/SupervisorStatus.java new file mode 100644 index 0000000..a624984 --- /dev/null +++ b/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/SupervisorStatus.java @@ -0,0 +1,144 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to you 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.metron.rest.model; + +public class SupervisorStatus { + /* + /api/v1/supervisor/summary(GET) + + returns all supervisors summary + Response Fields: + Field Value Description + id String Supervisor's id + host String Supervisor's host name + upTime String Shows how long the supervisor is running + slotsTotal Integer Total number of available worker slots for this supervisor + slotsUsed Integer + Number of worker slots used on this supervisor + + Sample Response: + json + + { + "supervisors": [{ + "id":"0b879808-2a26-442b-8f7d-23101e0c3696", "host":"10.11.1.7", + "upTime":"5m 58s", "slotsTotal":4, "slotsUsed":3 + } ]} + + */ + + private String id; + private String host; + private String uptime; + private int slotsTotal; + private int slotsUsed; + + public SupervisorStatus() { + } + + /** + * Creates a new SupervisorStatus. + * + * @param id Supervisor ID + * @param host Supervisor Host + * @param upTime the uptime + * @param slotsTotal The number of slots total + * @param slotsUsed The number of slots used + */ + public SupervisorStatus(String id, String host, String upTime, int slotsTotal, int slotsUsed) { + this.id = id; + this.host = host; + this.uptime = upTime; + this.slotsTotal = slotsTotal; + this.slotsUsed = slotsUsed; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getUptime() { + return uptime; + } + + public void setUptime(String upTime) { + this.uptime = upTime; + } + + public int getSlotsTotal() { + return slotsTotal; + } + + public void setSlotsTotal(int slotsTotal) { + this.slotsTotal = slotsTotal; + } + + public int getSlotsUsed() { + return slotsUsed; + } + + public void setSlotsUsed(int slotsUsed) { + this.slotsUsed = slotsUsed; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + SupervisorStatus that = (SupervisorStatus) o; + + if (getSlotsTotal() != that.getSlotsTotal()) { + return false; + } + if (getSlotsUsed() != that.getSlotsUsed()) { + return false; + } + if (!getId().equals(that.getId())) { + return false; + } + if (!getHost().equals(that.getHost())) { + return false; + } + return getUptime().equals(that.getUptime()); + } + + @Override + public int hashCode() { + int result = id != null ? id.hashCode() : 0; + result = 31 * result + (host != null ? host.hashCode() : 0); + result = 31 * result + (uptime != null ? uptime.hashCode() : 0); + result = 31 * result + getSlotsTotal(); + result = 31 * result + getSlotsUsed(); + return result; + } +} http://git-wip-us.apache.org/repos/asf/metron/blob/ba46fa73/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/SupervisorSummary.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/SupervisorSummary.java b/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/SupervisorSummary.java new file mode 100644 index 0000000..5d6ac82 --- /dev/null +++ b/metron-interface/metron-rest-client/src/main/java/org/apache/metron/rest/model/SupervisorSummary.java @@ -0,0 +1,53 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.metron.rest.model; + +import java.util.Arrays; + +public class SupervisorSummary { + + private SupervisorStatus[] supervisors; + + public SupervisorSummary(){} + public SupervisorSummary(SupervisorStatus[] supervisors) { + this.supervisors = supervisors; + } + + public SupervisorStatus[] getSupervisors() { + return supervisors; + } + + public void setSupervisors(SupervisorStatus[] supervisors) { + this.supervisors = supervisors; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SupervisorSummary that = (SupervisorSummary) o; + + return supervisors != null ? Arrays.equals(supervisors, that.supervisors) : that.supervisors != null; + } + + @Override + public int hashCode() { + return supervisors != null ? Arrays.hashCode(supervisors) : 0; + } +} http://git-wip-us.apache.org/repos/asf/metron/blob/ba46fa73/metron-interface/metron-rest/README.md ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/README.md b/metron-interface/metron-rest/README.md index f8cafa4..add8f27 100644 --- a/metron-interface/metron-rest/README.md +++ b/metron-interface/metron-rest/README.md @@ -239,6 +239,7 @@ Request and Response objects are JSON formatted. The JSON schemas are available | [ `GET /api/v1/storm/parser/start/{name}`](#get-apiv1stormparserstartname)| | [ `GET /api/v1/storm/parser/stop/{name}`](#get-apiv1stormparserstopname)| | [ `GET /api/v1/storm/{name}`](#get-apiv1stormname)| +| [ `GET /api/v1/storm/supervisors`](#get-apiv1stormsupervisors)| | [ `GET /api/v1/user`](#get-apiv1user)| ### `GET /api/v1/global/config` @@ -602,6 +603,11 @@ Request and Response objects are JSON formatted. The JSON schemas are available * 200 - Returns topology status information * 404 - Topology is missing +### `GET /api/v1/storm/supervisors` + * Description: Retrieves the status of all Storm Supervisors + * Returns: + * 200 - Returns a list of the status of all Storm Supervisors + ### `GET /api/v1/user` * Description: Retrieves the current user * Returns: http://git-wip-us.apache.org/repos/asf/metron/blob/ba46fa73/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java index 43aaeae..9e32c7a 100644 --- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java +++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/MetronRestConstants.java @@ -34,6 +34,7 @@ public class MetronRestConstants { public static final String GROK_PATTERN_LABEL_KEY = "patternLabel"; public static final String STORM_UI_SPRING_PROPERTY = "storm.ui.url"; + public static final String SUPERVISOR_SUMMARY_URL = "/api/v1/supervisor/summary"; public static final String TOPOLOGY_SUMMARY_URL = "/api/v1/topology/summary"; public static final String TOPOLOGY_URL = "/api/v1/topology"; public static final String ENRICHMENT_TOPOLOGY_NAME = "enrichment"; http://git-wip-us.apache.org/repos/asf/metron/blob/ba46fa73/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/StormController.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/StormController.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/StormController.java index 915e304..292c668 100644 --- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/StormController.java +++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/StormController.java @@ -23,6 +23,7 @@ import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; import org.apache.metron.rest.MetronRestConstants; import org.apache.metron.rest.RestException; +import org.apache.metron.rest.model.SupervisorSummary; import org.apache.metron.rest.model.TopologyResponse; import org.apache.metron.rest.model.TopologyStatus; import org.apache.metron.rest.service.StormAdminService; @@ -49,6 +50,13 @@ public class StormController { @Autowired private StormAdminService stormAdminService; + @ApiOperation(value = "Retrieves the status of all Storm Supervisors") + @ApiResponse(message = "Returns a list of supervisors with status information", code = 200) + @RequestMapping(value = "/supervisors", method = RequestMethod.GET) + ResponseEntity<SupervisorSummary> getSupervisorSummary() throws RestException{ + return new ResponseEntity<>(stormStatusService.getSupervisorSummary(),HttpStatus.OK); + } + @ApiOperation(value = "Retrieves the status of all Storm topologies") @ApiResponse(message = "Returns a list of topologies with status information", code = 200) @RequestMapping(method = RequestMethod.GET) http://git-wip-us.apache.org/repos/asf/metron/blob/ba46fa73/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/StormStatusService.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/StormStatusService.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/StormStatusService.java index 76216d0..d44febc 100644 --- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/StormStatusService.java +++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/StormStatusService.java @@ -17,6 +17,7 @@ */ package org.apache.metron.rest.service; +import org.apache.metron.rest.model.SupervisorSummary; import org.apache.metron.rest.model.TopologyResponse; import org.apache.metron.rest.model.TopologyStatus; import org.apache.metron.rest.model.TopologySummary; @@ -25,6 +26,8 @@ import java.util.List; public interface StormStatusService { + SupervisorSummary getSupervisorSummary(); + TopologySummary getTopologySummary(); TopologyStatus getTopologyStatus(String name); http://git-wip-us.apache.org/repos/asf/metron/blob/ba46fa73/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/StormStatusServiceImpl.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/StormStatusServiceImpl.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/StormStatusServiceImpl.java index 9f89a3c..42de078 100644 --- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/StormStatusServiceImpl.java +++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/StormStatusServiceImpl.java @@ -1,22 +1,24 @@ /** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to you 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 + * 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. + * 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.metron.rest.service.impl; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.apache.metron.rest.model.SupervisorSummary; import org.apache.metron.rest.model.TopologyResponse; import org.apache.metron.rest.model.TopologyStatus; import org.apache.metron.rest.model.TopologyStatusCode; @@ -27,11 +29,8 @@ import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - import static org.apache.metron.rest.MetronRestConstants.STORM_UI_SPRING_PROPERTY; +import static org.apache.metron.rest.MetronRestConstants.SUPERVISOR_SUMMARY_URL; import static org.apache.metron.rest.MetronRestConstants.TOPOLOGY_SUMMARY_URL; import static org.apache.metron.rest.MetronRestConstants.TOPOLOGY_URL; @@ -49,8 +48,15 @@ public class StormStatusServiceImpl implements StormStatusService { } @Override + public SupervisorSummary getSupervisorSummary() { + return restTemplate + .getForObject(getStormUiProperty() + SUPERVISOR_SUMMARY_URL, SupervisorSummary.class); + } + + @Override public TopologySummary getTopologySummary() { - return restTemplate.getForObject(getStormUiProperty() + TOPOLOGY_SUMMARY_URL, TopologySummary.class); + return restTemplate + .getForObject(getStormUiProperty() + TOPOLOGY_SUMMARY_URL, TopologySummary.class); } @Override @@ -64,7 +70,8 @@ public class StormStatusServiceImpl implements StormStatusService { } } if (id != null) { - topologyResponse = restTemplate.getForObject(getStormUiProperty() + TOPOLOGY_URL + "/" + id, TopologyStatus.class); + topologyResponse = restTemplate + .getForObject(getStormUiProperty() + TOPOLOGY_URL + "/" + id, TopologyStatus.class); } return topologyResponse; } @@ -73,7 +80,9 @@ public class StormStatusServiceImpl implements StormStatusService { public List<TopologyStatus> getAllTopologyStatus() { List<TopologyStatus> topologyStatus = new ArrayList<>(); for (TopologyStatus topology : getTopologySummary().getTopologies()) { - topologyStatus.add(restTemplate.getForObject(getStormUiProperty() + TOPOLOGY_URL + "/" + topology.getId(), TopologyStatus.class)); + topologyStatus.add(restTemplate + .getForObject(getStormUiProperty() + TOPOLOGY_URL + "/" + topology.getId(), + TopologyStatus.class)); } return topologyStatus; } @@ -89,8 +98,10 @@ public class StormStatusServiceImpl implements StormStatusService { } } if (id != null) { - Map result = restTemplate.postForObject(getStormUiProperty() + TOPOLOGY_URL + "/" + id + "/activate", null, Map.class); - if("success".equals(result.get("status"))) { + Map result = restTemplate + .postForObject(getStormUiProperty() + TOPOLOGY_URL + "/" + id + "/activate", null, + Map.class); + if ("success".equals(result.get("status"))) { topologyResponse.setSuccessMessage(TopologyStatusCode.ACTIVE.toString()); } else { topologyResponse.setErrorMessage((String) result.get("status")); @@ -112,8 +123,10 @@ public class StormStatusServiceImpl implements StormStatusService { } } if (id != null) { - Map result = restTemplate.postForObject(getStormUiProperty() + TOPOLOGY_URL + "/" + id + "/deactivate", null, Map.class); - if("success".equals(result.get("status"))) { + Map result = restTemplate + .postForObject(getStormUiProperty() + TOPOLOGY_URL + "/" + id + "/deactivate", null, + Map.class); + if ("success".equals(result.get("status"))) { topologyResponse.setSuccessMessage(TopologyStatusCode.INACTIVE.toString()); } else { topologyResponse.setErrorMessage((String) result.get("status")); @@ -127,7 +140,7 @@ public class StormStatusServiceImpl implements StormStatusService { // If we don't have a protocol, choose http protected String getStormUiProperty() { String baseValue = environment.getProperty(STORM_UI_SPRING_PROPERTY); - if(!(baseValue.contains("://"))) { + if (!(baseValue.contains("://"))) { return "http://" + baseValue; } return baseValue; http://git-wip-us.apache.org/repos/asf/metron/blob/ba46fa73/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/StormControllerIntegrationTest.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/StormControllerIntegrationTest.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/StormControllerIntegrationTest.java index 111b510..5c6dd12 100644 --- a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/StormControllerIntegrationTest.java +++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/StormControllerIntegrationTest.java @@ -83,6 +83,9 @@ public class StormControllerIntegrationTest { this.mockMvc.perform(get(stormUrl)) .andExpect(status().isUnauthorized()); + this.mockMvc.perform(get(stormUrl + "/supervisors")) + .andExpect(status().isUnauthorized()); + this.mockMvc.perform(get(stormUrl + "/broTest")) .andExpect(status().isUnauthorized()); @@ -182,6 +185,16 @@ public class StormControllerIntegrationTest { .andExpect(jsonPath("$.status").value("SUCCESS")) .andExpect(jsonPath("$.message").value(TopologyStatusCode.STARTED.name())); + this.mockMvc.perform(get(stormUrl + "/supervisors").with(httpBasic(user,password))) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.parseMediaType("application/json;charset=UTF-8"))) + .andExpect(jsonPath("$.supervisors[0]").exists()) + .andExpect(jsonPath("$.supervisors[0].id").exists()) + .andExpect(jsonPath("$.supervisors[0].host").exists()) + .andExpect(jsonPath("$.supervisors[0].uptime").exists()) + .andExpect(jsonPath("$.supervisors[0].slotsTotal").exists()) + .andExpect(jsonPath("$.supervisors[0].slotsUsed").exists()); + this.mockMvc.perform(get(stormUrl + "/broTest").with(httpBasic(user,password))) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.parseMediaType("application/json;charset=UTF-8"))) http://git-wip-us.apache.org/repos/asf/metron/blob/ba46fa73/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/mock/MockStormRestTemplate.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/mock/MockStormRestTemplate.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/mock/MockStormRestTemplate.java index ebdefcd..ccf993d 100644 --- a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/mock/MockStormRestTemplate.java +++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/mock/MockStormRestTemplate.java @@ -18,9 +18,7 @@ package org.apache.metron.rest.mock; import org.apache.metron.rest.MetronRestConstants; -import org.apache.metron.rest.model.TopologyStatus; -import org.apache.metron.rest.model.TopologyStatusCode; -import org.apache.metron.rest.model.TopologySummary; +import org.apache.metron.rest.model.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.web.client.RestClientException; @@ -64,6 +62,13 @@ public class MockStormRestTemplate extends RestTemplate { } else if (url.startsWith(getStormUiProperty() + MetronRestConstants.TOPOLOGY_URL + "/")){ String name = url.substring(url.lastIndexOf('/') + 1, url.length()).replaceFirst("-id", ""); response = getTopologyStatus(name); + } else if (url.startsWith("http://" + environment.getProperty(MetronRestConstants.STORM_UI_SPRING_PROPERTY) + MetronRestConstants.SUPERVISOR_SUMMARY_URL)){ + SupervisorSummary supervisorSummary = new SupervisorSummary(); + List<SupervisorStatus> supervisorStatusList = new ArrayList<>(); + SupervisorStatus status = new SupervisorStatus("sup1","localhost","1m 2s",1,1); + supervisorStatusList.add(status); + supervisorSummary.setSupervisors(supervisorStatusList.toArray(new SupervisorStatus[1])); + response = supervisorSummary; } return response; }