From aee02ea884190f24409419d47eaec10fc9374622 Mon Sep 17 00:00:00 2001 From: "Captain.B" Date: Wed, 14 Apr 2021 16:34:36 +0800 Subject: [PATCH] =?UTF-8?q?refactor(=E6=80=A7=E8=83=BD=E6=B5=8B=E8=AF=95):?= =?UTF-8?q?=20=E6=8F=90=E4=BE=9B=E7=B1=BBconsul=E7=9A=84=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../metersphere/commons/utils/ShiroUtils.java | 3 + .../consul/CatalogApiController.java | 150 ++++++++++++++++++ .../io/metersphere/consul/ConsulService.java | 38 +++++ 3 files changed, 191 insertions(+) create mode 100644 backend/src/main/java/io/metersphere/consul/CatalogApiController.java create mode 100644 backend/src/main/java/io/metersphere/consul/ConsulService.java diff --git a/backend/src/main/java/io/metersphere/commons/utils/ShiroUtils.java b/backend/src/main/java/io/metersphere/commons/utils/ShiroUtils.java index 5dba7f7231..79413869ca 100644 --- a/backend/src/main/java/io/metersphere/commons/utils/ShiroUtils.java +++ b/backend/src/main/java/io/metersphere/commons/utils/ShiroUtils.java @@ -47,6 +47,9 @@ public class ShiroUtils { filterChainDefinitionMap.put("/document/**", "anon"); filterChainDefinitionMap.put("/system/theme", "anon"); + filterChainDefinitionMap.put("/v1/catalog/**", "anon"); + filterChainDefinitionMap.put("/v1/agent/**", "anon"); + filterChainDefinitionMap.put("/v1/health/**", "anon"); } public static void ignoreCsrfFilter(Map filterChainDefinitionMap) { diff --git a/backend/src/main/java/io/metersphere/consul/CatalogApiController.java b/backend/src/main/java/io/metersphere/consul/CatalogApiController.java new file mode 100644 index 0000000000..4611f83ece --- /dev/null +++ b/backend/src/main/java/io/metersphere/consul/CatalogApiController.java @@ -0,0 +1,150 @@ +package io.metersphere.consul; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import io.metersphere.controller.handler.annotation.NoResultHolder; +import org.apache.commons.lang3.RandomUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("v1") +public class CatalogApiController { + @Resource + private ConsulService consulService; + + @GetMapping("agent/self") + @NoResultHolder + public ResponseEntity self() { + + JSONObject result = JSONObject.parseObject("{\n" + + " \"Config\": {\n" + + " \"Datacenter\": \"dc1\",\n" + + " \"NodeName\": \"dade5a85b216\",\n" + + " \"NodeID\": \"6d1e33c5-c18b-8a5a-cbf2-c2314031cc25\",\n" + + " \"Revision\": \"10bb6cb3b\",\n" + + " \"Server\": true,\n" + + " \"Version\": \"1.9.4\"\n" + + " },\n" + + "}"); + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.set("X-Consul-Default-Acl-Policy", "allow"); + + return ResponseEntity.ok() + .headers(responseHeaders) + .body(result); + } + + @GetMapping("catalog/services") + @NoResultHolder + public ResponseEntity>> catalog() { + Map> activeNodes = consulService.getActiveNodes(); + HttpHeaders responseHeaders = new HttpHeaders(); + int index = RandomUtils.nextInt(1000, 20000); + responseHeaders.set("X-Consul-Default-Acl-Policy", "allow"); + responseHeaders.set("X-Consul-Effective-Consistency", "leader"); + responseHeaders.set("X-Consul-Index", index + ""); + responseHeaders.set("X-Consul-Knownleader", "true"); + responseHeaders.set("X-Consul-Lastcontact", "0"); + + // 刷新缓存 + return ResponseEntity.ok() + .headers(responseHeaders) + .body(activeNodes); + + } + + @GetMapping("health/service/{service}") + @NoResultHolder + public ResponseEntity health(@PathVariable String service) { + Map> activeNodes = consulService.getActiveNodes(); + int index = RandomUtils.nextInt(1000, 20000); + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.set("X-Consul-Default-Acl-Policy", "allow"); + responseHeaders.set("X-Consul-Index", index + ""); + responseHeaders.set("X-Consul-Knownleader", "true"); + responseHeaders.set("X-Consul-Lastcontact", "0"); + + if (!activeNodes.containsKey(service)) { + return ResponseEntity.ok() + .headers(responseHeaders) + .body(JSON.parseArray("[]")); + } + + String[] ipAndPort = service.split("-"); + String result = "[\n" + + " {\n" + + " \"Node\": {\n" + + " \"ID\": \"6d1e33c5-c18b-8a5a-cbf2-c2314031cc25\",\n" + + " \"Node\": \"dade5a85b216\",\n" + + " \"Address\": \"127.0.0.1\",\n" + + " \"Datacenter\": \"dc1\",\n" + + " \"TaggedAddresses\": {\n" + + " \"lan\": \"127.0.0.1\",\n" + + " \"lan_ipv4\": \"127.0.0.1\",\n" + + " \"wan\": \"127.0.0.1\",\n" + + " \"wan_ipv4\": \"127.0.0.1\"\n" + + " },\n" + + " \"Meta\": {\n" + + " \"consul-network-segment\": \"\"\n" + + " },\n" + + " \"CreateIndex\": 11,\n" + + " \"ModifyIndex\": 13\n" + + " },\n" + + " \"Service\": {\n" + + " \"ID\": \"" + service + "\",\n" + + " \"Service\": \"" + service + "\",\n" + + " \"Tags\": [\n" + + " \"test\"\n" + + " ],\n" + + " \"Address\": \"" + ipAndPort[0] + "\",\n" + + " \"Meta\": null,\n" + + " \"Port\": " + ipAndPort[1] + ",\n" + + " \"Weights\": {\n" + + " \"Passing\": 1,\n" + + " \"Warning\": 1\n" + + " },\n" + + " \"EnableTagOverride\": false,\n" + + " \"Proxy\": {\n" + + " \"MeshGateway\": {},\n" + + " \"Expose\": {}\n" + + " },\n" + + " \"Connect\": {},\n" + + " \"CreateIndex\": " + index + ",\n" + + " \"ModifyIndex\": " + index + "\n" + + " },\n" + + " \"Checks\": [\n" + + " {\n" + + " \"Node\": \"dade5a85b216\",\n" + + " \"CheckID\": \"serfHealth\",\n" + + " \"Name\": \"Serf Health Status\",\n" + + " \"Status\": \"passing\",\n" + + " \"Notes\": \"\",\n" + + " \"Output\": \"Agent alive and reachable\",\n" + + " \"ServiceID\": \"\",\n" + + " \"ServiceName\": \"\",\n" + + " \"ServiceTags\": [],\n" + + " \"Type\": \"\",\n" + + " \"Definition\": {},\n" + + " \"CreateIndex\": 11,\n" + + " \"ModifyIndex\": 11\n" + + " }\n" + + " ]\n" + + " }\n" + + "]"; + + + return ResponseEntity.ok() + .headers(responseHeaders) + .body(JSON.parseArray(result)); + } +} diff --git a/backend/src/main/java/io/metersphere/consul/ConsulService.java b/backend/src/main/java/io/metersphere/consul/ConsulService.java new file mode 100644 index 0000000000..696464780b --- /dev/null +++ b/backend/src/main/java/io/metersphere/consul/ConsulService.java @@ -0,0 +1,38 @@ +package io.metersphere.consul; + +import com.alibaba.fastjson.JSON; +import io.metersphere.base.domain.TestResource; +import io.metersphere.commons.constants.ResourcePoolTypeEnum; +import io.metersphere.dto.NodeDTO; +import io.metersphere.dto.TestResourcePoolDTO; +import io.metersphere.service.TestResourcePoolService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class ConsulService { + @Resource + private TestResourcePoolService testResourcePoolService; + + public Map> getActiveNodes() { + List testResourcePoolDTOS = testResourcePoolService.listValidResourcePools(); + Map> result = new HashMap<>(); + for (TestResourcePoolDTO pool : testResourcePoolDTOS) { + if (!StringUtils.equals(pool.getType(), ResourcePoolTypeEnum.NODE.name())) { + continue; + } + List resources = pool.getResources(); + for (TestResource resource : resources) { + NodeDTO node = JSON.parseObject(resource.getConfiguration(), NodeDTO.class); + result.put(node.getIp() + "-9100", Collections.singletonList("metersphere")); + } + } + return result; + } +}