aboutsummaryrefslogtreecommitdiffstats
path: root/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/ServiceFilter.java
diff options
context:
space:
mode:
Diffstat (limited to 'apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/ServiceFilter.java')
-rw-r--r--apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/ServiceFilter.java515
1 files changed, 515 insertions, 0 deletions
diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/ServiceFilter.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/ServiceFilter.java
new file mode 100644
index 0000000..49b7b49
--- /dev/null
+++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/ServiceFilter.java
@@ -0,0 +1,515 @@
+package org.onap.msb.apiroute.wrapper.util;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang3.StringUtils;
+import org.onap.msb.apiroute.api.MicroServiceFullInfo;
+import org.onap.msb.apiroute.api.Node;
+import org.onap.msb.apiroute.wrapper.consulextend.model.health.Service;
+import org.onap.msb.apiroute.wrapper.consulextend.model.health.ServiceHealth;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.orbitz.consul.model.health.HealthCheck;
+
+
+
+public class ServiceFilter {
+ private static ServiceFilter instance = new ServiceFilter();
+
+ private ServiceFilter() {}
+
+ public static ServiceFilter getInstance() {
+ return instance;
+ }
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ServiceFilter.class);
+
+
+ /**
+ * Determine whether the service needs to send a notification TODO: filter according to the
+ * agreement, the only notice of agreement for REST \HTTP\ UI interface MSB - REST
+ *
+ * @param protocol
+ * @return
+ */
+ public boolean isNeedNotifyByProtocol(String protocol) {
+ return CommonUtil.contain(RouteUtil.FILTER_PROTOCOLS, protocol.trim());
+ }
+
+ /**
+ * Determine whether the service needs to send a notification TODO: according to the visual range
+ * filter conditions Regular language: all 、 default 、 !default 、 A、 |A 、 A|B、 !A&!B
+ *
+ * @param visualRange
+ * @return
+ */
+ public boolean isNeedNotifyByNameSpace(String nameSpace) {
+
+ String namespaceMatches = ConfigUtil.getInstance().getNamespaceMatches();
+ String[] namespaceArray = StringUtils.split(namespaceMatches, "|");
+
+ if (CommonUtil.contain(namespaceArray, "all")) {
+ return true;
+ }
+
+ if (CommonUtil.contain(namespaceArray, "default")) {
+ if (StringUtils.isEmpty(nameSpace) || "default".equals(nameSpace) ) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ if (CommonUtil.contain(namespaceArray, "!default")) {
+ if (StringUtils.isNotEmpty(nameSpace) && !"default".equals(nameSpace)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ try {
+ String namespaceReg;
+ if (namespaceMatches.contains("!")) {
+ namespaceReg = "^" + namespaceMatches.replaceAll("!", "").replaceAll("&", "|") + "$";
+ return !Pattern.matches(namespaceReg, nameSpace);
+ } else {
+ namespaceReg = "^" + namespaceMatches + "$";
+ return Pattern.matches(namespaceReg, nameSpace);
+ }
+
+ } catch (Exception e) {
+ LOGGER.error(" Regular " + namespaceMatches + " throw exception:" + e.getMessage());
+ return false;
+ }
+ }
+
+ public boolean isNeedNotifyByVisualRange(String visualRange) {
+
+ String[] routeVisualRangeArray =
+ StringUtils.split(ConfigUtil.getInstance().getVisualRangeMatches(), "|");
+
+ String[] serviceVisualRangeArray = StringUtils.split(visualRange, "|");
+
+ if (CommonUtil.contain(serviceVisualRangeArray, routeVisualRangeArray)) {
+ return true;
+ }
+
+ return false;
+
+ }
+
+ public boolean isNeedNotifyByNetwork_plane_typeMatches(String network_plane_type) {
+
+ String network_plane_typeMatches = ConfigUtil.getInstance().getNetwork_plane_typeMatches();
+ if (StringUtils.isBlank(network_plane_typeMatches))
+ return true;
+
+ String[] routeNetwork_plane_typeArray = StringUtils.split(network_plane_typeMatches, "|");
+
+ String[] serviceVisualRangeArray = StringUtils.split(network_plane_type, "|");
+
+ if (CommonUtil.contain(serviceVisualRangeArray, routeNetwork_plane_typeArray)) {
+ return true;
+ }
+
+ return false;
+
+ }
+
+ /**
+ * Determine whether the service needs to send a notification TODO: according to the visual range
+ * filter conditions
+ *
+ * @param visualRange
+ * @return
+ */
+ public boolean isNeedNotifyByRouteLabels(Map<String, String> labelMap) {
+
+ Map<String, String> labelMapMatches = ConfigUtil.getInstance().getLabelMapMatches();
+
+ if (labelMapMatches == null || labelMapMatches.isEmpty()) {
+ return true;
+ }
+
+ for (Map.Entry<String, String> entry : labelMapMatches.entrySet()) {
+ String key = entry.getKey();
+ String value = entry.getValue();
+
+ // Multiple values match
+
+ if (StringUtils.isBlank(labelMap.get(key))) {
+ continue;
+ }
+
+ String[] routeLalelsArray = StringUtils.split(value, "|");
+
+ String[] serviceLabelsArray = StringUtils.split(labelMap.get(key), "|");
+
+ if (CommonUtil.contain(routeLalelsArray, serviceLabelsArray)) {
+ return true;
+ }
+
+ }
+
+ return false;
+ }
+
+
+
+ /*
+ * public boolean isNeedNotifyByRoute(String protocol, String namespace, String visualRange,
+ * String network_plane_type, Map<String, String> labelMap) {
+ *
+ * return isNeedNotifyByProtocol(protocol) && isNeedNotifyByNameSpace(namespace) &&
+ * isNeedNotifyByVisualRange(visualRange) && isNeedNotifyByRouteLabels(labelMap) &&
+ * isNeedNotifyByNetwork_plane_typeMatches(network_plane_type);
+ *
+ * }
+ */
+
+ public boolean isFilterCheck(ServiceHealth health){
+ return isFilterHealthCheck(health.getChecks()) && isFilterService(health.getService().getTags());
+ }
+
+ /**
+ * @Title isFilterHealthCheck
+ * @Description TODO(判断服务实例的健康检查信息,全部为passing表示健康检查有效)
+ * @param List<HealthCheck>
+ * @return boolean checkList示例——"Checks" : [{
+ "Node" : "server",
+ "CheckID" : "serfHealth",
+ "Name" : "Serf Health Status",
+ "Status" : "passing",
+ "Notes" : "",
+ "Output" : "Agent alive and reachable",
+ "ServiceID" : "",
+ "ServiceName" : "",
+ "CreateIndex" : 65536,
+ "ModifyIndex" : 65536
+ }, {
+ "Node" : "server",
+ "CheckID" : "service:_tcp_roundrobin_1_10.74.151.26_22",
+ "Name" : "Service 'tcp_roundrobin_1' check",
+ "Status" : "critical",
+ "Notes" : "",
+ "Output" : "dial tcp: missing port in address ok",
+ "ServiceID" : "_tcp_roundrobin_1_10.74.151.26_22",
+ "ServiceName" : "tcp_roundrobin_1",
+ "CreateIndex" : 75988,
+ "ModifyIndex" : 76173
+ }
+ ]
+ */
+ public boolean isFilterHealthCheck(List<HealthCheck> checkList){
+ if(checkList.isEmpty()){
+ return true;
+ }
+
+ for (HealthCheck check : checkList) {
+ if (!RouteUtil.HEALTH_CHECK_PASSING.equals(check.getStatus())) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+
+ /**
+ * @Title isFilterService
+ * @Description TODO(判断来自consul的服务信息是否需要过滤)
+ * @param List<String>
+ * @return boolean tagList示例—— [
+ * "\"base\":{\"protocol\":\"REST\",\"is_manual\":\"true\",\"version\":\"v1\",\"url\":\"/api/msbtest/v1\"}"
+ * , "\"ns\":{\"namespace\":\"nsName\"}",
+ * "\"labels\":{\"visualRange\":\"0\",\"network_plane_type\":\"net\",\"customLabel\":\"custom\"}"
+ * ]
+ */
+ @SuppressWarnings("unchecked")
+ public boolean isFilterService(List<String> tagList) {
+
+ if (tagList == null || tagList.size() == 0)
+ return false;
+
+ String visualRange = "", network_plane_type = "", protocol = "", namespace = "";
+
+ //针对多版本不同属性的tag会有多个,只要其中一个匹配即通过过滤,默认不通过
+ boolean visualRangeFilter=false,protocolFilter = false, namespaceFilter = false;
+ boolean hasnamespace=false;
+
+ try {
+
+ for (String tag : tagList) {
+
+ // 提取基础属性tag
+ if (!protocolFilter && tag.startsWith("\"base\"")) {
+ String ms_base_json = tag.split("\"base\":")[1];
+
+ Map<String, String> baseMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_base_json, Map.class);
+
+ if (baseMap.get("protocol") != null) {
+ protocol = baseMap.get("protocol");
+ if ("PORTAL".equalsIgnoreCase(protocol)) {
+ protocol = "HTTP";
+ }
+
+ if (isNeedNotifyByProtocol(protocol)) {
+ protocolFilter=true;
+ }
+
+ }
+
+
+
+ continue;
+ }
+
+ // 提取命名空间属性tag
+ if (!namespaceFilter && tag.startsWith("\"ns\"")) {
+ String ms_ns_json = tag.split("\"ns\":")[1];
+ Map<String, String> nsMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_ns_json, Map.class);
+
+ if (nsMap.get("namespace") != null) {
+ namespace = nsMap.get("namespace");
+ hasnamespace=true;
+
+ if (isNeedNotifyByNameSpace(namespace)) {
+ namespaceFilter=true;
+ }
+ }
+
+
+ continue;
+ }
+
+ // 提取Label属性tag
+ if (tag.startsWith("\"labels\"")) {
+ String ms_labels_json = "{" + tag.split("\"labels\":\\{")[1];
+ // 自定义label标签属性
+ Map<String, String> labelMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_labels_json, Map.class);
+
+
+
+ if (!visualRangeFilter && labelMap.get("visualRange") != null) {
+ visualRange = labelMap.get("visualRange");
+ labelMap.remove("visualRange"); // 自定义标签排除可见范围和网络平面
+
+ if(isNeedNotifyByVisualRange(visualRange)){
+ visualRangeFilter=true;
+ }
+ }
+
+
+ if (labelMap.get("network_plane_type") != null) {
+ network_plane_type = labelMap.get("network_plane_type");
+ labelMap.remove("network_plane_type");
+ }
+ if (!isNeedNotifyByNetwork_plane_typeMatches(network_plane_type)) {
+ return false;
+ }
+
+ if (!isNeedNotifyByRouteLabels(labelMap)) {
+ return false;
+ }
+
+ continue;
+ }
+
+ }
+
+ //针对无命名空间的服务判断是否过滤
+ if (!hasnamespace && isNeedNotifyByNameSpace(namespace)) {
+ namespaceFilter=true;
+ }
+
+ return visualRangeFilter && protocolFilter && namespaceFilter;
+
+
+ } catch (Exception e) {
+ LOGGER.error(" read tag throw exception", e);
+ return false;
+ }
+
+
+ }
+
+
+
+ @SuppressWarnings("unchecked")
+ public Map<String, MicroServiceFullInfo> transMicroServiceInfoFromConsul(
+ List<ServiceHealth> serviceNodeList) {
+ // 同名多版本服务MAP
+ Map<String, MicroServiceFullInfo> microServiceInfo4version =
+ new HashMap<String, MicroServiceFullInfo>();
+
+
+ for (ServiceHealth serviceNode : serviceNodeList) {
+
+ MicroServiceFullInfo microServiceInfo = new MicroServiceFullInfo();
+ String url = "";
+ String version = "", visualRange = "", protocol = "", lb_policy = "", namespace =
+ "", host = "", path = "", publish_port = "";
+ boolean enable_ssl = false;
+
+ HashSet<Node> nodes = new HashSet<Node>();
+
+ Service service = serviceNode.getService();
+ String serviceName = service.getService();
+
+ try {
+ List<String> tagList = service.getTags();
+
+ for (String tag : tagList) {
+
+ if (tag.startsWith("\"base\"")) {
+ String ms_base_json = tag.split("\"base\":")[1];
+
+
+ Map<String, String> baseMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_base_json, Map.class);
+ if (baseMap.get("url") != null) {
+ url = baseMap.get("url");
+ }
+
+ if (baseMap.get("version") != null) {
+ version = baseMap.get("version");
+ }
+
+ if (baseMap.get("protocol") != null) {
+ protocol = baseMap.get("protocol");
+ }
+
+ if (baseMap.get("host") != null) {
+ host = baseMap.get("host");
+ }
+
+ if (baseMap.get("path") != null) {
+ path = baseMap.get("path");
+ }
+
+ if (baseMap.get("publish_port") != null) {
+ publish_port = baseMap.get("publish_port");
+ }
+
+
+ if (baseMap.get("enable_ssl") != null) {
+ enable_ssl = Boolean.valueOf(baseMap.get("enable_ssl"));
+ }
+
+ continue;
+ }
+
+
+
+ if (tag.startsWith("\"ns\"")) {
+ String ms_ns_json = tag.split("\"ns\":")[1];
+ Map<String, String> nsMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_ns_json, Map.class);
+
+ if (nsMap.get("namespace") != null) {
+ namespace = nsMap.get("namespace");
+ }
+
+ continue;
+ }
+
+ if (tag.startsWith("\"labels\"")) {
+ String ms_labels_json = "{" + tag.split("\"labels\":\\{")[1];
+ Map<String, String> labelMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_labels_json, Map.class);
+
+
+ if (labelMap.get("visualRange") != null) {
+ visualRange = labelMap.get("visualRange");
+ }
+
+ /*if (labelMap.get("network_plane_type") != null) {
+ network_plane_type = labelMap.get("network_plane_type");
+ }*/
+
+ continue;
+ }
+
+ if (tag.startsWith("\"lb\"")) {
+ String ms_lb_json = tag.split("\"lb\":")[1];
+ Map<String, String> lbMap =
+ (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_lb_json, Map.class);
+
+ if (lbMap.get("lb_policy") != null) {
+ lb_policy = lbMap.get("lb_policy");
+ }
+ continue;
+ }
+
+ }
+
+
+
+ } catch (Exception e) {
+ LOGGER.error(serviceName + " read tag throw exception", e);
+ }
+
+ if (!microServiceInfo4version.containsKey(version)) {
+
+ if ("PORTAL".equalsIgnoreCase(protocol)) {
+ protocol = "HTTP";
+ microServiceInfo.setCustom(RouteUtil.CUSTOM_PORTAL);
+ }
+
+ microServiceInfo.setProtocol(protocol);
+ microServiceInfo.setUrl(url);
+ microServiceInfo.setServiceName(serviceName);
+ microServiceInfo.setLb_policy(lb_policy);
+ microServiceInfo.setVisualRange(visualRange);
+
+ microServiceInfo.setEnable_ssl(enable_ssl);
+ microServiceInfo.setVersion(version);
+ microServiceInfo.setNamespace(namespace);
+ microServiceInfo.setHost(host);
+ microServiceInfo.setPath(path);
+ //系统间apigateway 保存publish_port
+ if ("0".equals(ConfigUtil.getInstance().getVisualRangeMatches())) {
+ microServiceInfo.setPublish_port(publish_port);
+ }
+
+ nodes.add(new Node(service.getAddress(), String.valueOf(service.getPort())));
+ microServiceInfo.setNodes(nodes);
+
+ microServiceInfo4version.put(version, microServiceInfo);
+ } else {
+
+ Set<Node> newNodes = microServiceInfo4version.get(version).getNodes();
+ // 默认node是注册信息的IP和port
+ newNodes.add(new Node(service.getAddress(), String.valueOf(service.getPort())));
+
+ // 同名多版本同步
+ microServiceInfo4version.get(version).setNodes(newNodes);
+
+ }
+
+
+ /*
+ * // 健康检查信息 List<Check> checks = value.getChecks(); node.setStatus("passing"); for (Check
+ * check : checks) { if (!"passing".equals(check.getStatus())) {
+ * node.setStatus(check.getStatus()); break; } }
+ */
+
+
+
+ }
+
+ return microServiceInfo4version;
+
+ }
+
+}