1 /*******************************************************************************
2 * Copyright 2016-2017 ZTE, Inc. and others.
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
13 ******************************************************************************/
14 package org.onap.msb.apiroute.wrapper.util;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.List;
21 import java.util.regex.Pattern;
23 import org.apache.commons.lang3.StringUtils;
24 import org.onap.msb.apiroute.api.MicroServiceFullInfo;
25 import org.onap.msb.apiroute.api.Node;
26 import org.onap.msb.apiroute.wrapper.consulextend.model.health.Service;
27 import org.onap.msb.apiroute.wrapper.consulextend.model.health.ServiceHealth;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
31 import com.orbitz.consul.model.health.HealthCheck;
35 public class ServiceFilter {
36 private static ServiceFilter instance = new ServiceFilter();
38 private ServiceFilter() {}
40 public static ServiceFilter getInstance() {
44 private static final Logger LOGGER = LoggerFactory.getLogger(ServiceFilter.class);
48 * Determine whether the service needs to send a notification TODO: filter according to the
49 * agreement, the only notice of agreement for REST \HTTP\ UI interface MSB - REST
54 public boolean isNeedNotifyByProtocol(String protocol) {
55 return CommonUtil.contain(RouteUtil.FILTER_PROTOCOLS, protocol.trim());
59 * Determine whether the service needs to send a notification TODO: according to the visual
60 * range filter conditions Regular language: all 、 default 、 !default 、 A、 |A 、 A|B、 !A&!B
65 public boolean isNeedNotifyByNameSpace(String nameSpace) {
67 String namespaceMatches = ConfigUtil.getInstance().getNamespaceMatches();
68 String[] namespaceArray = StringUtils.split(namespaceMatches, "|");
70 if (CommonUtil.contain(namespaceArray, "all")) {
74 if (CommonUtil.contain(namespaceArray, "default")) {
75 if (StringUtils.isEmpty(nameSpace) || "default".equals(nameSpace)) {
82 if (CommonUtil.contain(namespaceArray, "!default")) {
83 if (StringUtils.isNotEmpty(nameSpace) && !"default".equals(nameSpace)) {
91 if (namespaceMatches.contains("!")) {
92 namespaceReg = "^" + namespaceMatches.replaceAll("!", "").replaceAll("&", "|") + "$";
93 return !Pattern.matches(namespaceReg, nameSpace);
95 namespaceReg = "^" + namespaceMatches + "$";
96 return Pattern.matches(namespaceReg, nameSpace);
99 } catch (Exception e) {
100 LOGGER.error(" Regular " + namespaceMatches + " throw exception:" + e.getMessage());
105 public boolean isNeedNotifyByVisualRange(String visualRange) {
107 String[] routeVisualRangeArray = StringUtils.split(ConfigUtil.getInstance().getVisualRangeMatches(), "|");
109 String[] serviceVisualRangeArray = StringUtils.split(visualRange, "|");
111 if (CommonUtil.contain(serviceVisualRangeArray, routeVisualRangeArray)) {
119 public boolean isNeedNotifyByNetwork_plane_typeMatches(String network_plane_type) {
121 String network_plane_typeMatches = ConfigUtil.getInstance().getNetwork_plane_typeMatches();
122 if (StringUtils.isBlank(network_plane_typeMatches))
125 String[] routeNetwork_plane_typeArray = StringUtils.split(network_plane_typeMatches, "|");
127 String[] serviceVisualRangeArray = StringUtils.split(network_plane_type, "|");
129 if (CommonUtil.contain(serviceVisualRangeArray, routeNetwork_plane_typeArray)) {
138 * Determine whether the service needs to send a notification TODO: according to the visual
139 * range filter conditions
144 public boolean isNeedNotifyByRouteLabels(Map<String, String> labelMap) {
146 Map<String, String> labelMapMatches = ConfigUtil.getInstance().getLabelMapMatches();
148 if (labelMapMatches == null || labelMapMatches.isEmpty()) {
152 for (Map.Entry<String, String> entry : labelMapMatches.entrySet()) {
153 String key = entry.getKey();
154 String value = entry.getValue();
156 // Multiple values match
158 if (StringUtils.isBlank(labelMap.get(key))) {
162 String[] routeLalelsArray = StringUtils.split(value, "|");
164 String[] serviceLabelsArray = StringUtils.split(labelMap.get(key), "|");
166 if (CommonUtil.contain(routeLalelsArray, serviceLabelsArray)) {
178 * public boolean isNeedNotifyByRoute(String protocol, String namespace, String visualRange,
179 * String network_plane_type, Map<String, String> labelMap) {
181 * return isNeedNotifyByProtocol(protocol) && isNeedNotifyByNameSpace(namespace) &&
182 * isNeedNotifyByVisualRange(visualRange) && isNeedNotifyByRouteLabels(labelMap) &&
183 * isNeedNotifyByNetwork_plane_typeMatches(network_plane_type);
188 public boolean isFilterCheck(ServiceHealth health) {
189 return isFilterHealthCheck(health.getChecks()) && isFilterService(health.getService().getTags());
193 * @Title isFilterHealthCheck
194 * @Description TODO(判断服务实例的健康检查信息,全部为passing表示健康检查有效)
195 * @param List<HealthCheck>
196 * @return boolean checkList示例——"Checks" : [{ "Node" : "server", "CheckID" : "serfHealth",
197 * "Name" : "Serf Health Status", "Status" : "passing", "Notes" : "", "Output" : "Agent
198 * alive and reachable", "ServiceID" : "", "ServiceName" : "", "CreateIndex" : 65536,
199 * "ModifyIndex" : 65536 }, { "Node" : "server", "CheckID" :
200 * "service:_tcp_roundrobin_1_10.74.151.26_22", "Name" : "Service 'tcp_roundrobin_1'
201 * check", "Status" : "critical", "Notes" : "", "Output" : "dial tcp: missing port in
202 * address ok", "ServiceID" : "_tcp_roundrobin_1_10.74.151.26_22", "ServiceName" :
203 * "tcp_roundrobin_1", "CreateIndex" : 75988, "ModifyIndex" : 76173 } ]
205 public boolean isFilterHealthCheck(List<HealthCheck> checkList) {
206 if (checkList.isEmpty()) {
210 for (HealthCheck check : checkList) {
211 if (!RouteUtil.HEALTH_CHECK_PASSING.equals(check.getStatus())) {
222 * @Title isFilterService
223 * @Description TODO(判断来自consul的服务信息是否需要过滤)
224 * @param List<String>
225 * @return boolean tagList示例—— [
226 * "\"base\":{\"protocol\":\"REST\",\"is_manual\":\"true\",\"version\":\"v1\",\"url\":\"/api/msbtest/v1\"}"
227 * , "\"ns\":{\"namespace\":\"nsName\"}",
228 * "\"labels\":{\"visualRange\":\"0\",\"network_plane_type\":\"net\",\"customLabel\":\"custom\"}"
231 @SuppressWarnings("unchecked")
232 public boolean isFilterService(List<String> tagList) {
234 if (tagList == null || tagList.size() == 0)
237 String visualRange = "", network_plane_type = "", protocol = "", namespace = "";
239 // 针对多版本不同属性的tag会有多个,只要其中一个匹配即通过过滤,默认不通过
240 boolean visualRangeFilter = false, protocolFilter = false, namespaceFilter = false;
241 boolean hasnamespace = false;
245 for (String tag : tagList) {
248 if (!protocolFilter && tag.startsWith("\"base\"")) {
249 String ms_base_json = tag.split("\"base\":")[1];
251 Map<String, String> baseMap =
252 (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_base_json, Map.class);
254 if (baseMap.get("protocol") != null) {
255 protocol = baseMap.get("protocol");
256 if ("PORTAL".equalsIgnoreCase(protocol)) {
260 if (isNeedNotifyByProtocol(protocol)) {
261 protocolFilter = true;
272 if (!namespaceFilter && tag.startsWith("\"ns\"")) {
273 String ms_ns_json = tag.split("\"ns\":")[1];
274 Map<String, String> nsMap = (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_ns_json, Map.class);
276 if (nsMap.get("namespace") != null) {
277 namespace = nsMap.get("namespace");
280 if (isNeedNotifyByNameSpace(namespace)) {
281 namespaceFilter = true;
290 if (tag.startsWith("\"labels\"")) {
291 String ms_labels_json = "{" + tag.split("\"labels\":\\{")[1];
293 Map<String, String> labelMap =
294 (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_labels_json, Map.class);
298 if (!visualRangeFilter && labelMap.get("visualRange") != null) {
299 visualRange = labelMap.get("visualRange");
300 labelMap.remove("visualRange"); // 自定义标签排除可见范围和网络平面
302 if (isNeedNotifyByVisualRange(visualRange)) {
303 visualRangeFilter = true;
308 if (labelMap.get("network_plane_type") != null) {
309 network_plane_type = labelMap.get("network_plane_type");
310 labelMap.remove("network_plane_type");
312 if (!isNeedNotifyByNetwork_plane_typeMatches(network_plane_type)) {
316 if (!isNeedNotifyByRouteLabels(labelMap)) {
326 if (!hasnamespace && isNeedNotifyByNameSpace(namespace)) {
327 namespaceFilter = true;
330 return visualRangeFilter && protocolFilter && namespaceFilter;
333 } catch (Exception e) {
334 LOGGER.error(" read tag throw exception", e);
343 @SuppressWarnings("unchecked")
344 public Map<String, MicroServiceFullInfo> transMicroServiceInfoFromConsul(List<ServiceHealth> serviceNodeList) {
346 Map<String, MicroServiceFullInfo> microServiceInfo4version = new HashMap<String, MicroServiceFullInfo>();
349 for (ServiceHealth serviceNode : serviceNodeList) {
351 MicroServiceFullInfo microServiceInfo = new MicroServiceFullInfo();
353 String version = "", visualRange = "", protocol = "", lb_policy = "", namespace = "", host = "", path = "",
355 boolean enable_ssl = false;
357 HashSet<Node> nodes = new HashSet<Node>();
359 Service service = serviceNode.getService();
360 String serviceName = service.getService();
363 List<String> tagList = service.getTags();
365 for (String tag : tagList) {
367 if (tag.startsWith("\"base\"")) {
368 String ms_base_json = tag.split("\"base\":")[1];
371 Map<String, String> baseMap =
372 (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_base_json, Map.class);
373 if (baseMap.get("url") != null) {
374 url = baseMap.get("url");
377 if (baseMap.get("version") != null) {
378 version = baseMap.get("version");
381 if (baseMap.get("protocol") != null) {
382 protocol = baseMap.get("protocol");
385 if (baseMap.get("host") != null) {
386 host = baseMap.get("host");
389 if (baseMap.get("path") != null) {
390 path = baseMap.get("path");
393 if (baseMap.get("publish_port") != null) {
394 publish_port = baseMap.get("publish_port");
398 if (baseMap.get("enable_ssl") != null) {
399 enable_ssl = Boolean.valueOf(baseMap.get("enable_ssl"));
407 if (tag.startsWith("\"ns\"")) {
408 String ms_ns_json = tag.split("\"ns\":")[1];
409 Map<String, String> nsMap =
410 (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_ns_json, Map.class);
412 if (nsMap.get("namespace") != null) {
413 namespace = nsMap.get("namespace");
419 if (tag.startsWith("\"labels\"")) {
420 String ms_labels_json = "{" + tag.split("\"labels\":\\{")[1];
421 Map<String, String> labelMap =
422 (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_labels_json, Map.class);
425 if (labelMap.get("visualRange") != null) {
426 visualRange = labelMap.get("visualRange");
430 * if (labelMap.get("network_plane_type") != null) { network_plane_type =
431 * labelMap.get("network_plane_type"); }
437 if (tag.startsWith("\"lb\"")) {
438 String ms_lb_json = tag.split("\"lb\":")[1];
439 Map<String, String> lbMap =
440 (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_lb_json, Map.class);
442 if (lbMap.get("lb_policy") != null) {
443 lb_policy = lbMap.get("lb_policy");
452 } catch (Exception e) {
453 LOGGER.error(serviceName + " read tag throw exception", e);
456 if (!microServiceInfo4version.containsKey(version)) {
458 if ("PORTAL".equalsIgnoreCase(protocol)) {
460 microServiceInfo.setCustom(RouteUtil.CUSTOM_PORTAL);
463 microServiceInfo.setProtocol(protocol);
464 microServiceInfo.setUrl(url);
465 microServiceInfo.setServiceName(serviceName);
466 microServiceInfo.setLb_policy(lb_policy);
467 microServiceInfo.setVisualRange(visualRange);
469 microServiceInfo.setEnable_ssl(enable_ssl);
470 microServiceInfo.setVersion(version);
471 microServiceInfo.setNamespace(namespace);
472 microServiceInfo.setHost(host);
473 microServiceInfo.setPath(path);
474 // 系统间apigateway 保存publish_port
475 if ("0".equals(ConfigUtil.getInstance().getVisualRangeMatches())) {
476 microServiceInfo.setPublish_port(publish_port);
479 nodes.add(new Node(service.getAddress(), String.valueOf(service.getPort())));
480 microServiceInfo.setNodes(nodes);
482 microServiceInfo4version.put(version, microServiceInfo);
485 Set<Node> newNodes = microServiceInfo4version.get(version).getNodes();
486 // 默认node是注册信息的IP和port
487 newNodes.add(new Node(service.getAddress(), String.valueOf(service.getPort())));
490 microServiceInfo4version.get(version).setNodes(newNodes);
496 * // 健康检查信息 List<Check> checks = value.getChecks(); node.setStatus("passing"); for
497 * (Check check : checks) { if (!"passing".equals(check.getStatus())) {
498 * node.setStatus(check.getStatus()); break; } }
505 return microServiceInfo4version;