diff options
author | 2017-07-25 15:18:33 +0800 | |
---|---|---|
committer | 2017-07-25 18:11:59 +0800 | |
commit | 672f3d40be83d9e380fd7be4b674d5e8d5fa36de (patch) | |
tree | 43105e1d5e2ba8e8accea8648e57e1cf87db3f00 /apiroute/apiroute-service/src/main/java/org/onap | |
parent | 41d3db15a8e1a0496f9c2a5e15db2998a32bb9bf (diff) |
Divide the MSB source codes into two repos
Change-Id: Ie76d545b214a8ce5191f215350a623e1529983d9
Issue-id: MSB-5
Signed-off-by: HuabingZhao <zhao.huabing@zte.com.cn>
Diffstat (limited to 'apiroute/apiroute-service/src/main/java/org/onap')
91 files changed, 10922 insertions, 0 deletions
diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/ApiRouteApp.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/ApiRouteApp.java new file mode 100644 index 0000000..5c3096f --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/ApiRouteApp.java @@ -0,0 +1,131 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute; +import io.dropwizard.Application; +import io.dropwizard.assets.AssetsBundle; +import io.dropwizard.server.SimpleServerFactory; +import io.dropwizard.setup.Bootstrap; +import io.dropwizard.setup.Environment; +import io.swagger.jaxrs.config.BeanConfig; +import io.swagger.jaxrs.listing.ApiListingResource; + +import org.onap.msb.apiroute.health.ApiRouteHealthCheck; +import org.onap.msb.apiroute.resources.ApiRouteResource; +import org.onap.msb.apiroute.resources.CustomRouteResource; +import org.onap.msb.apiroute.resources.IuiRouteResource; +import org.onap.msb.apiroute.resources.MicroServiceResource; +import org.onap.msb.apiroute.wrapper.InitRouteServiceWrapper; +import org.onap.msb.apiroute.wrapper.util.ConfigUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.annotation.JsonInclude; + +public class ApiRouteApp extends Application<ApiRouteAppConfig> { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApiRouteApp.class); + + public static void main(String[] args) throws Exception { + new ApiRouteApp().run(args); + + InitRouteServiceWrapper.getInstance().initFilterConfig(); + + InitRouteServiceWrapper.getInstance().initDataSynchro(); + + InitRouteServiceWrapper.getInstance().initHealthCheck(); + } + + + @Override + public String getName() { + return " MicroService Bus "; + } + + @Override + public void initialize(Bootstrap<ApiRouteAppConfig> bootstrap) { + super.initialize(bootstrap); + + } + + @Override + public void run(ApiRouteAppConfig configuration, Environment environment) throws Exception { + + + ConfigUtil.getInstance().initRootPath(); + + + String iuiRootPath=ConfigUtil.getInstance().getIUI_ROOT_PATH(); + + // new AssetsBundle("/iui-metrics", "/"+iuiRootPath+"/microservices/metrics","index.html", "iui-metrics").run(environment); + + new AssetsBundle("/iui-route", "/"+iuiRootPath+"/microservices", "index.html","iui-microservices").run(environment); + + new AssetsBundle("/api-doc", "/"+iuiRootPath+"/microservices/api-doc","index.html", "api-doc").run(environment); + + new AssetsBundle("/ext", "/"+iuiRootPath+"/microservices/ext","index.html", "ext").run(environment); + + + + + final ApiRouteHealthCheck healthCheck =new ApiRouteHealthCheck(); + environment.healthChecks().register("consulCheck", healthCheck); + + environment.jersey().register(new ApiRouteResource()); + environment.jersey().register(new IuiRouteResource()); + environment.jersey().register(new CustomRouteResource()); + environment.jersey().register(new MicroServiceResource()); + + // initSwaggerConfig(environment, configuration); + + ConfigUtil.getInstance().initConsulIp(); + ConfigUtil.getInstance().initDiscoverInfo(configuration); + // InitRouteServiceWrapper.getInstance().initMetricsConfig(configuration); + + + } + + + + + + + private void initSwaggerConfig(Environment environment, ApiRouteAppConfig configuration) { + + environment.jersey().register(new ApiListingResource()); + environment.getObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL); + + BeanConfig config = new BeanConfig(); + config.setTitle("ApiRoute RESTful API"); + config.setVersion("1.0.0"); + config.setResourcePackage("org.onap.msb.apiroute.resources"); + SimpleServerFactory simpleServerFactory =(SimpleServerFactory) configuration.getServerFactory(); + String basePath = simpleServerFactory.getApplicationContextPath(); + String rootPath = simpleServerFactory.getJerseyRootPath(); + + rootPath = rootPath.substring(0, rootPath.indexOf("/*")); + + basePath = basePath.equals("/") ? rootPath : (new StringBuilder()).append(basePath).append(rootPath).toString(); + + LOGGER.warn("getApplicationContextPath: " + basePath); + config.setBasePath(basePath); + config.setScan(true); + } + + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/ApiRouteAppConfig.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/ApiRouteAppConfig.java new file mode 100644 index 0000000..4c998e0 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/ApiRouteAppConfig.java @@ -0,0 +1,90 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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. + */ +/** +* Copyright (C) 2016 ZTE, Inc. and others. All rights reserved. (ZTE) +* +* 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.onap.msb.apiroute; + +import io.dropwizard.Configuration; + +import javax.validation.Valid; + +import org.hibernate.validator.constraints.NotEmpty; +import org.onap.msb.apiroute.api.DiscoverInfo; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ApiRouteAppConfig extends Configuration { + @NotEmpty + private String defaultWorkspace = "apiroute-works"; + + @NotEmpty + private String defaultName = "Stranger"; + + + @Valid + private DiscoverInfo discoverInfo; + + + @JsonProperty + public String getDefaultWorkspace() { + return defaultWorkspace; + } + + @JsonProperty + public void setDefaultWorkspace(String defaultWorkspace) { + this.defaultWorkspace = defaultWorkspace; + } + + @JsonProperty + public String getDefaultName() { + return defaultName; + } + + @JsonProperty + public void setDefaultName(String name) { + this.defaultName = name; + } + + + + @JsonProperty + public DiscoverInfo getDiscoverInfo() { + return discoverInfo; + } + + @JsonProperty + public void setDiscoverInfo(DiscoverInfo discoverInfo) { + this.discoverInfo = discoverInfo; + } + + + + +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/SyncDataManager.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/SyncDataManager.java new file mode 100644 index 0000000..865778e --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/SyncDataManager.java @@ -0,0 +1,135 @@ +package org.onap.msb.apiroute; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.http.HttpEntity; +import org.onap.msb.apiroute.wrapper.consulextend.Consul; +import org.onap.msb.apiroute.wrapper.consulextend.expose.CheckServiceDataEmptyAndAutoStopWatchFilter; +import org.onap.msb.apiroute.wrapper.consulextend.expose.CheckTagAndAutoStopWatchFilter; +import org.onap.msb.apiroute.wrapper.consulextend.expose.ServiceModifyIndexFilter; +import org.onap.msb.apiroute.wrapper.consulextend.expose.WatchCatalogServicesTask; +import org.onap.msb.apiroute.wrapper.consulextend.expose.WatchServiceHealthTask; +import org.onap.msb.apiroute.wrapper.consulextend.expose.WriteBufferHandler; +import org.onap.msb.apiroute.wrapper.queue.ServiceConsumer; +import org.onap.msb.apiroute.wrapper.queue.ServiceData; +import org.onap.msb.apiroute.wrapper.queue.ServiceListConsumer; +import org.onap.msb.apiroute.wrapper.util.RouteUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SyncDataManager { + private static Consul consul; + private static WatchCatalogServicesTask serviceListWatchTask; + private final static Map<String, WatchServiceHealthTask> serviceWatchTaskMap = new ConcurrentHashMap<String, WatchServiceHealthTask>(); + + private static final Logger LOGGER = LoggerFactory + .getLogger(SyncDataManager.class); + + private SyncDataManager() { + } + + public static void initSyncTask(final String ip, final int port) { + consul = Consul.builder().withHostAndPort(ip, port).build(); + startWatchServiceList(); + startQueueConsumer(); + } + + public static void startWatchServiceList() { + + LOGGER.info("===========start to WatchServiceList============"); + + // create service list watch task + serviceListWatchTask = new WatchCatalogServicesTask( + consul.catalogClient(), RouteUtil.WATCH_SECOND); + + // first,write data to serviceListQueue buffer. + // second,async thread will read data from serviceListQueue buffer. + serviceListWatchTask.addHandler(new WriteBufferHandler<HttpEntity>( + ServiceData.DataType.service_list)); + + // start watch + serviceListWatchTask.startWatch(); + } + + public static void startQueueConsumer() { + LOGGER.info("===========start to QueueConsumer Thread============"); + + // start ServiceListConsumer + new Thread(new ServiceListConsumer(), "ServiceListConsumerThread") + .start(); + + // start Service Consumer + int serviceQueneNum = RouteUtil.SERVICE_DATA_QUEUE_NUM; + for (int i = 0; i < serviceQueneNum; i++) { + new Thread(new ServiceConsumer(i), "ServiceConsumerThread" + i) + .start(); + } + + } + + public static void startWatchService(final String serviceName) { + + LOGGER.info("===========start to Watch Service[" + serviceName + + "]============"); + // create service watch task + WatchServiceHealthTask serviceWatchTask = new WatchServiceHealthTask( + consul.healthClient(), serviceName, RouteUtil.WATCH_SECOND); + + // 1.service Data Empty filter + serviceWatchTask + .addFilter(new CheckServiceDataEmptyAndAutoStopWatchFilter( + serviceName)); + + // 2.service change filter + serviceWatchTask.addFilter(new ServiceModifyIndexFilter()); + + // 3.apigateway tag filter:check tag and auto stop watch + serviceWatchTask.addFilter(new CheckTagAndAutoStopWatchFilter( + serviceName)); + + // start watch + serviceWatchTask.startWatch(); + + // save + serviceWatchTaskMap.put(serviceName, serviceWatchTask); + } + + public static void stopWatchServiceList() { + if (serviceListWatchTask != null) { + serviceListWatchTask.removeAllFilter(); + serviceListWatchTask.removeAllHandler(); + serviceListWatchTask.stopWatch(); + } + } + + public static void stopWatchService(String serviceName) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("stop " + serviceName + " service watch!"); + } + + WatchServiceHealthTask watchTask = serviceWatchTaskMap.get(serviceName); + if (watchTask != null) { + watchTask.removeAllFilter(); + watchTask.removeAllHandler(); + watchTask.stopWatch(); + } + serviceWatchTaskMap.remove(serviceName); + } + + public static boolean resetIndex(String serviceName) { + + WatchServiceHealthTask watchTask = serviceWatchTaskMap.get(serviceName); + + if (watchTask != null) { + return watchTask.resetIndex(); + } + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("reset modify index.did not find:" + serviceName); + } + + return false; + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/ApiRouteInfo.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/ApiRouteInfo.java new file mode 100644 index 0000000..1465000 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/ApiRouteInfo.java @@ -0,0 +1,107 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.api; + +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Objects; + + +public class ApiRouteInfo extends RouteInfo { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(example = "v1", required = true) + private String version; + + + private String apiJson=""; //swagger json Path + + @ApiModelProperty(value = "[apiJson Type] 0:local file 1: remote file", allowableValues = "0,1", example = "1") + private String apiJsonType="1"; + private String metricsUrl=""; + + + + public String getVersion() { + return version; + } + public void setVersion(String version) { + this.version = version; + } + + public String getApiJson() { + return apiJson; + } + public void setApiJson(String apiJson) { + this.apiJson = apiJson; + } + + + + + public String getApiJsonType() { + return apiJsonType; + } + public void setApiJsonType(String apiJsonType) { + this.apiJsonType = apiJsonType; + } + public String getMetricsUrl() { + return metricsUrl; + } + public void setMetricsUrl(String metricsUrl) { + this.metricsUrl = metricsUrl; + } + + + + + @Override + public Object clone() throws CloneNotSupportedException + { + return super.clone(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ApiRouteInfo that = (ApiRouteInfo) o; + return Objects.equals(isEnable_ssl(), that.isEnable_ssl()) && + Objects.equals(getServiceName(), that.getServiceName()) && + Objects.equals(version, that.version) && + Objects.equals(getUrl(), that.getUrl()) && + Objects.equals(apiJson, that.apiJson) && + Objects.equals(apiJsonType, that.apiJsonType) && + Objects.equals(metricsUrl, that.metricsUrl) && + Objects.equals(getControl(), that.getControl()) && + Objects.equals(getStatus(), that.getStatus()) && + Objects.equals(getVisualRange(), that.getVisualRange()) && + Objects.equals(getUseOwnUpstream(), that.getUseOwnUpstream()) && + Arrays.equals(getServers(), that.getServers()) && + Objects.equals(getHost(), that.getHost()) && + Objects.equals(getNamespace(), that.getNamespace()) && + Objects.equals(getPublish_port(), that.getPublish_port()) && + Objects.equals(getConsulServiceName(), that.getConsulServiceName()) && + Objects.equals(getPublishProtocol(), that.getPublishProtocol()); + } + + @Override + public int hashCode() { + return Objects.hash(getServiceName(), version, getUrl(), apiJson, apiJsonType, metricsUrl, getControl(), getStatus(), getVisualRange(), getServers(), getHost(), getNamespace(), getPublish_port(), isEnable_ssl(), getConsulServiceName(), getPublishProtocol()); + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/CustomDateSerializer.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/CustomDateSerializer.java new file mode 100644 index 0000000..709a995 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/CustomDateSerializer.java @@ -0,0 +1,39 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.api; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +public class CustomDateSerializer extends JsonSerializer<Date> { + + @Override + public void serialize(Date value, + JsonGenerator jsonGenerator, + SerializerProvider provider) + throws IOException, JsonProcessingException { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); + jsonGenerator.writeString(sdf.format(value)); + } + + +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/CustomRouteInfo.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/CustomRouteInfo.java new file mode 100644 index 0000000..788ce00 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/CustomRouteInfo.java @@ -0,0 +1,24 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.api; + + +public class CustomRouteInfo extends RouteInfo{ + + private static final long serialVersionUID = 1L; + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/DiscoverInfo.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/DiscoverInfo.java new file mode 100644 index 0000000..4a4708b --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/DiscoverInfo.java @@ -0,0 +1,55 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.api; + +import java.io.Serializable; + +public class DiscoverInfo implements Serializable{ + private static final long serialVersionUID = 1L; + private String ip; + private int port; + private boolean enabled; + + + public String getIp() { + return ip; + } + public void setIp(String ip) { + this.ip = ip; + } + public int getPort() { + return port; + } + public void setPort(int port) { + this.port = port; + } + public boolean isEnabled() { + return enabled; + } + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + @Override + public String toString() { + // TODO Auto-generated method stub + return this.ip+":"+this.port; + } + + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/IuiRouteInfo.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/IuiRouteInfo.java new file mode 100644 index 0000000..b3f3cf6 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/IuiRouteInfo.java @@ -0,0 +1,25 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.api; + + + +public class IuiRouteInfo extends RouteInfo{ + + private static final long serialVersionUID = 1L; + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/MicroServiceFullInfo.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/MicroServiceFullInfo.java new file mode 100644 index 0000000..ca0b235 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/MicroServiceFullInfo.java @@ -0,0 +1,195 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.api; + +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; +import java.util.Objects; +import java.util.Set; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class MicroServiceFullInfo implements Serializable { + private static final long serialVersionUID = 1L; + + + @ApiModelProperty(required = true) + private String serviceName; + + @ApiModelProperty(example = "v1") + private String version=""; + + @ApiModelProperty(value = "Target Service URL,start with /",example = "/api/serviceName/v1", required = true) + private String url=""; + + @ApiModelProperty(value = "Service Protocol", allowableValues = "REST,UI, MQ, FTP,SNMP,TCP,UDP", example = "REST",required = true) + private String protocol = ""; + + @ApiModelProperty(value = "[visual Range]interSystem:0,inSystem:1", allowableValues = "0,1", example = "1") + private String visualRange = "1"; + + @ApiModelProperty(value = "lb policy", allowableValues = "round-robin,hash,least_conn", example = "hash") + private String lb_policy=""; + + private String namespace=""; + + private String host=""; + + private String path=""; + + private String publish_port=""; + + @ApiModelProperty(value = "enable ssl", allowableValues = "true,false", example = "false") + private boolean enable_ssl=false; //true:https:开启SSL加密, false:http + + private String custom; //PORTAL协议标志 + + private Set<Node> nodes; + + @ApiModelProperty(value = "Service Status", allowableValues = "0,1", example = "1") + private String status = "1"; //0:disable 1:enable + + + + + public String getServiceName() { + return serviceName; + } + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + public String getVersion() { + return version; + } + public void setVersion(String version) { + this.version = version; + } + public String getUrl() { + return url; + } + public void setUrl(String url) { + this.url = url; + } + public String getProtocol() { + return protocol; + } + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getVisualRange() { + return visualRange; + } + + public void setVisualRange(String visualRange) { + this.visualRange = visualRange; + } + + + public String getLb_policy() { + return lb_policy; + } + + public void setLb_policy(String lb_policy) { + this.lb_policy = lb_policy; + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + + public String getHost() { + return host; + } + public void setHost(String host) { + this.host = host; + } + public String getPath() { + return path; + } + public void setPath(String path) { + this.path = path; + } + + + + public Set<Node> getNodes() { + return nodes; + } + + public void setNodes(Set<Node> nodes) { + this.nodes = nodes; + } + + public String getStatus() { + return status; + } + public void setStatus(String status) { + this.status = status; + } + public String getPublish_port() { + return publish_port; + } + public void setPublish_port(String publish_port) { + this.publish_port = publish_port; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MicroServiceFullInfo that = (MicroServiceFullInfo) o; + return Objects.equals(serviceName, that.serviceName) && + Objects.equals(version, that.version) && + Objects.equals(url, that.url) && + Objects.equals(protocol, that.protocol) && + Objects.equals(visualRange, that.visualRange) && + Objects.equals(lb_policy, that.lb_policy) && + Objects.equals(namespace, that.namespace) && + Objects.equals(host, that.host) && + Objects.equals(path, that.path) && + Objects.equals(publish_port, that.publish_port) && + Objects.equals(enable_ssl, that.enable_ssl) && + Objects.equals(nodes, that.nodes) && + Objects.equals(status, that.status); + } + + @Override + public int hashCode() { + return Objects.hash(serviceName, version, url, protocol, visualRange, lb_policy, namespace, host, path, publish_port, enable_ssl, nodes, status); + } + public boolean isEnable_ssl() { + return enable_ssl; + } + public void setEnable_ssl(boolean enable_ssl) { + this.enable_ssl = enable_ssl; + } + public String getCustom() { + return custom; + } + public void setCustom(String custom) { + this.custom = custom; + } + + +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/Node.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/Node.java new file mode 100644 index 0000000..c515820 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/Node.java @@ -0,0 +1,98 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.api; + +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; +import java.util.Objects; + +public class Node implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(required = true) + private String ip; + + @ApiModelProperty(required = true) + private String port; + + private String status="passing"; //实例健康检查状态 + + private int ttl=-1; + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public int getTtl() { + return ttl; + } + + public void setTtl(int ttl) { + this.ttl = ttl; + } + + public Node(){ + + } + + public Node(String ip,String port,int ttl){ + this.ip = ip; + this.port = port; + this.ttl = ttl; + } + + public Node(String ip,String port){ + this.ip = ip; + this.port = port; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Node node = (Node) o; + return Objects.equals(ttl, node.ttl) && + Objects.equals(ip, node.ip) && + Objects.equals(port, node.port) && + Objects.equals(status, node.status); + } + + @Override + public int hashCode() { + return Objects.hash(ip, port, status, ttl); + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/PublishFullAddress.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/PublishFullAddress.java new file mode 100644 index 0000000..3f62897 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/PublishFullAddress.java @@ -0,0 +1,48 @@ +package org.onap.msb.apiroute.api; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class PublishFullAddress implements Serializable { + private static final long serialVersionUID = 1L; + + + private String ip; + + private String port; + + + private String publish_protocol; + + public String getPublish_protocol() { + return publish_protocol; + } + + public void setPublish_protocol(String publish_protocol) { + this.publish_protocol = publish_protocol; + } + + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public PublishFullAddress(){ + + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/RouteInfo.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/RouteInfo.java new file mode 100644 index 0000000..5e36b9d --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/RouteInfo.java @@ -0,0 +1,179 @@ +package org.onap.msb.apiroute.api; + +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Objects; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class RouteInfo implements Serializable,Cloneable { + private static final long serialVersionUID = 1L; + @ApiModelProperty(required = true) + private String serviceName; + + @ApiModelProperty(value = "Target Service URL,start with /",example = "/test", required = true) + private String url; + + @ApiModelProperty(value = "[control Range] 0:default 1:readonly 2:hidden ", allowableValues = "0,1,2", example = "0") + private String control="0"; + + @ApiModelProperty(value = "[status] 1:abled 0:disabled ", allowableValues = "0,1", example = "1") + private String status="1"; + + @ApiModelProperty(value = "[visual Range]interSystem:0,inSystem:1", allowableValues = "0,1", example = "1") + private String visualRange = "1"; + + @ApiModelProperty(value = "[LB Policy]non_ip_hash:0,ip_hash:1", allowableValues = "0,1", example = "0") + private String useOwnUpstream="0"; //lb policy + + @ApiModelProperty(required = true) + private RouteServer servers[]; + + private String host=""; + + private String namespace=""; + + private String publish_port=""; + + private boolean enable_ssl=false; //true:https:开启SSL加密, false:http + + private String consulServiceName=""; + + private String publishProtocol="http"; + + + + public String getPublish_port() { + return publish_port; + } + public void setPublish_port(String publish_port) { + this.publish_port = publish_port; + } + + + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + +public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public RouteServer[] getServers() { + return servers.clone(); + } + + public void setServers(RouteServer[] servers) { + this.servers = servers.clone(); + } + + public String getControl() { + return control; + } + + public void setControl(String control) { + this.control = control; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getVisualRange() { + return visualRange; + } + + public void setVisualRange(String visualRange) { + this.visualRange = visualRange; + } + + public String getUseOwnUpstream() { + return useOwnUpstream; + } + + public void setUseOwnUpstream(String useOwnUpstream) { + this.useOwnUpstream = useOwnUpstream; + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + public String getConsulServiceName() { + return consulServiceName; + } + public void setConsulServiceName(String consulServiceName) { + this.consulServiceName = consulServiceName; + } + + @Override + public Object clone() throws CloneNotSupportedException + { + return super.clone(); + } + public String getPublishProtocol() { + return publishProtocol; + } + public void setPublishProtocol(String publishProtocol) { + this.publishProtocol = publishProtocol; + } + public boolean isEnable_ssl() { + return enable_ssl; + } + public void setEnable_ssl(boolean enable_ssl) { + this.enable_ssl = enable_ssl; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RouteInfo that = (RouteInfo) o; + return Objects.equals(enable_ssl, that.enable_ssl) && + Objects.equals(serviceName, that.serviceName) && + Objects.equals(url, that.url) && + Objects.equals(control, that.control) && + Objects.equals(status, that.status) && + Objects.equals(visualRange, that.visualRange) && + Objects.equals(useOwnUpstream, that.useOwnUpstream) && + Arrays.equals(servers, that.servers) && + Objects.equals(host, that.host) && + Objects.equals(namespace, that.namespace) && + Objects.equals(publish_port, that.publish_port) && + Objects.equals(consulServiceName, that.consulServiceName) && + Objects.equals(publishProtocol, that.publishProtocol); + } + + @Override + public int hashCode() { + return Objects.hash(serviceName, url, control, status, visualRange, useOwnUpstream, servers, host, namespace, publish_port, enable_ssl, consulServiceName, publishProtocol); + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/RouteServer.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/RouteServer.java new file mode 100644 index 0000000..310e623 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/RouteServer.java @@ -0,0 +1,83 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.api; + +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; +import java.util.Objects; + + +public class RouteServer implements Serializable{ + private static final long serialVersionUID = 1L; + @ApiModelProperty(required = true) + private String ip; + + @ApiModelProperty(required = true) + private String port; + private int weight=0; + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + public RouteServer(){ + + } + + public RouteServer(String ip,String port){ + this.ip=ip; + this.port=port; + this.weight=0; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RouteServer that = (RouteServer) o; + return Objects.equals(weight, that.weight) && + Objects.equals(ip, that.ip) && + Objects.equals(port, that.port); + } + + @Override + public int hashCode() { + return Objects.hash(ip, port, weight); + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/exception/ExtendedInternalServerErrorException.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/exception/ExtendedInternalServerErrorException.java new file mode 100644 index 0000000..de0d47a --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/exception/ExtendedInternalServerErrorException.java @@ -0,0 +1,28 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.api.exception; + +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +public class ExtendedInternalServerErrorException extends InternalServerErrorException { + + public ExtendedInternalServerErrorException(final String message) { + super(Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type(MediaType.TEXT_PLAIN).build()); + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/exception/ExtendedNotFoundException.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/exception/ExtendedNotFoundException.java new file mode 100644 index 0000000..34439d9 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/exception/ExtendedNotFoundException.java @@ -0,0 +1,28 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.api.exception; + +import javax.ws.rs.NotFoundException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +public class ExtendedNotFoundException extends NotFoundException { + + public ExtendedNotFoundException(final String message) { + super(Response.status(Response.Status.NOT_FOUND).entity(message).type(MediaType.TEXT_PLAIN).build()); + } +} + diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/exception/UnprocessableEntityException.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/exception/UnprocessableEntityException.java new file mode 100644 index 0000000..28cfd17 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/api/exception/UnprocessableEntityException.java @@ -0,0 +1,18 @@ +package org.onap.msb.apiroute.api.exception; + +import javax.ws.rs.ClientErrorException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.http.HttpStatus; + +public class UnprocessableEntityException extends ClientErrorException{ + private static final long serialVersionUID = -8266622745725405656L; + + public UnprocessableEntityException(final String message) { + super(Response.status(HttpStatus.SC_UNPROCESSABLE_ENTITY).entity(message).type(MediaType.TEXT_PLAIN).build()); + } + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/health/ApiRouteHealthCheck.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/health/ApiRouteHealthCheck.java new file mode 100644 index 0000000..82b5f21 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/health/ApiRouteHealthCheck.java @@ -0,0 +1,65 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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. + */ +/** +* Copyright (C) 2016 ZTE, Inc. and others. All rights reserved. (ZTE) +* +* 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.onap.msb.apiroute.health; + +import org.onap.msb.apiroute.api.DiscoverInfo; +import org.onap.msb.apiroute.wrapper.util.ConfigUtil; +import org.onap.msb.apiroute.wrapper.util.HttpClientUtil; +import org.onap.msb.apiroute.wrapper.util.RouteUtil; + +import com.codahale.metrics.health.HealthCheck; + +public class ApiRouteHealthCheck extends HealthCheck { + + + public ApiRouteHealthCheck() { + } + + @Override + protected Result check() throws Exception { + DiscoverInfo discoverInfo=ConfigUtil.getInstance().getDiscoverInfo(); + + String checkUrl = + (new StringBuilder().append("http://").append(discoverInfo.toString()) + .append(RouteUtil.MSB_CHECK_URL)).toString(); + + int resultStatus = HttpClientUtil.httpGetStatus(checkUrl); + + if(resultStatus==200){ + return Result.healthy(); + } + else{ + return Result.unhealthy("check consul fail:[status]"+resultStatus); + } + + + } +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/health/ConsulLinkHealthCheck.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/health/ConsulLinkHealthCheck.java new file mode 100644 index 0000000..916d2f8 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/health/ConsulLinkHealthCheck.java @@ -0,0 +1,132 @@ +package org.onap.msb.apiroute.health; + +import org.apache.commons.lang3.StringUtils; +import org.onap.msb.apiroute.ApiRouteApp; +import org.onap.msb.apiroute.wrapper.InitRouteServiceWrapper; +import org.onap.msb.apiroute.wrapper.util.ConfigUtil; +import org.onap.msb.apiroute.wrapper.util.HttpClientUtil; +import org.onap.msb.apiroute.wrapper.util.HttpGetResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.codahale.metrics.health.HealthCheck; + +public class ConsulLinkHealthCheck extends HealthCheck implements Runnable { + + private static final Logger LOGGER = LoggerFactory + .getLogger(ConsulLinkHealthCheck.class); + + private final static String CONSUL_IP_ENV = ConfigUtil.getInstance().getConsul_ip(); + + private static int failedLoopCheckNum = 12; + private static int failedTimer = 5 * 1000; + + private static int normalTimer = 20 * 1000; + private static Result result = Result.healthy(); + + private String CHECK_IP = "127.0.0.1"; + private String CHECK_PORT = "8500"; + private String CHECK_URL = "http://" + CHECK_IP + ":" + CHECK_PORT + + "/v1/status/leader"; + + public static Result getResult() { + return result; + } + + @Override + protected Result check() { + // TODO Auto-generated method stub + + if (!StringUtils.isBlank(CONSUL_IP_ENV)) { + CHECK_IP = CONSUL_IP_ENV; + CHECK_URL = "http://" + CHECK_IP + ":" + CHECK_PORT + + "/v1/status/leader"; + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("check consul URL:" + CHECK_URL); + } + + try { + + HttpGetResult result = HttpClientUtil + .httpGetStatusAndBody(CHECK_URL); + + //response format:"127.0.0.1:8300" + if (result.getStatusCode() == 200 && result.getBody() != null + && result.getBody().contains(":8300")) { + return Result.healthy(); + } else { + return Result.unhealthy("check consul link " + CHECK_URL + + " fail:" + result.getStatusCode()+":"+result.getBody()); + } + + } catch (Exception e) { + LOGGER.warn( + "ConsulLinkHealthCheck:" + CHECK_URL + " execption", e); + return Result.unhealthy("check consul link " + CHECK_URL + + " exception:{}"); + } + + } + + return Result.healthy(); + } + + @Override + public void run() { + // TODO Auto-generated method stub + while (true) { + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("consul link check starttime:" + + System.currentTimeMillis()); + } + + result = checkWithPolicy(); + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("consul link check result:" + result.isHealthy() + + " message:" + result.getMessage()); + + LOGGER.debug("consul link check endtime:" + + System.currentTimeMillis()); + } + + try { + Thread.sleep(normalTimer); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + LOGGER.warn("loop check consul,thread sleep excepiton", e); + } + } + } + + private Result checkWithPolicy() { + int failedNum = 0; + Result temp = Result.healthy(); + + do { + // check again + temp = check(); + + // healthy break; + if (temp.isHealthy()) { + break; + } + + // unhealthy go on + failedNum++; + + try { + Thread.sleep(failedTimer); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + LOGGER.warn("loop check consul,thread sleep excepiton", e); + } + + } while (failedNum <= failedLoopCheckNum); + + return temp; + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/health/OpenRestyHealthCheck.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/health/OpenRestyHealthCheck.java new file mode 100644 index 0000000..fb0379f --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/health/OpenRestyHealthCheck.java @@ -0,0 +1,39 @@ +package org.onap.msb.apiroute.health; + +import org.apache.commons.lang3.StringUtils; +import org.onap.msb.apiroute.wrapper.util.HttpClientUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.codahale.metrics.health.HealthCheck; + +public class OpenRestyHealthCheck extends HealthCheck { + private static final Logger LOGGER = LoggerFactory + .getLogger(OpenRestyHealthCheck.class); + private String CHECK_IP="127.0.0.1"; + private String CHECK_PORT="80"; + private String CHECK_URL = "http://"+CHECK_IP+":"+CHECK_PORT+"/api/microservices/v1/apiRoute/discoverInfo"; + + @Override + protected Result check() throws Exception { + // TODO Auto-generated method stub + + if(!StringUtils.isBlank(System.getenv("HTTP_OVERWRITE_PORT"))) + { + CHECK_PORT=System.getenv("HTTP_OVERWRITE_PORT"); + CHECK_URL = "http://"+CHECK_IP+":"+CHECK_PORT+"/api/microservices/v1/apiRoute/discoverInfo"; + LOGGER.info("check openresty URL:"+CHECK_URL); + } + + int resultStatus = HttpClientUtil.httpGetStatus(CHECK_URL); + + if (resultStatus == 200) { + return Result.healthy(); + } else { + return Result + .unhealthy("check openresty fail:" + resultStatus); + } + + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/health/RedisHealthCheck.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/health/RedisHealthCheck.java new file mode 100644 index 0000000..7cef3d0 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/health/RedisHealthCheck.java @@ -0,0 +1,160 @@ +package org.onap.msb.apiroute.health; + +import java.text.SimpleDateFormat; + +import org.onap.msb.apiroute.wrapper.util.JedisUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import redis.clients.jedis.Jedis; + +import com.codahale.metrics.health.HealthCheck; + +public class RedisHealthCheck extends HealthCheck implements Runnable { + private static final Logger LOGGER = LoggerFactory + .getLogger(RedisHealthCheck.class); + + public static boolean writeCheckFlag = true; + private static Result result = Result.healthy(); + + private static int failedLoopCheckNum = 12; + private static int failedTimer = 5 * 1000; + + private static int normalTimer = 20 * 1000; + + public static Result getResult() { + return result; + } + + @Override + protected Result check() { + + // check write + if (writeCheckFlag) { + Result writeCheckResult = checkWrite(); + if (writeCheckResult.isHealthy()) { + writeCheckFlag = false; + } + + // write failed + if (!writeCheckResult.isHealthy()) { + return writeCheckResult; + } + } + + // check read + Result readCheckResult = checkRead(); + + // read failed + if (!readCheckResult.isHealthy()) { + return readCheckResult; + } + + return Result.healthy(); + } + + private Result checkRead() { + Jedis jedisHandle = null; + + Result healthRst = Result.healthy(); + try { + + jedisHandle = JedisUtil.borrowJedisInstance(); + jedisHandle.get("healthchek:checktime"); + + } catch (Exception e) { + LOGGER.warn("RedisHealthCheck exception", e); + healthRst = Result.unhealthy(e); + } finally { + JedisUtil.returnJedisInstance(jedisHandle); + } + + return healthRst; + } + + private Result checkWrite() { + Jedis jedisHandle = null; + + Result healthRst = Result.healthy(); + try { + + long currentTime = System.currentTimeMillis(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String date = sdf.format(currentTime); + + jedisHandle = JedisUtil.borrowJedisInstance(); + String statusCode = jedisHandle.set("healthchek:checktime", date); + + if (statusCode != null && statusCode.equals("OK")) { + healthRst = Result.healthy("check redis:" + statusCode); + } else { + healthRst = Result.unhealthy("check redis:" + statusCode); + } + + } catch (Exception e) { + LOGGER.warn("RedisHealthCheck exception", e); + healthRst = Result.unhealthy(e); + } finally { + JedisUtil.returnJedisInstance(jedisHandle); + } + + return healthRst; + } + + @Override + public void run() { + // TODO Auto-generated method stub + while (true) { + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("redis check starttime:" + + System.currentTimeMillis()); + } + + result = checkWithPolicy(); + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("redis check result:" + result.isHealthy() + + " message:" + result.getMessage()); + + LOGGER.debug("redis check endtime:" + + System.currentTimeMillis()); + } + + try { + Thread.sleep(normalTimer); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + LOGGER.warn("loop check redis,thread sleep excepiton", e); + } + } + } + + private Result checkWithPolicy() { + int failedNum = 0; + Result temp = Result.healthy(); + + do { + // check again + temp = check(); + + // healthy break; + if (temp.isHealthy()) { + break; + } + + // unhealthy go on + failedNum++; + + try { + Thread.sleep(failedTimer); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + LOGGER.warn("loop check redis,thread sleep excepiton", e); + } + + } while (failedNum <= failedLoopCheckNum); + + return temp; + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/resources/ApiRouteResource.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/resources/ApiRouteResource.java new file mode 100644 index 0000000..e969e7a --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/resources/ApiRouteResource.java @@ -0,0 +1,214 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.resources; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.net.URI; +import java.util.List; + +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.core.UriInfo; + +import org.apache.http.HttpStatus; +import org.onap.msb.apiroute.api.ApiRouteInfo; +import org.onap.msb.apiroute.api.DiscoverInfo; +import org.onap.msb.apiroute.wrapper.ApiRouteServiceWrapper; +import org.onap.msb.apiroute.wrapper.CustomRouteServiceWrapper; +import org.onap.msb.apiroute.wrapper.IuiRouteServiceWrapper; +import org.onap.msb.apiroute.wrapper.util.CommonUtil; +import org.onap.msb.apiroute.wrapper.util.ConfigUtil; +import org.onap.msb.apiroute.wrapper.util.JacksonJsonUtil; + +import com.codahale.metrics.annotation.Timed; + +@Path("/apiRoute") +@Api(tags = { "ApiRoute" }) +@Produces(MediaType.APPLICATION_JSON) +public class ApiRouteResource { + + @Context + UriInfo uriInfo; // actual uri info + + @GET + @Path("/") + @ApiOperation(value = "get all ApiRoute ", code = HttpStatus.SC_OK,response = ApiRouteInfo.class, responseContainer = "List") + @ApiResponses(value = {@ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get ApiRouteInfo List fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public List<ApiRouteInfo> getApiRoutes(@ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + return ApiRouteServiceWrapper.getInstance().getAllApiRouteInstances(routeWay); + } + + @POST + @Path("/") + @ApiOperation(value = "add one ApiRoute ", code = HttpStatus.SC_CREATED,response = ApiRouteInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable ApiRouteInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "add ApiRouteInfo fail", response = String.class), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Unprocessable ApiRouteInfo JSON REQUEST", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response addApiRoute( + @ApiParam(value = "ApiRoute Instance Info", required = true) ApiRouteInfo apiRouteInfo, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + ApiRouteInfo new_apiRouteInfo = ApiRouteServiceWrapper.getInstance().saveApiRouteInstance4Rest(apiRouteInfo,routeWay); + URI returnURI = uriInfo.getAbsolutePathBuilder().path("/" + new_apiRouteInfo.getServiceName()+"/version/"+new_apiRouteInfo.getVersion()).build(); + return Response.created(returnURI).entity(new_apiRouteInfo).build(); + + } + + @GET + @Path("/{serviceName}/version/{version}") + @ApiOperation(value = "get one ApiRoute ",code = HttpStatus.SC_OK, response = ApiRouteInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "ApiRouteInfo not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable ApiRouteInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get ApiRouteInfo fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public ApiRouteInfo getApiRoute( + @ApiParam(value = "ApiRoute serviceName", required = true) @PathParam("serviceName") String serviceName, + @ApiParam(value = "ApiRoute version,if the version is empty, please enter \"null\"", required = false) @PathParam("version") @DefaultValue("") String version, + @ApiParam(value = "ApiRoute host", required = false) @QueryParam("host") String host, + @ApiParam(value = "ApiRoute Publish port", required = false) @QueryParam("publish_port") @DefaultValue("")String publish_port, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + + return ApiRouteServiceWrapper.getInstance().getApiRouteInstance(serviceName,version,host,publish_port,routeWay); + + } + + @PUT + @Path("/{serviceName}/version/{version}") + @ApiOperation(value = "update one ApiRoute by serviceName and version", code = HttpStatus.SC_CREATED,response = ApiRouteInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable ApiRouteInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "update ApiRouteInfo fail", response = String.class), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Unprocessable ApiRouteInfo JSON REQUEST", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response updateApiRoute( + @ApiParam(value = "ApiRoute serviceName", required = true) @PathParam("serviceName") String serviceName, + @ApiParam(value = "ApiRoute version,if the version is empty, please enter \"null\"", required = false) @PathParam("version") @DefaultValue("") String version, + @ApiParam(value = "ApiRoute Instance Info", required = true) ApiRouteInfo apiRouteInfo, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + + ApiRouteInfo new_apiRouteInfo = ApiRouteServiceWrapper.getInstance().saveApiRouteInstance4Rest(apiRouteInfo,routeWay); + URI returnURI =uriInfo.getAbsolutePathBuilder().path("/" + new_apiRouteInfo.getServiceName()+"/version/"+new_apiRouteInfo.getVersion()).build(); + return Response.created(returnURI).entity(new_apiRouteInfo).build(); + + } + + + + @DELETE + @Path("/{serviceName}/version/{version}") + @ApiOperation(value = "delete one ApiRoute by serviceName and version", code = HttpStatus.SC_NO_CONTENT) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NO_CONTENT, message = "delete ApiRouteInfo succeed "), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "ApiRouteInfo not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "delete ApiRouteInfo fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public void deleteApiRoute( + @ApiParam(value = "ApiRoute serviceName", required = true) @PathParam("serviceName") String serviceName, + @ApiParam(value = "ApiRoute version,if the version is empty, please enter \"null\"", required = false) @PathParam("version") @DefaultValue("") String version, + @ApiParam(value = "ApiRoute host", required = false) @QueryParam("host") String host, + @ApiParam(value = "ApiRoute Publish port", required = false) @QueryParam("publish_port") @DefaultValue("")String publish_port, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + + ApiRouteServiceWrapper.getInstance().deleteApiRoute(serviceName, version,host,publish_port,routeWay); + } + + + @GET + @Path("/apiDocs") + @ApiOperation(value = "get all Local apiDoc ", code = HttpStatus.SC_OK, response = String.class, responseContainer = "List") + @ApiResponses(value = {@ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get apiDoc List fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public String[] getApiDocs() { + + return ApiRouteServiceWrapper.getInstance().getAllApiDocs(); + } + + + @GET + @Path("/discoverInfo") + @ApiOperation(value = "get discover Info ", code = HttpStatus.SC_OK,response = DiscoverInfo.class) + @ApiResponses(value = {@ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get discover Info fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public DiscoverInfo getServiceDiscoverInfo() { + + return ConfigUtil.getInstance().getDiscoverInfo(); + } + + @PUT + @Path("/{serviceName}/version/{version}/status/{status}") + @ApiOperation(value = "update one ApiRoute status by serviceName and version", code = HttpStatus.SC_CREATED,response = ApiRouteInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable ApiRouteInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "ApiRouteInfo not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "update status fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response updateApiRouteStatus( + @ApiParam(value = "ApiRoute serviceName", required = true) @PathParam("serviceName") String serviceName, + @ApiParam(value = "ApiRoute version,if the version is empty, please enter \"null\"", required = false) @PathParam("version") @DefaultValue("") String version, + @ApiParam(value = "ApiRoute status,1:abled 0:disabled", required = true) @PathParam("status") String status, + @ApiParam(value = "ApiRoute host", required = false) @QueryParam("host") String host, + @ApiParam(value = "ApiRoute Publish port", required = false) @QueryParam("publish_port") @DefaultValue("")String publish_port, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + + ApiRouteInfo new_apiRouteInfo = ApiRouteServiceWrapper.getInstance().updateApiRouteStatus(serviceName,version,host,publish_port,status,routeWay); + return Response.created(uriInfo.getAbsolutePathBuilder().build()).entity(new_apiRouteInfo).build(); + + } + + @GET + @Path("/export") + @ApiOperation(value = "export all route service Info by json-file", code = HttpStatus.SC_OK,response = String.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "export fail", response = String.class), + @ApiResponse(code = HttpStatus.SC_NOT_ACCEPTABLE, message = " not Acceptable client-side", response = String.class)}) + @Produces(MediaType.TEXT_PLAIN) + public Response exportService(@ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) throws Exception { + + ResponseBuilder response = Response.ok( ApiRouteServiceWrapper.getInstance().getAllrouteByJson(routeWay)); + return response.header("Content-Disposition", "attachment; filename=\"RouteService.json\"").build(); + + } + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/resources/CustomRouteResource.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/resources/CustomRouteResource.java new file mode 100644 index 0000000..92b3408 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/resources/CustomRouteResource.java @@ -0,0 +1,164 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.resources; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.net.URI; +import java.util.List; + +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.apache.http.HttpStatus; +import org.onap.msb.apiroute.api.CustomRouteInfo; +import org.onap.msb.apiroute.wrapper.CustomRouteServiceWrapper; + +import com.codahale.metrics.annotation.Timed; + +@Path("/customRoute") +@Api(tags = { "CustomRoute" }) +@Produces(MediaType.APPLICATION_JSON) +public class CustomRouteResource { + + @Context + UriInfo uriInfo; // actual uri info + + @GET + @Path("/all") + @ApiOperation(value = "get all CustomRoute ", code = HttpStatus.SC_OK,response = CustomRouteInfo.class, responseContainer = "List") + @ApiResponses(value = {@ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get CustomRouteInfo List fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public List<CustomRouteInfo> getCustomRoutes(@ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + return CustomRouteServiceWrapper.getInstance().getAllCustomRouteInstances(routeWay); + } + + @POST + @Path("/instance") + @ApiOperation(value = "add one CustomRoute ", code = HttpStatus.SC_CREATED,response = CustomRouteInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable CustomRouteInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "add CustomRouteInfo fail", response = String.class), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Unprocessable CustomRouteInfo JSON REQUEST", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response addCustomRoute( + @ApiParam(value = "CustomRoute Instance Info", required = true) CustomRouteInfo customRouteInfo, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + CustomRouteInfo new_customRouteInfo = CustomRouteServiceWrapper.getInstance().saveCustomRouteInstance4Rest(customRouteInfo,routeWay); + URI returnURI =uriInfo.getAbsolutePathBuilder().path("/instance?serviceName=" + new_customRouteInfo.getServiceName()).build(); + return Response.created(returnURI).entity(new_customRouteInfo).build(); + + } + + @GET + @Path("/instance") + @ApiOperation(value = "get one CustomRoute ",code = HttpStatus.SC_OK, response = CustomRouteInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "CustomRoute not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable CustomRoute Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get CustomRoute fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public CustomRouteInfo getCustomRoute( + @ApiParam(value = "CustomRoute serviceName", required = false) @QueryParam("serviceName") String serviceName, + @ApiParam(value = "CustomRoute host", required = false) @QueryParam("host") String host, + @ApiParam(value = "CustomRoute Publish port", required = false) @QueryParam("publish_port") @DefaultValue("")String publish_port, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + + + return CustomRouteServiceWrapper.getInstance().getCustomRouteInstance(serviceName,host,publish_port,routeWay); + + } + + @PUT + @Path("/instance") + @ApiOperation(value = "update one CustomRoute by serviceName", code = HttpStatus.SC_CREATED,response = CustomRouteInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable CustomRoute Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "update CustomRoute fail", response = String.class), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Unprocessable CustomRoute JSON REQUEST", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response updateCustomRoute( + @ApiParam(value = "CustomRoute serviceName", required = true) @QueryParam("serviceName") String serviceName, + @ApiParam(value = "CustomRoute Instance Info", required = true) CustomRouteInfo customRoute, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay + ) { + + CustomRouteInfo new_customRouteInfo= CustomRouteServiceWrapper.getInstance().saveCustomRouteInstance4Rest(customRoute,routeWay); + + return Response.created(uriInfo.getAbsolutePathBuilder().build()).entity(new_customRouteInfo).build(); + + } + + @DELETE + @Path("/instance") + @ApiOperation(value = "delete one CustomRoute by serviceName", code = HttpStatus.SC_NO_CONTENT) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NO_CONTENT, message = "delete customRoute succeed "), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "customRoute not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "delete customRoute fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public void deleteCustomRoute( + @ApiParam(value = "CustomRoute serviceName", required = true) @QueryParam("serviceName") String serviceName, + @ApiParam(value = "CustomRoute host", required = false) @QueryParam("host") String host, + @ApiParam(value = "CustomRoute Publish port", required = false) @QueryParam("publish_port") @DefaultValue("")String publish_port, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + + CustomRouteServiceWrapper.getInstance().deleteCustomRoute(serviceName,host,publish_port,routeWay); + + } + + @PUT + @Path("/status") + @ApiOperation(value = "update one CustomRoute status by serviceName ",code = HttpStatus.SC_CREATED, response = CustomRouteInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable customRoute Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "customRoute not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "update status fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response updateCustomRouteStatus( + @ApiParam(value = "CustomRoute serviceName", required = true) @QueryParam("serviceName") String serviceName, + @ApiParam(value = "CustomRoute host", required = false) @QueryParam("host") String host, + @ApiParam(value = "CustomRoute status,1:abled 0:disabled", required = true) @QueryParam("status") String status, + @ApiParam(value = "CustomRoute Publish port", required = false) @QueryParam("publish_port") @DefaultValue("")String publish_port, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + + CustomRouteInfo new_customRouteInfo = CustomRouteServiceWrapper.getInstance().updateCustomRouteStatus(serviceName,host,publish_port,status,routeWay); + return Response.created(uriInfo.getAbsolutePathBuilder().build()).entity(new_customRouteInfo).build(); + + + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/resources/IuiRouteResource.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/resources/IuiRouteResource.java new file mode 100644 index 0000000..fea6645 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/resources/IuiRouteResource.java @@ -0,0 +1,163 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.resources; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.net.URI; +import java.util.List; + +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.apache.http.HttpStatus; +import org.onap.msb.apiroute.api.IuiRouteInfo; +import org.onap.msb.apiroute.wrapper.IuiRouteServiceWrapper; + +import com.codahale.metrics.annotation.Timed; + +@Path("/iuiRoute") +@Api(tags = { "iuiRoute" }) +@Produces(MediaType.APPLICATION_JSON) +public class IuiRouteResource { + + @Context + UriInfo uriInfo; // actual uri info + + @GET + @Path("/") + @ApiOperation(value = "get all iuiRoute ", code = HttpStatus.SC_OK,response = IuiRouteInfo.class, responseContainer = "List") + @ApiResponses(value = {@ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get iuiRouteInfo List fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public List<IuiRouteInfo> getIuiRoutes(@ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + return IuiRouteServiceWrapper.getInstance().getAllIuiRouteInstances(routeWay); + } + + @POST + @Path("/") + @ApiOperation(value = "add one iuiRoute ", code = HttpStatus.SC_CREATED,response = IuiRouteInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable iuiRouteInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "add iuiRouteInfo fail", response = String.class), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Unprocessable iuiRouteInfo JSON REQUEST", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response addIuiRoute( + @ApiParam(value = "iuiRoute Instance Info", required = true) IuiRouteInfo iuiRouteInfo, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + IuiRouteInfo new_iuiRouteInfo = IuiRouteServiceWrapper.getInstance().saveIuiRouteInstance4Rest(iuiRouteInfo,routeWay); + URI returnURI =uriInfo.getAbsolutePathBuilder().path("/" + new_iuiRouteInfo.getServiceName()).build(); + return Response.created(returnURI).entity(new_iuiRouteInfo).build(); + + } + + @GET + @Path("/{serviceName}") + @ApiOperation(value = "get one iuiRoute ",code = HttpStatus.SC_OK, response = IuiRouteInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "IuiRouteInfo not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable IuiRouteInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get IuiRouteInfo fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public IuiRouteInfo getIuiRoute( + @ApiParam(value = "iuiRoute serviceName", required = true) @PathParam("serviceName") String serviceName, + @ApiParam(value = "iuiRoute host", required = false) @QueryParam("host") String host, + @ApiParam(value = "iuiRoute Publish port", required = false) @QueryParam("publish_port") @DefaultValue("")String publish_port, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + + return IuiRouteServiceWrapper.getInstance().getIuiRouteInstance(serviceName,host,publish_port,routeWay); + + } + + @PUT + @Path("/{serviceName}") + @ApiOperation(value = "update one iuiRoute by serviceName", code = HttpStatus.SC_CREATED,response = IuiRouteInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable IuiRouteInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "update IuiRouteInfo fail", response = String.class), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Unprocessable IuiRouteInfo JSON REQUEST", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response updateIuiRoute( + @ApiParam(value = "iuiRoute serviceName", required = true) @PathParam("serviceName") String serviceName, + @ApiParam(value = "iuiRoute Instance Info", required = true) IuiRouteInfo iuiRouteInfo, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + + IuiRouteInfo new_iuiRouteInfo = IuiRouteServiceWrapper.getInstance().saveIuiRouteInstance4Rest(iuiRouteInfo,routeWay); + URI returnURI =uriInfo.getAbsolutePathBuilder().path("/" + serviceName).build(); + return Response.created(returnURI).entity(new_iuiRouteInfo).build(); + } + + @DELETE + @Path("/{serviceName}") + @ApiOperation(value = "delete one iuiRoute by serviceName", code = HttpStatus.SC_NO_CONTENT) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NO_CONTENT, message = "delete IuiRouteInfo succeed "), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "IuiRouteInfo not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "delete IuiRouteInfo fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public void deleteIuiRoute( + @ApiParam(value = "iuiRoute serviceName", required = true) @PathParam("serviceName") String serviceName, + @ApiParam(value = "iuiRoute host", required = false) @QueryParam("host") String host, + @ApiParam(value = "iuiRoute Publish port", required = false) @QueryParam("publish_port") @DefaultValue("")String publish_port, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + + IuiRouteServiceWrapper.getInstance().deleteIuiRoute(serviceName,host,publish_port,routeWay); + + } + + @PUT + @Path("/{serviceName}/status/{status}") + @ApiOperation(value = "update one iuiRoute status by serviceName ",code = HttpStatus.SC_CREATED, response = IuiRouteInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable IuiRouteInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "IuiRouteInfo not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "update IuiRouteInfo status fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response updateIuiRouteStatus( + @ApiParam(value = "iuiRoute serviceName", required = true) @PathParam("serviceName") String serviceName, + @ApiParam(value = "iuiRoute host", required = false) @QueryParam("host") String host, + @ApiParam(value = "iuiRoute status,1:abled 0:disabled", required = true) @PathParam("status") String status, + @ApiParam(value = "iuiRoute Publish port", required = false) @QueryParam("publish_port") @DefaultValue("")String publish_port, + @ApiParam(value = "Route Way", required = false) @QueryParam("routeWay") @DefaultValue("ip")String routeWay) { + + IuiRouteInfo new_iuiRouteInfo = IuiRouteServiceWrapper.getInstance().updateIuiRouteStatus(serviceName,host,publish_port,status,routeWay); + URI returnURI =uriInfo.getAbsolutePathBuilder().path("/" + serviceName).build(); + return Response.created(returnURI).entity(new_iuiRouteInfo).build(); + + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/resources/MicroServiceResource.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/resources/MicroServiceResource.java new file mode 100644 index 0000000..5beb209 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/resources/MicroServiceResource.java @@ -0,0 +1,229 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.resources; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.net.URI; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.apache.http.HttpStatus; +import org.onap.msb.apiroute.api.MicroServiceFullInfo; +import org.onap.msb.apiroute.api.exception.ExtendedInternalServerErrorException; +import org.onap.msb.apiroute.health.ConsulLinkHealthCheck; +import org.onap.msb.apiroute.health.RedisHealthCheck; +import org.onap.msb.apiroute.wrapper.MicroServiceWrapper; +import org.onap.msb.apiroute.wrapper.util.MicroServiceUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.codahale.metrics.annotation.Timed; +import com.codahale.metrics.health.HealthCheck.Result; + +@Path("/services") +// @Api(tags = {"MSB-Service Resource"}) +@Produces(MediaType.APPLICATION_JSON) +public class MicroServiceResource { + + private static final Logger LOGGER = LoggerFactory.getLogger(MicroServiceResource.class); + + @Context + UriInfo uriInfo; // actual uri info + + @GET + @Path("/") + @ApiOperation(value = "get all microservices ", code = HttpStatus.SC_OK, response = MicroServiceFullInfo.class, responseContainer = "List") + @ApiResponses(value = {@ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get microservice List fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public List<MicroServiceFullInfo> getMicroService() { + return MicroServiceWrapper.getInstance().getAllMicroServiceInstances(); + } + + @POST + @Path("/") + @ApiOperation(value = "add one microservice ", code = HttpStatus.SC_CREATED, response = MicroServiceFullInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "add microservice fail", response = String.class), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Unprocessable MicroServiceInfo JSON REQUEST", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response addMicroService( + @ApiParam(value = "MicroServiceInfo Instance Info", required = true) MicroServiceFullInfo microServiceInfo, + @Context HttpServletRequest request, + @ApiParam(value = "createOrUpdate", required = false) @QueryParam("createOrUpdate") @DefaultValue("true") boolean createOrUpdate, + @ApiParam(value = "port", required = false) @QueryParam("port") @DefaultValue("") String port) { + + String ip=MicroServiceUtil.getRealIp(request); + + MicroServiceFullInfo microServiceFullInfo =MicroServiceWrapper.getInstance().saveMicroServiceInstance(microServiceInfo,createOrUpdate,ip,port); + URI returnURI =uriInfo.getAbsolutePathBuilder().path("/" + microServiceInfo.getServiceName() + "/version/"+ microServiceInfo.getVersion()).build(); + return Response.created(returnURI).entity(microServiceFullInfo).build(); + } + + + + @GET + @Path("/{serviceName}/version/{version}") + @ApiOperation(value = "get one microservice ", code = HttpStatus.SC_OK, response = MicroServiceFullInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "microservice not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get microservice fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public MicroServiceFullInfo getMicroService( + @ApiParam(value = "microservice serviceName") @PathParam("serviceName") String serviceName, + @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"") @PathParam("version") @DefaultValue("") String version) { + + + return MicroServiceWrapper.getInstance().getMicroServiceInstance(serviceName, version); + + + } + + @PUT + @Path("/{serviceName}/version/{version}") + @ApiOperation(value = "update one microservice by serviceName and version", code = HttpStatus.SC_CREATED, response = MicroServiceFullInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "update microservice fail", response = String.class), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Unprocessable MicroServiceInfo JSON REQUEST", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response updateMicroService( + @ApiParam(value = "microservice serviceName") @PathParam("serviceName") String serviceName, + @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"") @PathParam("version") @DefaultValue("") String version, + @ApiParam(value = "microservice Instance Info", required = true) MicroServiceFullInfo microServiceInfo, + @Context HttpServletRequest request) { + + String ip=MicroServiceUtil.getRealIp(request); + MicroServiceFullInfo microServiceFullInfo = MicroServiceWrapper.getInstance().saveMicroServiceInstance(microServiceInfo, + false,ip,""); + return Response.created(uriInfo.getAbsolutePathBuilder().build()).entity(microServiceFullInfo).build(); + + } + + + + + @DELETE + @Path("/{serviceName}/version/{version}/nodes/{ip}/{port}") + @ApiOperation(value = "delete single node by serviceName and version and node", code = HttpStatus.SC_NO_CONTENT) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NO_CONTENT, message = "delete node succeed "), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "node not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "delete node fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public void deleteNode( + @ApiParam(value = "microservice serviceName", required = true) @PathParam("serviceName") String serviceName, + @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"", required = false) @PathParam("version") @DefaultValue("") String version, + @ApiParam(value = "ip") @PathParam("ip") String ip, + @ApiParam(value = "port") @PathParam("port") String port) { + + MicroServiceWrapper.getInstance().deleteMicroServiceInstance(serviceName, version, ip,port); + + } + + + @DELETE + @Path("/{serviceName}/version/{version}") + @ApiOperation(value = "delete one full microservice by serviceName and version", code = HttpStatus.SC_NO_CONTENT) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NO_CONTENT, message = "delete microservice succeed "), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "microservice not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "delete microservice fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public void deleteMicroService( + @ApiParam(value = "microservice serviceName", required = true) @PathParam("serviceName") String serviceName, + @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"", required = false) @PathParam("version") @DefaultValue("") String version) { + + MicroServiceWrapper.getInstance().deleteMicroService(serviceName, version); + + } + + @PUT + @Path("/{serviceName}/version/{version}/status/{status}") + @ApiOperation(value = "update microservice status by serviceName and version", code = HttpStatus.SC_CREATED, response = MicroServiceFullInfo.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "microservice not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "update status fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response updateServiceStatus( + @ApiParam(value = "microservice serviceName", required = true) @PathParam("serviceName") String serviceName, + @ApiParam(value = "microservice version,if the version is empty, please enter \"null\"", required = false) @PathParam("version") @DefaultValue("") String version, + @ApiParam(value = "status,1:abled 0:disabled") @PathParam("status") String status) { + + MicroServiceFullInfo microServiceFullInfo = MicroServiceWrapper.getInstance().updateMicroServiceStatus(serviceName, version,status); + + return Response.created(uriInfo.getAbsolutePathBuilder().build()).entity(microServiceFullInfo).build(); + + } + + @GET + @Path("/health") + @ApiOperation(value = "apigateway healthy check ", code = HttpStatus.SC_OK, response = String.class) + @ApiResponses(value = { @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "check fail", response = String.class) }) + @Produces(MediaType.TEXT_PLAIN) + @Timed + public Response health() { + + // redis + Result rst = RedisHealthCheck.getResult(); + if (!rst.isHealthy()) { + LOGGER.warn("health check failed:"+rst.getMessage()); + throw new ExtendedInternalServerErrorException(rst.getMessage()); + } + + //consul + rst = ConsulLinkHealthCheck.getResult(); + if (!rst.isHealthy()) { + LOGGER.warn("health check failed:"+rst.getMessage()); + throw new ExtendedInternalServerErrorException(rst.getMessage()); + } + + return Response.ok("apigateway healthy check:ok").build(); + } + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/ApiRouteServiceWrapper.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/ApiRouteServiceWrapper.java new file mode 100644 index 0000000..80dc607 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/ApiRouteServiceWrapper.java @@ -0,0 +1,273 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.wrapper; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URL; +import java.util.List; + +import org.onap.msb.apiroute.api.ApiRouteInfo; +import org.onap.msb.apiroute.api.exception.ExtendedInternalServerErrorException; +import org.onap.msb.apiroute.api.exception.ExtendedNotFoundException; +import org.onap.msb.apiroute.wrapper.service.ApiRouteService; +import org.onap.msb.apiroute.wrapper.util.CommonUtil; +import org.onap.msb.apiroute.wrapper.util.FileUtil; +import org.onap.msb.apiroute.wrapper.util.JacksonJsonUtil; +import org.onap.msb.apiroute.wrapper.util.RouteUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +public class ApiRouteServiceWrapper { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApiRouteServiceWrapper.class); + + + private static ApiRouteServiceWrapper instance = new ApiRouteServiceWrapper(); + + private ApiRouteServiceWrapper() {} + + public static ApiRouteServiceWrapper getInstance() { + return instance; + } + + + public List<ApiRouteInfo> getAllApiRouteInstances(String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + try { + String apiRedisKey=RouteUtil.getMutiRedisKey(RouteUtil.APIROUTE, routeWay); + + return ApiRouteService.getInstance().getMultiApiRouteInstances(apiRedisKey); + + } catch (Exception e) { + throw new ExtendedInternalServerErrorException(e.getMessage()); + } + } + + + + /** + * @Title: getApiRouteInstance + * @Description: TODO(Through the name + version for a single service object information) + * @param: @param serviceName + * @param: @param version + * @param: @return + * @return: ApiRouteInfo + */ + public ApiRouteInfo getApiRouteInstance(String serviceName, String version, String host,String publish_port,String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + if ("null".equals(version)) { + version = ""; + } + + RouteUtil.checkServiceNameAndVersion(serviceName,version); + + String apiRedisPrefixedKey=RouteUtil.getAPIRedisPrefixedKey(serviceName, version, host, publish_port, routeWay); + + ApiRouteInfo apiRouteInfo; + try { + apiRouteInfo = ApiRouteService.getInstance().getApiRouteInstance(apiRedisPrefixedKey); + } catch (Exception e) { + LOGGER.error("get ApiRouteInstance throw exception", e); + throw new ExtendedInternalServerErrorException("get ApiRouteInstance throw exception" + e.getMessage()); + } + + + + if (null == apiRouteInfo) { + throw new ExtendedNotFoundException("Api RouteInfo not found"); + } + + return apiRouteInfo; + + } + + + + /** + * @Title updateApiRouteStatus + * @Description TODO(update ApiRoute Status) + * @param serviceName + * @param version + * @param status + * @return + * @return RouteResult + */ + public synchronized ApiRouteInfo updateApiRouteStatus(String serviceName, String version,String host,String publish_port, + String status,String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + if ("null".equals(version)) { + version = ""; + } + + RouteUtil.checkServiceNameAndVersion(serviceName,version); + + RouteUtil.checkServiceStatus(status); + + + String apiRedisPrefixedKey=RouteUtil.getAPIRedisPrefixedKey(serviceName, version, host, publish_port, routeWay); + + try { + ApiRouteService.getInstance().updateApiRouteStatus2Redis(apiRedisPrefixedKey, status); + } catch (Exception e) { + LOGGER.error("update ApiRoute status throw exception", e); + throw new ExtendedInternalServerErrorException(e.getMessage()); + } + + ApiRouteInfo new_apiRouteInfo = getApiRouteInstance(serviceName, version,host,publish_port,routeWay); + return new_apiRouteInfo; + } + + + /** + * @Title: saveApiRouteInstance + * @Description: TODO(save ApiRouteInstance) + * @param: @param apiRouteInfo + * @param: @return + * @return: ApiRouteInfo + */ + public synchronized ApiRouteInfo saveApiRouteInstance4Rest(ApiRouteInfo apiRouteInfo,String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + RouteUtil.checkRouterInfoFormat(apiRouteInfo); + + try { + saveApiRouteInstance(apiRouteInfo,routeWay); + } catch (Exception e) { + throw new ExtendedInternalServerErrorException("save apiRouteInfo fail: [serviceName]"+apiRouteInfo.getServiceName()+"[version]"+apiRouteInfo.getVersion()+" [routeWay]"+routeWay+e.getMessage()); + } + + return apiRouteInfo; + } + + + + public synchronized void saveApiRouteInstance(ApiRouteInfo apiRouteInfo,String routeWay) throws Exception { + try { + String apiRedisPrefixedKey=RouteUtil.getAPIRedisPrefixedKey(apiRouteInfo.getServiceName(), apiRouteInfo.getVersion(), apiRouteInfo.getHost(), apiRouteInfo.getPublish_port(), routeWay); + + ApiRouteService.getInstance().saveApiRouteService2Redis(apiRouteInfo, apiRedisPrefixedKey); + LOGGER.info("save apiRouteInfo [serviceName]"+apiRouteInfo.getServiceName()+"[version]"+apiRouteInfo.getVersion()+" [routeWay]"+routeWay+" success"); + } catch (Exception e) { + LOGGER.error("save apiRouteInfo [serviceName]"+apiRouteInfo.getServiceName()+"[version]"+apiRouteInfo.getVersion()+" [routeWay]"+routeWay+" throw exception", e); + throw e; + } + + + } + + + + /** + * @Title: deleteApiRoute + * @Description: TODO(delete one ApiRoute) + * @param: @param type + * @param: @param serviceName + * @param: @param version + * @param: @param delKey + * @param: @return + * @return: void + */ + public synchronized void deleteApiRoute(String serviceName, String version, String host,String publish_port,String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + if ("null".equals(version)) { + version = ""; + } + + RouteUtil.checkServiceNameAndVersion(serviceName,version); + + String apiRedisPrefixedKey=RouteUtil.getAPIRedisPrefixedKey(serviceName, version, host, publish_port, routeWay); + + + try { + ApiRouteService.getInstance() + .deleteApiRouteService2Redis(apiRedisPrefixedKey); + LOGGER.info("delete apiRouteInfo [serviceName]"+serviceName+"[version]"+version+" [host]"+host +" [publish_port]"+publish_port+" [routeWay]"+routeWay+" success"); + + } + catch (ExtendedNotFoundException e) { + throw e; + }catch (Exception e) { + LOGGER.error("delete apiRouteInfo [serviceName]"+serviceName+"[version]"+version+" [host]"+host +" [publish_port]"+publish_port+" [routeWay]"+routeWay+" throw exception", e); + + throw new ExtendedInternalServerErrorException("delete apiRouteInfo [serviceName]"+serviceName+"[version]"+version+e.getMessage()); + } + + + } + + + /** + * @Title: getAllApiDocs + * @Description: TODO(For local ext\initSwaggerJson directory of all the json file directory) + * @param: @return + * @return: String[] + */ + public String[] getAllApiDocs() { + URL apiDocsPath = ApiRouteServiceWrapper.class.getResource("/ext/initSwaggerJson"); + if (apiDocsPath != null) { + String path = apiDocsPath.getPath(); + + try { + return FileUtil.readfile(path); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + LOGGER.error("read ApiDocs Files throw FileNotFoundException", e); + throw new ExtendedInternalServerErrorException("read ApiDocs Files throw FileNotFoundException:" + e.getMessage()); + } catch (IOException e) { + // TODO Auto-generated catch block + LOGGER.error("read ApiDocs Files throw IOexception", e); + throw new ExtendedInternalServerErrorException("read ApiDocs Files throw IOexception:" + e.getMessage()); + } + + } + + return null; + } + + public String getAllrouteByJson(String routeWay){ + + Object[] apirouteArray= ApiRouteServiceWrapper.getInstance().getAllApiRouteInstances(routeWay).toArray(); + Object[] iuirouteArray= IuiRouteServiceWrapper.getInstance().getAllIuiRouteInstances(routeWay).toArray(); + Object[] customrouteArray= CustomRouteServiceWrapper.getInstance().getAllCustomRouteInstances(routeWay).toArray(); + + Object[] temprouteArray =CommonUtil.concat(apirouteArray, iuirouteArray); + Object[] allrouteArray=CommonUtil.concat(temprouteArray, customrouteArray); + + + String allrouteJson; + try { + allrouteJson = JacksonJsonUtil.beanToJson(allrouteArray); + } catch (Exception e) { + LOGGER.error("exportService beanToJson throw Exception", e); + throw new ExtendedInternalServerErrorException("exportService beanToJson throw Exception:"+ e.getMessage()); + } + return allrouteJson; + } + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/CustomRouteServiceWrapper.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/CustomRouteServiceWrapper.java new file mode 100644 index 0000000..50747b6 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/CustomRouteServiceWrapper.java @@ -0,0 +1,217 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.wrapper; + +import java.util.List; + +import org.onap.msb.apiroute.api.CustomRouteInfo; +import org.onap.msb.apiroute.api.exception.ExtendedInternalServerErrorException; +import org.onap.msb.apiroute.api.exception.ExtendedNotFoundException; +import org.onap.msb.apiroute.wrapper.service.CustomRouteService; +import org.onap.msb.apiroute.wrapper.util.RouteUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CustomRouteServiceWrapper { + + + private static final Logger LOGGER = LoggerFactory.getLogger(CustomRouteServiceWrapper.class); + + private static CustomRouteServiceWrapper instance = new CustomRouteServiceWrapper(); + + private CustomRouteServiceWrapper() {} + + public static CustomRouteServiceWrapper getInstance() { + return instance; + } + + + /** + * @Title: getAllCustomRouteService + * @Description: TODO(get AllCustomRoute Service) + * @param: @return + * @return: CustomRouteInfo[] + */ + public List<CustomRouteInfo> getAllCustomRouteInstances(String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + try { + String customRedisKey = RouteUtil.getMutiRedisKey(RouteUtil.CUSTOMROUTE, routeWay); + return CustomRouteService.getInstance().getMultiCustomRouteInstances(customRedisKey); + + } catch (Exception e) { + throw new ExtendedInternalServerErrorException(e.getMessage()); + } + + + } + + + + /** + * @Title: getCustomRouteInstance + * @Description: TODO(get CustomRouteInstance by serviceName) + * @param: @param serviceName + * @param: @return + * @return: CustomRouteInfo + */ + public CustomRouteInfo getCustomRouteInstance(String serviceName, String host, + String publish_port, String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + String customRedisPrefixedKey = + RouteUtil.getRedisPrefixedKey(RouteUtil.CUSTOMROUTE, serviceName, host, publish_port, + routeWay); + + CustomRouteInfo customRouteInfo; + try { + customRouteInfo = + CustomRouteService.getInstance().getCustomRouteInstance(customRedisPrefixedKey); + } catch (Exception e) { + LOGGER.error("get customRouteInstance throw exception", e); + throw new ExtendedInternalServerErrorException("get customRouteInstance throw exception"+ e.getMessage()); + } + + + if (null == customRouteInfo) { + throw new ExtendedNotFoundException("customRoute Info not found"); + + } + + return customRouteInfo; + + } + + + /** + * @Title updateCustomRouteStatus + * @Description TODO(update one CustomRoute Status) + * @param serviceName + * @param status + * @return + * @return RouteResult + */ + public synchronized CustomRouteInfo updateCustomRouteStatus(String serviceName, String host, + String publish_port, String status, String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + RouteUtil.checkServiceStatus(status); + + String customRedisPrefixedKey = + RouteUtil.getRedisPrefixedKey(RouteUtil.CUSTOMROUTE, serviceName, host, publish_port, + routeWay); + + + try { + CustomRouteService.getInstance() + .updateCustomRouteStatus2Redis(customRedisPrefixedKey, status); + } catch (Exception e) { + LOGGER.error("update CustomRoute status throw exception", e); + throw new ExtendedInternalServerErrorException(e.getMessage()); + } + + CustomRouteInfo new_customRouteInfo = + getCustomRouteInstance(serviceName, host, publish_port, routeWay); + + return new_customRouteInfo; + } + + /** + * @Title: saveCustomRouteInstance + * @Description: TODO(save one CustomRouteInstance) + * @param: @param CustomRouteInfo + * @param: @return + * @return: CustomRouteInfo + */ + public synchronized CustomRouteInfo saveCustomRouteInstance4Rest(CustomRouteInfo customRouteInfo, + String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + RouteUtil.checkRouterInfoFormat(customRouteInfo); + + try { + saveCustomRouteInstance(customRouteInfo, routeWay); + + } catch (Exception e) { + + throw new ExtendedInternalServerErrorException("save CustomRouteInfo fail: [serviceName]"+customRouteInfo.getServiceName()+e.getMessage()); + } + + return customRouteInfo; + + } + + + public synchronized CustomRouteInfo saveCustomRouteInstance(CustomRouteInfo customRouteInfo, + String routeWay) throws Exception { + try { + String customRedisPrefixedKey = + RouteUtil.getRedisPrefixedKey(RouteUtil.CUSTOMROUTE, customRouteInfo.getServiceName(), + customRouteInfo.getHost(), customRouteInfo.getPublish_port(), routeWay);; + + + CustomRouteService.getInstance().saveCustomRouteService2Redis(customRouteInfo, + customRedisPrefixedKey); + LOGGER.info("save CustomRouteInfo [serviceName]"+customRouteInfo.getServiceName()+" [host]"+customRouteInfo.getHost() +" [publish_port]"+customRouteInfo.getPublish_port()+" [routeWay]"+routeWay+" success"); + + } catch (Exception e) { + LOGGER.error("save CustomRouteInfo [serviceName]"+customRouteInfo.getServiceName()+" [host]"+customRouteInfo.getHost() +" [publish_port]"+customRouteInfo.getPublish_port()+" [routeWay]"+routeWay+" throw exception", e); + + throw e; + } + + return customRouteInfo; + + } + + + /** + * @Title: deleteCustomRoute + * @Description: TODO(delete one CustomRoute) + * @param: @param type + * @param: @param serviceName + * @param: @param delKey + * @param: @return + * @return: void + */ + public synchronized void deleteCustomRoute(String serviceName, String host, String publish_port, + String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + String customRedisPrefixedKey = + RouteUtil.getRedisPrefixedKey(RouteUtil.CUSTOMROUTE, serviceName, host, publish_port, + routeWay); + + try { + CustomRouteService.getInstance().deleteCustomRouteService2Redis(customRedisPrefixedKey); + LOGGER.info("delete CustomRouteInfo [serviceName]"+serviceName+" [host]"+host +" [publish_port]"+publish_port+" [routeWay]"+routeWay+" success"); + + } catch (ExtendedNotFoundException e) { + throw e; + } catch (Exception e) { + LOGGER.error("delete CustomRouteInfo [serviceName]"+serviceName+" [host]"+host +" [publish_port]"+publish_port+" [routeWay]"+routeWay+" throw exception", e); + throw new ExtendedInternalServerErrorException("delete CustomRouteInfo [serviceName]"+serviceName+e.getMessage()); + } + + + + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/InitRouteServiceWrapper.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/InitRouteServiceWrapper.java new file mode 100644 index 0000000..76be3d2 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/InitRouteServiceWrapper.java @@ -0,0 +1,416 @@ +package org.onap.msb.apiroute.wrapper; + +import io.dropwizard.jetty.HttpConnectorFactory; +import io.dropwizard.server.SimpleServerFactory; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.net.URL; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.onap.msb.apiroute.ApiRouteApp; +import org.onap.msb.apiroute.ApiRouteAppConfig; +import org.onap.msb.apiroute.SyncDataManager; +import org.onap.msb.apiroute.api.ApiRouteInfo; +import org.onap.msb.apiroute.api.CustomRouteInfo; +import org.onap.msb.apiroute.api.DiscoverInfo; +import org.onap.msb.apiroute.api.IuiRouteInfo; +import org.onap.msb.apiroute.api.RouteServer; +import org.onap.msb.apiroute.api.exception.ExtendedNotFoundException; +import org.onap.msb.apiroute.health.ConsulLinkHealthCheck; +import org.onap.msb.apiroute.health.RedisHealthCheck; +import org.onap.msb.apiroute.wrapper.serviceListener.MicroServiceChangeListener; +import org.onap.msb.apiroute.wrapper.serviceListener.RouteNotify; +import org.onap.msb.apiroute.wrapper.util.ConfigUtil; +import org.onap.msb.apiroute.wrapper.util.FileUtil; +import org.onap.msb.apiroute.wrapper.util.JacksonJsonUtil; +import org.onap.msb.apiroute.wrapper.util.JedisUtil; +import org.onap.msb.apiroute.wrapper.util.RegExpTestUtil; +import org.onap.msb.apiroute.wrapper.util.RouteUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import redis.clients.jedis.Jedis; + +import com.fasterxml.jackson.core.type.TypeReference; + +public class InitRouteServiceWrapper { + + private static final Logger LOGGER = LoggerFactory.getLogger(InitRouteServiceWrapper.class); + + + private static InitRouteServiceWrapper instance = new InitRouteServiceWrapper(); + + private InitRouteServiceWrapper() {} + + public static InitRouteServiceWrapper getInstance() { + return instance; + } + + + /** + * The listener registration service changes + */ + public void registerServiceChangeListener() { + + RouteNotify.getInstance().addServiceChangeListener(new MicroServiceChangeListener()); + + } + + public void initFilterConfig(){ + //route init + ConfigUtil.getInstance().initRouteWay(); + ConfigUtil.getInstance().initApiGatewayPort(); + ConfigUtil.getInstance().initRouteNameSpaceMatches(); + ConfigUtil.getInstance().initRouteLabelsMatches(); + ConfigUtil.getInstance().initNodeMetaQueryParam(); + + } + + public void initDataSynchro(){ + + registerServiceChangeListener(); + + boolean ifRedisConnect=startCheckRedisConnect(); + + if(ifRedisConnect){ + initRouteInfoFromJson(); + runConsulClientApp(); + } + } + + public void initHealthCheck() + { + LOGGER.info("start check consul link thread"); + Thread tConsul= new Thread(new ConsulLinkHealthCheck(),"_healthcheck_consul_"); + tConsul.setDaemon(true); + tConsul.start(); + + LOGGER.info("start check redis thread"); + Thread tRedies= new Thread(new RedisHealthCheck(),"_healthcheck_redis_"); + tRedies.setDaemon(true); + tRedies.start(); + } + + + + + public boolean startCheckRedisConnect() { + + int n = 0; + while (true) { + if (!checkRedisConnect()) { + n++; + LOGGER.warn(n + "/10 : Initial Route Configuration——redis connection fail..."); + + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + LOGGER.error("Thread.sleep throw except:" + e.getMessage()); + } + + + if (n >= 10) { + LOGGER.error("Initial Route Configuration——redis connection fail,timeout exit..."); + return false; + } + } else { + LOGGER.warn(" Initial Route Configuration——redis connection success..."); + return true; + } + } + + + } + + + // Open the consul to monitor subscription service + public void runConsulClientApp() { + + String consulIP; + int consulPort; + String consulConfSource="Default"; + + + DiscoverInfo discoverInfo = ConfigUtil.getInstance().getDiscoverInfo(); + + if (discoverInfo.isEnabled()) { + LOGGER.warn("starting to initial consul Configuration"); + String[] routeWay = ConfigUtil.getInstance().getRouteWay(); + try { + String sys_consulIp=ConfigUtil.getInstance().getConsul_ip(); + if (StringUtils.isNotBlank(sys_consulIp)) { + consulIP = sys_consulIp.trim(); + consulPort = RouteUtil.consulDeafultPort; + consulConfSource="env:CONSUL_IP"; + } else { + consulIP = discoverInfo.getIp(); + consulPort = discoverInfo.getPort(); + consulConfSource="init discoverInfo"; + } + + LOGGER.warn("init consul sync Address from [ "+consulConfSource+" ]:" + consulIP + ":" + consulPort); + + // Registration service discovery routing + // api + ApiRouteInfo discoverApiService = new ApiRouteInfo(); + discoverApiService.setServiceName("msdiscover"); + discoverApiService.setUrl("/api/microservices/v1"); + discoverApiService.setVersion("v1"); + discoverApiService.setMetricsUrl("/admin/metrics"); + discoverApiService.setApiJson("/api/microservices/v1/swagger.json"); + discoverApiService.setHost("msb"); + + RouteServer[] servers = new RouteServer[1]; + servers[0] = new RouteServer(discoverInfo.getIp(), String.valueOf(discoverInfo.getPort())); + discoverApiService.setServers(servers); + + + for (int i = 0; i < routeWay.length; i++) { + ApiRouteServiceWrapper.getInstance().saveApiRouteInstance4Rest(discoverApiService, + routeWay[i]); + } + + + + // iui + IuiRouteInfo discoverIUIService = new IuiRouteInfo(); + discoverIUIService.setServiceName("msdiscover"); + discoverIUIService.setUrl("/iui/microservices"); + discoverIUIService.setHost("msb"); + discoverIUIService.setServers(servers); + + for (int i = 0; i < routeWay.length; i++) { + IuiRouteServiceWrapper.getInstance() + .saveIuiRouteInstance(discoverIUIService, routeWay[i]); + } + + + /* + * ConsulClientApp consulClientApp = new ConsulClientApp(consulIP, consulPort); + * consulClientApp.startServiceListen(); + */ + + // SyncDataManager syncDataManager = new SyncDataManager(); + // Monitor serviceList change + SyncDataManager.initSyncTask(consulIP, consulPort); + + + LOGGER.warn("start monitor consul service--" + consulIP + ":" + consulPort); + } catch (Exception e) { + LOGGER.error("start monitor consul service fail:" + e.getMessage()); + } + } + + + + } + + + + /** + * @Title: initRouteInfoFromJson + * @Description: TODO(According to the JSON file configuration initialization route data) + * @return: void + */ + public void initRouteInfoFromJson() { + LOGGER.info("starting to initial Route Configuration"); + URL apiDocsPath = InitRouteServiceWrapper.class.getResource("/ext/initServices"); + if (apiDocsPath != null) { + String path = apiDocsPath.getPath(); + + LOGGER.info("read JsonFilefolder:" + path); + + try { + File[] files = FileUtil.readFileFolder(path); + for (int i = 0; i < files.length; i++) { + File file = files[i]; + if (file.isFile() && file.getName().endsWith(".json")) { + LOGGER.info("read JsonFile:" + file.getPath()); + String fileContent = FileUtil.readFile(file.getPath()); + saveInitService2redis(fileContent); + } else { + LOGGER.warn(file.getName() + " is not a right file"); + } + } + + + + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + LOGGER.error("read initServices Files throw FileNotFoundException", e); + } catch (IOException e) { + // TODO Auto-generated catch block + LOGGER.error("read initServices Files throw IOexception", e); + } + + } + + + + } + + + + private void saveInitService2redis(String fileContent) { + + String[] routeWay = ConfigUtil.getInstance().getRouteWay(); + String iuiRootPath = ConfigUtil.getInstance().getIUI_ROOT_PATH(); + + try { + List<ApiRouteInfo> routeList = + JacksonJsonUtil.jsonToListBean(fileContent, new TypeReference<List<ApiRouteInfo>>() {}); + for (ApiRouteInfo route : routeList) { + String url = route.getUrl(); + + if (RegExpTestUtil.urlRegExpTest(route.getServiceName())) { + + for (int i = 0; i < routeWay.length; i++) { + try { + + CustomRouteServiceWrapper.getInstance().getCustomRouteInstance( + route.getServiceName(), route.getHost(), "", routeWay[i]); + + } catch (ExtendedNotFoundException e) { + + LOGGER.info("initCustomRoute: ServiceName--" + route.getServiceName()); + + CustomRouteInfo customRouteInfo = new CustomRouteInfo(); + customRouteInfo.setControl(route.getControl()); + customRouteInfo.setServers(route.getServers()); + customRouteInfo.setServiceName(route.getServiceName()); + customRouteInfo.setStatus(route.getStatus()); + customRouteInfo.setUrl(route.getUrl()); + customRouteInfo.setHost(route.getHost()); + + + + CustomRouteServiceWrapper.getInstance().saveCustomRouteInstance(customRouteInfo, + routeWay[i]); + + } + } + } else { + + if (RegExpTestUtil.apiRouteUrlRegExpTest(url) || url.startsWith("/api/microservices/") || url.startsWith("/admin/microservices/")) { + + for (int i = 0; i < routeWay.length; i++) { + try { + + ApiRouteServiceWrapper.getInstance().getApiRouteInstance(route.getServiceName(), + route.getVersion(), route.getHost(), route.getPublish_port(), routeWay[i]); + + } catch (ExtendedNotFoundException e) { + LOGGER.info("initapiRoute: ServiceName--" + route.getServiceName()); + + if (url.startsWith("/api/microservices")) { + if (StringUtils.isNotBlank(System.getenv("dwApp_server_connector_port"))) { + replaceApigatewayPort(route.getServers(), + System.getenv("dwApp_server_connector_port")); + } + } + + if (url.startsWith("/admin/microservices")) { + replaceApigatewayPort(route.getServers(),ConfigUtil.getInstance().getServerPort()); + } + + ApiRouteServiceWrapper.getInstance().saveApiRouteInstance4Rest(route, routeWay[i]); + + } + } + + + } else if (RegExpTestUtil.iuiRouteUrlRegExpTest(url) || url.equals("/iui/microservices")) { + + for (int i = 0; i < routeWay.length; i++) { + try { + + IuiRouteServiceWrapper.getInstance().getIuiRouteInstance(route.getServiceName(), + route.getHost(), "", routeWay[i]); + + } catch (ExtendedNotFoundException e) { + + LOGGER.info(" initiuiRoute: ServiceName--" + route.getServiceName()); + IuiRouteInfo iuiRouteInfo = new IuiRouteInfo(); + iuiRouteInfo.setControl(route.getControl()); + iuiRouteInfo.setServers(route.getServers()); + iuiRouteInfo.setServiceName(route.getServiceName()); + iuiRouteInfo.setStatus(route.getStatus()); + iuiRouteInfo.setHost(route.getHost()); + + + if (url.equals("/iui/microservices")) { + iuiRouteInfo.setUrl("/" + iuiRootPath + "/microservices"); + if (StringUtils.isNotBlank(System.getenv("dwApp_server_connector_port"))) { + replaceApigatewayPort(iuiRouteInfo.getServers(), + System.getenv("dwApp_server_connector_port")); + } + } else { + iuiRouteInfo.setUrl(route.getUrl()); + } + + IuiRouteServiceWrapper.getInstance() + .saveIuiRouteInstance(iuiRouteInfo, routeWay[i]); + + + } + } + + } else { + LOGGER.error("init Service throw exception——serviceName: " + route.getServiceName() + + ",url:" + url); + } + } + + + + } + + } catch (Exception e) { + // TODO Auto-generated catch block + LOGGER.error("read initServices Files throw exception", e); + } + + } + + private void replaceApigatewayPort(RouteServer[] servers, String apigatewayPort) { + for (int i = 0; i < servers.length; i++) { + servers[i].setPort(apigatewayPort); + } + } + + public void initMetricsConfig(ApiRouteAppConfig configuration) { + + SimpleServerFactory simpleServerFactory = + (SimpleServerFactory) configuration.getServerFactory(); + HttpConnectorFactory httpConnectorFactory = + (HttpConnectorFactory) simpleServerFactory.getConnector(); + String metricsUrl = + "http://127.0.0.1:" + httpConnectorFactory.getPort() + + simpleServerFactory.getAdminContextPath() + "/metrics"; + ConfigUtil.getInstance().setMetricsUrl(metricsUrl); + } + + + private boolean checkRedisConnect() { + Jedis jedis = null; + try { + jedis = JedisUtil.borrowJedisInstance(); + return true; + } catch (Exception e) { + LOGGER.error("checkRedisConnect call redis throw exception", e); + }finally { + JedisUtil.returnJedisInstance(jedis); + } + + return false; + } + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/IuiRouteServiceWrapper.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/IuiRouteServiceWrapper.java new file mode 100644 index 0000000..d66de21 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/IuiRouteServiceWrapper.java @@ -0,0 +1,221 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.wrapper; + +import java.util.List; + +import org.onap.msb.apiroute.api.IuiRouteInfo; +import org.onap.msb.apiroute.api.exception.ExtendedInternalServerErrorException; +import org.onap.msb.apiroute.api.exception.ExtendedNotFoundException; +import org.onap.msb.apiroute.wrapper.service.IuiRouteService; +import org.onap.msb.apiroute.wrapper.util.RouteUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class IuiRouteServiceWrapper { + + + private static final Logger LOGGER = LoggerFactory.getLogger(IuiRouteServiceWrapper.class); + + private static IuiRouteServiceWrapper instance = new IuiRouteServiceWrapper(); + + private IuiRouteServiceWrapper() {} + + public static IuiRouteServiceWrapper getInstance() { + return instance; + } + + + + /** + * @Title: getAllIuiRouteService + * @Description: TODO(get All IuiRouteServices) + * @param: @return + * @return: IuiRouteInfo[] + */ + public List<IuiRouteInfo> getAllIuiRouteInstances(String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + try { + String iuiRedisKey = RouteUtil.getMutiRedisKey(RouteUtil.IUIROUTE, routeWay); + + return IuiRouteService.getInstance().getMultiIuiRouteInstances(iuiRedisKey); + + } catch (Exception e) { + throw new ExtendedInternalServerErrorException(e.getMessage()); + } + + + } + + + + /** + * @Title: getIuiRouteInstance + * @Description: TODO(get one IuiRouteInstance by serviceName) + * @param: @param serviceName + * @param: @return + * @return: IuiRouteInfo + */ + public IuiRouteInfo getIuiRouteInstance(String serviceName, String host, String publish_port, + String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + String iuiRedisPrefixedKey = + RouteUtil + .getRedisPrefixedKey(RouteUtil.IUIROUTE, serviceName, host, publish_port, routeWay); + + IuiRouteInfo iuiRouteInfo; + try { + iuiRouteInfo = IuiRouteService.getInstance().getIuiRouteInstance(iuiRedisPrefixedKey); + } catch (Exception e) { + LOGGER.error("get IuiRouteInstance throw exception", e); + throw new ExtendedInternalServerErrorException("get IuiRouteInstance throw exception" + + e.getMessage()); + } + + + + if (null == iuiRouteInfo) { + throw new ExtendedNotFoundException("iui RouteInfo not found"); + } + + return iuiRouteInfo; + } + + + + /** + * @Title updateIuiRouteStatus + * @Description TODO(update one IuiRoute Status) + * @param serviceName + * @param status + * @return + * @return RouteResult + */ + public synchronized IuiRouteInfo updateIuiRouteStatus(String serviceName, String host, + String publish_port, String status, String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + RouteUtil.checkServiceStatus(status); + + try { + String iuiRedisPrefixedKey = + RouteUtil.getRedisPrefixedKey(RouteUtil.IUIROUTE, serviceName, host, publish_port, + routeWay); + + IuiRouteService.getInstance().updateIuiRouteStatus2Redis(iuiRedisPrefixedKey, status); + + + } catch (Exception e) { + LOGGER.error("update IuiRoute status throw exception", e); + throw new ExtendedInternalServerErrorException(e.getMessage()); + } + + IuiRouteInfo new_iuiRouteInfo = getIuiRouteInstance(serviceName, host, publish_port, routeWay); + + return new_iuiRouteInfo; + } + + /** + * @Title: saveIuiRouteInstance + * @Description: TODO(save one IuiRouteInstance) + * @param: @param IuiRouteInfo + * @param: @return + * @return: IuiRouteInfo + */ + public synchronized IuiRouteInfo saveIuiRouteInstance4Rest(IuiRouteInfo iuiRouteInfo, + String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + RouteUtil.checkRouterInfoFormat(iuiRouteInfo); + + + try { + saveIuiRouteInstance(iuiRouteInfo, routeWay); + } catch (Exception e) { + throw new ExtendedInternalServerErrorException("save iuiRouteInfo fail: [serviceName]" + + iuiRouteInfo.getServiceName() + e.getMessage()); + } + + return iuiRouteInfo; + } + + + public synchronized void saveIuiRouteInstance(IuiRouteInfo iuiRouteInfo, String routeWay) + throws Exception { + try { + String iuiRedisPrefixedKey = + RouteUtil.getRedisPrefixedKey(RouteUtil.IUIROUTE, iuiRouteInfo.getServiceName(), + iuiRouteInfo.getHost(), iuiRouteInfo.getPublish_port(), routeWay); + + IuiRouteService.getInstance().saveIuiRouteService2Redis(iuiRouteInfo, iuiRedisPrefixedKey); + LOGGER.info("save iuiRouteInfo [serviceName]" + iuiRouteInfo.getServiceName() + " [host]" + + iuiRouteInfo.getHost() + " [publish_port]" + iuiRouteInfo.getPublish_port() + + " [routeWay]" + routeWay + " success"); + + } catch (Exception e) { + LOGGER.error("save iuiRouteInfo [serviceName]" + iuiRouteInfo.getServiceName() + " [host]" + + iuiRouteInfo.getHost() + " [publish_port]" + iuiRouteInfo.getPublish_port() + + " [routeWay]" + routeWay + " throw exception", e); + throw e; + } + } + + + + /** + * @Title: deleteIuiRoute + * @Description: TODO(delete one IuiRoute) + * @param: @param type + * @param: @param serviceName + * @param: @param delKey + * @param: @return + * @return: void + */ + public synchronized void deleteIuiRoute(String serviceName, String host, String publish_port, + String routeWay) { + + RouteUtil.checkRouteWay(routeWay); + + String iuiRedisPrefixedKey = + RouteUtil + .getRedisPrefixedKey(RouteUtil.IUIROUTE, serviceName, host, publish_port, routeWay); + + try { + IuiRouteService.getInstance().deleteIuiRouteService2Redis(iuiRedisPrefixedKey); + LOGGER.info("delete iuiRouteInfo [serviceName]" + serviceName + " [host]" + host + + " [publish_port]" + publish_port + " [routeWay]" + routeWay + " success"); + + } catch (ExtendedNotFoundException e) { + throw e; + } catch (Exception e) { + LOGGER.error("delete iuiRouteInfo [serviceName]" + serviceName + " [host]" + host + + " [publish_port]" + publish_port + " [routeWay]" + routeWay + " throw exception", e); + throw new ExtendedInternalServerErrorException("delete iuiRouteInfo [serviceName]" + serviceName +e.getMessage()); + } + + + + } + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/MicroServiceWrapper.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/MicroServiceWrapper.java new file mode 100644 index 0000000..a30151e --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/MicroServiceWrapper.java @@ -0,0 +1,398 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.wrapper; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.onap.msb.apiroute.api.MicroServiceFullInfo; +import org.onap.msb.apiroute.api.Node; +import org.onap.msb.apiroute.api.exception.ExtendedInternalServerErrorException; +import org.onap.msb.apiroute.api.exception.ExtendedNotFoundException; +import org.onap.msb.apiroute.api.exception.UnprocessableEntityException; +import org.onap.msb.apiroute.wrapper.dao.RedisAccessWrapper; +import org.onap.msb.apiroute.wrapper.service.MicroServiceFullService; +import org.onap.msb.apiroute.wrapper.serviceListener.RouteNotify; +import org.onap.msb.apiroute.wrapper.util.MicroServiceUtil; +import org.onap.msb.apiroute.wrapper.util.RegExpTestUtil; +import org.onap.msb.apiroute.wrapper.util.RouteUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MicroServiceWrapper { + + private static final Logger LOGGER = LoggerFactory.getLogger(MicroServiceWrapper.class); + + private static MicroServiceWrapper instance = new MicroServiceWrapper(); + + + private MicroServiceWrapper() {} + + public static MicroServiceWrapper getInstance() { + return instance; + } + + + + + /** + * @Title: getAllMicroServiceInstances + * @Description: getAllMicroServiceInstances + * @param: @return + * @return: Response + * @throws Exception + */ + public List<MicroServiceFullInfo> getAllMicroServiceInstances() { + + try { + return MicroServiceFullService.getInstance().getAllMicroServiceInstances(); + + } catch (Exception e) { + throw new ExtendedInternalServerErrorException(e.getMessage()); + } + + } + + public Set<String> getAllMicroServiceKey() { + int failedNum = 0; + int retryCount=3; + int failedTimer = 5 * 1000; + + Set<String> serviceKeys=null; + + do { + + try { + serviceKeys= MicroServiceFullService.getInstance().getAllMicroServiceKey(); + break; + + } catch (Exception e) { + + LOGGER.error(failedNum + "/"+retryCount+" : get AllMicroServiceKey fail"+e); + failedNum++; + + try { + Thread.sleep(failedTimer); + } catch (InterruptedException ex) { + LOGGER.warn("get AllMicroServiceKey Thread.sleep throw except:" + ex.getMessage()); + } + } + + }while (failedNum <= retryCount); + + + return serviceKeys; + + } + + + + + /** + * @Title: getMicroServiceInstance + * @Description: (getMicroServiceInstance) + * @param: @param serviceName + * @param: @param version + * @param: @return + * @return: ApiRouteInfo + */ + public MicroServiceFullInfo getMicroServiceInstance(String serviceName, String version) { + if ("null".equals(version)) { + version = ""; + } + serviceName = serviceName.replace("*", "/"); + + RouteUtil.checkServiceNameAndVersion(serviceName, version); + + MicroServiceFullInfo microServiceInfo; + try { + microServiceInfo = + MicroServiceFullService.getInstance().getMicroServiceInstance(serviceName, version); + + } catch (Exception e) { + throw new ExtendedInternalServerErrorException(e.getMessage()); + } + + if (null == microServiceInfo) { + String errInfo = "microservice not found: serviceName-" + serviceName + ",version-" + version; + throw new ExtendedNotFoundException(errInfo); + + } + + return microServiceInfo; + } + + + + /** + * @Title updateMicroServiceStatus + * @Description updateMicroServiceStatus + * @param serviceName + * @param version + * @param status + * @return + * @return RouteResult + */ + + public synchronized MicroServiceFullInfo updateMicroServiceStatus(String serviceName, + String version, String status) { + + if ("null".equals(version)) { + version = ""; + } + serviceName = serviceName.replace("*", "/"); + + RouteUtil.checkServiceNameAndVersion(serviceName, version); + + RouteUtil.checkServiceStatus(status); + + try { + + MicroServiceFullService.getInstance().updateMicroServiceStatus(serviceName, version, status); + + MicroServiceFullInfo newMicroServiceInfo = + MicroServiceFullService.getInstance().getMicroServiceInstance(serviceName, version); + + // Notify the listeners + RouteNotify.getInstance().noticeUpdateStatusListener(newMicroServiceInfo, status); + + + return newMicroServiceInfo; + } catch (NullPointerException e) { + throw new ExtendedNotFoundException(e.getMessage()); + } catch (Exception e) { + LOGGER.error("update MicroServiceNode throw exception", e); + throw new ExtendedInternalServerErrorException(e.getMessage()); + } + + + } + + + public synchronized MicroServiceFullInfo saveMicroServiceInstance( + MicroServiceFullInfo microServiceInfo, boolean createOrUpdate, String requestIP, + String serverPort) { + + RouteUtil.checkMicroServiceInfoFormat(microServiceInfo, requestIP); + + try { + + if (createOrUpdate == false) { + deleteServiceAndnoticeRoute(microServiceInfo); + } + + saveServiceAndnoticeRoute(microServiceInfo); + + + MicroServiceFullInfo newMicroServiceInfo = + MicroServiceFullService.getInstance().getMicroServiceInstance( + microServiceInfo.getServiceName(), microServiceInfo.getVersion()); + + + return newMicroServiceInfo; + + } catch (UnprocessableEntityException e) { + throw e; + } catch (Exception e) { + throw new ExtendedInternalServerErrorException("save MicroServiceInfo fail :[serviceName]" + microServiceInfo.getServiceName() + + "[version]" + microServiceInfo.getVersion()+ e.getMessage()); + } + + } + + + public synchronized void deleteMicroService4AllVersion(String serviceName) { + try { + + List<MicroServiceFullInfo> microServiceList4AllVersion = + MicroServiceFullService.getInstance().getAllVersionsOfTheService(serviceName); + + if (microServiceList4AllVersion.size() == 0) { + LOGGER.info("delete MicroServiceInfo for All Version Fail:serviceName-" + serviceName + + " not fond"); + } else { + for (MicroServiceFullInfo microServiceInfo : microServiceList4AllVersion) { + deleteServiceAndnoticeRoute(microServiceInfo); + } + } + + } catch (Exception e) { + LOGGER.error("delete MicroServiceInfo for all version :serviceName-" + serviceName +" throw exception", e); + + } + } + + + public synchronized void deleteMicroService(String serviceName, String version) { + if ("null".equals(version)) { + version = ""; + } + serviceName = serviceName.replace("*", "/"); + + RouteUtil.checkServiceNameAndVersion(serviceName, version); + + try { + + MicroServiceFullInfo microServiceInfo = + MicroServiceFullService.getInstance().getMicroServiceInstance(serviceName, version); + + if (microServiceInfo == null) { + LOGGER.error("delete MicroServiceInfo FAIL:serviceName-" + serviceName + ",version-"+ version + " not fond "); + } else { + + deleteServiceAndnoticeRoute(microServiceInfo); + } + + + } catch (ExtendedNotFoundException e) { + throw e; + } catch (Exception e) { + + throw new ExtendedInternalServerErrorException("delete MicroServiceInfo serviceName-" + serviceName + ",version-" + version+e.getMessage()); + + } + + + } + + public synchronized void deleteMicroServiceInstance(String serviceName, String version, + String ip, String port) { + if ("null".equals(version)) { + version = ""; + } + serviceName = serviceName.replace("*", "/"); + + RouteUtil.checkServiceNameAndVersion(serviceName, version); + + if (!RegExpTestUtil.ipRegExpTest(ip)) { + throw new UnprocessableEntityException("delete MicroServiceInfo FAIL:IP(" + ip+ ")is not a valid IP address"); + } + + if (!RegExpTestUtil.portRegExpTest(port)) { + throw new UnprocessableEntityException("delete MicroServiceInfo FAIL:Port(" + port + ")is not a valid Port address"); + } + + + try { + MicroServiceFullInfo microServiceInfo = + MicroServiceFullService.getInstance().getMicroServiceInstance(serviceName, version); + + if (microServiceInfo == null) { + throw new UnprocessableEntityException("delete MicroServiceInfo FAIL:serviceName-"+ serviceName + ",version-" + version + " not fond "); + } + + Set<Node> nodes = microServiceInfo.getNodes(); + + boolean ifFindBNode = false; + + for (Node node : nodes) { + if (node.getIp().equals(ip) && node.getPort().equals(port)) { + ifFindBNode = true; + nodes.remove(node); + + if (nodes.isEmpty()) { + // delete MicroService + deleteServiceAndnoticeRoute(microServiceInfo); + } else { + // delete Node + MicroServiceFullService.getInstance().saveMicroServiceInfo2Redis(microServiceInfo); + RouteNotify.getInstance().noticeRouteListener4Update(serviceName, version, + microServiceInfo); + } + + break; + } + } + + if (!ifFindBNode) { + throw new ExtendedNotFoundException("delete MicroServiceInfo FAIL:serviceName-"+ serviceName + ",version-" + version +",node-" + ip + ":" + port + " not fond "); + } + + + } catch (ExtendedNotFoundException e) { + throw e; + } catch (Exception e) { + throw new ExtendedInternalServerErrorException("delete MicroServiceInfo :serviceName-"+ serviceName + ",version-" + version+",node-" + ip + ":" + port +"throw exception"+e.getMessage()); + + } + + } + + + public void deleteServiceAndnoticeRoute(MicroServiceFullInfo service) throws Exception { + + try { + // Delete the redis record + MicroServiceFullService.getInstance().deleteMicroService(service.getServiceName(), + service.getVersion()); + LOGGER.info("delete MicroServiceInfo And notice to Route success:[serviceName]"+ service.getServiceName() + "[version]" + service.getVersion()); + + // Notify the listeners + RouteNotify.getInstance().noticeRouteListener4Delete(service); + + } catch (Exception e) { + LOGGER.error("delete MicroService And synchro to Route:[serviceName]"+ service.getServiceName() + "[version]" + service.getVersion()+" throw exception", e); + throw e; + } + } + + public void saveServiceAndnoticeRoute(MicroServiceFullInfo service) throws Exception { + + try { + // save the redis record + MicroServiceFullService.getInstance().saveMicroServiceInfo2Redis(service); + + LOGGER.info("save MicroServiceInfo And notice to Route success:[serviceName]"+ service.getServiceName() + "[version]" + service.getVersion()); + + // Notify the listeners + RouteNotify.getInstance().noticeRouteListener4Add(service); + + + } catch (Exception e) { + LOGGER.error("save MicroServiceInfo And synchro to Route fail :[serviceName]" + service.getServiceName()+ "[version]" + service.getVersion() + " throw exception", e); + throw e; + } + } + + public Set<String> getAllVersion(String serviceName) { + Set<String> serviceVersionSet = new HashSet<String>(); + try { + String pattern = MicroServiceUtil.getServiceKey(serviceName, "*"); + Set<String> serviceKeySet = RedisAccessWrapper.filterKeys(pattern); + + + Pattern serviceKeyRegexPattern = MicroServiceUtil.getServiceKeyRegexPattern(); + for (String serviceKey : serviceKeySet) { + Matcher matcher = serviceKeyRegexPattern.matcher(serviceKey); + if (matcher.matches()) { + serviceVersionSet.add(matcher.group("version")); + } + } + } catch (Exception e) { + LOGGER.error("getAllVersion [serviceName]:" + serviceName + " throw exception", e); + } + + return serviceVersionSet; + + } + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/CatalogClient.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/CatalogClient.java new file mode 100644 index 0000000..94a709d --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/CatalogClient.java @@ -0,0 +1,87 @@ +package org.onap.msb.apiroute.wrapper.consulextend; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpHost; +import org.onap.msb.apiroute.wrapper.consulextend.async.ConsulResponseCallback; +import org.onap.msb.apiroute.wrapper.consulextend.util.Http; +import org.onap.msb.apiroute.wrapper.util.ConfigUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.orbitz.consul.option.CatalogOptions; +import com.orbitz.consul.option.QueryOptions; + +/** + * HTTP Client for /v1/catalog/ endpoints. + */ +public class CatalogClient { + + private static final Logger LOGGER = LoggerFactory + .getLogger(CatalogClient.class); + + private static final TypeReference<HttpEntity> TYPE_SERVICES_MAP = new TypeReference<HttpEntity>() { + }; + + + private static final String CATALOG_URI_8500 = "/v1/catalog"; + private static final String CATAlOG_URI_10081 = "/api/catalog/v1"; + + private static final String GET_SERVICES_URI = "/services"; + + private static final Http httpClient = Http.getInstance(); + + private HttpHost targetHost = null; + private String catalogUri = CATAlOG_URI_10081; + + CatalogClient(final HttpHost targetHost) { + this.targetHost = targetHost; + if (targetHost.getPort() == 8500) { + catalogUri = CATALOG_URI_8500; + } + } + + /** + * Retrieves all services for a given datacenter with + * {@link com.orbitz.consul.option.QueryOptions}. + * + * GET /v1/catalog/services?dc={datacenter} + * + * @param catalogOptions + * Catalog specific options to use. + * @param queryOptions + * The Query Options to use. + * @return A {@link com.orbitz.consul.model.ConsulResponse} containing a map + * of service name to list of tags. + */ + public void getServices(CatalogOptions catalogOptions, + QueryOptions queryOptions, + ConsulResponseCallback<HttpEntity> callback) { + + // prepare access path + // path:10081 vs 8500 + String path = targetHost.toString() + catalogUri + GET_SERVICES_URI; + + // params:wait,index,dc...... + String params = Http.optionsFrom(catalogOptions, queryOptions); + + // node meta: ns,external,internal..... + String node_meta = ConfigUtil.getInstance().getNodeMetaQueryParam(); + + // add params + path = (params != null && !params.isEmpty()) ? path += "?" + params + : path; + + // add node_meta + if (node_meta != null && !node_meta.isEmpty()) { + path = path.contains("?") ? path +"&"+ node_meta : path + "?" + + node_meta; + } + + // async watch services + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("get all services:" + path); + } + httpClient.asyncGetDelayHandle(path, TYPE_SERVICES_MAP, callback); + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/Consul.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/Consul.java new file mode 100644 index 0000000..cf8196a --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/Consul.java @@ -0,0 +1,97 @@ +package org.onap.msb.apiroute.wrapper.consulextend; + +import org.apache.http.HttpHost; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.annotations.VisibleForTesting; + +public class Consul { + /** + * Default Consul HTTP API host. + */ + public static final String DEFAULT_HTTP_HOST = "localhost"; + + /** + * Default Consul HTTP API port. + */ + public static final int DEFAULT_HTTP_PORT = 8500; + + private static final Logger LOGGER = LoggerFactory + .getLogger(Consul.class); + + private final CatalogClient catalogClient; + private final HealthClient healthClient; + + private Consul(CatalogClient catalogClient, HealthClient healthClient) { + this.catalogClient = catalogClient; + this.healthClient = healthClient; + } + + /** + * Get the Catalog HTTP client. + * <p> + * /v1/catalog + * + * @return The Catalog HTTP client. + */ + public CatalogClient catalogClient() { + return catalogClient; + } + + /** + * Get the Health HTTP client. + * <p> + * /v1/health + * + * @return The Health HTTP client. + */ + public HealthClient healthClient() { + return healthClient; + } + + /** + * Creates a new {@link Builder} object. + * + * @return A new Consul builder. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Used to create a default Consul client. + * + * @return A default {@link Consul} client. + */ + @VisibleForTesting + public static Consul newClient() { + return builder().build(); + } + + public static class Builder { + + private HttpHost targetHost; + + { + targetHost = new HttpHost(DEFAULT_HTTP_HOST, DEFAULT_HTTP_PORT); + } + + Builder() { + + } + + public Builder withHostAndPort(String hostname, int port) { + this.targetHost = new HttpHost(hostname, port); + return this; + } + + public Consul build() { + LOGGER.info("********build consul:"+targetHost.toString()+"****************"); + CatalogClient catalogClient = new CatalogClient(targetHost); + HealthClient healthClient = new HealthClient(targetHost); + return new Consul(catalogClient,healthClient); + } + + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/HealthClient.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/HealthClient.java new file mode 100644 index 0000000..899a57a --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/HealthClient.java @@ -0,0 +1,112 @@ +package org.onap.msb.apiroute.wrapper.consulextend; + +import java.util.List; + +import org.apache.http.HttpHost; +import org.onap.msb.apiroute.wrapper.consulextend.async.ConsulResponseCallback; +import org.onap.msb.apiroute.wrapper.consulextend.model.health.ServiceHealth; +import org.onap.msb.apiroute.wrapper.consulextend.util.Http; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.orbitz.consul.option.CatalogOptions; +import com.orbitz.consul.option.QueryOptions; + +/** + * HTTP Client for /v1/health/ endpoints. + */ +public class HealthClient { + private final static Logger LOGGER = LoggerFactory + .getLogger(HealthClient.class); + + private static final TypeReference<List<ServiceHealth>> TYPE_SERVICE_HEALTH_LIST = new TypeReference<List<ServiceHealth>>() { + }; + + private static final String HEALTH_URI_10081 = "/api/health/v1"; + private static final String HEALTH_URI_8500 = "/v1/health"; + private static final String GET_HEALTH_SERVICE_URI = "/service"; + +// private static final String GET_HEALTH_SERVICE_URI = "/v1/health/service"; + +// private static final String GET_HEALTH_SERVICE_URI = "/api/health/v1/service"; + + private final static Http httpClient = Http.getInstance(); + + private HttpHost targetHost = null; + private String healthUri = HEALTH_URI_10081; + + HealthClient(final HttpHost targetHost) { + this.targetHost = targetHost; + + if(targetHost.getPort() == 8500) + { + healthUri = HEALTH_URI_8500; + } + } + + /** + * Asynchronously retrieves the healthchecks for all healthy service + * instances in a given datacenter with + * {@link com.orbitz.consul.option.QueryOptions}. + * + * GET /v1/health/service/{service}?dc={datacenter}&passing + * + * Experimental. + * + * @param service + * The service to query. + * @param catalogOptions + * The catalog specific options to use. + * @param queryOptions + * The Query Options to use. + * @param callback + * Callback implemented by callee to handle results. + */ + public void getHealthyServiceInstances(String service, + CatalogOptions catalogOptions, QueryOptions queryOptions, + ConsulResponseCallback<List<ServiceHealth>> callback) { + // prepare access path + String path = targetHost.toString() + healthUri + GET_HEALTH_SERVICE_URI + "/"+ service; + + String params = Http.optionsFrom(catalogOptions, queryOptions); + path = (params != null && !params.isEmpty()) ? path += "?" + + params : path; //query all nodes without filter for health + + // async watch +// LOGGER.info("get health paasing service:" + path); + httpClient.asyncGetDelayHandle(path, TYPE_SERVICE_HEALTH_LIST, callback); + } + + /** + * Asynchronously retrieves the healthchecks for all nodes in a given + * datacenter with {@link com.orbitz.consul.option.QueryOptions}. + * + * GET /v1/health/service/{service}?dc={datacenter} + * + * Experimental. + * + * @param service + * The service to query. + * @param catalogOptions + * The catalog specific options to use. + * @param queryOptions + * The Query Options to use. + * @param callback + * Callback implemented by callee to handle results. + */ + public void getAllServiceInstances(String service, + CatalogOptions catalogOptions, QueryOptions queryOptions, + ConsulResponseCallback<List<ServiceHealth>> callback) { + + // prepare access path + String path = targetHost.toString() + healthUri + GET_HEALTH_SERVICE_URI + "/"+ service; + String params = Http.optionsFrom(catalogOptions, queryOptions); + path = (params != null && !params.isEmpty()) ? path += "?" + params + : path; + + // async watch +// LOGGER.debug("get service:" + path); + httpClient.asyncGetDelayHandle(path, TYPE_SERVICE_HEALTH_LIST, callback); + } +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/async/ConsulResponseCallback.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/async/ConsulResponseCallback.java new file mode 100644 index 0000000..ab5b74a --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/async/ConsulResponseCallback.java @@ -0,0 +1,33 @@ +package org.onap.msb.apiroute.wrapper.consulextend.async; + +import com.orbitz.consul.model.ConsulResponse; + +/** + * For API calls that support long-polling, this callback is used to handle + * the result on success or failure for an async HTTP call. + * + * @param <T> The Response type. + */ +public interface ConsulResponseCallback<T> { + + /** + * Callback for a successful {@link com.orbitz.consul.model.ConsulResponse}. + * + * @param consulResponse The Consul response. + */ + void onComplete(ConsulResponse<T> consulResponse); + + /** + * Callback for a successful {@link com.orbitz.consul.model.ConsulResponse}. + * + * @param consulResponse The Consul response. + */ + void onDelayComplete(OriginalConsulResponse<T> originalConsulResponse); + + /** + * Callback for an unsuccessful request. + * + * @param throwable The exception thrown. + */ + void onFailure(Throwable throwable); +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/async/ConsulResponseHeader.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/async/ConsulResponseHeader.java new file mode 100644 index 0000000..ae8291a --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/async/ConsulResponseHeader.java @@ -0,0 +1,27 @@ +package org.onap.msb.apiroute.wrapper.consulextend.async; + +import java.math.BigInteger; + +public class ConsulResponseHeader { + private final long lastContact; + private final boolean knownLeader; + private final BigInteger index; + + public ConsulResponseHeader(long lastContact, boolean knownLeader, BigInteger index) { + this.lastContact = lastContact; + this.knownLeader = knownLeader; + this.index = index; + } + + public long getLastContact() { + return lastContact; + } + + public boolean isKnownLeader() { + return knownLeader; + } + + public BigInteger getIndex() { + return index; + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/async/OriginalConsulResponse.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/async/OriginalConsulResponse.java new file mode 100644 index 0000000..dbad13b --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/async/OriginalConsulResponse.java @@ -0,0 +1,27 @@ +package org.onap.msb.apiroute.wrapper.consulextend.async; + +import org.apache.http.HttpResponse; + +import com.fasterxml.jackson.core.type.TypeReference; + +public class OriginalConsulResponse<T> { + final HttpResponse response; + final TypeReference<T> responseType; + + public OriginalConsulResponse(HttpResponse response, TypeReference<T> responseType) { + this.response = response; + this.responseType = responseType; + + } + + public HttpResponse getResponse() { + return response; + } + + public TypeReference<T> getResponseType() { + return responseType; + } + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/cache/ConsulCache.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/cache/ConsulCache.java new file mode 100644 index 0000000..809a8dc --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/cache/ConsulCache.java @@ -0,0 +1,301 @@ +package org.onap.msb.apiroute.wrapper.consulextend.cache; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + +import java.math.BigInteger; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import org.onap.msb.apiroute.wrapper.consulextend.async.ConsulResponseCallback; +import org.onap.msb.apiroute.wrapper.consulextend.async.ConsulResponseHeader; +import org.onap.msb.apiroute.wrapper.consulextend.async.OriginalConsulResponse; +import org.onap.msb.apiroute.wrapper.consulextend.util.Http; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Strings; +import com.orbitz.consul.ConsulException; +import com.orbitz.consul.model.ConsulResponse; +import com.orbitz.consul.option.ImmutableQueryOptions; +import com.orbitz.consul.option.QueryOptions; + +/** + * A cache structure that can provide an up-to-date read-only map backed by + * consul data + * + * @param <V> + */ +public class ConsulCache<T> { + + enum State { + latent, starting, started, stopped + } + + private final static Logger LOGGER = LoggerFactory + .getLogger(ConsulCache.class); + + @VisibleForTesting + static final String BACKOFF_DELAY_PROPERTY = "com.orbitz.consul.cache.backOffDelay"; + private static final long BACKOFF_DELAY_QTY_IN_MS = getBackOffDelayInMs(System + .getProperties()); + + private final AtomicReference<BigInteger> latestIndex = new AtomicReference<BigInteger>( + null); + private final AtomicReference<State> state = new AtomicReference<State>( + State.latent); + private final CountDownLatch initLatch = new CountDownLatch(1); + private final ScheduledExecutorService executorService = Executors + .newSingleThreadScheduledExecutor(); + private final CopyOnWriteArrayList<Listener<T>> listeners = new CopyOnWriteArrayList<Listener<T>>(); + + private final CallbackConsumer<T> callBackConsumer; + private final ConsulResponseCallback<T> responseCallback; + + ConsulCache(CallbackConsumer<T> callbackConsumer) { + + this.callBackConsumer = callbackConsumer; + + this.responseCallback = new ConsulResponseCallback<T>() { + @Override + public void onComplete(ConsulResponse<T> consulResponse) { + + if (consulResponse.isKnownLeader()) { + if (!isRunning()) { + return; + } + updateIndex(consulResponse); + + for (Listener<T> l : listeners) { + l.notify(consulResponse); + } + + if (state.compareAndSet(State.starting, State.started)) { + initLatch.countDown(); + } + + runCallback(); + } else { + onFailure(new ConsulException( + "Consul cluster has no elected leader")); + } + } + + @Override + public void onDelayComplete( + OriginalConsulResponse<T> originalConsulResponse) { + + try { + // get header + ConsulResponseHeader consulResponseHeader = Http + .consulResponseHeader(originalConsulResponse + .getResponse()); + + if (consulResponseHeader.isKnownLeader()) { + if (!isRunning()) { + return; + } + + boolean isConuslIndexChanged = isConuslIndexChanged(consulResponseHeader + .getIndex()); + // consul index different + if (isConuslIndexChanged) { + + updateIndex(consulResponseHeader.getIndex()); + + // get T type data + ConsulResponse<T> consulResponse = Http + .consulResponse(originalConsulResponse + .getResponseType(), + originalConsulResponse + .getResponse()); + + // notify customer to custom T data + for (Listener<T> l : listeners) { + l.notify(consulResponse); + } + } + + if (state.compareAndSet(State.starting, State.started)) { + initLatch.countDown(); + } + + runCallback(); + + } else { + onFailure(new ConsulException( + "Consul cluster has no elected leader")); + } + } catch (Exception e) { + onFailure(e); + } + + } + + @Override + public void onFailure(Throwable throwable) { + + if (!isRunning()) { + return; + } + LOGGER.error( + String.format( + "Error getting response from consul. will retry in %d %s", + BACKOFF_DELAY_QTY_IN_MS, TimeUnit.MILLISECONDS), + throwable); + + executorService.schedule(new Runnable() { + @Override + public void run() { + runCallback(); + } + }, BACKOFF_DELAY_QTY_IN_MS, TimeUnit.MILLISECONDS); + } + }; + } + + @VisibleForTesting + static long getBackOffDelayInMs(Properties properties) { + String backOffDelay = null; + try { + backOffDelay = properties.getProperty(BACKOFF_DELAY_PROPERTY); + if (!Strings.isNullOrEmpty(backOffDelay)) { + return Long.parseLong(backOffDelay); + } + } catch (Exception ex) { + LOGGER.warn( + backOffDelay != null ? String.format( + "Error parsing property variable %s: %s", + BACKOFF_DELAY_PROPERTY, backOffDelay) : String + .format("Error extracting property variable %s", + BACKOFF_DELAY_PROPERTY), ex); + } + return TimeUnit.SECONDS.toMillis(10); + } + + public void start() throws Exception { + checkState(state.compareAndSet(State.latent, State.starting), + "Cannot transition from state %s to %s", state.get(), + State.starting); + runCallback(); + } + + public void stop() throws Exception { + State previous = state.getAndSet(State.stopped); + if (previous != State.stopped) { + executorService.shutdownNow(); + } + } + + private void runCallback() { + if (isRunning()) { + callBackConsumer.consume(latestIndex.get(), responseCallback); + } + } + + private boolean isRunning() { + return state.get() == State.started || state.get() == State.starting; + } + + public boolean awaitInitialized(long timeout, TimeUnit unit) + throws InterruptedException { + return initLatch.await(timeout, unit); + } + + private void updateIndex(ConsulResponse<T> consulResponse) { + if (consulResponse != null && consulResponse.getIndex() != null) { + this.latestIndex.set(consulResponse.getIndex()); + } + } + + public void updateIndex(BigInteger index) { + if (index != null) { + this.latestIndex.set(index); + } + } + + protected static QueryOptions watchParams(final BigInteger index, + final int blockSeconds, QueryOptions queryOptions) { + checkArgument(!queryOptions.getIndex().isPresent() + && !queryOptions.getWait().isPresent(), + "Index and wait cannot be overridden"); + + return ImmutableQueryOptions.builder() + .from(watchDefaultParams(index, blockSeconds)) + .token(queryOptions.getToken()) + .consistencyMode(queryOptions.getConsistencyMode()) + .near(queryOptions.getNear()).build(); + } + + private static QueryOptions watchDefaultParams(final BigInteger index, + final int blockSeconds) { + if (index == null) { + return QueryOptions.BLANK; + } else { + return QueryOptions.blockSeconds(blockSeconds, index).build(); + } + } + + /** + * passed in by creators to vary the content of the cached values + * + * @param <V> + */ + protected interface CallbackConsumer<T> { + void consume(BigInteger index, ConsulResponseCallback<T> callback); + } + + /** + * Implementers can register a listener to receive a new map when it changes + * + * @param <V> + */ + public interface Listener<T> { + void notify(ConsulResponse<T> newValues); + } + + public boolean addListener(Listener<T> listener) { + boolean added = listeners.add(listener); + return added; + } + + public List<Listener<T>> getListeners() { + return Collections.unmodifiableList(listeners); + } + + public boolean removeListener(Listener<T> listener) { + return listeners.remove(listener); + } + + @VisibleForTesting + protected State getState() { + return state.get(); + } + + private boolean isConuslIndexChanged(final BigInteger index) { + + if (index != null && !index.equals(latestIndex.get())) { + + if (LOGGER.isDebugEnabled()) { + // 第一次不打印 + if (latestIndex.get() != null) { + LOGGER.debug("consul index compare:new-" + index + " old-" + + latestIndex.get()); + } + + } + + return true; + } + + return false; + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/cache/ServiceHealthCache.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/cache/ServiceHealthCache.java new file mode 100644 index 0000000..b46ffce --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/cache/ServiceHealthCache.java @@ -0,0 +1,65 @@ +package org.onap.msb.apiroute.wrapper.consulextend.cache; + +import java.math.BigInteger; +import java.util.List; + +import org.onap.msb.apiroute.wrapper.consulextend.HealthClient; +import org.onap.msb.apiroute.wrapper.consulextend.async.ConsulResponseCallback; +import org.onap.msb.apiroute.wrapper.consulextend.model.health.ServiceHealth; + +import com.orbitz.consul.option.CatalogOptions; +import com.orbitz.consul.option.QueryOptions; + +public class ServiceHealthCache extends ConsulCache<List<ServiceHealth>> { + private ServiceHealthCache(CallbackConsumer<List<ServiceHealth>> callbackConsumer) { + super(callbackConsumer); + } + + /** + * Factory method to construct a string/{@link ServiceHealth} map for a particular service. + * <p/> + * Keys will be a {@link HostAndPort} object made up of the service's address/port combo + * + * @param healthClient the {@link HealthClient} + * @param serviceName the name of the service + * @param passing include only passing services? + * @return a cache object + */ + public static ServiceHealthCache newCache( + final HealthClient healthClient, + final String serviceName, + final boolean passing, + final CatalogOptions catalogOptions, + final int watchSeconds, + final QueryOptions queryOptions) { + + CallbackConsumer<List<ServiceHealth>> callbackConsumer = new CallbackConsumer<List<ServiceHealth>>() { + @Override + public void consume(BigInteger index, + ConsulResponseCallback<List<ServiceHealth>> callback) { + // TODO Auto-generated method stub + QueryOptions params = watchParams(index, watchSeconds, queryOptions); + if (passing) { + healthClient.getHealthyServiceInstances(serviceName, catalogOptions, params, callback); + } else { + healthClient.getAllServiceInstances(serviceName, catalogOptions, params, callback); + } + } + }; + + return new ServiceHealthCache(callbackConsumer); + } + + public static ServiceHealthCache newCache( + final HealthClient healthClient, + final String serviceName, + final boolean passing, + final CatalogOptions catalogOptions, + final int watchSeconds) { + return newCache(healthClient, serviceName, passing, catalogOptions, watchSeconds, QueryOptions.BLANK); + } + + public static ServiceHealthCache newCache(final HealthClient healthClient, final String serviceName) { + return newCache(healthClient, serviceName, true, CatalogOptions.BLANK, 10); + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/cache/ServicesCatalogCache.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/cache/ServicesCatalogCache.java new file mode 100644 index 0000000..08c7369 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/cache/ServicesCatalogCache.java @@ -0,0 +1,39 @@ +package org.onap.msb.apiroute.wrapper.consulextend.cache; + +import java.math.BigInteger; + +import org.apache.http.HttpEntity; +import org.onap.msb.apiroute.wrapper.consulextend.CatalogClient; +import org.onap.msb.apiroute.wrapper.consulextend.async.ConsulResponseCallback; + +import com.orbitz.consul.option.CatalogOptions; +import com.orbitz.consul.option.QueryOptions; + +public class ServicesCatalogCache extends ConsulCache<HttpEntity> { + + private ServicesCatalogCache(CallbackConsumer<HttpEntity> callbackConsumer) { + super(callbackConsumer); + } + + public static ServicesCatalogCache newCache( + final CatalogClient catalogClient, + final CatalogOptions catalogOptions, + final QueryOptions queryOptions, + final int watchSeconds) { + + CallbackConsumer<HttpEntity> callbackConsumer = new CallbackConsumer<HttpEntity>() { + @Override + public void consume(BigInteger index, ConsulResponseCallback<HttpEntity> callback) { + QueryOptions params = watchParams(index, watchSeconds, queryOptions); + catalogClient.getServices(catalogOptions, params,callback); + } + }; + + return new ServicesCatalogCache(callbackConsumer); + + } + + public static ServicesCatalogCache newCache(final CatalogClient catalogClient) { + return newCache(catalogClient, CatalogOptions.BLANK, QueryOptions.BLANK, 10); + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/CheckServiceDataEmptyAndAutoStopWatchFilter.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/CheckServiceDataEmptyAndAutoStopWatchFilter.java new file mode 100644 index 0000000..01b5168 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/CheckServiceDataEmptyAndAutoStopWatchFilter.java @@ -0,0 +1,98 @@ +package org.onap.msb.apiroute.wrapper.consulextend.expose; + +import java.util.ArrayList; +import java.util.List; + +import org.onap.msb.apiroute.SyncDataManager; +import org.onap.msb.apiroute.wrapper.consulextend.model.health.ImmutableService; +import org.onap.msb.apiroute.wrapper.consulextend.model.health.ImmutableServiceHealth; +import org.onap.msb.apiroute.wrapper.consulextend.model.health.Service; +import org.onap.msb.apiroute.wrapper.consulextend.model.health.ServiceHealth; +import org.onap.msb.apiroute.wrapper.queue.QueueManager; +import org.onap.msb.apiroute.wrapper.queue.ServiceData; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.orbitz.consul.model.ConsulResponse; +import com.orbitz.consul.model.health.ImmutableNode; + + + +public class CheckServiceDataEmptyAndAutoStopWatchFilter implements + WatchTask.Filter<List<ServiceHealth>> { + + private final static Logger LOGGER = LoggerFactory + .getLogger(CheckServiceDataEmptyAndAutoStopWatchFilter.class); + private final String serviceName; + + public CheckServiceDataEmptyAndAutoStopWatchFilter( + final String serviceName) { + this.serviceName = serviceName; + } + + @Override + public boolean filter(ConsulResponse<List<ServiceHealth>> object) { + // TODO Auto-generated method stub + boolean result = check(object); + + if (!result) { + // create delete + writeServiceToQueue4Del(); + // stop watch + SyncDataManager.stopWatchService(serviceName); + } + + return result; + } + + // when: + // 1)service had been deleted + // 2)service Health check was not passing + // single service return [],size==0 + // stop this service watching task and create delete event + private boolean check(ConsulResponse<List<ServiceHealth>> object) { + boolean result = true; + + if (object == null || object.getResponse() == null + || object.getResponse().size() == 0) { + LOGGER.info("check service-{},its data is empty", + serviceName); + return false; + } + + return result; + } + + private void writeServiceToQueue4Del() { + ServiceData<List<ServiceHealth>> data = new ServiceData<List<ServiceHealth>>(); + data.setDataType(ServiceData.DataType.service); + data.setOperate(ServiceData.Operate.delete); + + // tell the subsequent operation the service name which will be deleted + Service service = ImmutableService.builder().id("").port(0).address("") + .service(serviceName).addTags("").createIndex(0).modifyIndex(0).build(); + ServiceHealth serviceHealth = ImmutableServiceHealth.builder() + .service(service) + .node(ImmutableNode.builder().node("").address("").build()) + .build(); + List<ServiceHealth> serviceHealthList = new ArrayList<ServiceHealth>(); + serviceHealthList.add(serviceHealth); + + data.setData(serviceHealthList); + + LOGGER.info("put delete service[" + + serviceName + + "] to service queue :because of deleted "); + + try { + QueueManager.getInstance().putIn(data); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + LOGGER.warn( + "put delete service[" + + serviceName + + "] to service queue interrupted because of deleted:", + e); + } + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/CheckTagAndAutoStopWatchFilter.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/CheckTagAndAutoStopWatchFilter.java new file mode 100644 index 0000000..311edce --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/CheckTagAndAutoStopWatchFilter.java @@ -0,0 +1,96 @@ +package org.onap.msb.apiroute.wrapper.consulextend.expose; + +import java.util.ArrayList; +import java.util.List; + +import org.onap.msb.apiroute.SyncDataManager; +import org.onap.msb.apiroute.wrapper.consulextend.model.health.ServiceHealth; +import org.onap.msb.apiroute.wrapper.queue.QueueManager; +import org.onap.msb.apiroute.wrapper.queue.ServiceData; +import org.onap.msb.apiroute.wrapper.queue.ServiceData.Operate; +import org.onap.msb.apiroute.wrapper.util.ServiceFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.orbitz.consul.model.ConsulResponse; + +public class CheckTagAndAutoStopWatchFilter implements + WatchTask.Filter<List<ServiceHealth>> { + + private final static Logger LOGGER = LoggerFactory + .getLogger(CheckTagAndAutoStopWatchFilter.class); + + private final String serviceName; + + public CheckTagAndAutoStopWatchFilter(final String serviceName) { + this.serviceName = serviceName; + } + + // from consul,the response data:List<ServiceHealth> + // filter ServiceHealth list and find the ServiceHealths which satisfy the + // tags conditions + // 1)if all ServiceHealth don't satisfy,create delete event and stop watch + // 2)if have some ServiceHealths satisfy the tags conditions,create update + // event and send these ServiceHealths + @Override + public boolean filter(ConsulResponse<List<ServiceHealth>> object) { + // TODO Auto-generated method stub + + // find #ServiceHealth# which satisfy the tag conditions + List<ServiceHealth> satisfyList = getSatisfyList(object); + + // no satisfied ServiceHealth + if (satisfyList.isEmpty()) { + + LOGGER.info("put delete service[" + + serviceName + + "] to service queue :because of NO tag meet the conditions"); + + // create delete + writeServiceToQueue(object.getResponse(), + ServiceData.Operate.delete); + // stop watch + //SyncDataManager.stopWatchService(serviceName); + return false; + } + + LOGGER.info("put update service[" + + serviceName + + "] to service queue :which tags meet the conditions"); + + // put the satisfy list to queue + writeServiceToQueue(satisfyList, ServiceData.Operate.update); + + return true; + } + + private List<ServiceHealth> getSatisfyList( + ConsulResponse<List<ServiceHealth>> object) { + List<ServiceHealth> satisfyList = new ArrayList<ServiceHealth>(); + for (ServiceHealth health : object.getResponse()) { + + if (ServiceFilter.getInstance().isFilterCheck(health)) { + satisfyList.add(health); + } + } + + return satisfyList; + } + + private void writeServiceToQueue(List<ServiceHealth> serviceData, + Operate operate) { + ServiceData<List<ServiceHealth>> data = new ServiceData<List<ServiceHealth>>(); + data.setOperate(operate); + data.setDataType(ServiceData.DataType.service); + data.setData(serviceData); + + + try { + QueueManager.getInstance().putIn(data); + } catch (InterruptedException e) { + LOGGER.warn("put " + operate + " service[" + serviceName + + "] to service queue interrupted ", e); + } + + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/ConsulIndexFilter.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/ConsulIndexFilter.java new file mode 100644 index 0000000..14ab2c7 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/ConsulIndexFilter.java @@ -0,0 +1,48 @@ +package org.onap.msb.apiroute.wrapper.consulextend.expose; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicReference; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.orbitz.consul.model.ConsulResponse; + +public class ConsulIndexFilter<T> implements WatchTask.Filter<T> { + + private final static Logger LOGGER = LoggerFactory + .getLogger(ConsulIndexFilter.class); + + private final AtomicReference<BigInteger> latestIndex = new AtomicReference<BigInteger>( + null); + + @Override + public boolean filter(final ConsulResponse<T> object) { + // TODO Auto-generated method stub + return isChanged(object); + } + + private boolean isChanged(final ConsulResponse<T> consulResponse) { + + if (consulResponse != null && consulResponse.getIndex() != null + && !consulResponse.getIndex().equals(latestIndex.get())) { + + if(LOGGER.isDebugEnabled()){ + //第一次不打印 + if (latestIndex.get()!=null) { + LOGGER.debug("consul index compare:new-" + + consulResponse.getIndex() + " old-" + + latestIndex.get()); + } + + } + + this.latestIndex.set(consulResponse.getIndex()); + return true; + } + + return false; + } + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/ServiceModifyIndexFilter.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/ServiceModifyIndexFilter.java new file mode 100644 index 0000000..38fb7c6 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/ServiceModifyIndexFilter.java @@ -0,0 +1,121 @@ +package org.onap.msb.apiroute.wrapper.consulextend.expose; + +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +import org.onap.msb.apiroute.wrapper.consulextend.model.health.Service; +import org.onap.msb.apiroute.wrapper.consulextend.model.health.ServiceHealth; +import org.onap.msb.apiroute.wrapper.util.ServiceFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableList; +import com.orbitz.consul.model.ConsulResponse; +import com.orbitz.consul.model.health.HealthCheck; + +public class ServiceModifyIndexFilter implements WatchTask.Filter<List<ServiceHealth>> { + + private final AtomicReference<ImmutableList<ServiceHealth>> lastResponse = + new AtomicReference<ImmutableList<ServiceHealth>>(ImmutableList.<ServiceHealth>of()); + + private final static Logger LOGGER = LoggerFactory.getLogger(ServiceModifyIndexFilter.class); + + + @Override + public boolean filter(ConsulResponse<List<ServiceHealth>> object) { + // TODO Auto-generated method stub + + List<ServiceHealth> newList=object.getResponse(); + if(realFilter(newList)){ + lastResponse.set(ImmutableList.copyOf(newList)); + return true; + } + + return false; + } + + private boolean realFilter(List<ServiceHealth> newList) { + // 1)判断list的size,不等则改变 + if (newList.size() != lastResponse.get().size()) { + // 第一次不打印 + if (lastResponse.get().size() != 0) { + LOGGER.info(newList.get(0).getService().getService() + + " instance count is different.new_count:" + newList.size() + " old_count:" + + lastResponse.get().size()); + } + + return true; + } + + + // 2)循环服务实例判断服务内容和健康检查是否改变 + for (ServiceHealth newData : newList) { + ServiceHealth sameIdOldData = findSameIdInOldList(newData); + // 若在oldlist中不存在,则改变 + if (sameIdOldData == null) { + + LOGGER.info(newData.getService().getId() + + " is a new service instance.the createindex:" + + newData.getService().getCreateIndex() + + " the modifyIndex:" + + newData.getService().getModifyIndex()); + + return true; + } + + // 若在oldlist中存在,则比较ModifyIndex的值和健康检查状态.不等则改变 + if(!compareService(newData,sameIdOldData)){ + LOGGER.info(newData.getService().getId() +" instance is change because of modifyIndex or health check" ); + return true; + } + } + + return false; + + + } + + + private boolean compareService(ServiceHealth oldData,ServiceHealth newData) { + + return compareServiceInfo(oldData.getService(),newData.getService()) && + compareServiceHealthStatus(oldData.getChecks(),newData.getChecks()); + + } + + + + private boolean compareServiceInfo(Service oldServiceInfo, Service newServiceInfo) { + if (oldServiceInfo.getModifyIndex() != newServiceInfo.getModifyIndex()) { + LOGGER.info(newServiceInfo.getId() + " new_modifyIndex:" + + newServiceInfo.getModifyIndex() + " old_modifyIndex:" + + oldServiceInfo.getModifyIndex()); + return false; + } + return true; + } + + private boolean compareServiceHealthStatus(List<HealthCheck> oldData, List<HealthCheck> newData) { + boolean oldHealthCheck=ServiceFilter.getInstance().isFilterHealthCheck(oldData); + boolean newHealthCheck=ServiceFilter.getInstance().isFilterHealthCheck(newData); + return oldHealthCheck==newHealthCheck; + + } + + + private ServiceHealth findSameIdInOldList(ServiceHealth newData) { + for (ServiceHealth oldData : lastResponse.get()) { + if (oldData.getService().getId().equals(newData.getService().getId())) { + return oldData; + } + } + + return null; + } + + public boolean resetModifyIndex() { + // clear last response + lastResponse.set(ImmutableList.<ServiceHealth>of()); + return true; + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/WatchCatalogServicesTask.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/WatchCatalogServicesTask.java new file mode 100644 index 0000000..c21295f --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/WatchCatalogServicesTask.java @@ -0,0 +1,90 @@ +package org.onap.msb.apiroute.wrapper.consulextend.expose; + +import org.apache.http.HttpEntity; +import org.onap.msb.apiroute.wrapper.consulextend.CatalogClient; +import org.onap.msb.apiroute.wrapper.consulextend.cache.ServicesCatalogCache; +import org.onap.msb.apiroute.wrapper.consulextend.cache.ConsulCache.Listener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.orbitz.consul.option.CatalogOptions; +import com.orbitz.consul.option.QueryOptions; + +public class WatchCatalogServicesTask extends WatchTask<HttpEntity> { + + private final static Logger LOGGER = LoggerFactory + .getLogger(WatchCatalogServicesTask.class); + + private ServicesCatalogCache servicesCache = null; + + public WatchCatalogServicesTask( + final CatalogClient catalogClient, + final CatalogOptions catalogOptions, + final QueryOptions queryOptions, + final int watchSeconds) + { + initCache(catalogClient,catalogOptions,queryOptions,watchSeconds); + } + + public WatchCatalogServicesTask( + final CatalogClient catalogClient, + final int watchSeconds) + { + initCache(catalogClient,CatalogOptions.BLANK,QueryOptions.BLANK,watchSeconds); + } + + public WatchCatalogServicesTask( + final CatalogClient catalogClient) + { + initCache(catalogClient,CatalogOptions.BLANK,QueryOptions.BLANK,10); + } + + private ServicesCatalogCache initCache(final CatalogClient catalogClient, + final CatalogOptions catalogOptions, + final QueryOptions queryOptions, + final int watchSeconds) { + LOGGER.info("************create all services watch task*****************"); + servicesCache = ServicesCatalogCache.newCache(catalogClient, + catalogOptions, queryOptions, watchSeconds); + + servicesCache + .addListener((Listener<HttpEntity>) new InternalListener()); + + return servicesCache; + } + + @Override + public boolean startWatch() { + // TODO Auto-generated method stub + if(servicesCache!=null) + { + try { + servicesCache.start(); + LOGGER.info("************start all services watch task*****************"); + return true; + } catch (Exception e) { + // TODO Auto-generated catch block + LOGGER.warn("start service list watch failed:", e); + } + } + + return false; + } + + @Override + public boolean stopWatch() { + // TODO Auto-generated method stub + if (servicesCache != null) { + try { + servicesCache.stop(); + LOGGER.info("************stop all services watch task*****************"); + return true; + } catch (Exception e) { + // TODO Auto-generated catch block + LOGGER.warn("stop service list watch failed:", e); + } + } + return false; + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/WatchServiceHealthTask.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/WatchServiceHealthTask.java new file mode 100644 index 0000000..b0d64a7 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/WatchServiceHealthTask.java @@ -0,0 +1,128 @@ +package org.onap.msb.apiroute.wrapper.consulextend.expose; + +import java.math.BigInteger; +import java.util.List; + +import org.onap.msb.apiroute.wrapper.consulextend.HealthClient; +import org.onap.msb.apiroute.wrapper.consulextend.cache.ServiceHealthCache; +import org.onap.msb.apiroute.wrapper.consulextend.cache.ConsulCache.Listener; +import org.onap.msb.apiroute.wrapper.consulextend.model.health.ServiceHealth; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.orbitz.consul.option.CatalogOptions; +import com.orbitz.consul.option.QueryOptions; + +public class WatchServiceHealthTask extends WatchTask<List<ServiceHealth>> { + private final static Logger LOGGER = LoggerFactory + .getLogger(WatchServiceHealthTask.class); + + private ServiceHealthCache serviceHealthCache = null; + private String serviceName=""; + + public String getServiceName() { + return serviceName; + } + + public WatchServiceHealthTask(final HealthClient healthClient, + final String serviceName,final boolean passing, + final CatalogOptions catalogOptions, final int watchSeconds, + final QueryOptions queryOptions) { + initCache(healthClient, serviceName, passing, catalogOptions, + watchSeconds, queryOptions); + } + + public WatchServiceHealthTask(final HealthClient healthClient, + final String serviceName,final boolean passing, + final int watchSeconds) + + { + initCache(healthClient, serviceName, passing, CatalogOptions.BLANK, + watchSeconds, QueryOptions.BLANK); + } + + public WatchServiceHealthTask(final HealthClient healthClient, + final String serviceName, final int watchSeconds) + + { + initCache(healthClient, serviceName, true, CatalogOptions.BLANK, + watchSeconds, QueryOptions.BLANK); + } + + private ServiceHealthCache initCache(final HealthClient healthClient, + final String serviceName,final boolean passing, + final CatalogOptions catalogOptions, final int watchSeconds, + final QueryOptions queryOptions) { +// LOGGER.info("************create {} watch task*****************",serviceName); + this.serviceName = serviceName; + serviceHealthCache = ServiceHealthCache.newCache(healthClient, + serviceName, passing, catalogOptions, watchSeconds, + queryOptions); + + serviceHealthCache + .addListener((Listener<List<ServiceHealth>>) new InternalListener()); + + return serviceHealthCache; + } + + public boolean startWatch() { + + if(serviceHealthCache!=null) + { + try { + serviceHealthCache.start(); + LOGGER.info("************start {} watch task*****************",serviceName); + return true; + } catch (Exception e) { + // TODO Auto-generated catch block + LOGGER.warn("start service watch failed:", e); + } + } + + return false; + + } + + public boolean stopWatch(){ + if (serviceHealthCache != null) { + try { + serviceHealthCache.stop(); + LOGGER.info("************stop {} watch task*****************",serviceName); + return true; + } catch (Exception e) { + // TODO Auto-generated catch block + LOGGER.warn("stop service watch failed:", e); + } + } + + return false; + } + + + public boolean resetIndex() + { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("reset " + serviceName + " consul index"); + } + + //reset consul index + serviceHealthCache.updateIndex(BigInteger.valueOf(0)); + + + //reset modify index + for (WatchTask.Filter<List<ServiceHealth>> filter : getAllFilters()) { + if (filter instanceof ServiceModifyIndexFilter) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("reset " + serviceName + " modify index"); + } + return ((ServiceModifyIndexFilter) filter).resetModifyIndex(); + } + } + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("reset modify index.did not find filter:" + serviceName); + } + + return false; + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/WatchTask.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/WatchTask.java new file mode 100644 index 0000000..2ada19d --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/WatchTask.java @@ -0,0 +1,87 @@ +package org.onap.msb.apiroute.wrapper.consulextend.expose; + +import java.util.concurrent.CopyOnWriteArrayList; + +import org.onap.msb.apiroute.wrapper.consulextend.cache.ConsulCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.orbitz.consul.model.ConsulResponse; + +public abstract class WatchTask<T> { + private final CopyOnWriteArrayList<Filter<T>> filters = new CopyOnWriteArrayList<Filter<T>>(); + private final CopyOnWriteArrayList<Handler<T>> handlers = new CopyOnWriteArrayList<Handler<T>>(); + private final static Logger LOGGER = LoggerFactory + .getLogger(WatchTask.class); + + //start + public abstract boolean startWatch(); + + //stop + public abstract boolean stopWatch(); + + // filters + public interface Filter<T> { + public boolean filter(final ConsulResponse<T> object); + } + + public boolean addFilter(Filter<T> filter) { + boolean added = filters.add(filter); + return added; + } + + public void removeAllFilter() { + filters.clear(); + } + + + public final CopyOnWriteArrayList<Filter<T>> getAllFilters(){ + return filters; + } + + // handlers + public interface Handler<T> { + void handle(final ConsulResponse<T> object); + } + + public boolean addHandler(Handler<T> handler) { + boolean added = handlers.add(handler); + return added; + } + + public void removeAllHandler() { + handlers.clear(); + } + + // internal listener + protected class InternalListener implements ConsulCache.Listener<T> { + @Override + public void notify(ConsulResponse<T> newValues) { + + long startTime = System.currentTimeMillis(); + + // filter + for (Filter<T> f : filters) { + // false,return + if (!f.filter(newValues)) { + return; + } + } + + // handle + for (Handler<T> h : handlers) { + h.handle(newValues); + } + + long endTime = System.currentTimeMillis(); + + if(endTime-startTime > 10*1000) + { + LOGGER.info("WatchTask THEAD WORK TIMEOUT"); + } + } + + } + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/WriteBufferHandler.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/WriteBufferHandler.java new file mode 100644 index 0000000..6df10e3 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/expose/WriteBufferHandler.java @@ -0,0 +1,36 @@ +package org.onap.msb.apiroute.wrapper.consulextend.expose; + +import org.onap.msb.apiroute.wrapper.queue.QueueManager; +import org.onap.msb.apiroute.wrapper.queue.ServiceData; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.orbitz.consul.model.ConsulResponse; + +public class WriteBufferHandler<T> implements WatchTask.Handler<T> { + + private static final Logger LOGGER = LoggerFactory + .getLogger(WriteBufferHandler.class); + private final ServiceData.DataType dataType; + + + public WriteBufferHandler(final ServiceData.DataType dataType) { + this.dataType =dataType; + } + + @Override + public void handle(ConsulResponse<T> object) { + // TODO Auto-generated method stub + ServiceData<T> data = new ServiceData<T>(); + data.setDataType(dataType); + data.setData(object.getResponse()); + + try { + QueueManager.getInstance().putIn(data); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + LOGGER.warn("put data to buffer interrupted:", e); + } + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/model/health/Service.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/model/health/Service.java new file mode 100644 index 0000000..fd7f3fa --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/model/health/Service.java @@ -0,0 +1,39 @@ +package org.onap.msb.apiroute.wrapper.consulextend.model.health; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.google.common.collect.ImmutableList; +import org.immutables.value.Value; + +import java.util.List; + +@Value.Immutable +@JsonSerialize(as = ImmutableService.class) +@JsonDeserialize(as = ImmutableService.class) +@JsonIgnoreProperties(ignoreUnknown = true) +public abstract class Service { + + @JsonProperty("ID") + public abstract String getId(); + + @JsonProperty("Service") + public abstract String getService(); + + @JsonProperty("Tags") + @JsonDeserialize(as = ImmutableList.class, contentAs = String.class) + public abstract List<String> getTags(); + + @JsonProperty("Address") + public abstract String getAddress(); + + @JsonProperty("Port") + public abstract int getPort(); + + @JsonProperty("CreateIndex") + public abstract int getCreateIndex(); + + @JsonProperty("ModifyIndex") + public abstract int getModifyIndex(); +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/model/health/ServiceHealth.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/model/health/ServiceHealth.java new file mode 100644 index 0000000..a739b4b --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/model/health/ServiceHealth.java @@ -0,0 +1,30 @@ +package org.onap.msb.apiroute.wrapper.consulextend.model.health; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.google.common.collect.ImmutableList; +import com.orbitz.consul.model.health.HealthCheck; +import com.orbitz.consul.model.health.Node; + +import org.immutables.value.Value; + +import java.util.List; +@Value.Immutable +@JsonSerialize(as = ImmutableServiceHealth.class) +@JsonDeserialize(as = ImmutableServiceHealth.class) +@JsonIgnoreProperties(ignoreUnknown = true) +public abstract class ServiceHealth { + + @JsonProperty("Node") + public abstract Node getNode(); + + @JsonProperty("Service") + public abstract Service getService(); + + @JsonProperty("Checks") + @JsonDeserialize(as = ImmutableList.class, contentAs = HealthCheck.class) + public abstract List<HealthCheck> getChecks(); + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/util/Http.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/util/Http.java new file mode 100644 index 0000000..9f0980c --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/consulextend/util/Http.java @@ -0,0 +1,281 @@ +package org.onap.msb.apiroute.wrapper.consulextend.util; + +import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.math.BigInteger; +import java.util.List; +import java.util.Map; + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.concurrent.FutureCallback; +import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; +import org.apache.http.impl.nio.client.HttpAsyncClients; +import org.eclipse.jetty.http.HttpStatus; +import org.onap.msb.apiroute.wrapper.consulextend.async.ConsulResponseCallback; +import org.onap.msb.apiroute.wrapper.consulextend.async.ConsulResponseHeader; +import org.onap.msb.apiroute.wrapper.consulextend.async.OriginalConsulResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Sets; +import com.orbitz.consul.ConsulException; +import com.orbitz.consul.model.ConsulResponse; +import com.orbitz.consul.option.CatalogOptions; +import com.orbitz.consul.option.QueryOptions; +import com.orbitz.consul.util.Jackson; + +public class Http { + private static final Logger LOGGER = LoggerFactory.getLogger(Http.class); + + private final static CloseableHttpAsyncClient httpAsyncClient = HttpAsyncClients + .custom().setMaxConnTotal(Integer.MAX_VALUE) + .setMaxConnPerRoute(Integer.MAX_VALUE).build(); + + private static Http instance = null; + + private Http() { + } + + public static Http getInstance() { + if (instance == null) { + instance = new Http(); + httpAsyncClient.start(); + } + + return instance; + } + + // async get data from consul,and handle response immediately + public <T> void asyncGet(String requestURI, + final TypeReference<T> responseType, + final ConsulResponseCallback<T> callback, final Integer... okCodes) { + // LOGGER.info("Async request:"+requestURI); + + httpAsyncClient.execute(new HttpGet(requestURI), + new FutureCallback<HttpResponse>() { + + public void completed(final HttpResponse response) { + callback.onComplete(consulResponse(responseType, + response)); + } + + public void failed(final Exception ex) { + callback.onFailure(ex); + } + + public void cancelled() { + LOGGER.warn("cancelled async request"); + } + }); + } + + // async get data from consul,and handle response delay + public <T> void asyncGetDelayHandle(String requestURI, + final TypeReference<T> responseType, + final ConsulResponseCallback<T> callback, final Integer... okCodes) { + + httpAsyncClient.execute(new HttpGet(requestURI), + new FutureCallback<HttpResponse>() { + + public void completed(final HttpResponse response) { + OriginalConsulResponse<T> originalConsulResponse = new OriginalConsulResponse<T>( + response, responseType); + + //handle not 2xx code + if (!isSuccessful(response)) { + + LOGGER.warn("response statuscode:" + + response.getStatusLine().getStatusCode()); + + callback.onFailure(new ConsulException( + "response statuscode:" + + response.getStatusLine() + .getStatusCode())); + } else { + callback.onDelayComplete(originalConsulResponse); + } + + } + + public void failed(final Exception ex) { + callback.onFailure(ex); + } + + public void cancelled() { + LOGGER.warn("cancelled async request"); + } + }); + } + + public static ConsulResponseHeader consulResponseHeader( + HttpResponse response) { + String indexHeaderValue = response.getFirstHeader("X-Consul-Index") + .getValue(); + String lastContactHeaderValue = response.getFirstHeader( + "X-Consul-Lastcontact").getValue(); + String knownLeaderHeaderValue = response.getFirstHeader( + "X-Consul-Knownleader").getValue(); + + BigInteger index = indexHeaderValue == null ? new BigInteger("0") + : new BigInteger(indexHeaderValue); + long lastContact = lastContactHeaderValue == null ? 0 : Long + .parseLong(lastContactHeaderValue); + boolean knownLeader = knownLeaderHeaderValue == null ? false : Boolean + .parseBoolean(knownLeaderHeaderValue); + + return new ConsulResponseHeader(lastContact, knownLeader, index); + } + + public static <T> ConsulResponse<T> consulResponse( + TypeReference<T> responseType, HttpResponse response) { + + String indexHeaderValue = response.getFirstHeader("X-Consul-Index") + .getValue(); + String lastContactHeaderValue = response.getFirstHeader( + "X-Consul-Lastcontact").getValue(); + String knownLeaderHeaderValue = response.getFirstHeader( + "X-Consul-Knownleader").getValue(); + + BigInteger index = indexHeaderValue == null ? new BigInteger("0") + : new BigInteger(indexHeaderValue); + long lastContact = lastContactHeaderValue == null ? 0 : Long + .parseLong(lastContactHeaderValue); + boolean knownLeader = knownLeaderHeaderValue == null ? false : Boolean + .parseBoolean(knownLeaderHeaderValue); + + ConsulResponse<T> consulResponse = new ConsulResponse<T>(readResponse( + response, responseType), lastContact, knownLeader, index); + return consulResponse; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static <T> T readResponse(HttpResponse response, + TypeReference<T> responseType) { + + // read streamed entity + T object; + + // HttpEntity,read original data. + Type _type = responseType.getType(); + if (_type instanceof Class + && (((Class) _type).isAssignableFrom(HttpEntity.class))) { + object = (T) response.getEntity(); + return object; + } + + // String,read original data. + if (_type instanceof Class + && (((Class) _type).isAssignableFrom(String.class))) { + + try { + + object = (T) IOUtils + .toString(response.getEntity().getContent()); + response.getEntity().getContent().close(); + + } catch (UnsupportedOperationException e) { + object = (T) ""; + LOGGER.warn("covert streamed entity to String exception:", e); + } catch (IOException e) { + object = (T) ""; + LOGGER.warn("covert streamed entity to String exception:", e); + } + + return object; + } + + // change data type + try { + object = Jackson.MAPPER.readValue( + response.getEntity().getContent(), responseType); + } catch (IOException e) { + LOGGER.warn("covert streamed entity to object exception:", e); + object = readDefaultResponse(responseType); + } + + return object; + } + + @SuppressWarnings("unchecked") + public static <T> T readDefaultResponse(TypeReference<T> responseType) { + Type _type = responseType.getType(); + if (_type instanceof ParameterizedType + && ((ParameterizedType) _type).getRawType() == List.class) { + return (T) ImmutableList.of(); + } else if (_type instanceof ParameterizedType + && ((ParameterizedType) _type).getRawType() == Map.class) { + return (T) ImmutableMap.of(); + } else { + // Not sure if this case will be reached, but if it is it'll be nice + // to know + throw new IllegalStateException( + "Cannot determine empty representation for " + _type); + } + } + + public static boolean isSuccessful(HttpResponse response, + Integer... okCodes) { + return HttpStatus.isSuccess(response.getStatusLine().getStatusCode()) + || Sets.newHashSet(okCodes).contains( + response.getStatusLine().getStatusCode()); + } + + public static String optionsFrom(CatalogOptions catalogOptions, + QueryOptions queryOptions) { + String params = ""; + + if (catalogOptions != null) { + Map<String, Object> options = catalogOptions.toQuery(); + + if (options.containsKey("dc")) { + params += "dc=" + options.get("dc"); + } + if (options.containsKey("tag")) { + params += params.isEmpty() ? "" : "&"; + params += "tag=" + options.get("tag"); + } + } + + if (queryOptions != null) { + Map<String, Object> options = queryOptions.toQuery(); + + if (options.containsKey("consistent")) { + params += params.isEmpty() ? "" : "&"; + params += "consistent=" + options.get("consistent"); + } + if (options.containsKey("stale")) { + params += params.isEmpty() ? "" : "&"; + params += "stale=" + options.get("stale"); + } + if (options.containsKey("wait")) { + params += params.isEmpty() ? "" : "&"; + params += "wait=" + options.get("wait"); + } + + if (options.containsKey("index")) { + params += params.isEmpty() ? "" : "&"; + params += "index=" + options.get("index"); + } + if (options.containsKey("token")) { + params += params.isEmpty() ? "" : "&"; + params += "token=" + options.get("token"); + } + if (options.containsKey("near")) { + params += params.isEmpty() ? "" : "&"; + params += "near=" + options.get("near"); + } + if (options.containsKey("dc")) { + params += params.isEmpty() ? "" : "&"; + params += "dc=" + options.get("dc"); + } + } + return params; + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/DAOConstants.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/DAOConstants.java new file mode 100644 index 0000000..ab3b3f1 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/DAOConstants.java @@ -0,0 +1,6 @@ +package org.onap.msb.apiroute.wrapper.dao; + +public class DAOConstants { + public static final String ROUTE_KIND = "route"; + public static final String SERVICE_KIND = "service"; +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/DAOFactory.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/DAOFactory.java new file mode 100644 index 0000000..0fb3e14 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/DAOFactory.java @@ -0,0 +1,18 @@ +package org.onap.msb.apiroute.wrapper.dao; + +import org.onap.msb.apiroute.wrapper.dao.route.IRouteDAO; +import org.onap.msb.apiroute.wrapper.dao.route.RouteDAOImpl; +import org.onap.msb.apiroute.wrapper.dao.service.IServiceDAO; +import org.onap.msb.apiroute.wrapper.dao.service.ServiceDAOImpl; + +public class DAOFactory { + private static final IRouteDAO routeDAO = new RouteDAOImpl(); + private static final IServiceDAO serviceDAO = new ServiceDAOImpl(); + + public static IRouteDAO getRouteDAO(){ + return routeDAO; + } + public static IServiceDAO getServiceDAO(){ + return serviceDAO; + } +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/RedisAccessWrapper.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/RedisAccessWrapper.java new file mode 100644 index 0000000..06799b1 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/RedisAccessWrapper.java @@ -0,0 +1,133 @@ +package org.onap.msb.apiroute.wrapper.dao; + +import org.onap.msb.apiroute.wrapper.util.JedisUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.ScanParams; +import redis.clients.jedis.ScanResult; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class RedisAccessWrapper { + private static final Logger LOGGER = LoggerFactory.getLogger(RedisAccessWrapper.class); + //An iteration starts when the cursor is set to 0 + private static final String REDIS_SCAN_POINTER_NEW_ITERATION = "0"; + //An iteration terminated when the cursor returned by the server is 0 + private static final String REDIS_SCAN_POINTER_ITERATION_END = "0"; + private static final int REDIS_SCAN_COUNT = 50; + + + public static void save(String key,String value) throws Exception { + Jedis jedis = null; + try { + jedis = JedisUtil.borrowJedisInstance(); + jedis.set(key,value); + } finally { + JedisUtil.returnJedisInstance(jedis); + } + } + + public static String query(String key) throws Exception { + Jedis jedis = null; + String value = null; + try { + jedis = JedisUtil.borrowJedisInstance(); + value = jedis.get(key); + }finally { + JedisUtil.returnJedisInstance(jedis); + } + return value; + } + + public static long delete(String key) throws Exception { + Jedis jedis = null; + long reply = 0L; + try { + jedis = JedisUtil.borrowJedisInstance(); + reply = jedis.del(key); + } finally { + JedisUtil.returnJedisInstance(jedis); + } + return reply; + } + + public static boolean isExist(String key) throws Exception { + boolean isExist = false; + Jedis jedis = null; + try { + jedis = JedisUtil.borrowJedisInstance(); + isExist = jedis.exists(key); + } finally { + JedisUtil.returnJedisInstance(jedis); + } + return isExist; + } + + public static List<String> queryMultiKeys(String keyPattern) throws Exception { + Set<String> keySet = filterKeys(keyPattern); + List<String> valueList = new ArrayList<>(); + Jedis jedis = null; + try { + jedis = JedisUtil.borrowJedisInstance(); + for(String key : keySet){ + String value = jedis.get(key); + if(value !=null && !"".equals(value)){ + valueList.add(value); + } + } + } finally { + JedisUtil.returnJedisInstance(jedis); + } + return valueList; + } + + public static long deleteMultiKeys(String keyPattern) throws Exception { + Set<String> keySet = filterKeys(keyPattern); + long replySum = 0L; + Jedis jedis = null; + try { + jedis = JedisUtil.borrowJedisInstance(); + for(String key : keySet){ + long reply = jedis.del(key); + replySum = replySum + reply; + } + } finally { + JedisUtil.returnJedisInstance(jedis); + } + return replySum; + } + + /** + * filter the keys according to the given pattern + * using "scan" instead of using "keys", incrementally iterate the keys space + * @param pattern the input filter pattern + * @return the matched keys set + */ + public static Set<String> filterKeys(String pattern) throws Exception{ + long start = System.currentTimeMillis(); + Jedis jedis = null; + Set<String> filteredKeys = new HashSet<>(); + ScanParams scanParams = new ScanParams(); + scanParams.match(pattern); + scanParams.count(REDIS_SCAN_COUNT); + try { + jedis = JedisUtil.borrowJedisInstance(); + ScanResult<String> scanResult = jedis.scan(REDIS_SCAN_POINTER_NEW_ITERATION,scanParams); + filteredKeys.addAll(scanResult.getResult()); + while(!scanResult.getStringCursor().equals(REDIS_SCAN_POINTER_ITERATION_END)){ + scanResult = jedis.scan(scanResult.getStringCursor(),scanParams); + filteredKeys.addAll(scanResult.getResult()); + } + } finally { + JedisUtil.returnJedisInstance(jedis); + } + long end = System.currentTimeMillis(); + long costTime = end-start; + LOGGER.info("filterKeys " + pattern + " count:" + filteredKeys.size() + " cost: " + costTime); + return filteredKeys; + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/IRouteDAO.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/IRouteDAO.java new file mode 100644 index 0000000..f2f51c1 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/IRouteDAO.java @@ -0,0 +1,18 @@ +package org.onap.msb.apiroute.wrapper.dao.route; + +import java.util.List; + +import org.onap.msb.apiroute.wrapper.dao.route.bean.RouteInfo; + +public interface IRouteDAO { + public void saveRoute(String key, RouteInfo routeInfo) throws Exception; + + public RouteInfo queryRoute(String key) throws Exception; + + public List<RouteInfo> queryMultiRoute(String keyPattern) throws Exception; + + public long deleteRoute(String key) throws Exception; + + public long deleteMultiRoute(String keyPattern) throws Exception; + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/RouteDAOImpl.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/RouteDAOImpl.java new file mode 100644 index 0000000..83e868b --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/RouteDAOImpl.java @@ -0,0 +1,63 @@ +package org.onap.msb.apiroute.wrapper.dao.route; + +import com.fasterxml.jackson.core.JsonProcessingException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.onap.msb.apiroute.wrapper.dao.RedisAccessWrapper; +import org.onap.msb.apiroute.wrapper.dao.route.bean.RouteInfo; +import org.onap.msb.apiroute.wrapper.util.Jackson; + +public class RouteDAOImpl implements IRouteDAO{ + public void saveRoute(String key, RouteInfo routeInfo) throws Exception { + String routeInfoStr = null; + // change orginal url from “/” to empty string accord to the rewrite rule while forwarding + if("/".equals(routeInfo.getSpec().getUrl())){ + routeInfo.getSpec().setUrl(""); + } + try { + routeInfoStr = Jackson.MAPPER.writeValueAsString(routeInfo); + } catch (JsonProcessingException e) { + throw new Exception("error occurred while parsing RouteInfo to json data",e); + } + RedisAccessWrapper.save(key, routeInfoStr); + } + + public RouteInfo queryRoute(String key) throws Exception { + RouteInfo routeInfo = null; + String routeInfoStr = RedisAccessWrapper.query(key); + if (null == routeInfoStr || "".equals(routeInfoStr)) + return null; + try { + routeInfo = Jackson.MAPPER.readValue(routeInfoStr, RouteInfo.class); + } catch (IOException e) { + throw new Exception("error occurred while parsing the redis json data to RouteInfo",e); + } + return routeInfo; + } + + public List<RouteInfo> queryMultiRoute(String keyPattern) throws Exception { + List<String> routeInfoStrList = RedisAccessWrapper.queryMultiKeys(keyPattern); + List<RouteInfo> routeInfoList = new ArrayList<>(); + for (String routeInfoStr : routeInfoStrList) { + RouteInfo routeInfo = null; + try { + routeInfo = Jackson.MAPPER.readValue(routeInfoStr, RouteInfo.class); + routeInfoList.add(routeInfo); + } catch (IOException e) { + throw new Exception("error occurred while parsing the redis json data to RouteInfo",e); + } + } + return routeInfoList; + } + + public long deleteRoute(String key) throws Exception { + return RedisAccessWrapper.delete(key); + } + + public long deleteMultiRoute(String keyPattern) throws Exception{ + return RedisAccessWrapper.deleteMultiKeys(keyPattern); + } +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/bean/Metadata.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/bean/Metadata.java new file mode 100644 index 0000000..3e11fcc --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/bean/Metadata.java @@ -0,0 +1,48 @@ +package org.onap.msb.apiroute.wrapper.dao.route.bean; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@AllArgsConstructor +@NoArgsConstructor +@Getter @Setter +public class Metadata { + private String name; + private String namespace; + private String uid = ""; + //@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + //private Date creationTimestamp; + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX") + private Date updateTimestamp; + private Map labels = new HashMap(); + private String[] annotations = null; + + /* + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Metadata metadata = (Metadata) o; + return Objects.equals(name, metadata.name) && + Objects.equals(namespace, metadata.namespace) && + Objects.equals(uid, metadata.uid) && + //Objects.equals(creationTimestamp, metadata.creationTimestamp) && + Objects.equals(updateTimestamp, metadata.updateTimestamp) && + Objects.equals(labels, metadata.labels) && + Objects.equals(annotations, metadata.annotations); + } + + @Override + public int hashCode() { + //return Objects.hash(name, namespace, uid, creationTimestamp, updateTimestamp, labels, annotations); + return Objects.hash(name, namespace, uid, updateTimestamp, labels, annotations); + } + */ +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/bean/Node.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/bean/Node.java new file mode 100644 index 0000000..a328c3c --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/bean/Node.java @@ -0,0 +1,32 @@ +package org.onap.msb.apiroute.wrapper.dao.route.bean; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@AllArgsConstructor +@NoArgsConstructor +@Getter @Setter +public class Node { + private String ip; + private int port; + private int weight=0; + + /* + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Node node = (Node) o; + return Objects.equals(port, node.port) && + Objects.equals(weight, node.weight) && + Objects.equals(ip, node.ip); + } + + @Override + public int hashCode() { + return Objects.hash(ip, port, weight); + } + */ +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/bean/RouteInfo.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/bean/RouteInfo.java new file mode 100644 index 0000000..e5ab7bf --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/bean/RouteInfo.java @@ -0,0 +1,79 @@ +package org.onap.msb.apiroute.wrapper.dao.route.bean; + +import org.onap.msb.apiroute.wrapper.dao.DAOConstants; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class RouteInfo { + private String kind = DAOConstants.ROUTE_KIND; + private String apiVersion = ""; + private String status = ""; + private Metadata metadata; + private Spec spec; + + /** + Example route: + { + "kind" : "route", + "apiVersion" : "v1", + "status" : "1" + "metadata" : { + "name" : "kubernetes", + "namespace" : "default", + "uid" : "0b6f198e-c6ab-11e6-86aa-fa163ee2118b", + "creationTimestamp" : "2016-12-20T11:54:21Z", + "updateTimestamp" : "", + "labels" : { + "component" : "apiserver", + "provider" : "kubernetes" + }, + "annotations" : {} + }, + "spec" : { + "visualRange" : 0, + "url" : "", + "publish_port" : "", + "host" : "", + "apijson" : "", + "apijsontype" : "" + "metricsUrl" : "" + "consulServiceName" : "" + "useOwnUpstream" : "" //是否使用该服务独立的upstream转发 + "publishProtocol" : "", //发布地址使用http还是http协议 + "enable_ssl" : "0|1", //转发时,使用http还是http转发。http:0/https:1 + "controll" : "", //是否可以修改 + "nodes" : [{ + "ip" : 10.10.10.2, + "port" : 8080, + "weight" : "" + } + ], + } +} + */ + /* + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + RouteInfo that = (RouteInfo) o; + return Objects.equals(kind, that.kind) && + Objects.equals(apiVersion, that.apiVersion) && + Objects.equals(status, that.status) && + Objects.equals(metadata, that.metadata) && + Objects.equals(spec, that.spec); + } + + @Override + public int hashCode() { + return Objects.hash(kind, apiVersion, status, metadata, spec); + } + */ +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/bean/Spec.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/bean/Spec.java new file mode 100644 index 0000000..8e9a54b --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/route/bean/Spec.java @@ -0,0 +1,52 @@ +package org.onap.msb.apiroute.wrapper.dao.route.bean; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@AllArgsConstructor +@NoArgsConstructor +@Getter @Setter +public class Spec { + private String visualRange = ""; + private String url = ""; + private String publish_port; + private String host = ""; + private String apijson = ""; + private String apijsontype = ""; + private String metricsUrl = ""; + private String consulServiceName = ""; + private String useOwnUpstream = ""; + private String publish_protocol = ""; + private boolean enable_ssl = false; + private String control = ""; + private Node[] nodes; + + /* + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Spec spec = (Spec) o; + return Objects.equals(enable_ssl, spec.enable_ssl) && + Objects.equals(visualRange, spec.visualRange) && + Objects.equals(url, spec.url) && + Objects.equals(publish_port, spec.publish_port) && + Objects.equals(host, spec.host) && + Objects.equals(apijson, spec.apijson) && + Objects.equals(apijsontype, spec.apijsontype) && + Objects.equals(metricsUrl, spec.metricsUrl) && + Objects.equals(consulServiceName, spec.consulServiceName) && + Objects.equals(useOwnUpstream, spec.useOwnUpstream) && + Objects.equals(publish_protocol, spec.publish_protocol) && + Objects.equals(control, spec.control) && + Arrays.equals(nodes, spec.nodes); + } + + @Override + public int hashCode() { + return Objects.hash(visualRange, url, publish_port, host, apijson, apijsontype, metricsUrl, consulServiceName, useOwnUpstream, publish_protocol, enable_ssl, control, nodes); + } + */ +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/IServiceDAO.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/IServiceDAO.java new file mode 100644 index 0000000..d63f656 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/IServiceDAO.java @@ -0,0 +1,17 @@ +package org.onap.msb.apiroute.wrapper.dao.service; + +import java.util.List; + +import org.onap.msb.apiroute.wrapper.dao.service.bean.ServiceInfo; + +public interface IServiceDAO { + public void saveService(String key, ServiceInfo serviceInfo) throws Exception; + + public ServiceInfo queryService(String key) throws Exception; + + public List<ServiceInfo> queryMultiService(String keyPattern) throws Exception; + + public long deleteService(String key) throws Exception; + + public long deleteMultiService(String keyPattern) throws Exception; +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/ServiceDAOImpl.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/ServiceDAOImpl.java new file mode 100644 index 0000000..e9f4586 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/ServiceDAOImpl.java @@ -0,0 +1,59 @@ +package org.onap.msb.apiroute.wrapper.dao.service; + +import com.fasterxml.jackson.core.JsonProcessingException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.onap.msb.apiroute.wrapper.dao.RedisAccessWrapper; +import org.onap.msb.apiroute.wrapper.dao.service.bean.ServiceInfo; +import org.onap.msb.apiroute.wrapper.util.Jackson; + +public class ServiceDAOImpl implements IServiceDAO{ + public void saveService(String key, ServiceInfo serviceInfo) throws Exception { + String serviceInfoStr = null; + try { + serviceInfoStr = Jackson.MAPPER.writeValueAsString(serviceInfo); + } catch (JsonProcessingException e) { + throw new Exception("error occurred while parsing ServiceInfo to json data",e); + } + RedisAccessWrapper.save(key, serviceInfoStr); + } + + public ServiceInfo queryService(String key) throws Exception { + ServiceInfo serviceInfo = null; + String serviceInfoStr = RedisAccessWrapper.query(key); + if (null == serviceInfoStr || "".equals(serviceInfoStr)) + return null; + try { + serviceInfo = Jackson.MAPPER.readValue(serviceInfoStr, ServiceInfo.class); + } catch (IOException e) { + throw new Exception("error occurred while parsing the redis json data to ServiceInfo",e); + } + return serviceInfo; + } + + public List<ServiceInfo> queryMultiService(String keyPattern) throws Exception { + List<String> serviceInfoStrList = RedisAccessWrapper.queryMultiKeys(keyPattern); + List<ServiceInfo> routeInfoList = new ArrayList<>(); + for (String serviceInfoStr : serviceInfoStrList) { + ServiceInfo serviceInfo = null; + try { + serviceInfo = Jackson.MAPPER.readValue(serviceInfoStr, ServiceInfo.class); + routeInfoList.add(serviceInfo); + } catch (IOException e) { + throw new Exception("error occurred while parsing the redis json data to ServiceInfo",e); + } + } + return routeInfoList; + } + + public long deleteService(String key) throws Exception { + return RedisAccessWrapper.delete(key); + } + + public long deleteMultiService(String keyPattern) throws Exception{ + return RedisAccessWrapper.deleteMultiKeys(keyPattern); + } +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/bean/Metadata.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/bean/Metadata.java new file mode 100644 index 0000000..6ce6126 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/bean/Metadata.java @@ -0,0 +1,50 @@ +package org.onap.msb.apiroute.wrapper.dao.service.bean; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@AllArgsConstructor +@NoArgsConstructor +@Getter @Setter +public class Metadata { + private String name; + private String namespace; + private String uid = ""; + //@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + //private Date creationTimestamp; + // @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX") + private Date updateTimestamp; + private Map labels = new HashMap(); + //private String[] annotations = new String[]{}; + private String[] annotations = null; + + /* + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Metadata metadata = (Metadata) o; + return Objects.equals(name, metadata.name) && + Objects.equals(namespace, metadata.namespace) && + Objects.equals(uid, metadata.uid) && + //Objects.equals(creationTimestamp, metadata.creationTimestamp) && + Objects.equals(updateTimestamp, metadata.updateTimestamp) && + Objects.equals(labels, metadata.labels) && + Objects.equals(annotations, metadata.annotations); + } + + @Override + public int hashCode() { + //return Objects.hash(name, namespace, uid, creationTimestamp, updateTimestamp, labels, annotations); + return Objects.hash(name, namespace, uid, updateTimestamp, labels, annotations); + } + */ +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/bean/Node.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/bean/Node.java new file mode 100644 index 0000000..fecf4bd --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/bean/Node.java @@ -0,0 +1,32 @@ +package org.onap.msb.apiroute.wrapper.dao.service.bean; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@AllArgsConstructor +@NoArgsConstructor +@Getter @Setter +public class Node { + private String ip; + private String port; + private int ttl=-1; + + /* + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Node node = (Node) o; + return Objects.equals(port, node.port) && + Objects.equals(ttl, node.ttl) && + Objects.equals(ip, node.ip); + } + + @Override + public int hashCode() { + return Objects.hash(ip, port, ttl); + } + */ +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/bean/ServiceInfo.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/bean/ServiceInfo.java new file mode 100644 index 0000000..01ab3a9 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/bean/ServiceInfo.java @@ -0,0 +1,76 @@ +package org.onap.msb.apiroute.wrapper.dao.service.bean; + +import org.onap.msb.apiroute.wrapper.dao.DAOConstants; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class ServiceInfo { + private String kind = DAOConstants.SERVICE_KIND; + private String apiVersion = ""; + private String status = ""; + private Metadata metadata; + private Spec spec; + + /** + Example Service: + { + "kind" : "service", + "apiVersion" : "v1", + "metadata" : { + "name" : "kubernetes", + "namespace" : "default", + "uid" : "0b6f198e-c6ab-11e6-86aa-fa163ee2118b", + "creationTimestamp" : "2016-12-20T11:54:21Z", + "labels" : { + "component" : "apiserver", + "provider" : "kubernetes" + }, + "annotations" : {} + }, + "spec" : { + "visualRange" : 0, + "url" : "", + "path" : "", + "publish_port" : "", + "host" : "", + "protocol" : "", + "lb_policy" : "", + "enable_ssl" : "0|1", //转发时,使用http还是http转发。http:0/https:1 + "nodes" : [{ + "ip" : 10.10.10.2, + "port" : 8080, + "ttl" : + } + ], + } + "status" : "" + } + + */ + + /* + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ServiceInfo that = (ServiceInfo) o; + return Objects.equals(kind, that.kind) && + Objects.equals(apiVersion, that.apiVersion) && + Objects.equals(status, that.status) && + Objects.equals(metadata, that.metadata) && + Objects.equals(spec, that.spec); + } + + @Override + public int hashCode() { + return Objects.hash(kind, apiVersion, status, metadata, spec); + } + */ +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/bean/Spec.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/bean/Spec.java new file mode 100644 index 0000000..65e769b --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/dao/service/bean/Spec.java @@ -0,0 +1,44 @@ +package org.onap.msb.apiroute.wrapper.dao.service.bean; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@AllArgsConstructor +@NoArgsConstructor +@Getter @Setter +public class Spec { + private String visualRange = ""; + private String url = ""; + private String path = ""; + private String publish_port; + private String host = ""; + private String protocol = ""; + private String lb_policy = ""; + private boolean enable_ssl = false; + private Node[] nodes; + + /* + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Spec spec = (Spec) o; + return Objects.equals(enable_ssl, spec.enable_ssl) && + Objects.equals(visualRange, spec.visualRange) && + Objects.equals(url, spec.url) && + Objects.equals(path, spec.path) && + Objects.equals(publish_port, spec.publish_port) && + Objects.equals(host, spec.host) && + Objects.equals(protocol, spec.protocol) && + Objects.equals(lb_policy, spec.lb_policy) && + Arrays.equals(nodes, spec.nodes); + } + + @Override + public int hashCode() { + return Objects.hash(visualRange, url, path, publish_port, host, protocol, lb_policy, enable_ssl, nodes); + } + */ +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/BaseQueue.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/BaseQueue.java new file mode 100644 index 0000000..dce3b12 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/BaseQueue.java @@ -0,0 +1,36 @@ +package org.onap.msb.apiroute.wrapper.queue; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +public abstract class BaseQueue<T> { + + private final List<BlockingQueue<ServiceData<T>>> queueArray= new ArrayList<BlockingQueue<ServiceData<T>>>(); + + public BaseQueue(int queueNum,int queueCapacity) + { + for(int i=0;queueNum>0 && i<queueNum;i++) + { + queueArray.add(new LinkedBlockingQueue<ServiceData<T>>(queueCapacity)); + } + } + + public int getQueneNum(){ + return queueArray.size(); + } + + protected BlockingQueue<ServiceData<T>> getQueue(int index) + { + return queueArray.get(index); + } + + public abstract void put(final ServiceData<T> data) throws InterruptedException; + + public abstract ServiceData<T> take(final int queueIndex) throws InterruptedException; + + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/QueueManager.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/QueueManager.java new file mode 100644 index 0000000..20525c8 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/QueueManager.java @@ -0,0 +1,65 @@ +package org.onap.msb.apiroute.wrapper.queue; + +import java.util.List; +import java.util.Map; + +import org.apache.http.HttpEntity; +import org.onap.msb.apiroute.wrapper.consulextend.model.health.ServiceHealth; +import org.onap.msb.apiroute.wrapper.util.RouteUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +public class QueueManager { + + private static final Logger LOGGER = LoggerFactory + .getLogger(QueueManager.class); + + private final BaseQueue<HttpEntity> serviceListQueue; + private final BaseQueue<List<ServiceHealth>> serviceQueue; + + private volatile static QueueManager instance = null; + + public static QueueManager getInstance() { + if (instance == null) { + synchronized (QueueManager.class) { + if (instance == null) { + instance = new QueueManager(); + } + } + } + return instance; + } + + private QueueManager() { + serviceListQueue = new ServiceListQueue( + RouteUtil.SERVICE_LIST_QUEUE_CAPACITY); + serviceQueue = new ServiceQueue(RouteUtil.SERVICE_DATA_QUEUE_NUM, + RouteUtil.SERVICE_QUEUE_CAPACITY); + } + + public ServiceData<HttpEntity> takeFromServiceListQueue( + int queueIndex) throws InterruptedException { + return serviceListQueue.take(queueIndex); + } + + public ServiceData<List<ServiceHealth>> takeFromServiceQueue(int queueIndex) + throws InterruptedException { + return serviceQueue.take(queueIndex); + } + + + @SuppressWarnings("unchecked") + public <T> void putIn(ServiceData<T> data) throws InterruptedException { + + if (data.getDataType() == ServiceData.DataType.service_list) { + LOGGER.debug("putIn service_list queue success"); + serviceListQueue.put((ServiceData<HttpEntity>) data); + } else if (data.getDataType() == ServiceData.DataType.service) { + serviceQueue.put((ServiceData<List<ServiceHealth>>) data); + } else { + LOGGER.warn("DATA TYPE NOT SUPPORT:"+data.getDataType()); + } + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceConsumer.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceConsumer.java new file mode 100644 index 0000000..29d705f --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceConsumer.java @@ -0,0 +1,167 @@ +package org.onap.msb.apiroute.wrapper.queue; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.onap.msb.apiroute.SyncDataManager; +import org.onap.msb.apiroute.api.MicroServiceFullInfo; +import org.onap.msb.apiroute.health.RedisHealthCheck; +import org.onap.msb.apiroute.wrapper.MicroServiceWrapper; +import org.onap.msb.apiroute.wrapper.consulextend.model.health.ServiceHealth; +import org.onap.msb.apiroute.wrapper.util.CommonUtil; +import org.onap.msb.apiroute.wrapper.util.ServiceFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class ServiceConsumer implements Runnable { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceConsumer.class); + + private boolean isRunning = true; + + private int index; + + + private static final int retryCount=3; + + //缓存服务信息:key:服务名 和对应的版本列表Set<String> + private final Map<String, Set<String>> lastVersionResponse = new HashMap<String, Set<String>>(); + + public ServiceConsumer(final int index) { + this.index = index; + } + + + public void run() { + + LOGGER.info("run Service Consumer Thread [" + index + "]"); + + while (isRunning) { + try { + ServiceData<List<ServiceHealth>> serviceData; + + serviceData = QueueManager.getInstance().takeFromServiceQueue(index); + + // LOGGER.info("Service Consumer Thread [" + index + + // "] take out serviceData from Queue successfully"); + + if (serviceData.getOperate() == ServiceData.Operate.delete) { + // 删除服务 + deleteMicroService(serviceData); + } else { + // 更新服务 + updateMicroService(serviceData); + } + } catch (InterruptedException e) { + LOGGER.error("ServiceConsumer throw InterruptedException: ", e); + Thread.currentThread().interrupt(); + } + + } + } + + + + private void deleteMicroService(ServiceData<List<ServiceHealth>> serviceData) { + String serviceName = null; + try { + if (serviceData.getData() == null || serviceData.getData().size() == 0) { + throw new Exception("sysn deleteMicroService is wrong:serviceData is empty"); + } + + serviceName = serviceData.getData().get(0).getService().getService(); +// LOGGER.info("Service Consumer [" + index + "] start to delete MicroService:[serviceName] " +// + serviceName); + + //ServiceListCache.removeService(serviceName); + MicroServiceWrapper.getInstance().deleteMicroService4AllVersion(serviceName); + + } catch (Exception e) { + LOGGER.error("delete MicroServiceInfo 4AllVersion fail from consul:[serviceName]" + serviceName, e); + //删除失败,重试三次 + for(int i=0;i<retryCount;i++){ + + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + LOGGER.error("delete MicroServiceInfo 4AllVersion Thread.sleep throw except:" + ex.getMessage()); + } + if(reDeleteMicroService(serviceName)){ + LOGGER.info((i+1) + "/"+retryCount+" : retry to delete MicroServiceInfo success [serviceName]" + serviceName); + break; + } + else{ + LOGGER.error((i+1) + "/"+retryCount+" : retry to delete MicroServiceInfo still fail [serviceName]" + serviceName); + } + } + } + } + + private boolean reDeleteMicroService(String serviceName){ + try { + MicroServiceWrapper.getInstance().deleteMicroService4AllVersion(serviceName); + return true; + } catch (Exception e) { + return false; + } + } + + private void updateMicroService(ServiceData<List<ServiceHealth>> serviceData) { + + if (serviceData.getData() == null || serviceData.getData().size() == 0) { + LOGGER.warn("sysn updateMicroService is wrong:serviceData is empty "); + return; + } + + String serviceName = ""; + + try { + + serviceName = serviceData.getData().get(0).getService().getService(); + List<ServiceHealth> serviceNodeList = serviceData.getData(); + + + Map<String, MicroServiceFullInfo> microServiceInfo4version = + ServiceFilter.getInstance().transMicroServiceInfoFromConsul(serviceNodeList); + + // 删除数据库中已不存在的版本号服务信息 + Set<String> newAllVersion = microServiceInfo4version.keySet(); + + if (lastVersionResponse.containsKey(serviceName)) { + Set<String> dbAllVersionSet = lastVersionResponse.get(serviceName); + // Set<String> dbAllVersionSet=MicroServiceWrapper.getInstance().getAllVersion(serviceName); + Set<String> delVersionList = CommonUtil.getDiffrent(newAllVersion, dbAllVersionSet); + + if (delVersionList.size() > 0) { + + LOGGER.info("MicroService version is change from consul:[serviceName]" + serviceName + + "[version]" + delVersionList); + + + for (String version : delVersionList) { + MicroServiceWrapper.getInstance().deleteMicroService(serviceName, version); + } + + } + } + + lastVersionResponse.put(serviceName, newAllVersion); + + for (Map.Entry<String, MicroServiceFullInfo> entry : microServiceInfo4version.entrySet()) { + MicroServiceFullInfo new_microServiceFullInfo = entry.getValue(); + MicroServiceWrapper.getInstance().saveServiceAndnoticeRoute(new_microServiceFullInfo); + + } + + + } catch (Exception e) { + LOGGER.error("update MicroServiceInfo fail from consul:[serviceName]" + serviceName); + //更新失败,重置任务服务的modifyIndex,等待重新更新 + RedisHealthCheck.writeCheckFlag = true; + SyncDataManager.resetIndex(serviceName); + } + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceData.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceData.java new file mode 100644 index 0000000..aaadbe9 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceData.java @@ -0,0 +1,53 @@ +package org.onap.msb.apiroute.wrapper.queue; + +public class ServiceData<T> { + public static enum Type { + consul + }; + + public static enum Operate { + update, delete + }; + + public static enum DataType { + service_list, service + } + + private Type type = Type.consul; + private DataType dataType; + private T data; + private Operate operate = Operate.update; + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public DataType getDataType() { + return dataType; + } + + public void setDataType(DataType dataType) { + this.dataType = dataType; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + public Operate getOperate() { + return operate; + } + + public void setOperate(Operate operate) { + this.operate = operate; + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceListCache.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceListCache.java new file mode 100644 index 0000000..59be2e4 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceListCache.java @@ -0,0 +1,35 @@ +package org.onap.msb.apiroute.wrapper.queue; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class ServiceListCache { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceListCache.class); + + private final static AtomicReference<Set<String>> serviceNameList4Cache = new AtomicReference<Set<String>>(new HashSet<String>()); + + public static Set<String> getLatestServiceNamelist() { + return serviceNameList4Cache.get(); + } + + public static void setLatestServiceNamelist(Set<String> newServicenamelist){ + serviceNameList4Cache.set(newServicenamelist); + LOGGER.info("------current total Watch Service Num :"+ newServicenamelist.size()); + } + + public synchronized static void removeService(String serviceName){ + + Set<String> servicenamelist=serviceNameList4Cache.get(); + servicenamelist.remove(serviceName); + serviceNameList4Cache.set(servicenamelist); + LOGGER.info("------current total Watch Service Num :"+ servicenamelist.size()); + } + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceListConsumer.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceListConsumer.java new file mode 100644 index 0000000..e3a8aa7 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceListConsumer.java @@ -0,0 +1,209 @@ +package org.onap.msb.apiroute.wrapper.queue; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.http.HttpEntity; +import org.onap.msb.apiroute.SyncDataManager; +import org.onap.msb.apiroute.wrapper.MicroServiceWrapper; +import org.onap.msb.apiroute.wrapper.util.CommonUtil; +import org.onap.msb.apiroute.wrapper.util.ServiceFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; + + +public class ServiceListConsumer implements Runnable { + + private static final Logger LOGGER = LoggerFactory + .getLogger(ServiceListConsumer.class); + + private boolean isRunning = true; + + private int index; + + + public ServiceListConsumer() { + this.index = 0; + } + + public void run() { + LOGGER.info("run ServiceList Consumer Thread [" + index + "]"); + + while (isRunning) { + try { + // 取最新一条记录 + ServiceData<HttpEntity> serviceData = QueueManager + .getInstance().takeFromServiceListQueue(index); + LOGGER.debug("ServiceList Consumer Thread [" + index + + "] take out serviceData from Queue successfully"); + + HttpEntity newValues = serviceData.getData(); + + Set<String> newServiceNameList = filterServiceList(newValues); + + if (ServiceListCache.getLatestServiceNamelist().size() == 0) { + boolean initSuccess=initServiceList(newServiceNameList); + if(initSuccess){ + ServiceListCache.setLatestServiceNamelist(newServiceNameList); + } + } else { + updateServiceList(newServiceNameList); + ServiceListCache.setLatestServiceNamelist(newServiceNameList); + } + + + } catch (Exception e) { + LOGGER.error( + "ServiceListConsumer throw Exception: ", e); + } + } + } + + private void startWatchService(String serviceName) { + // start to Watch service nodes + + SyncDataManager.startWatchService(serviceName); + } + + private void updateServiceList(Set<String> newServiceNameList) { + Set<String> registerServiceNameList = CommonUtil.getDiffrent( + ServiceListCache.getLatestServiceNamelist(), newServiceNameList); + + if (registerServiceNameList.size() > 0) { + LOGGER.info("***need to start Watch Service num from consul :" + + registerServiceNameList.size()); + + for (String serviceName : registerServiceNameList) { + startWatchService(serviceName); + } + } + } + + private boolean initServiceList(Set<String> newServiceNameList) { + LOGGER.info("***start to initialize service List when System startup ***"); + + Set<String> dbServiceNameList = MicroServiceWrapper + .getInstance().getAllMicroServiceKey(); + + if(dbServiceNameList==null){ + LOGGER.error("init ServiceList from redis fail "); + return false; + } + + + // 对比删除redis脏数据 + Set<String> delServiceNameList = CommonUtil.getDiffrent( + newServiceNameList, dbServiceNameList); + + LOGGER.info("***need to delete Service num from redis :" + + delServiceNameList.size()); + for (String serviceName : delServiceNameList) { + try { + MicroServiceWrapper.getInstance() + .deleteMicroService4AllVersion(serviceName); + LOGGER.info("delete MicroService success from initialize:[serviceName]" + + serviceName); + + } catch (Exception e) { + LOGGER.error( + "initialize serviceList :Delete MicroServiceInfo serviceName:" + + serviceName + " FAIL : ", e); + } + } + + // 启动同步开启监听全部服务列表 + LOGGER.info("***need to start Watch Service num from initialize :" + + newServiceNameList.size()); + + for (String serviceName : newServiceNameList) { + startWatchService(serviceName); + } + + return true; + + } + + /*private ImmutableSet<String> filterServiceList( + final Map<String, List<String>> serviceList) { + if (serviceList == null || serviceList.isEmpty()) { + return ImmutableSet.of(); + } + + final ImmutableSet.Builder<String> builder = ImmutableSet.builder(); + + for (Map.Entry<String, List<String>> entry : serviceList.entrySet()) { + + String key = entry.getKey(); + if (key != null && !"consul".equals(key)) { + + List<String> value = entry.getValue(); + if (ServiceFilter.getInstance().isFilterService(value)) { + builder.add(key); + } + } + } + + LOGGER.info("consul all service num:" + serviceList.size()); + LOGGER.info("consul filter service num:" + builder.build().size()); + + return builder.build(); + } +*/ + private Set<String> filterServiceList(final HttpEntity serviceList) { + + if (serviceList == null || serviceList.getContentLength() == 0) { + return new HashSet<String>(); + } + + final Set<String> builder = new HashSet<String>(); + + JsonFactory f = new JsonFactory(); + JsonParser jp = null; + List<String> tagList = null; + int inputServiceNum = 0; + try { + jp = f.createParser(serviceList.getContent()); + jp.nextToken(); + while (jp.nextToken() != JsonToken.END_OBJECT) { + String serviceName = jp.getCurrentName(); + inputServiceNum++; + jp.nextToken(); + tagList = new ArrayList<>(); + while (jp.nextToken() != JsonToken.END_ARRAY) { + tagList.add(jp.getText()); + } + + if (serviceName != null && !"consul".equals(serviceName)) { + if (ServiceFilter.getInstance().isFilterService(tagList)) { + builder.add(serviceName); + } + } + } + } catch (IOException e) { + LOGGER.warn("parse service list error",e); + return new HashSet<String>(); + } finally { + try { + jp.close(); + } catch (IOException e) { + LOGGER.warn("parse service list error",e); + return new HashSet<String>(); + } + } + + int latestServiceNum=ServiceListCache.getLatestServiceNamelist().size(); +// if(latestServiceNum!=builder.size()){ + LOGGER.info("[consul] all service num:" + inputServiceNum+ ", filter service num: new——" + builder.size()+" old——"+latestServiceNum); +// } + + return builder; + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceListQueue.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceListQueue.java new file mode 100644 index 0000000..84ea286 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceListQueue.java @@ -0,0 +1,59 @@ +package org.onap.msb.apiroute.wrapper.queue; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.BlockingQueue; + +import org.apache.http.HttpEntity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ServiceListQueue extends BaseQueue<HttpEntity> { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceListQueue.class); + + + private static final int SERVICE_LIST_DATA_QUEUE_NUM = 1; + private static final int SERVICE_LIST_QUEUE_INDEX = 0; + + public ServiceListQueue(final int queueCapacity) { + super(SERVICE_LIST_DATA_QUEUE_NUM,queueCapacity); + } + + @Override + public void put(ServiceData<HttpEntity> data) throws InterruptedException { + BlockingQueue<ServiceData<HttpEntity>> queue=getQueue(SERVICE_LIST_QUEUE_INDEX); + + int size=queue.size(); +// LOGGER.info("before put ServiceListQueue[size:"+size+"] success :[service num]"+data.getData().size()); + //先清空队列 + if(size>0){ + queue.clear(); + } + //插入记录 + queue.put(data); + + } + + @Override + public ServiceData<HttpEntity> take(int queueIndex) throws InterruptedException { + BlockingQueue<ServiceData<HttpEntity>> queue = getQueue(queueIndex); + ServiceData<HttpEntity> serviceData = queue.take(); + return serviceData; + + /*//取队列最新一条数据 + if (queue.isEmpty()) { + LOGGER.info("take a single serviceData from ServiceListQueue "); + return serviceData; + } else { + List<ServiceData<Map<String, List<String>>>> serviceDataList = + new ArrayList<ServiceData<Map<String, List<String>>>>(); + //一次性从BlockingQueue获取所有数据 + queue.drainTo(serviceDataList); + LOGGER.info("take multiple serviceDatas from ServiceListQueue :[num]"+serviceDataList.size()); + return serviceDataList.get(serviceDataList.size() - 1); + }*/ + } + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceQueue.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceQueue.java new file mode 100644 index 0000000..6c179fc --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/queue/ServiceQueue.java @@ -0,0 +1,45 @@ +package org.onap.msb.apiroute.wrapper.queue; + +import java.util.List; +import java.util.concurrent.BlockingQueue; + +import org.onap.msb.apiroute.wrapper.consulextend.model.health.ServiceHealth; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class ServiceQueue extends BaseQueue<List<ServiceHealth>> { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceQueue.class); + + private int queneNum; + + public ServiceQueue(final int queneNum,final int queueCapacity) { + super(queneNum,queueCapacity); + this.queneNum=queneNum; + } + + + @Override + public void put(final ServiceData<List<ServiceHealth>> data) throws InterruptedException { + if(data.getData()==null || data.getData().size()==0) return; + + String serviceName = data.getData().get(0).getService().getService(); + long serviceNameHashCode=serviceName.hashCode() & 0x7FFFFFFF; + int queneIndex=(int) (serviceNameHashCode % queneNum); + +// LOGGER.info("put ServiceQueue [serviceName.hashCode():"+serviceNameHashCode+",queneIndex:"+queneIndex+",queneNum:"+queneNum+"] :[serviceName]"+serviceName); + + BlockingQueue<ServiceData<List<ServiceHealth>>> queue=getQueue(queneIndex); + queue.put(data); + + LOGGER.info("put ServiceQueue[index:"+queneIndex+",size:"+queue.size()+"] success :[serviceName]"+serviceName); + } + + @Override + public ServiceData<List<ServiceHealth>> take(final int queueIndex) throws InterruptedException { + return getQueue(queueIndex).take(); + } + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/service/ApiRouteService.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/service/ApiRouteService.java new file mode 100644 index 0000000..c8265b3 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/service/ApiRouteService.java @@ -0,0 +1,159 @@ +package org.onap.msb.apiroute.wrapper.service; + +import org.onap.msb.apiroute.api.ApiRouteInfo; +import org.onap.msb.apiroute.api.RouteServer; +import org.onap.msb.apiroute.wrapper.dao.DAOFactory; +import org.onap.msb.apiroute.wrapper.dao.route.IRouteDAO; +import org.onap.msb.apiroute.wrapper.dao.route.bean.Metadata; +import org.onap.msb.apiroute.wrapper.dao.route.bean.Node; +import org.onap.msb.apiroute.wrapper.dao.route.bean.RouteInfo; +import org.onap.msb.apiroute.wrapper.dao.route.bean.Spec; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + + +public class ApiRouteService { + private static final Logger LOGGER = LoggerFactory.getLogger(ApiRouteService.class); + private static final ApiRouteService instance = new ApiRouteService(); + private IRouteDAO routeDAO = DAOFactory.getRouteDAO(); + + private ApiRouteService() { + } + + public static ApiRouteService getInstance() { + return instance; + } + + public void saveApiRouteService2Redis(ApiRouteInfo apiRouteInfo, String routeKey) throws Exception { + if(apiRouteInfo ==null){ + throw new Exception("input apiRouteInfo to be saved is null!"); + } + RouteInfo routeInfo = APIRouteAdapter.toRouteInfo(apiRouteInfo); + routeDAO.saveRoute(routeKey, routeInfo); + } + + public long deleteApiRouteService2Redis(String routeKey) throws Exception { + return routeDAO.deleteRoute(routeKey); + } + + public long deleteMultiApiRouteService2Redis(String routeKeyPattern) throws Exception { + return routeDAO.deleteMultiRoute(routeKeyPattern); + } + + public ApiRouteInfo getApiRouteInstance(String routeKey) throws Exception { + ApiRouteInfo apiRouteInfo = null; + RouteInfo routeInfo = null; + routeInfo = routeDAO.queryRoute(routeKey); + if(routeInfo!=null) { + apiRouteInfo = APIRouteAdapter.fromRouteInfo(routeInfo); + } + return apiRouteInfo; + } + + public List<ApiRouteInfo> getMultiApiRouteInstances(String apiRedisKeyPattern) throws Exception { + List<ApiRouteInfo> apiRouteList = new ArrayList<>(); + List<RouteInfo> routeInfoList = routeDAO.queryMultiRoute(apiRedisKeyPattern); + for (RouteInfo routeInfo : routeInfoList) { + if (routeInfo != null) { + ApiRouteInfo apiRouteInfo = APIRouteAdapter.fromRouteInfo(routeInfo);; + apiRouteList.add(apiRouteInfo); + } + } + return apiRouteList; + } + + public void updateApiRouteStatus2Redis(String routeKey,String status) throws Exception { + RouteInfo routeInfo = routeDAO.queryRoute(routeKey); + if(routeInfo != null){ + routeInfo.setStatus(status); + routeDAO.saveRoute(routeKey,routeInfo); + }else{ + throw new Exception("service to be updated is not exist! Update failed"); + } + } +} + +class APIRouteAdapter { + public static RouteInfo toRouteInfo(ApiRouteInfo apiRouteInfo) { + RouteInfo routeInfo = new RouteInfo(); + routeInfo.setApiVersion(apiRouteInfo.getVersion()); + routeInfo.setStatus(apiRouteInfo.getStatus()); + + + Spec spec = new Spec(); + spec.setVisualRange(apiRouteInfo.getVisualRange()); + spec.setUrl(apiRouteInfo.getUrl().trim()); + spec.setPublish_port(apiRouteInfo.getPublish_port()); + spec.setHost(apiRouteInfo.getHost()); + spec.setApijson(apiRouteInfo.getApiJson()); + spec.setApijsontype(apiRouteInfo.getApiJsonType()); + spec.setMetricsUrl(apiRouteInfo.getMetricsUrl()); + spec.setConsulServiceName(apiRouteInfo.getConsulServiceName()); + spec.setUseOwnUpstream(apiRouteInfo.getUseOwnUpstream()); + spec.setPublish_protocol(apiRouteInfo.getPublishProtocol()); + spec.setEnable_ssl(apiRouteInfo.isEnable_ssl()); + spec.setControl(apiRouteInfo.getControl()); + RouteServer[] routeServers = apiRouteInfo.getServers(); + List<Node> nodeList = new ArrayList<>(); + for (RouteServer server: routeServers){ + Node node = new Node(); + node.setIp(server.getIp()); + node.setPort(Integer.parseInt(server.getPort())); + node.setWeight(server.getWeight()); + nodeList.add(node); + } + spec.setNodes(nodeList.toArray(new Node[]{})); + routeInfo.setSpec(spec); + + Metadata metadata = new Metadata(); + metadata.setName(apiRouteInfo.getServiceName()); + metadata.setNamespace(apiRouteInfo.getNamespace()); + Calendar now = Calendar.getInstance(); + now.set(Calendar.MILLISECOND, 0); + metadata.setUpdateTimestamp(now.getTime()); + routeInfo.setMetadata(metadata); + + return routeInfo; + } + + public static ApiRouteInfo fromRouteInfo(RouteInfo routeInfo) { + ApiRouteInfo apiRouteInfo = new ApiRouteInfo(); + + apiRouteInfo.setVersion(routeInfo.getApiVersion()); + apiRouteInfo.setStatus(routeInfo.getStatus()); + + Spec spec = routeInfo.getSpec(); + apiRouteInfo.setVisualRange(spec.getVisualRange()); + apiRouteInfo.setUrl(spec.getUrl()); + apiRouteInfo.setPublish_port(spec.getPublish_port()); + apiRouteInfo.setHost(spec.getHost()); + apiRouteInfo.setApiJson(spec.getApijson()); + apiRouteInfo.setApiJsonType(spec.getApijsontype()); + apiRouteInfo.setMetricsUrl(spec.getMetricsUrl()); + apiRouteInfo.setConsulServiceName(spec.getConsulServiceName()); + apiRouteInfo.setUseOwnUpstream(spec.getUseOwnUpstream()); + apiRouteInfo.setPublishProtocol(spec.getPublish_protocol()); + apiRouteInfo.setEnable_ssl(spec.isEnable_ssl()); + apiRouteInfo.setControl(spec.getControl()); + Node[] nodes = spec.getNodes(); + List<RouteServer> routeServerList = new ArrayList<>(); + for (Node node: nodes){ + RouteServer routeServer = new RouteServer(); + routeServer.setIp(node.getIp()); + routeServer.setPort(String.valueOf(node.getPort())); + routeServer.setWeight(node.getWeight()); + routeServerList.add(routeServer); + } + apiRouteInfo.setServers(routeServerList.toArray(new RouteServer[]{})); + + Metadata metadata = routeInfo.getMetadata(); + apiRouteInfo.setServiceName(metadata.getName()); + apiRouteInfo.setNamespace(metadata.getNamespace()); + + return apiRouteInfo; + } +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/service/CustomRouteService.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/service/CustomRouteService.java new file mode 100644 index 0000000..6ea680e --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/service/CustomRouteService.java @@ -0,0 +1,152 @@ +package org.onap.msb.apiroute.wrapper.service; + +import org.onap.msb.apiroute.api.CustomRouteInfo; +import org.onap.msb.apiroute.api.RouteServer; +import org.onap.msb.apiroute.wrapper.dao.DAOFactory; +import org.onap.msb.apiroute.wrapper.dao.route.IRouteDAO; +import org.onap.msb.apiroute.wrapper.dao.route.bean.Metadata; +import org.onap.msb.apiroute.wrapper.dao.route.bean.Node; +import org.onap.msb.apiroute.wrapper.dao.route.bean.RouteInfo; +import org.onap.msb.apiroute.wrapper.dao.route.bean.Spec; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + + +public class CustomRouteService { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomRouteService.class); + + private static final CustomRouteService instance = new CustomRouteService(); + private IRouteDAO routeDAO = DAOFactory.getRouteDAO(); + + private CustomRouteService() { + } + + public static CustomRouteService getInstance() { + return instance; + } + + public void saveCustomRouteService2Redis(CustomRouteInfo customRouteInfo, String routeKey) throws Exception { + if(customRouteInfo ==null){ + throw new Exception("input customRouteInfo to be saved is null!"); + } + RouteInfo routeInfo = CustomRouteAdapter.toRouteInfo(customRouteInfo); + routeDAO.saveRoute(routeKey, routeInfo); + } + + public long deleteCustomRouteService2Redis(String routeKey) throws Exception { + return routeDAO.deleteRoute(routeKey); + } + + public long deleteMultiCustomRouteService2Redis(String routeKeyPattern) throws Exception { + return routeDAO.deleteMultiRoute(routeKeyPattern); + } + + public CustomRouteInfo getCustomRouteInstance(String routeKey) throws Exception { + CustomRouteInfo customRouteInfo = null; + RouteInfo routeInfo = null; + routeInfo = routeDAO.queryRoute(routeKey); + if(routeInfo!=null) { + customRouteInfo = CustomRouteAdapter.fromRouteInfo(routeInfo); + } + return customRouteInfo; + } + + public List<CustomRouteInfo> getMultiCustomRouteInstances(String customRedisKeyPattern) throws Exception { + List<CustomRouteInfo> customRouteList = new ArrayList<>(); + List<RouteInfo> routeInfoList = routeDAO.queryMultiRoute(customRedisKeyPattern); + for (RouteInfo routeInfo : routeInfoList) { + if (routeInfo != null) { + CustomRouteInfo customRouteInfo = CustomRouteAdapter.fromRouteInfo(routeInfo);; + customRouteList.add(customRouteInfo); + } + } + return customRouteList; + } + + public void updateCustomRouteStatus2Redis(String routeKey,String status) throws Exception { + RouteInfo routeInfo = routeDAO.queryRoute(routeKey); + if(routeInfo != null){ + routeInfo.setStatus(status); + routeDAO.saveRoute(routeKey,routeInfo); + }else{ + throw new Exception("service to be updated is not exist! Update failed"); + } + } + +} + +class CustomRouteAdapter { + public static RouteInfo toRouteInfo(CustomRouteInfo customRouteInfo) { + RouteInfo routeInfo = new RouteInfo(); + routeInfo.setStatus(customRouteInfo.getStatus()); + + + Spec spec = new Spec(); + spec.setVisualRange(customRouteInfo.getVisualRange()); + spec.setUrl(customRouteInfo.getUrl().trim()); + spec.setPublish_port(customRouteInfo.getPublish_port()); + spec.setHost(customRouteInfo.getHost()); + spec.setConsulServiceName(customRouteInfo.getConsulServiceName()); + spec.setUseOwnUpstream(customRouteInfo.getUseOwnUpstream()); + spec.setPublish_protocol(customRouteInfo.getPublishProtocol()); + spec.setEnable_ssl(customRouteInfo.isEnable_ssl()); + spec.setControl(customRouteInfo.getControl()); + RouteServer[] routeServers = customRouteInfo.getServers(); + List<Node> nodeList = new ArrayList<>(); + for (RouteServer server: routeServers){ + Node node = new Node(); + node.setIp(server.getIp()); + node.setPort(Integer.parseInt(server.getPort())); + node.setWeight(server.getWeight()); + nodeList.add(node); + } + spec.setNodes(nodeList.toArray(new Node[]{})); + routeInfo.setSpec(spec); + + Metadata metadata = new Metadata(); + metadata.setName(customRouteInfo.getServiceName()); + metadata.setNamespace(customRouteInfo.getNamespace()); + Calendar now = Calendar.getInstance(); + now.set(Calendar.MILLISECOND, 0); + metadata.setUpdateTimestamp(now.getTime()); + routeInfo.setMetadata(metadata); + + return routeInfo; + } + + public static CustomRouteInfo fromRouteInfo(RouteInfo routeInfo) { + CustomRouteInfo customRouteInfo = new CustomRouteInfo(); + customRouteInfo.setStatus(routeInfo.getStatus()); + + Spec spec = routeInfo.getSpec(); + customRouteInfo.setVisualRange(spec.getVisualRange()); + customRouteInfo.setUrl(spec.getUrl()); + customRouteInfo.setPublish_port(spec.getPublish_port()); + customRouteInfo.setHost(spec.getHost()); + customRouteInfo.setConsulServiceName(spec.getConsulServiceName()); + customRouteInfo.setUseOwnUpstream(spec.getUseOwnUpstream()); + customRouteInfo.setPublishProtocol(spec.getPublish_protocol()); + customRouteInfo.setEnable_ssl(spec.isEnable_ssl()); + customRouteInfo.setControl(spec.getControl()); + Node[] nodes = spec.getNodes(); + List<RouteServer> routeServerList = new ArrayList<>(); + for (Node node: nodes){ + RouteServer routeServer = new RouteServer(); + routeServer.setIp(node.getIp()); + routeServer.setPort(String.valueOf(node.getPort())); + routeServer.setWeight(node.getWeight()); + routeServerList.add(routeServer); + } + customRouteInfo.setServers(routeServerList.toArray(new RouteServer[]{})); + + Metadata metadata = routeInfo.getMetadata(); + customRouteInfo.setServiceName(metadata.getName()); + customRouteInfo.setNamespace(metadata.getNamespace()); + + return customRouteInfo; + } +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/service/IuiRouteService.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/service/IuiRouteService.java new file mode 100644 index 0000000..c46cb75 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/service/IuiRouteService.java @@ -0,0 +1,151 @@ +package org.onap.msb.apiroute.wrapper.service; + +import org.onap.msb.apiroute.api.IuiRouteInfo; +import org.onap.msb.apiroute.api.RouteServer; +import org.onap.msb.apiroute.wrapper.dao.DAOFactory; +import org.onap.msb.apiroute.wrapper.dao.route.IRouteDAO; +import org.onap.msb.apiroute.wrapper.dao.route.bean.Metadata; +import org.onap.msb.apiroute.wrapper.dao.route.bean.Node; +import org.onap.msb.apiroute.wrapper.dao.route.bean.RouteInfo; +import org.onap.msb.apiroute.wrapper.dao.route.bean.Spec; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + + +public class IuiRouteService { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomRouteService.class); + + private static final IuiRouteService instance = new IuiRouteService(); + private IRouteDAO routeDAO = DAOFactory.getRouteDAO(); + + private IuiRouteService() { + } + + public static IuiRouteService getInstance() { + return instance; + } + + public void saveIuiRouteService2Redis(IuiRouteInfo iuiRouteInfo, String routeKey) throws Exception { + if(iuiRouteInfo ==null){ + throw new Exception("input apiRouteInfo to be saved is null!"); + } + RouteInfo routeInfo = IuiRouteAdapter.toRouteInfo(iuiRouteInfo); + routeDAO.saveRoute(routeKey, routeInfo); + } + + public long deleteIuiRouteService2Redis(String routeKey) throws Exception { + return routeDAO.deleteRoute(routeKey); + } + + public long deleteMultiIuiRouteService2Redis(String routeKeyPattern) throws Exception { + return routeDAO.deleteMultiRoute(routeKeyPattern); + } + + public IuiRouteInfo getIuiRouteInstance(String routeKey) throws Exception { + IuiRouteInfo iuiRouteInfo = null; + RouteInfo routeInfo = null; + routeInfo = routeDAO.queryRoute(routeKey); + if(routeInfo!=null) { + iuiRouteInfo = IuiRouteAdapter.fromRouteInfo(routeInfo); + } + return iuiRouteInfo; + } + + public List<IuiRouteInfo> getMultiIuiRouteInstances(String apiRedisKeyPattern) throws Exception { + List<IuiRouteInfo> iuiRouteList = new ArrayList<>(); + List<RouteInfo> routeInfoList = routeDAO.queryMultiRoute(apiRedisKeyPattern); + for (RouteInfo routeInfo : routeInfoList) { + if (routeInfo != null) { + IuiRouteInfo iuiRouteInfo = IuiRouteAdapter.fromRouteInfo(routeInfo);; + iuiRouteList.add(iuiRouteInfo); + } + } + return iuiRouteList; + } + + public void updateIuiRouteStatus2Redis(String routeKey,String status) throws Exception { + RouteInfo routeInfo = routeDAO.queryRoute(routeKey); + if(routeInfo != null){ + routeInfo.setStatus(status); + routeDAO.saveRoute(routeKey,routeInfo); + }else{ + throw new Exception("service to be updated is not exist! Update failed"); + } + } + +} + +class IuiRouteAdapter { + public static RouteInfo toRouteInfo(IuiRouteInfo iuiRouteInfo) { + RouteInfo routeInfo = new RouteInfo(); + routeInfo.setStatus(iuiRouteInfo.getStatus()); + + + Spec spec = new Spec(); + spec.setVisualRange(iuiRouteInfo.getVisualRange()); + spec.setUrl(iuiRouteInfo.getUrl().trim()); + spec.setPublish_port(iuiRouteInfo.getPublish_port()); + spec.setHost(iuiRouteInfo.getHost()); + spec.setConsulServiceName(iuiRouteInfo.getConsulServiceName()); + spec.setUseOwnUpstream(iuiRouteInfo.getUseOwnUpstream()); + spec.setPublish_protocol(iuiRouteInfo.getPublishProtocol()); + spec.setEnable_ssl(iuiRouteInfo.isEnable_ssl()); + spec.setControl(iuiRouteInfo.getControl()); + RouteServer[] routeServers = iuiRouteInfo.getServers(); + List<Node> nodeList = new ArrayList<>(); + for (RouteServer server: routeServers){ + Node node = new Node(); + node.setIp(server.getIp()); + node.setPort(Integer.parseInt(server.getPort())); + node.setWeight(server.getWeight()); + nodeList.add(node); + } + spec.setNodes(nodeList.toArray(new Node[]{})); + routeInfo.setSpec(spec); + + Metadata metadata = new Metadata(); + metadata.setName(iuiRouteInfo.getServiceName()); + metadata.setNamespace(iuiRouteInfo.getNamespace()); + Calendar now = Calendar.getInstance(); + now.set(Calendar.MILLISECOND, 0); + metadata.setUpdateTimestamp(now.getTime()); + routeInfo.setMetadata(metadata); + return routeInfo; + } + + public static IuiRouteInfo fromRouteInfo(RouteInfo routeInfo) { + IuiRouteInfo iuiRouteInfo = new IuiRouteInfo(); + iuiRouteInfo.setStatus(routeInfo.getStatus()); + + Spec spec = routeInfo.getSpec(); + iuiRouteInfo.setVisualRange(spec.getVisualRange()); + iuiRouteInfo.setUrl(spec.getUrl()); + iuiRouteInfo.setPublish_port(spec.getPublish_port()); + iuiRouteInfo.setHost(spec.getHost()); + iuiRouteInfo.setConsulServiceName(spec.getConsulServiceName()); + iuiRouteInfo.setUseOwnUpstream(spec.getUseOwnUpstream()); + iuiRouteInfo.setPublishProtocol(spec.getPublish_protocol()); + iuiRouteInfo.setEnable_ssl(spec.isEnable_ssl()); + iuiRouteInfo.setControl(spec.getControl()); + Node[] nodes = spec.getNodes(); + List<RouteServer> routeServerList = new ArrayList<>(); + for (Node node: nodes){ + RouteServer routeServer = new RouteServer(); + routeServer.setIp(node.getIp()); + routeServer.setPort(String.valueOf(node.getPort())); + routeServer.setWeight(node.getWeight()); + routeServerList.add(routeServer); + } + iuiRouteInfo.setServers(routeServerList.toArray(new RouteServer[]{})); + + Metadata metadata = routeInfo.getMetadata(); + iuiRouteInfo.setServiceName(metadata.getName()); + iuiRouteInfo.setNamespace(metadata.getNamespace()); + + return iuiRouteInfo; + } +}
\ No newline at end of file diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/service/MicroServiceFullService.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/service/MicroServiceFullService.java new file mode 100644 index 0000000..af005ae --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/service/MicroServiceFullService.java @@ -0,0 +1,220 @@ +package org.onap.msb.apiroute.wrapper.service; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.onap.msb.apiroute.api.MicroServiceFullInfo; +import org.onap.msb.apiroute.wrapper.dao.DAOFactory; +import org.onap.msb.apiroute.wrapper.dao.RedisAccessWrapper; +import org.onap.msb.apiroute.wrapper.dao.service.IServiceDAO; +import org.onap.msb.apiroute.wrapper.dao.service.bean.Metadata; +import org.onap.msb.apiroute.wrapper.dao.service.bean.ServiceInfo; +import org.onap.msb.apiroute.wrapper.dao.service.bean.Spec; +import org.onap.msb.apiroute.wrapper.util.MicroServiceUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableSet; + +public class MicroServiceFullService { + private static final Logger LOGGER = LoggerFactory.getLogger(MicroServiceFullService.class); + + private static MicroServiceFullService instance = new MicroServiceFullService(); + + private IServiceDAO serviceDAO = DAOFactory.getServiceDAO(); + + private MicroServiceFullService() { + } + + public static MicroServiceFullService getInstance() { + return instance; + } + + public List<MicroServiceFullInfo> getAllMicroServiceInstances() throws Exception { + String serviceKeyPattern = MicroServiceUtil.getPrefixedKey("*"); + + List<MicroServiceFullInfo> microServiceFullInfoList = new ArrayList<>(); + List<ServiceInfo> serviceInfoList = serviceDAO.queryMultiService(serviceKeyPattern); + for (ServiceInfo serviceInfo : serviceInfoList) { + if (serviceInfo != null) { + MicroServiceFullInfo microServiceFullInfo = MicroServiceFullAdapter.fromServiceInfo(serviceInfo); + ; + microServiceFullInfoList.add(microServiceFullInfo); + } + } + return microServiceFullInfoList; + } + + public Set<String> getAllMicroServiceKey() throws Exception { + final Set<String> builder = new HashSet<String>(); + + String serviceKeyPattern = MicroServiceUtil.getPrefixedKey("*"); + Set<String> serviceKeySet = RedisAccessWrapper.filterKeys(serviceKeyPattern); + + Pattern serviceKeyRegexPattern = MicroServiceUtil.getServiceKeyRegexPattern(); + for (String serviceKey : serviceKeySet) { + Matcher matcher = serviceKeyRegexPattern.matcher(serviceKey); + if (matcher.matches()) { + builder.add(matcher.group("servicename")); + } + } + return builder; + } + + public void saveMicroServiceInfo2Redis(MicroServiceFullInfo microServiceFullInfo) throws Exception { + if(microServiceFullInfo ==null){ + throw new Exception("input microServiceInfo to be saved is null!"); + } + ServiceInfo serviceInfo = MicroServiceFullAdapter.toServiceInfo(microServiceFullInfo); + String serviceKey = MicroServiceUtil.getServiceKey(microServiceFullInfo.getServiceName(),microServiceFullInfo.getVersion()); + serviceDAO.saveService(serviceKey,serviceInfo); + } + + public void updateMicroServiceStatus(String serviceName, String version, String status) + throws Exception { + if (null == version || "null".equals(version)) { + version = ""; + } + String serviceKey = MicroServiceUtil.getServiceKey(serviceName, version); + ServiceInfo serviceInfo = serviceDAO.queryService(serviceKey); + if(serviceInfo != null){ + serviceInfo.setStatus(status); + serviceDAO.saveService(serviceKey,serviceInfo); + } + } + + public boolean existsMicroServiceInstance(String serviceName, String version) + throws Exception { + if (null == version || "null".equals(version)) { + version = ""; + } + String serviceKey = MicroServiceUtil.getServiceKey(serviceName, version); + return RedisAccessWrapper.isExist(serviceKey); + } + + public MicroServiceFullInfo getMicroServiceInstance(String serviceName, String version) + throws Exception { + if (null == version || "null".equals(version)) { + version = ""; + } + String serviceKey = MicroServiceUtil.getServiceKey(serviceName, version); + + MicroServiceFullInfo microServiceInfo = null; + + ServiceInfo serviceInfo = null; + serviceInfo = serviceDAO.queryService(serviceKey); + if(serviceInfo!=null) { + microServiceInfo = MicroServiceFullAdapter.fromServiceInfo(serviceInfo); + } + return microServiceInfo; + } + + /** + * query all the versions of the given ServiceName + * @param serviceName + * @return + * @throws Exception + */ + public List<MicroServiceFullInfo> getAllVersionsOfTheService(String serviceName) throws Exception { + String serviceKeyPattern = MicroServiceUtil.getPrefixedKey(serviceName, "*"); + + List<MicroServiceFullInfo> microServiceFullInfoList = new ArrayList<>(); + List<ServiceInfo> serviceInfoList = serviceDAO.queryMultiService(serviceKeyPattern); + for (ServiceInfo serviceInfo : serviceInfoList) { + if (serviceInfo != null) { + MicroServiceFullInfo microServiceFullInfo = MicroServiceFullAdapter.fromServiceInfo(serviceInfo); + microServiceFullInfoList.add(microServiceFullInfo); + } + } + return microServiceFullInfoList; + } + + public void deleteMicroService(String serviceName, String version) throws Exception { + if (null == version || "null".equals(version)) { + version = ""; + } + String serviceKey = MicroServiceUtil.getServiceKey(serviceName, version); + serviceDAO.deleteService(serviceKey); + } + + public long deleteMultiMicroService(String keyPattern) throws Exception { + return serviceDAO.deleteMultiService(keyPattern); + } +} + +class MicroServiceFullAdapter { + public static ServiceInfo toServiceInfo(MicroServiceFullInfo microServiceFullInfo) { + ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.setApiVersion(microServiceFullInfo.getVersion()); + serviceInfo.setStatus(microServiceFullInfo.getStatus()); + + + Spec spec = new Spec(); + spec.setVisualRange(microServiceFullInfo.getVisualRange()); + spec.setUrl(microServiceFullInfo.getUrl()); + spec.setPublish_port(microServiceFullInfo.getPublish_port()); + spec.setHost(microServiceFullInfo.getHost()); + spec.setProtocol(microServiceFullInfo.getProtocol()); + spec.setLb_policy(microServiceFullInfo.getLb_policy()); + spec.setEnable_ssl(microServiceFullInfo.isEnable_ssl()); + Set<org.onap.msb.apiroute.api.Node> nodeSet = microServiceFullInfo.getNodes(); + List<org.onap.msb.apiroute.wrapper.dao.service.bean.Node> serviceNodeList = new ArrayList<>(); + for (org.onap.msb.apiroute.api.Node node : nodeSet) { + org.onap.msb.apiroute.wrapper.dao.service.bean.Node serviceNode = new org.onap.msb.apiroute.wrapper.dao.service.bean.Node(); + serviceNode.setIp(node.getIp()); + serviceNode.setPort(node.getPort()); + serviceNode.setTtl(node.getTtl()); + serviceNodeList.add(serviceNode); + } + spec.setNodes(serviceNodeList.toArray(new org.onap.msb.apiroute.wrapper.dao.service.bean.Node[]{})); + serviceInfo.setSpec(spec); + + Metadata metadata = new Metadata(); + metadata.setName(microServiceFullInfo.getServiceName()); + metadata.setNamespace(microServiceFullInfo.getNamespace()); + Calendar now = Calendar.getInstance(); + now.set(Calendar.MILLISECOND, 0); + metadata.setUpdateTimestamp(now.getTime()); + serviceInfo.setMetadata(metadata); + + return serviceInfo; + } + + public static MicroServiceFullInfo fromServiceInfo(ServiceInfo serviceInfo) { + MicroServiceFullInfo microServiceFullInfo = new MicroServiceFullInfo(); + + microServiceFullInfo.setVersion(serviceInfo.getApiVersion()); + microServiceFullInfo.setStatus(serviceInfo.getStatus()); + + Spec spec = serviceInfo.getSpec(); + microServiceFullInfo.setVisualRange(spec.getVisualRange()); + microServiceFullInfo.setUrl(spec.getUrl()); + microServiceFullInfo.setPath(spec.getPath()); + microServiceFullInfo.setPublish_port(spec.getPublish_port()); + microServiceFullInfo.setHost(spec.getHost()); + microServiceFullInfo.setProtocol(spec.getProtocol()); + microServiceFullInfo.setLb_policy(spec.getLb_policy()); + microServiceFullInfo.setEnable_ssl(spec.isEnable_ssl()); + org.onap.msb.apiroute.wrapper.dao.service.bean.Node[] serviceNodes = spec.getNodes(); + List<org.onap.msb.apiroute.api.Node> nodeList = new ArrayList<>(); + for (org.onap.msb.apiroute.wrapper.dao.service.bean.Node serviceNode : serviceNodes) { + org.onap.msb.apiroute.api.Node node = new org.onap.msb.apiroute.api.Node(); + node.setIp(serviceNode.getIp()); + node.setPort(String.valueOf(serviceNode.getPort())); + node.setTtl(serviceNode.getTtl()); + nodeList.add(node); + } + microServiceFullInfo.setNodes(new HashSet<org.onap.msb.apiroute.api.Node>(nodeList)); + + Metadata metadata = serviceInfo.getMetadata(); + microServiceFullInfo.setServiceName(metadata.getName()); + microServiceFullInfo.setNamespace(metadata.getNamespace()); + + return microServiceFullInfo; + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/serviceListener/IMicroServiceChangeListener.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/serviceListener/IMicroServiceChangeListener.java new file mode 100644 index 0000000..68e31f8 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/serviceListener/IMicroServiceChangeListener.java @@ -0,0 +1,37 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.wrapper.serviceListener; + +import org.onap.msb.apiroute.api.MicroServiceFullInfo; +import org.onap.msb.apiroute.api.Node; + + +public interface IMicroServiceChangeListener { + public void onSave(MicroServiceFullInfo microServiceInfo) throws Exception; + + public void onDelete(MicroServiceFullInfo microServiceInfo) throws Exception; + + public void onChange(String serviceName,String version,MicroServiceFullInfo microServiceInfo) throws Exception; + + public void onStatusChange(String serviceName,String version,String host, String protocol,String publish_port, + String status); + + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/serviceListener/MicroServiceChangeListener.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/serviceListener/MicroServiceChangeListener.java new file mode 100644 index 0000000..73b6a9c --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/serviceListener/MicroServiceChangeListener.java @@ -0,0 +1,779 @@ +package org.onap.msb.apiroute.wrapper.serviceListener; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.apache.commons.lang3.StringUtils; +import org.onap.msb.apiroute.api.ApiRouteInfo; +import org.onap.msb.apiroute.api.CustomRouteInfo; +import org.onap.msb.apiroute.api.DiscoverInfo; +import org.onap.msb.apiroute.api.IuiRouteInfo; +import org.onap.msb.apiroute.api.MicroServiceFullInfo; +import org.onap.msb.apiroute.api.Node; +import org.onap.msb.apiroute.api.PublishFullAddress; +import org.onap.msb.apiroute.api.RouteServer; +import org.onap.msb.apiroute.wrapper.ApiRouteServiceWrapper; +import org.onap.msb.apiroute.wrapper.CustomRouteServiceWrapper; +import org.onap.msb.apiroute.wrapper.IuiRouteServiceWrapper; +import org.onap.msb.apiroute.wrapper.util.CommonUtil; +import org.onap.msb.apiroute.wrapper.util.ConfigUtil; +import org.onap.msb.apiroute.wrapper.util.HttpClientUtil; +import org.onap.msb.apiroute.wrapper.util.JacksonJsonUtil; +import org.onap.msb.apiroute.wrapper.util.RegExpTestUtil; +import org.onap.msb.apiroute.wrapper.util.RouteUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; + +public class MicroServiceChangeListener implements IMicroServiceChangeListener { + + private static final Logger LOGGER = LoggerFactory.getLogger(MicroServiceChangeListener.class); + + @Override + public void onDelete(MicroServiceFullInfo microServiceInfo) throws Exception { + + String path = microServiceInfo.getPath(); + + String[] routeWay = ConfigUtil.getInstance().getRouteWay(); + + for (int i = 0; i < routeWay.length; i++) { + + if (StringUtils.isNotBlank(path) && !"/".equals(path)) { + // 1.按path优先判断类型 + String host = getHost(microServiceInfo); + deleteServiceByUrl(path, host, microServiceInfo.getPublish_port(), routeWay[i]); + } else { + // 2.1 域名判断url + if (RouteUtil.ROUTEWAY_DOMAIN.equals(routeWay[i]) && ifRootByDomain(microServiceInfo)) { + deleteServiceByDomain4Root(microServiceInfo); + } else { + // 2.2 按协议优先判断类型 + deleteServiceByProtocol(microServiceInfo, routeWay[i]); + } + + } + + + } + + } + + + @Override + public void onSave(MicroServiceFullInfo microServiceInfo) throws Exception { + + String path = microServiceInfo.getPath(); + String[] routeWay = ConfigUtil.getInstance().getRouteWay(); + + for (int i = 0; i < routeWay.length; i++) { + // 1.按path优先判断类型 + if (StringUtils.isNotBlank(path) && !"/".equals(path)) { + saveServiceByPath(microServiceInfo, routeWay[i]); + } else { + // 2.1 域名判断url + if (RouteUtil.ROUTEWAY_DOMAIN.equals(routeWay[i]) && ifRootByDomain(microServiceInfo)) { + saveServiceByDomain4Root(microServiceInfo); + } else { + // 2.2 按协议优先判断类型 + saveServiceByProtocol(microServiceInfo, routeWay[i]); + } + } + } + + } + + + //判断按协议发布地址是否和注册的URL一致,如果一致发布地址保存为/,否则保存为协议类型的发布地址 + private boolean ifRootByDomain(MicroServiceFullInfo microServiceInfo){ + + + if("/".equals(microServiceInfo.getUrl())) return true; + + String protocol = microServiceInfo.getProtocol(); + String routeName = + RouteUtil.getRouteNameByns(microServiceInfo.getServiceName(), + microServiceInfo.getNamespace()); + String publishUrl=""; + String version = ""; + if (StringUtils.isNotBlank(microServiceInfo.getVersion())) { + version = "/" + microServiceInfo.getVersion(); + } + + switch (protocol) { + case RouteUtil.PROTOCOL_UI: + publishUrl = "/iui/" + routeName; + break; + case RouteUtil.PROTOCOL_REST: + publishUrl = "/api/" + routeName + version; + break; + case RouteUtil.PROTOCOL_HTTP: + publishUrl = "/" + routeName + version; + break; + } + return publishUrl.equals(microServiceInfo.getUrl()); + + } + + + private void saveServiceByDomain4Root(MicroServiceFullInfo microServiceInfo) throws Exception { + + CustomRouteInfo[] customRouteInfos = + this.buildCustomRouteInfo(microServiceInfo, "/", RouteUtil.ROUTEWAY_DOMAIN); + for (int i = 0; i < customRouteInfos.length; i++) { + customRouteInfos[i].setUrl("/"); + CustomRouteServiceWrapper.getInstance().saveCustomRouteInstance(customRouteInfos[i], + RouteUtil.ROUTEWAY_DOMAIN); + } + } + + private void deleteServiceByDomain4Root(MicroServiceFullInfo microServiceInfo) throws Exception { + + CustomRouteServiceWrapper.getInstance().deleteCustomRoute("/", getHost(microServiceInfo), + microServiceInfo.getPublish_port(), RouteUtil.ROUTEWAY_DOMAIN); + } + + /** + * @Title saveServiceByProtocol + * @Description TODO(按用户注册协议保存服务) + * @param microServiceInfo + * @param routeWay + * @return void + * @throws Exception + */ + private void saveServiceByProtocol(MicroServiceFullInfo microServiceInfo, String routeWay) + throws Exception { + String protocol = microServiceInfo.getProtocol(); + String routeName = + RouteUtil.getRouteNameByns(microServiceInfo.getServiceName(), + microServiceInfo.getNamespace()); + + switch (protocol) { + case RouteUtil.PROTOCOL_UI: + IuiRouteInfo[] iuiRouteInfos = + this.buildIuiRouteInfo(microServiceInfo, routeName, routeWay); + for (int i = 0; i < iuiRouteInfos.length; i++) { + IuiRouteServiceWrapper.getInstance().saveIuiRouteInstance(iuiRouteInfos[i], routeWay); + } + break; + + case RouteUtil.PROTOCOL_REST: + + ApiRouteInfo[] apiRouteInfos = + this.buildApiRouteInfo(microServiceInfo, routeName, microServiceInfo.getVersion(), + routeWay); + for (int i = 0; i < apiRouteInfos.length; i++) { + ApiRouteServiceWrapper.getInstance().saveApiRouteInstance(apiRouteInfos[i], routeWay); + } + break; + case RouteUtil.PROTOCOL_HTTP: + CustomRouteInfo[] customRouteInfos = + this.buildCustomRouteInfo(microServiceInfo, + getHttpName(routeName, microServiceInfo.getVersion()), routeWay); + for (int i = 0; i < customRouteInfos.length; i++) { + CustomRouteServiceWrapper.getInstance().saveCustomRouteInstance(customRouteInfos[i], + routeWay); + } + break; + } + } + + /** + * @Title deleteServiceByProtocol + * @Description TODO(按用户注册协议删除服务) + * @param microServiceInfo + * @param routeWay + * @return void + */ + private void deleteServiceByProtocol(MicroServiceFullInfo microServiceInfo, String routeWay) { + String protocol = microServiceInfo.getProtocol(); + String host = getHost(microServiceInfo); + String routeName = + RouteUtil.getRouteNameByns(microServiceInfo.getServiceName(), + microServiceInfo.getNamespace()); + + if (RouteUtil.PROTOCOL_UI.equals(protocol)) { + + if (RouteUtil.ROUTEWAY_IP.equals(routeWay)) { + // two ports + String[] publishPorts = StringUtils.split(microServiceInfo.getPublish_port(), "|"); + if (publishPorts.length == 2) { + IuiRouteServiceWrapper.getInstance().deleteIuiRoute(routeName, host, publishPorts[0], + routeWay); + IuiRouteServiceWrapper.getInstance().deleteIuiRoute(routeName, host, publishPorts[1], + routeWay); + return; + } + } + + IuiRouteServiceWrapper.getInstance().deleteIuiRoute(routeName, host, + microServiceInfo.getPublish_port(), routeWay); + } else if (RouteUtil.PROTOCOL_REST.equals(protocol)) { + + if (RouteUtil.ROUTEWAY_IP.equals(routeWay)) { + // two ports + String[] publishPorts = StringUtils.split(microServiceInfo.getPublish_port(), "|"); + if (publishPorts.length == 2) { + ApiRouteServiceWrapper.getInstance().deleteApiRoute(routeName, + microServiceInfo.getVersion(), host, publishPorts[0], routeWay); + ApiRouteServiceWrapper.getInstance().deleteApiRoute(routeName, + microServiceInfo.getVersion(), host, publishPorts[1], routeWay); + return; + } + } + ApiRouteServiceWrapper.getInstance().deleteApiRoute(routeName, microServiceInfo.getVersion(), + host, microServiceInfo.getPublish_port(), routeWay); + } else if (RouteUtil.PROTOCOL_HTTP.equals(protocol)) { + + if (RouteUtil.ROUTEWAY_IP.equals(routeWay)) { + // two ports + String[] publishPorts = StringUtils.split(microServiceInfo.getPublish_port(), "|"); + if (publishPorts.length == 2) { + CustomRouteServiceWrapper.getInstance().deleteCustomRoute( + getHttpName(routeName, microServiceInfo.getVersion()), host, publishPorts[0], + routeWay); + CustomRouteServiceWrapper.getInstance().deleteCustomRoute( + getHttpName(routeName, microServiceInfo.getVersion()), host, publishPorts[1], + routeWay); + return; + } + } + CustomRouteServiceWrapper.getInstance().deleteCustomRoute( + getHttpName(routeName, microServiceInfo.getVersion()), host, + microServiceInfo.getPublish_port(), routeWay); + } + } + + /** + * @Title saveServiceByUrl + * @Description TODO(按URL地址判断服务协议并保存到路由表) + * @param url + * @param microServiceInfo + * @param routeWay + * @return void + * @throws Exception + */ + private void saveServiceByPath(MicroServiceFullInfo microServiceInfo, String routeWay) + throws Exception { + String redis_serviceName; + String path=microServiceInfo.getPath(); + if (RegExpTestUtil.apiRouteUrlRegExpTest(path)) { + // protocol:"REST" + String[] serviceKey = RegExpTestUtil.apiServiceNameMatch4URL(path); + if (serviceKey == null) { + LOGGER.error("save api Service ByUrl is error:[url]" + path); + return; + } + redis_serviceName = serviceKey[0]; + String redis_serviceVersion = serviceKey[1]; + + ApiRouteInfo[] apiRouteInfos = + this.buildApiRouteInfo(microServiceInfo, redis_serviceName, redis_serviceVersion, + routeWay); + for (int i = 0; i < apiRouteInfos.length; i++) { + ApiRouteServiceWrapper.getInstance().saveApiRouteInstance(apiRouteInfos[i], routeWay); + } + } else if (RegExpTestUtil.iuiRouteUrlRegExpTest(path)) { + // protocol:"UI" + // 根据url获取服务名 + redis_serviceName = RegExpTestUtil.iuiServiceNameMatch4URL(path); + if (redis_serviceName == null) { + LOGGER.error("save iui Service ByUrl is error:[url]" + path); + return; + } + IuiRouteInfo[] iuiRouteInfos = + this.buildIuiRouteInfo(microServiceInfo, redis_serviceName, routeWay); + for (int i = 0; i < iuiRouteInfos.length; i++) { + IuiRouteServiceWrapper.getInstance().saveIuiRouteInstance(iuiRouteInfos[i], routeWay); + } + } else { + // protocol:"HTTP"; + redis_serviceName = path; + CustomRouteInfo[] customRouteInfos = + this.buildCustomRouteInfo(microServiceInfo, redis_serviceName, routeWay); + for (int i = 0; i < customRouteInfos.length; i++) { + CustomRouteServiceWrapper.getInstance().saveCustomRouteInstance(customRouteInfos[i], + routeWay); + } + } + } + + /** + * @Title deleteServiceByUrl + * @Description TODO(按URL地址判断服务协议并从路由表删除) + * @param url + * @param host + * @param publish_port + * @param routeWay + * @return void + */ + private void deleteServiceByUrl(String url, String host, String publish_port, String routeWay) { + // 根据Url格式判断服务类型 + String redis_serviceName; + + if (RegExpTestUtil.apiRouteUrlRegExpTest(url)) { + // protocol:"REST" + String[] serviceKey = RegExpTestUtil.apiServiceNameMatch4URL(url); + if (serviceKey == null) { + LOGGER.error("delete api Service ByUrl is error:[url]" + url); + return; + } + + redis_serviceName = serviceKey[0]; + String redis_serviceVersion = serviceKey[1]; + + if (RouteUtil.ROUTEWAY_IP.equals(routeWay)) { + // two ports + String[] publishPorts = StringUtils.split(publish_port, "|"); + if (publishPorts.length == 2) { + ApiRouteServiceWrapper.getInstance().deleteApiRoute(redis_serviceName, + redis_serviceVersion, host, publishPorts[0], routeWay); + ApiRouteServiceWrapper.getInstance().deleteApiRoute(redis_serviceName, + redis_serviceVersion, host, publishPorts[1], routeWay); + return; + } + } + + ApiRouteServiceWrapper.getInstance().deleteApiRoute(redis_serviceName, redis_serviceVersion, + host, publish_port, routeWay); + + + + } else if (RegExpTestUtil.iuiRouteUrlRegExpTest(url)) { + // protocol:"UI" + // 根据url获取服务名 + redis_serviceName = RegExpTestUtil.iuiServiceNameMatch4URL(url); + if (redis_serviceName == null) { + LOGGER.error("delete iui Service ByUrl is error:[url]" + url); + return; + } + + if (RouteUtil.ROUTEWAY_IP.equals(routeWay)) { + // two ports + String[] publishPorts = StringUtils.split(publish_port, "|"); + if (publishPorts.length == 2) { + IuiRouteServiceWrapper.getInstance().deleteIuiRoute(redis_serviceName, host, + publishPorts[0], routeWay); + IuiRouteServiceWrapper.getInstance().deleteIuiRoute(redis_serviceName, host, + publishPorts[1], routeWay); + return; + } + } + + IuiRouteServiceWrapper.getInstance().deleteIuiRoute(redis_serviceName, host, publish_port, + routeWay); + + + } else { + // protocol:"HTTP"; + redis_serviceName = url; + + if (RouteUtil.ROUTEWAY_IP.equals(routeWay)) { + // two ports + String[] publishPorts = StringUtils.split(publish_port, "|"); + if (publishPorts.length == 2) { + CustomRouteServiceWrapper.getInstance().deleteCustomRoute(redis_serviceName, host, + publishPorts[0], routeWay); + CustomRouteServiceWrapper.getInstance().deleteCustomRoute(redis_serviceName, host, + publishPorts[1], routeWay); + return; + } + } + + CustomRouteServiceWrapper.getInstance().deleteCustomRoute(redis_serviceName, host, + publish_port, routeWay); + } + + } + + + + /** + * @Title getCustomName + * @Description TODO(获取HTTP服务路由名) + * @param routeName + * @param version + * @return + * @return String + */ + private String getHttpName(String routeName, String version) { + if (!routeName.startsWith("/")) { + routeName = "/" + routeName; + } + + if (StringUtils.isNotBlank(version)) { + routeName += "/" + version; + } + return routeName; + } + + + private String getHost(MicroServiceFullInfo microServiceInfo) { + String host; + if (StringUtils.isNotBlank(microServiceInfo.getHost())) { + host = microServiceInfo.getHost().toLowerCase(); + } else { + // host为空,取默认规则 服务名-ns + host = microServiceInfo.getServiceName().toLowerCase(); + } + + return host; + } + + + + @Override + public void onChange(String serviceName, String version, MicroServiceFullInfo microServiceInfo) + throws Exception { + // TODO Auto-generated method stub + + if (RouteUtil.PROTOCOL_UI.equals(microServiceInfo.getProtocol())) { + IuiRouteInfo[] iuiRouteInfos = + this.buildIuiRouteInfo(microServiceInfo, serviceName, RouteUtil.ROUTEWAY_IP); + for (int i = 0; i < iuiRouteInfos.length; i++) { + IuiRouteServiceWrapper.getInstance().saveIuiRouteInstance(iuiRouteInfos[i], + RouteUtil.ROUTEWAY_IP); + } + } else if (RouteUtil.PROTOCOL_REST.equals(microServiceInfo.getProtocol())) { + ApiRouteInfo[] apiRouteInfos = + this.buildApiRouteInfo(microServiceInfo, serviceName, version, RouteUtil.ROUTEWAY_IP); + for (int i = 0; i < apiRouteInfos.length; i++) { + ApiRouteServiceWrapper.getInstance().saveApiRouteInstance(apiRouteInfos[i], + RouteUtil.ROUTEWAY_IP); + } + } else if (RouteUtil.PROTOCOL_HTTP.equals(microServiceInfo.getProtocol())) { + if (!serviceName.startsWith("/")) { + serviceName = "/" + serviceName; + } + CustomRouteInfo[] customRouteInfos = + this.buildCustomRouteInfo(microServiceInfo, serviceName, RouteUtil.ROUTEWAY_IP); + for (int i = 0; i < customRouteInfos.length; i++) { + CustomRouteServiceWrapper.getInstance().saveCustomRouteInstance(customRouteInfos[i], + RouteUtil.ROUTEWAY_IP); + } + } + } + + + @Override + public void onStatusChange(String serviceName, String version, String host, String protocol, + String publish_port, String status) { + + // 获取服务的host + + if (StringUtils.isBlank(host)) { + host = serviceName.toLowerCase(); + } + + if (RouteUtil.PROTOCOL_UI.equals(protocol)) { + + IuiRouteServiceWrapper.getInstance().updateIuiRouteStatus(serviceName, host, publish_port, + status, RouteUtil.ROUTEWAY_IP); + + } else if (RouteUtil.PROTOCOL_REST.equals(protocol)) { + ApiRouteServiceWrapper.getInstance().updateApiRouteStatus(serviceName, version, host, + publish_port, status, RouteUtil.ROUTEWAY_IP); + + } else if (RouteUtil.PROTOCOL_HTTP.equals(protocol)) { + if (!serviceName.startsWith("/")) { + serviceName = "/" + serviceName; + } + CustomRouteServiceWrapper.getInstance().updateCustomRouteStatus(serviceName, host, + publish_port, status, RouteUtil.ROUTEWAY_IP); + } + + + } + + private boolean buildRouteHttpProtocol(MicroServiceFullInfo microServiceInfo, String routeWay) { + + // Portal协议处理 + if (RouteUtil.CUSTOM_PORTAL.equals(microServiceInfo.getCustom())) { + if (RouteUtil.ROUTEWAY_DOMAIN.equals(routeWay)) { + return true; + } else { + return false; + } + } + + // 自定义开启SSL处理 + return microServiceInfo.isEnable_ssl(); + + } + + private RouteServer[] buildRouteNodes(MicroServiceFullInfo microServiceInfo, String routeWay) { + + // 针对custom=portal场景的域名路由使用apigateway发布地址作为node + if (RouteUtil.CUSTOM_PORTAL.equals(microServiceInfo.getCustom())) { + if (RouteUtil.ROUTEWAY_DOMAIN.equals(routeWay)) { + + String discoverServiceName = + RouteUtil.getRouteNameByns(microServiceInfo.getServiceName(), + microServiceInfo.getNamespace()); + List<Node> publishNodes = + getPublishNodes(discoverServiceName, microServiceInfo.getVersion(), + microServiceInfo.getNamespace()); + if (publishNodes != null && publishNodes.size() > 0) { + RouteServer[] routeServers = new RouteServer[publishNodes.size()]; + int i = 0; + for (Node node : publishNodes) { + RouteServer routeServer = new RouteServer(node.getIp(), node.getPort()); + routeServers[i] = routeServer; + i++; + } + return routeServers; + } + } + } + + + Set<Node> nodes = microServiceInfo.getNodes(); + RouteServer[] routeServers = new RouteServer[nodes.size()]; + int n = 0; + for (Node node : nodes) { + RouteServer routeServer = new RouteServer(node.getIp(), node.getPort()); + routeServers[n] = routeServer; + n++; + } + + return routeServers; + + } + + /** + * From MicroServiceInfo to ApiRouteInfo + * + * @param microServiceInfo + * @return + */ + private ApiRouteInfo[] buildApiRouteInfo(MicroServiceFullInfo microServiceInfo, + String redis_serviceName, String redis_version, String routeWay) { + + ApiRouteInfo apiRouteInfo = new ApiRouteInfo(); + apiRouteInfo.setUrl(microServiceInfo.getUrl()); + + apiRouteInfo.setServers(buildRouteNodes(microServiceInfo, routeWay)); + + apiRouteInfo.setVisualRange(RouteUtil.getVisualRangeByRouter(microServiceInfo.getVisualRange())); + + + if ("ip_hash".equals(microServiceInfo.getLb_policy())) { + apiRouteInfo.setUseOwnUpstream("1"); + } + + apiRouteInfo.setConsulServiceName(microServiceInfo.getServiceName()); + apiRouteInfo.setServiceName(redis_serviceName); + apiRouteInfo.setVersion(redis_version); + apiRouteInfo.setApiJson(microServiceInfo.getUrl() + "/swagger.json"); + apiRouteInfo.setMetricsUrl("/admin/metrics"); + apiRouteInfo.setEnable_ssl(buildRouteHttpProtocol(microServiceInfo, routeWay)); + // 默认 HttpProtocol和PublishProtocol=http + if (apiRouteInfo.isEnable_ssl()) { + apiRouteInfo.setPublishProtocol("https"); + } + + // 获取服务的host + String host = getHost(microServiceInfo); + + apiRouteInfo.setHost(host.toLowerCase()); + apiRouteInfo.setNamespace(microServiceInfo.getNamespace()); + + if (RouteUtil.ROUTEWAY_IP.equals(routeWay)) { + + if (StringUtils.isNotBlank(microServiceInfo.getPublish_port())) { + apiRouteInfo.setPublishProtocol("https"); + } + + // 获取服务的发布端口(支持多端口格式:https|http) + String[] publishPorts = StringUtils.split(microServiceInfo.getPublish_port(), "|"); + if (publishPorts.length == 2) { + apiRouteInfo.setPublishProtocol("https"); + apiRouteInfo.setPublish_port(publishPorts[0]); + + try { + ApiRouteInfo apiRouteInfo_http = (ApiRouteInfo) apiRouteInfo.clone(); + apiRouteInfo.setPublishProtocol("http"); + apiRouteInfo.setPublish_port(publishPorts[1]); + return new ApiRouteInfo[] {apiRouteInfo, apiRouteInfo_http}; + } catch (CloneNotSupportedException e) { + LOGGER.error("CLONE is wrong:" + apiRouteInfo); + return new ApiRouteInfo[] {apiRouteInfo}; + } + + } + } + + + + apiRouteInfo.setPublish_port(microServiceInfo.getPublish_port()); + return new ApiRouteInfo[] {apiRouteInfo}; + + + } + + + /** + * From MicroServiceInfo to CustomRouteInfo + * + * @param microServiceInfo + * @return + */ + private CustomRouteInfo[] buildCustomRouteInfo(MicroServiceFullInfo microServiceInfo, + String redis_serviceName, String routeWay) { + + CustomRouteInfo customRouteInfo = new CustomRouteInfo(); + customRouteInfo.setUrl(microServiceInfo.getUrl()); + + + customRouteInfo.setServers(buildRouteNodes(microServiceInfo, routeWay)); + + customRouteInfo.setVisualRange(RouteUtil.getVisualRangeByRouter(microServiceInfo.getVisualRange())); + + if ("ip_hash".equals(microServiceInfo.getLb_policy())) { + customRouteInfo.setUseOwnUpstream("1"); + } + + customRouteInfo.setConsulServiceName(microServiceInfo.getServiceName()); + customRouteInfo.setServiceName(redis_serviceName); + + // 获取服务的host + String host = getHost(microServiceInfo); + + customRouteInfo.setHost(host.toLowerCase()); + customRouteInfo.setNamespace(microServiceInfo.getNamespace()); + customRouteInfo.setEnable_ssl(buildRouteHttpProtocol(microServiceInfo, routeWay)); + + if (customRouteInfo.isEnable_ssl()) { + customRouteInfo.setPublishProtocol("https"); + } + + + if (RouteUtil.ROUTEWAY_IP.equals(routeWay)) { + if (StringUtils.isNotBlank(microServiceInfo.getPublish_port())) { + customRouteInfo.setPublishProtocol("https"); + } + + String[] publishPorts = StringUtils.split(microServiceInfo.getPublish_port(), "|"); + if (publishPorts.length == 2) { + // 获取服务的发布端口(支持多端口格式:https|http) + customRouteInfo.setPublishProtocol("https"); + customRouteInfo.setPublish_port(publishPorts[0]); + + try { + CustomRouteInfo customRouteInfo_http = (CustomRouteInfo) customRouteInfo.clone(); + customRouteInfo.setPublishProtocol("http"); + customRouteInfo.setPublish_port(publishPorts[1]); + return new CustomRouteInfo[] {customRouteInfo, customRouteInfo_http}; + } catch (CloneNotSupportedException e) { + LOGGER.error("CLONE is wrong:" + customRouteInfo); + return new CustomRouteInfo[] {customRouteInfo}; + } + + } + } + + + customRouteInfo.setPublish_port(microServiceInfo.getPublish_port()); + return new CustomRouteInfo[] {customRouteInfo}; + } + + + /** + * From MicroServiceInfo to IuiRouteInfo + * + * @param microServiceInfo + * @return + */ + private IuiRouteInfo[] buildIuiRouteInfo(MicroServiceFullInfo microServiceInfo, + String redis_serviceName, String routeWay) { + + IuiRouteInfo iuiRouteInfo = new IuiRouteInfo(); + iuiRouteInfo.setUrl(microServiceInfo.getUrl()); + + iuiRouteInfo.setServers(buildRouteNodes(microServiceInfo, routeWay)); + + iuiRouteInfo.setVisualRange(RouteUtil.getVisualRangeByRouter(microServiceInfo.getVisualRange())); + + if ("ip_hash".equals(microServiceInfo.getLb_policy())) { + iuiRouteInfo.setUseOwnUpstream("1"); + } + + + iuiRouteInfo.setConsulServiceName(microServiceInfo.getServiceName()); + iuiRouteInfo.setServiceName(redis_serviceName); + + // 获取服务的host + String host = getHost(microServiceInfo); + + iuiRouteInfo.setHost(host.toLowerCase()); + iuiRouteInfo.setNamespace(microServiceInfo.getNamespace()); + iuiRouteInfo.setEnable_ssl(buildRouteHttpProtocol(microServiceInfo, routeWay)); + if (iuiRouteInfo.isEnable_ssl()) { + iuiRouteInfo.setPublishProtocol("https"); + } + + if (RouteUtil.ROUTEWAY_IP.equals(routeWay)) { + + if (StringUtils.isNotBlank(microServiceInfo.getPublish_port())) { + iuiRouteInfo.setPublishProtocol("https"); + } + + String[] publishPorts = StringUtils.split(microServiceInfo.getPublish_port(), "|"); + if (publishPorts.length == 2) { + // 获取服务的发布端口(支持多端口格式:https|http) + iuiRouteInfo.setPublishProtocol("https"); + iuiRouteInfo.setPublish_port(publishPorts[0]); + + try { + IuiRouteInfo iuiRouteInfo_http = (IuiRouteInfo) iuiRouteInfo.clone(); + iuiRouteInfo.setPublishProtocol("http"); + iuiRouteInfo.setPublish_port(publishPorts[1]); + return new IuiRouteInfo[] {iuiRouteInfo, iuiRouteInfo_http}; + } catch (CloneNotSupportedException e) { + LOGGER.error("CLONE is wrong:" + iuiRouteInfo); + return new IuiRouteInfo[] {iuiRouteInfo}; + } + + } + } + iuiRouteInfo.setPublish_port(microServiceInfo.getPublish_port()); + return new IuiRouteInfo[] {iuiRouteInfo}; + } + + + + private List<Node> getPublishNodes(String discoverServiceName, String version, String namespace) { + List<Node> nodes = new ArrayList<Node>(); + + if (StringUtils.isBlank(version)) { + version = "null"; + } + + DiscoverInfo discoverInfo = ConfigUtil.getInstance().getDiscoverInfo(); + + String allpublishaddressUrl = + (new StringBuilder().append("http://").append(discoverInfo.toString()) + .append(RouteUtil.MSB_ROUTE_URL).append("/").append(discoverServiceName) + .append("/version/").append(version).append("/allpublishaddress?namespace=") + .append(namespace).append("&visualRange=0")).toString(); + + String resultJson = HttpClientUtil.httpGet(allpublishaddressUrl); + List<PublishFullAddress> publishFullAddressList = + JacksonJsonUtil + .jsonToListBean(resultJson, new TypeReference<List<PublishFullAddress>>() {}); + if (publishFullAddressList != null && publishFullAddressList.size() > 0) { + for (PublishFullAddress publishFullAddress : publishFullAddressList) { + if (StringUtils.isNotBlank(publishFullAddress.getIp()) + && "https".equals(publishFullAddress.getPublish_protocol())) { + nodes.add(new Node(publishFullAddress.getIp(), publishFullAddress.getPort())); + } + + } + } + + return nodes; + } + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/serviceListener/RouteNotify.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/serviceListener/RouteNotify.java new file mode 100644 index 0000000..3cd2d8a --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/serviceListener/RouteNotify.java @@ -0,0 +1,77 @@ +package org.onap.msb.apiroute.wrapper.serviceListener; + +import java.util.ArrayList; +import java.util.List; + +import org.onap.msb.apiroute.api.MicroServiceFullInfo; +import org.onap.msb.apiroute.wrapper.util.ServiceFilter; + +public class RouteNotify { + + private static RouteNotify instance = new RouteNotify(); + + private List<IMicroServiceChangeListener> serviceListenerlist = + new ArrayList<IMicroServiceChangeListener>(); + + private RouteNotify() {} + + public static RouteNotify getInstance() { + return instance; + } + + + public void addServiceChangeListener(IMicroServiceChangeListener listener) { + synchronized (serviceListenerlist) { + serviceListenerlist.add(listener); + } + } + + + /* public void removeServiceChangeListener(IMicroServiceChangeListener listener) { + synchronized (serviceListenerlist) { + serviceListenerlist.remove(listener); + } + }*/ + + + public void noticeRouteListener4Update(String serviceName, String version, MicroServiceFullInfo microServiceInfo) throws Exception { + if (ServiceFilter.getInstance().isNeedNotifyByProtocol(microServiceInfo.getProtocol())) { + for (IMicroServiceChangeListener serviceListener : serviceListenerlist) { + serviceListener.onChange(serviceName, version, microServiceInfo); + } + } + + } + + public void noticeUpdateStatusListener(MicroServiceFullInfo microServiceInfo, String status) { + + for (IMicroServiceChangeListener serviceListener : serviceListenerlist) { + serviceListener.onStatusChange(microServiceInfo.getServiceName(), + microServiceInfo.getVersion(), microServiceInfo.getHost(),microServiceInfo.getProtocol(), microServiceInfo.getPublish_port(),status); + } + } + + + + + public void noticeRouteListener4Add(MicroServiceFullInfo microServiceInfo) throws Exception { + if (ServiceFilter.getInstance().isNeedNotifyByProtocol(microServiceInfo.getProtocol())) { + for (IMicroServiceChangeListener serviceListener : serviceListenerlist) { + serviceListener.onSave(microServiceInfo); + } + } + } + + public void noticeRouteListener4Delete(MicroServiceFullInfo microServiceInfo) throws Exception { + if (ServiceFilter.getInstance().isNeedNotifyByProtocol(microServiceInfo.getProtocol())) { + for (IMicroServiceChangeListener serviceListener : serviceListenerlist) { + serviceListener.onDelete(microServiceInfo); + } + } + } + + + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/CommonUtil.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/CommonUtil.java new file mode 100644 index 0000000..2ad84a7 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/CommonUtil.java @@ -0,0 +1,76 @@ +package org.onap.msb.apiroute.wrapper.util; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.commons.lang3.StringUtils; + +public class CommonUtil { + + public static final int SC_OK = 200; + + public static Object[] concat(Object[] a, Object[] b) { + Object[] c = new Object[a.length + b.length]; + System.arraycopy(a, 0, c, 0, a.length); + System.arraycopy(b, 0, c, a.length, b.length); + return c; + } + + public static boolean contain(String strArray, String str) { + String[] array = StringUtils.split(strArray, ","); + return contain(array, str); + } + + public static boolean contain(String[] array, String str) { + for (int i = 0; i < array.length; i++) { + if (array[i].trim().equals(str)) { + return true; + } + } + return false; + + } + + public static boolean contain(String[] array, String value[]) { + for (int i = 0; i < array.length; i++) { + for (int n = 0; n < value.length; n++) { + if (array[i].equals(value[n])) { + return true; + } + } + } + return false; + + } + + /** + * @param <T> + * @Title getDiffrent + * @Description TODO(Extract the list1 and list2 different data sets) + * @param list1 + * @param list2 + * @return TODO(a new List in list2 but not in list1) + * @return List<String> + */ + public static <T> Set<T> getDiffrent(Set<T> list1, Set<T> list2) { + + HashSet<T> set_all = new HashSet<T>(); + + for (T t1 : list1) { + set_all.add(t1); + } + + + Set<T> diff = new HashSet<T>(); + + for (T t2 : list2) { + if (set_all.add(t2)) { // in list2 but not in list1 + diff.add(t2); + } + } + + + return diff; + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/ConfigUtil.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/ConfigUtil.java new file mode 100644 index 0000000..80f99f4 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/ConfigUtil.java @@ -0,0 +1,446 @@ +package org.onap.msb.apiroute.wrapper.util; + +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.StringUtils; +import org.onap.msb.apiroute.ApiRouteAppConfig; +import org.onap.msb.apiroute.api.DiscoverInfo; +import org.onap.msb.apiroute.wrapper.InitRouteServiceWrapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +@SuppressWarnings("unchecked") +public class ConfigUtil { + private final static ConfigUtil instance = new ConfigUtil(); + + + private ConfigUtil() {} + + public static ConfigUtil getInstance() { + return instance; + } + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigUtil.class); + + private String serverPort="80"; + + private String IUI_ROOT_PATH="iui"; + + private String API_ROOT_PATH="api"; + + private String namespaceMatches="all"; + + private String visualRangeMatches="0"; + + private String nodeMetaQueryParam=""; + + private String network_plane_typeMatches=""; + + private String[] routeWay={"ip"}; + + private Map<String,String> labelMapMatches; + + private DiscoverInfo discoverInfo=new DiscoverInfo(); + + private String consul_ip=""; + + private String metricsUrl = "http://127.0.0.1:8066/admin/metrics"; + + public void initRootPath() { + String apiRootPathConfSource="Default"; + String iuiRootPathConfSource="Default"; + + try { + + URL urlRootPath = + ConfigUtil.class.getResource("/ext/initUrlRootPath/initUrlRootPath.json"); + if (urlRootPath != null) { + String path = urlRootPath.getPath(); + + LOGGER.warn("read initUrlRootPath:" + path); + + String fileContent = FileUtil.readFile(path); + ObjectMapper mapper = new ObjectMapper(); + + Map<String, String> map = mapper.readValue(fileContent, HashMap.class); + if (map.get("iuiRootPath") != null) { + IUI_ROOT_PATH = map.get("iuiRootPath"); + iuiRootPathConfSource="initUrlRootPath.json"; + } + if (map.get("apiRootPath") != null) { + API_ROOT_PATH = map.get("apiRootPath"); + apiRootPathConfSource="initUrlRootPath.json"; + } + + } + } catch (IOException e) { + // TODO Auto-generated catch block + LOGGER.error("init UrlRootPath throw exception", e); + } + + LOGGER.warn("init IUI_ROOT_PATH from ["+iuiRootPathConfSource+"]:"+IUI_ROOT_PATH); + LOGGER.warn("init API_ROOT_PATH from ["+apiRootPathConfSource+"]:"+API_ROOT_PATH); + + } + + public void initApiGatewayPort() { + + String env_APIGATEWAY_EXPOSE_PORT=System.getenv("APIGATEWAY_EXPOSE_PORT"); + String httpExposePortConfSource="Default"; + try { + // read initApiGatewayConfig + if (StringUtils.isBlank(env_APIGATEWAY_EXPOSE_PORT)) { + URL apiGatewayConfigPath = + ConfigUtil.class + .getResource("/ext/initApiGatewayConfig/initApiGatewayConfig.json"); + if (apiGatewayConfigPath != null) { + String path = apiGatewayConfigPath.getPath(); + + LOGGER.warn("read initApiGatewayConfig:" + path); + + String fileContent = FileUtil.readFile(path); + ObjectMapper mapper = new ObjectMapper(); + + Map<String, Object> labelMap = mapper.readValue(fileContent, Map.class); + if (labelMap.get("port") != null) { + serverPort = (String) labelMap.get("port"); + httpExposePortConfSource="initApiGatewayConfig.json"; + } + } + } else { + serverPort = env_APIGATEWAY_EXPOSE_PORT; + httpExposePortConfSource="env:APIGATEWAY_EXPOSE_PORT"; + } + LOGGER.warn("init APIGATEWAY http publish Port from ["+httpExposePortConfSource+"]:"+serverPort); + } catch (Exception e) { + // TODO Auto-generated catch block + LOGGER.error( + "read initApiGatewayConfig Files or env(APIGATEWAY_EXPOSE_PORT) throw exception", e); + } + + + } + + public void initConsulIp() { + String sys_consulIp=System.getenv("CONSUL_IP"); + if (StringUtils.isNotBlank(sys_consulIp)) { + consul_ip=sys_consulIp; + LOGGER.warn("init consul_Ip from [env:CONSUL_IP]:" + sys_consulIp); + } + else{ + LOGGER.warn("init consul_Ip from [env:CONSUL_IP] is blank"); + } + + + } + + public void initRouteNameSpaceMatches() { + String env_NAMESPACE=System.getenv("NAMESPACE"); + String namespaceConfSource="Default"; + try { + // read NAMESPACE + if (StringUtils.isBlank(env_NAMESPACE)) { + URL routeLabelsPath = + InitRouteServiceWrapper.class + .getResource("/ext/initRouteLabels/initRouteLabelsMatches.json"); + if (routeLabelsPath != null) { + String path = routeLabelsPath.getPath(); + + String fileContent = FileUtil.readFile(path); + ObjectMapper mapper = new ObjectMapper(); + + Map<String, Object> labelMap = mapper.readValue(fileContent, Map.class); + if (labelMap.get("namespace") != null) { + namespaceMatches = (String) labelMap.get("namespace"); + namespaceConfSource="initRouteLabelsMatches.json"; + } + } + } else { + namespaceMatches =env_NAMESPACE; + namespaceConfSource="env:NAMESPACE"; + } + LOGGER.warn("init namespace Filter from ["+namespaceConfSource+"]:" + namespaceMatches); + } + catch (Exception e) { + // TODO Auto-generated catch block + LOGGER.error("read initRouteNameSpaceMatches Files or env(NAMESPACE) throw exception", + e); + } + + + + } + /** + * @Title: initRouteLabelsMatches + * @Description: TODO(According to the environment variable or a JSON file configuration + * initialization Route filter conditions) + * @return: void + */ + public void initRouteLabelsMatches() { + String env_ROUTE_LABELS=System.getenv("ROUTE_LABELS"); + String visualRangeConfSource="Default"; + String networkPlaneConfSource="Default"; + String labelConfSource="Default"; + try { + + // read ROUTE_LABELS + if (StringUtils.isBlank(env_ROUTE_LABELS)) { + URL routeLabelsPath = + InitRouteServiceWrapper.class + .getResource("/ext/initRouteLabels/initRouteLabelsMatches.json"); + if (routeLabelsPath != null) { + String path = routeLabelsPath.getPath(); + + String fileContent = FileUtil.readFile(path); + ObjectMapper mapper = new ObjectMapper(); + + Map<?, ?> labelMap = mapper.readValue(fileContent, Map.class); + if (labelMap.get("predefineLabels") != null) { + Map<String, String> predefineLabelMapMatches = + (Map<String, String>) labelMap.get("predefineLabels"); + if (predefineLabelMapMatches.get("visualRange") != null) { + visualRangeMatches = predefineLabelMapMatches.get("visualRange"); + visualRangeConfSource="initRouteLabelsMatches.json"; + } + if (predefineLabelMapMatches.get("network_plane_type") != null) { + network_plane_typeMatches = + predefineLabelMapMatches.get("network_plane_type"); + networkPlaneConfSource="initRouteLabelsMatches.json"; + } + } + + if (labelMap.get("customLabels") != null) { + labelMapMatches = (Map<String, String>) labelMap.get("customLabels"); + labelConfSource="initRouteLabelsMatches.json"; + } + + } + } else { + String[] env_routeLabels = StringUtils.split(env_ROUTE_LABELS, ","); + Map<String, String> labelMap = new HashMap<String, String>(); + + for (int i = 0; i < env_routeLabels.length; i++) { + String[] labels = StringUtils.split(env_routeLabels[i], ":"); + + if ("visualRange".equals(labels[0])) { + visualRangeMatches = labels[1]; + visualRangeConfSource="env:ROUTE_LABELS"; + } else if ("network_plane_type".equals(labels[0])) { + network_plane_typeMatches = labels[1]; + networkPlaneConfSource="env:ROUTE_LABELS"; + } else { + labelMap.put(labels[0], labels[1]); + } + + } + + labelConfSource="env:ROUTE_LABELS"; + labelMapMatches = labelMap; + + } + LOGGER.warn("init visualRange Filter from [ "+visualRangeConfSource+" ]:" + visualRangeMatches); + LOGGER.warn("init network_plane_type Filter from [ "+networkPlaneConfSource+" ]:" + network_plane_typeMatches); + LOGGER.warn("init customLabels Filter from [ "+labelConfSource+" ]:" + labelMapMatches); + } catch (IOException e) { + // TODO Auto-generated catch block + LOGGER.error( + "read initRouteLabelsPathMatches Files or env(ROUTE_LABELS) throw exception", + e); + } + } + + public void initRouteWay() { + String env_ROUTE_WAY=System.getenv("ROUTE_WAY"); + try { + // read NAMESPACE + if (StringUtils.isBlank(env_ROUTE_WAY)) { + URL routeLabelsPath = + InitRouteServiceWrapper.class.getResource("/ext/initRouteWay/initRouteWay.json"); + if (routeLabelsPath != null) { + String path = routeLabelsPath.getPath(); + + String fileContent = FileUtil.readFile(path); + ObjectMapper mapper = new ObjectMapper(); + + Map<String, Object> routeWayMap = mapper.readValue(fileContent, Map.class); + String routeWayFromConfig=(String)routeWayMap.get("routeWay"); + if (StringUtils.isNotBlank(routeWayFromConfig)) { + routeWay = + StringUtils.split(routeWayFromConfig, RouteUtil.SPLIT_LINE); + LOGGER.warn("init RouteWay from [initRouteWay.json]:" + routeWayFromConfig); + } + } + } else { + routeWay = StringUtils.split(env_ROUTE_WAY, RouteUtil.SPLIT_LINE); + LOGGER.warn("read initRouteWay from [env:ROUTE_WAY]:" + env_ROUTE_WAY); + } + + + + + + } catch (Exception e) { + // TODO Auto-generated catch block + LOGGER.error("read initRouteWay Files or env(ROUTE_WAY) throw exception", e); + } + } + + + public void initDiscoverInfo(ApiRouteAppConfig configuration){ + DiscoverInfo config_discoverInfo = configuration.getDiscoverInfo(); + + + discoverInfo.setEnabled(config_discoverInfo.isEnabled()); + + String discoverInfoConfSource="yaml config"; + + if (config_discoverInfo.isEnabled()) { + + String discoverIP; + String env_SDCLIENT_IP=System.getenv("SDCLIENT_IP"); + + if (StringUtils.isBlank(env_SDCLIENT_IP)) { + // yml + discoverIP = config_discoverInfo.getIp(); + } else { + discoverIP = env_SDCLIENT_IP; + discoverInfoConfSource="env:SDCLIENT_IP"; + } + + discoverInfo.setIp(discoverIP.trim()); + discoverInfo.setPort(config_discoverInfo.getPort()); + } + + LOGGER.warn("init DiscoverInfo from ["+discoverInfoConfSource+"]--" + discoverInfo.toString()+" Enabled:"+discoverInfo.isEnabled()); + } + + public void initNodeMetaQueryParam() { + // judge consul register node:caltalog + String env_CONSUL_REGISTER_MODE = System.getenv("CONSUL_REGISTER_MODE"); + + if (env_CONSUL_REGISTER_MODE == null + || !env_CONSUL_REGISTER_MODE.trim().equals("catalog")) { + nodeMetaQueryParam = ""; + return; + } + + // visual range + String nodemeta_visualrange = nodemeta_visualrange(visualRangeMatches); + + LOGGER.warn("calc nodemeta_visualrange from [" + visualRangeMatches + + "]:" + nodemeta_visualrange); + + nodeMetaQueryParam = nodemeta_visualrange; + + // name space + String nodemeta_namespace = nodemeta_namespace(namespaceMatches); + LOGGER.warn("calc nodemeta_namespace from [" + namespaceMatches + "]:" + + nodemeta_namespace); + + if (!nodeMetaQueryParam.isEmpty() && !nodemeta_namespace.isEmpty()) { + nodeMetaQueryParam += "&"; + } + nodeMetaQueryParam += nodemeta_namespace; + + /* + * // nodemeta = (!nodemeta_visualrange.isEmpty() && !nodemeta_namespace + * .isEmpty()) ? nodemeta_visualrange + "&" + nodemeta_namespace : + * nodemeta_visualrange + nodemeta_namespace; + */ + + } + + private String nodemeta_visualrange(final String visualRangeMatches) { + + if (visualRangeMatches == null || visualRangeMatches.isEmpty()) { + return ""; + } + + // external:0 + if (visualRangeMatches.trim().equals("0")) { + return "node-meta=external:true"; + } + + // internal:1 + if (visualRangeMatches.trim().equals("1")) { + return "node-meta=internal:true"; + } + + return ""; + } + + + private String nodemeta_namespace(final String namespaceMatches) { + + // exclude null,"",all,&,|,! + if (namespaceMatches == null || namespaceMatches.isEmpty() + || namespaceMatches.contains("all") + || namespaceMatches.contains("&") + || namespaceMatches.contains("|") + || namespaceMatches.contains("!")) { + return ""; + } + + return "node-meta=ns:" + namespaceMatches; + } + + public String getServerPort() { + return serverPort; + } + + public String getIUI_ROOT_PATH() { + return IUI_ROOT_PATH; + } + + public String getAPI_ROOT_PATH() { + return API_ROOT_PATH; + } + + public String getNamespaceMatches() { + return namespaceMatches; + } + + public String getVisualRangeMatches() { + return visualRangeMatches; + } + + public String getNetwork_plane_typeMatches() { + return network_plane_typeMatches; + } + + public String[] getRouteWay() { + return routeWay.clone(); + } + + public Map<String, String> getLabelMapMatches() { + return labelMapMatches; + } + + public DiscoverInfo getDiscoverInfo() { + return discoverInfo; + } + + public String getMetricsUrl() { + return metricsUrl; + } + + public void setMetricsUrl(String metricsUrl) { + this.metricsUrl = metricsUrl; + } + + public String getNodeMetaQueryParam() { + return nodeMetaQueryParam; + } + + public String getConsul_ip() { + return consul_ip; + } + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/FileUtil.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/FileUtil.java new file mode 100644 index 0000000..1e89f82 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/FileUtil.java @@ -0,0 +1,78 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.wrapper.util; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; + +public final class FileUtil { + + /** + * Read all the files under a folder + */ + public static File[] readFileFolder(String filepath) throws FileNotFoundException, IOException { + File file = new File(filepath); + if (file.isDirectory()) { + File[] filelist = file.listFiles(); + return filelist; + } + + return null; + } + + public static String readFile(String Path) throws IOException{ + BufferedReader reader = null; + StringBuffer fileContent = new StringBuffer(); + try { + FileInputStream fileInputStream = new FileInputStream(Path); + InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8"); + reader = new BufferedReader(inputStreamReader); + String tempString = null; + while ((tempString = reader.readLine()) != null) { + fileContent.append(tempString); + } + reader.close(); + } catch (IOException e) { + throw e; + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + throw e; + } + } + } + return fileContent.toString(); + } + + /** + * Read all the files under a folder + */ + public static String[] readfile(String filepath) throws FileNotFoundException, IOException { + File file = new File(filepath); + if (file.isDirectory()) { + String[] filelist = file.list(); + return filelist; + } + return null; + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/HttpClientUtil.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/HttpClientUtil.java new file mode 100644 index 0000000..eb5ed1e --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/HttpClientUtil.java @@ -0,0 +1,117 @@ +package org.onap.msb.apiroute.wrapper.util; + +import java.io.IOException; + +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HttpClientUtil { + + private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class); + + private static int connectionTimeOut = 2*1000; + + + public static String httpGet(String url){ + String result = null; + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpGet httpGet = new HttpGet(url); + httpGet.addHeader("Content-type", "application/json; charset=utf-8"); + httpGet.setHeader("Accept", "application/json"); + try { + CloseableHttpResponse res = httpClient.execute(httpGet); + result = EntityUtils.toString(res.getEntity()); + if (res.getStatusLine().getStatusCode() != CommonUtil.SC_OK) { + logger.error(result); + } + res.close(); + } catch (ClientProtocolException e) { + logger.error(url + ":httpGetWithJSON connect faild"); + } catch (IOException e) { + logger.error( url + ":httpGetWithJSON connect faild"); + } finally { + try { + httpClient.close(); + } catch (IOException e) { + logger.error(url + ":close httpClient faild"); + } + } + + return result; + + } + + public static HttpGetResult httpGetStatusAndBody(String url){ + HttpGetResult result= new HttpGetResult(); + String body = null; + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpGet httpGet = new HttpGet(url); + httpGet.addHeader("Content-type", "application/json; charset=utf-8"); + httpGet.setHeader("Accept", "application/json"); + + RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectionTimeOut).build(); + httpGet.setConfig(requestConfig); + + try { + CloseableHttpResponse res = httpClient.execute(httpGet); + body = EntityUtils.toString(res.getEntity()); + if (res.getStatusLine().getStatusCode() != CommonUtil.SC_OK) { + logger.error(body); + } + result.setBody(body); + result.setStatusCode(res.getStatusLine().getStatusCode()); + res.close(); + } catch (ClientProtocolException e) { + logger.error(url + ":httpGetWithJSON connect faild",e); + } catch (IOException e) { + logger.error( url + ":httpGetWithJSON connect faild",e); + } finally { + try { + httpClient.close(); + } catch (IOException e) { + logger.error(url + ":close httpClient faild"); + } + } + + return result; + + } + + public static int httpGetStatus(String url) throws Exception{ + int iStatus=500; + CloseableHttpClient httpClient = HttpClients.createDefault(); + + + HttpGet httpGet = new HttpGet(url); + RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).build();//设置请求和传输超时时间 + httpGet.setConfig(requestConfig); + httpGet.addHeader("Content-type", "application/json; charset=utf-8"); + httpGet.setHeader("Accept", "application/json"); + try { + CloseableHttpResponse res = httpClient.execute(httpGet); + + iStatus=res.getStatusLine().getStatusCode(); + res.close(); + } catch (ClientProtocolException e) { + logger.error(url + " httpGet connect faild:"+e.getMessage()); + } catch (IOException e) { + logger.error(url + " httpGet connect faild:"+e.getMessage()); + } finally { + try { + httpClient.close(); + } catch (IOException e) { + logger.error(url + " httpGet close faild:"+e.getMessage()); + } + } + + return iStatus; + + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/HttpGetResult.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/HttpGetResult.java new file mode 100644 index 0000000..5b943e3 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/HttpGetResult.java @@ -0,0 +1,19 @@ +package org.onap.msb.apiroute.wrapper.util; + +public class HttpGetResult { + private int statusCode; + private String body; + public int getStatusCode() { + return statusCode; + } + public void setStatusCode(int statusCode) { + this.statusCode = statusCode; + } + public String getBody() { + return body; + } + public void setBody(String body) { + this.body = body; + } + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/Jackson.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/Jackson.java new file mode 100644 index 0000000..20b60d4 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/Jackson.java @@ -0,0 +1,28 @@ +package org.onap.msb.apiroute.wrapper.util; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.guava.GuavaModule; +import com.fasterxml.jackson.datatype.jdk7.Jdk7Module; +import com.fasterxml.jackson.datatype.joda.JodaModule; + +public class Jackson { + //use static singleton, make sure to reuse! + public static final ObjectMapper MAPPER = newObjectMapper(); + + private Jackson() { + /* singleton */ + } + + private static ObjectMapper newObjectMapper() { + final ObjectMapper mapper = new ObjectMapper(); + return configure(mapper); + } + + private static ObjectMapper configure(ObjectMapper mapper) { + mapper.registerModule(new GuavaModule()); + mapper.registerModule(new JodaModule()); + mapper.registerModule(new Jdk7Module()); + + return mapper; + } +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/JacksonJsonUtil.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/JacksonJsonUtil.java new file mode 100644 index 0000000..4a7f50e --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/JacksonJsonUtil.java @@ -0,0 +1,110 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.wrapper.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + + +public class JacksonJsonUtil { + + private static final Logger logger = LoggerFactory.getLogger(JacksonJsonUtil.class); + + private volatile static ObjectMapper mapper = null; + + private static ObjectMapper getMapperInstance() { + if (mapper == null) { + synchronized (JacksonJsonUtil.class) { + if (mapper == null) { + mapper = new ObjectMapper(); + } + } + } + return mapper; + } + + /** + * from java object to json + * + * @param obj + * @return json + * @throws Exception + */ + public static String beanToJson(Object obj) throws Exception { + String json = null; + + ObjectMapper objectMapper = getMapperInstance(); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + json = objectMapper.writeValueAsString(obj); + + return json; + } + + + + /** + * from json to java object + * + * @param json + * @param cls + * @return + * @throws Exception + */ + public static Object jsonToBean(String json, Class<?> cls) throws Exception { + Object vo = null; + try { + ObjectMapper objectMapper = getMapperInstance(); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + vo = objectMapper.readValue(json, cls); + + } catch (Exception e) { + logger.error(cls + " JsonTobean faild"); + throw new Exception(cls + " JsonTobean faild"); + } + return vo; + } + + /** + * from json to java List + * + * @param json + * @return + * @throws Exception + */ + + public static <T> T jsonToListBean(String json, TypeReference<T> valueTypeRef) { + try { + + ObjectMapper objectMapper = getMapperInstance(); + + + return objectMapper.readValue(json, valueTypeRef); + + } catch (Exception e) { + String errorMsg = " JsonTobean faild:" + e.getMessage(); + logger.error(errorMsg); + } + return null; + } + + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/JedisUtil.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/JedisUtil.java new file mode 100644 index 0000000..ac9421b --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/JedisUtil.java @@ -0,0 +1,208 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.wrapper.util; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + +import org.apache.commons.lang3.StringUtils; +import org.onap.msb.apiroute.wrapper.InitRouteServiceWrapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + + + +public class JedisUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(JedisUtil.class); + private static String host = "127.0.0.1"; + private static int port = 6379; + private static int connectionTimeout = 2000; + private static int DEFAULT_DB_INDEX = 0; + + private volatile static JedisPool jedisPool = null; + + + public static String propertiesName = "redis.properties"; + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + + private JedisUtil() { + // private constructor + + } + + private synchronized static JedisPool initialPool() throws IOException { + + JedisPoolConfig config = new JedisPoolConfig(); + config.setMaxTotal(50); + config.setMaxIdle(30); + config.setMaxWaitMillis(5000); + config.setTestOnBorrow(false); + config.setTestOnReturn(true); + + URL urlPath = JedisUtil.class.getResource("/ext/redisConf/redis.properties"); + if (urlPath != null) { + String propertiesPath = urlPath.getPath(); + + + File propertiesFile = new File(propertiesPath); + + if (propertiesFile.exists()) { + + + BufferedInputStream inputStream = + new BufferedInputStream(new FileInputStream(propertiesPath)); + ResourceBundle bundle = new PropertyResourceBundle(inputStream); + + if (bundle == null) { + throw new IllegalArgumentException("[redis.properties] is not found!"); + } + + + // Set up the connection pool basic information + String strHost = bundle.getString("redis.host"); + if (StringUtils.isNotEmpty(strHost)) { + host = strHost; + } + + // redis port: first read from env + if (StringUtils.isNotBlank(System.getenv("APIGATEWAY_REDIS_PORT"))) { + port = Integer.parseInt(System.getenv("APIGATEWAY_REDIS_PORT")); + } else { + String strPort = bundle.getString("redis.port"); + if (StringUtils.isNotEmpty(strPort)) { + port = Integer.parseInt(strPort); + } + } + + + String strTimeout = bundle.getString("redis.connectionTimeout"); + if (StringUtils.isNotEmpty(strTimeout)) { + connectionTimeout = Integer.parseInt(strTimeout); + } + + + String strDbIndex = bundle.getString("redis.db_index"); + if (StringUtils.isNotEmpty(strDbIndex)) { + DEFAULT_DB_INDEX = Integer.parseInt(strDbIndex); + } + + String strMaxTotal = bundle.getString("redis.pool.maxTotal"); + if (StringUtils.isNotEmpty(strMaxTotal)) { + config.setMaxTotal(Integer.parseInt(strMaxTotal)); + } + + String strMaxIdle = bundle.getString("redis.pool.maxIdle"); + if (StringUtils.isNotEmpty(strMaxIdle)) { + config.setMaxIdle(Integer.parseInt(strMaxIdle)); + } + + String strMaxWaitMillis = bundle.getString("redis.pool.maxWaitMillis"); + if (StringUtils.isNotEmpty(strMaxWaitMillis)) { + config.setMaxWaitMillis(Long.parseLong(strMaxWaitMillis)); + } + + String strTestOnBorrow = bundle.getString("redis.pool.testOnBorrow"); + if (StringUtils.isNotEmpty(strTestOnBorrow)) { + config.setTestOnBorrow(Boolean.valueOf(strTestOnBorrow)); + } + + String strTestOnReturn = bundle.getString("redis.pool.testOnReturn"); + if (StringUtils.isNotEmpty(strTestOnReturn)) { + config.setTestOnReturn(Boolean.valueOf(strTestOnReturn)); + } + + } + } + + StringBuffer redisinfo = new StringBuffer(); + redisinfo.append("------redis.properties------").append(LINE_SEPARATOR); + redisinfo.append("redis.host: ").append(host).append(":").append(port).append(LINE_SEPARATOR); + redisinfo.append("redis.connectionTimeout: ").append(connectionTimeout).append(LINE_SEPARATOR); + redisinfo.append("redis.pool.maxTotal: ").append(config.getMaxTotal()).append(LINE_SEPARATOR); + redisinfo.append("redis.pool.maxIdle: ").append(config.getMaxIdle()).append(LINE_SEPARATOR); + redisinfo.append("redis.pool.maxWaitMillis: ").append(config.getMaxWaitMillis()) + .append(LINE_SEPARATOR); + redisinfo.append("redis.pool.testOnBorrow: ").append(config.getTestOnBorrow()) + .append(LINE_SEPARATOR); + redisinfo.append("redis.pool.testOnReturn: ").append(config.getTestOnReturn()) + .append(LINE_SEPARATOR); + + + LOGGER.info(redisinfo.toString()); + return new JedisPool(config, host, port, connectionTimeout); + + } + + /** + * From the connection pool to obtain jedis instance, use the default database index number 0 + * + * @return + * @throws Exception + */ + public static Jedis borrowJedisInstance() throws Exception { + return borrowJedisInstance(DEFAULT_DB_INDEX); + } + + /** + * From the connection pool to obtain jedis instance, using the specified database index number + * + * @return + * @throws Exception + */ + + public static Jedis borrowJedisInstance(final int dbIndex) throws Exception { + if (jedisPool == null) { + synchronized (JedisUtil.class) { + if (jedisPool == null) { + jedisPool = initialPool(); + } + } + } + Jedis resource = jedisPool.getResource(); + + if (resource == null) { + throw new Exception("fetch from jedis pool failed,null object!"); + } + + resource.select(dbIndex); + return resource; + + } + + /** + * returned to the pool jedis instance + * + * @param jedis + */ + public static void returnJedisInstance(final Jedis jedis) { + if (jedis != null) { + jedis.close(); + } + } + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/MicroServiceUtil.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/MicroServiceUtil.java new file mode 100644 index 0000000..1081579 --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/MicroServiceUtil.java @@ -0,0 +1,78 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.wrapper.util; + +import org.apache.commons.lang3.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import java.util.regex.Pattern; + + +public class MicroServiceUtil { + public static final String PREFIX_PATH = "discover:microservices"; + + private static final Pattern SERVICE_KEY_REGEX_PATTERN = + Pattern.compile("discover:microservices:(?<servicename>[^:]+)(:(?<version>[^:]*))"); + + + public static String getPrefixedKey(String... paths) { + StringBuffer sb = new StringBuffer(); + + sb.append(PREFIX_PATH); + + for (int i = 0; i < paths.length; i++) { + sb.append(":"); + sb.append(paths[i]); + } + return sb.toString(); + } + + + public static String getServiceKey(String serviceName, String version) { + return getPrefixedKey(serviceName, version); + } + + public static Pattern getServiceKeyRegexPattern(){ + return SERVICE_KEY_REGEX_PATTERN; + } + + + + public static String getRealIp(HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) { + // After the reverse proxy can have multiple IP value for many times, the first IP is the real IP + int index = ip.indexOf(","); + if (index != -1) { + return ip.substring(0, index); + } else { + return ip; + } + } + ip = request.getHeader("X-Real-IP"); + + if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) { + return ip; + } + + + return request.getRemoteAddr(); + + } + + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/RegExpTestUtil.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/RegExpTestUtil.java new file mode 100644 index 0000000..0edcfda --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/RegExpTestUtil.java @@ -0,0 +1,115 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.wrapper.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RegExpTestUtil { + + + private final static String API_KEY_PATTERN ="/api/(?<servicename>[^/]+)(/(?<version>[^/]*)).*"; + + private final static String IUI_KEY_PATTERN ="/iui/(?<servicename>[^/]+)/.*"; + + public static boolean hostRegExpTest(String host){ + + String hostReg = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\." + +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)" + +":(\\d{1,5})$"; + return Pattern.matches(hostReg, host); + + } + + public static boolean ipRegExpTest(String ip){ + + String hostReg = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\." + +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + +"(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$"; + return Pattern.matches(hostReg, ip); + + } + + public static boolean portRegExpTest(String port){ + + String hostReg = "^\\d{1,5}$"; + return Pattern.matches(hostReg, port); + + } + +public static boolean versionRegExpTest(String version){ + + String versionReg = "^v\\d+(\\.\\d+)?$"; + return Pattern.matches(versionReg, version); + + } + +public static boolean urlRegExpTest(String url){ + if(url.equals("/")) return true; + + String urlReg = "^\\/.*((?!\\/).)$"; + return Pattern.matches(urlReg, url); + +} + +public static boolean apiRouteUrlRegExpTest(String url){ + + String urlReg = "^\\/"+ConfigUtil.getInstance().getAPI_ROOT_PATH()+"\\/.*$"; + return Pattern.matches(urlReg, url); + +} + +public static boolean iuiRouteUrlRegExpTest(String url){ + + String urlReg = "^\\/"+ConfigUtil.getInstance().getIUI_ROOT_PATH()+"\\/.*$"; + return Pattern.matches(urlReg, url); + +} + +public static String[] apiServiceNameMatch4URL(String url){ + Pattern redisKeyPattern =Pattern.compile(API_KEY_PATTERN); + Matcher matcher = redisKeyPattern.matcher(url+"/"); + if (matcher.matches()) { + String version; + if(versionRegExpTest(matcher.group("version"))){ + version=matcher.group("version"); + } + else{ + version=""; + } + return new String[]{matcher.group("servicename"),version}; + } + else{ + return null; + } +} + + +public static String iuiServiceNameMatch4URL(String url){ + Pattern redisKeyPattern =Pattern.compile(IUI_KEY_PATTERN); + Matcher matcher = redisKeyPattern.matcher(url+"/"); + if (matcher.matches()) { + return matcher.group("servicename"); + } + else{ + return null; + } +} + +} diff --git a/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/RouteUtil.java b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/RouteUtil.java new file mode 100644 index 0000000..331671f --- /dev/null +++ b/apiroute/apiroute-service/src/main/java/org/onap/msb/apiroute/wrapper/util/RouteUtil.java @@ -0,0 +1,345 @@ +/** + * Copyright 2016 ZTE, Inc. and others. + * + * 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.onap.msb.apiroute.wrapper.util; + +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.api.RouteInfo; +import org.onap.msb.apiroute.api.RouteServer; +import org.onap.msb.apiroute.api.exception.UnprocessableEntityException; + + +public class RouteUtil { + + + public static final int consulDeafultPort=8500; + + public static final String ROUTE_PATH="msb:routing"; + + public static final String ROUTE_PORT_PATH="msb:"; + + public static final String ROUTE_PATH_HOST="msb:host"; + + public static final String APIROUTE="api"; + + public static final String IUIROUTE="iui"; + + public static final String CUSTOMROUTE="custom"; + + public static final String HTTPS_PROTOCOL="https"; + + public static final String CUSTOM_PORTAL="portal"; + + + public static final String PROTOCOL_LIST="REST,HTTP,UI,MQ,FTP,SNMP,TCP,UDP"; + + public static final String MSB_ROUTE_URL = "/api/microservices/v1/services"; + + public static final String MSB_CHECK_URL = "/api/catalog/v1/service/router-all"; + + public static final String visualRangeRange="0,1"; + + public static final String controlRangeMatches="0,1,2"; + + public static final String statusRangeMatches="0,1"; + + public static final String useOwnUpstreamRangeMatches="0,1"; + + public static final String ROUTEWAY_IP="ip"; + + public static final String ROUTEWAY_DOMAIN="domain"; + + public static final String SPLIT_LINE="|"; + + public static final String PROTOCOL_REST="REST"; + + public static final String PROTOCOL_UI="UI"; + + public static final String PROTOCOL_HTTP="HTTP"; + + public static final String FILTER_PROTOCOLS="REST,UI,HTTP"; + + public static final int SERVICE_DATA_QUEUE_NUM=5; + + public static final int SERVICE_QUEUE_CAPACITY=100; + + public static final int SERVICE_LIST_QUEUE_CAPACITY=5; + + public static final int WATCH_SECOND=120; + + public static final String HEALTH_CHECK_PASSING="passing"; + + + + + /** + * @Title: getPrefixedKey + * @Description: TODO(Add base path prefix radis assembly path) + * @param: @param serviceName + * @param: @param version + * @param: @param type + * @param: @return + * @return: String + */ + + public static String getPrefixedKey(String...paths){ + StringBuffer sb= new StringBuffer(); + + if(paths[0].trim().equals("") || paths[0].equals(ConfigUtil.getInstance().getServerPort())){ + sb.append(ROUTE_PATH); + } + else{ + sb.append(ROUTE_PORT_PATH).append(paths[0]); + } + + for (int i = 1; i < paths.length; i++) { + sb.append(":"); + sb.append(paths[i]); + } + return sb.toString(); + } + + public static String getPrefixedKey4Host(String...paths){ + StringBuffer sb= new StringBuffer(); + + sb.append(ROUTE_PATH_HOST); + + + for (int i = 0; i < paths.length; i++) { + sb.append(":"); + sb.append(paths[i]); + } + return sb.toString(); + } + + + + + public static void checkRouteWay(String routeWay){ + if(!CommonUtil.contain(ConfigUtil.getInstance().getRouteWay(),routeWay)){ + String errInfo = "routeWay does not support,must be ip or domain"; + throw new UnprocessableEntityException(errInfo); + } + } + + public static void checkServiceNameAndVersion(String serviceName,String version){ + if (StringUtils.isBlank(serviceName)) { + throw new UnprocessableEntityException("serviceName can't be empty"); + } + + if (StringUtils.isNotBlank(version)) { + if (!RegExpTestUtil.versionRegExpTest(version)) { + throw new UnprocessableEntityException("version is not a valid format"); + } + } + } + + public static void checkServiceStatus(String status){ + if (!CommonUtil.contain(statusRangeMatches, status)) { + throw new UnprocessableEntityException( + "save RouteInfo Status FAIL:status is wrong,value range:(" + + RouteUtil.statusRangeMatches + ")"); + } + } + + + + public static void checkRouterInfoFormat(RouteInfo routeInfo) { + + if (StringUtils.isBlank(routeInfo.getServiceName()) || routeInfo.getServers().length == 0) { + throw new UnprocessableEntityException( + "save RouteInfo FAIL: Some required fields are empty"); + } + + if (StringUtils.isNotBlank(routeInfo.getUrl())) { + if (!RegExpTestUtil.urlRegExpTest(routeInfo.getUrl())) { + throw new UnprocessableEntityException( + "save RouteInfo FAIL:url is not a valid format(url must be begin with /)"); + + } + } + + if (!CommonUtil.contain(RouteUtil.visualRangeRange, routeInfo.getVisualRange())) { + throw new UnprocessableEntityException( + "save RouteInfo FAIL:VisualRange is wrong,value range:(" + + RouteUtil.visualRangeRange + ")"); + } + + if (!CommonUtil.contain(RouteUtil.controlRangeMatches, routeInfo.getControl())) { + throw new UnprocessableEntityException( + "save RouteInfo FAIL:control is wrong,value range:(" + + RouteUtil.controlRangeMatches + ")"); + } + + if (!CommonUtil.contain(RouteUtil.statusRangeMatches, routeInfo.getStatus())) { + throw new UnprocessableEntityException( + "save RouteInfo FAIL:status is wrong,value range:(" + + RouteUtil.statusRangeMatches + ")"); + } + + if (!CommonUtil.contain(RouteUtil.useOwnUpstreamRangeMatches, routeInfo.getUseOwnUpstream())) { + throw new UnprocessableEntityException( + "save RouteInfo FAIL:useOwnUpstream is wrong,value range:(" + + RouteUtil.useOwnUpstreamRangeMatches + ")"); + } + + // Check the service instance format + RouteServer[] serverList = routeInfo.getServers(); + for (int i = 0; i < serverList.length; i++) { + RouteServer server = serverList[i]; + if (!RegExpTestUtil.ipRegExpTest(server.getIp())) { + throw new UnprocessableEntityException("save RouteInfo FAIL:IP(" + server.getIp() + + ")is not a valid ip address"); + } + + if (!RegExpTestUtil.portRegExpTest(server.getPort())) { + throw new UnprocessableEntityException("save RouteInfo FAIL:Port(" + server.getPort() + + ")is not a valid Port address"); + } + } + } + + public static void checkMicroServiceInfoFormat(MicroServiceFullInfo microServiceInfo,String requestIP){ + // Check the service instance format + if (StringUtils.isBlank(microServiceInfo.getServiceName()) + || StringUtils.isBlank(microServiceInfo.getProtocol()) + || microServiceInfo.getNodes().size() == 0) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL: Some required fields are empty"); + } + + for (Node node : microServiceInfo.getNodes()) { + + if (node.getIp() == null || node.getIp().isEmpty()) { + node.setIp(requestIP); + } else if (!RegExpTestUtil.ipRegExpTest(node.getIp())) { + throw new UnprocessableEntityException("register MicroServiceInfo FAIL:IP(" + node.getIp() + + ")is not a valid ip address"); + } + + if (!RegExpTestUtil.portRegExpTest(node.getPort())) { + throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Port(" + + node.getPort() + ")is not a valid Port address"); + } + } + + if (StringUtils.isNotBlank(microServiceInfo.getVersion())) { + if (!RegExpTestUtil.versionRegExpTest(microServiceInfo.getVersion())) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:version is not a valid format"); + + } + } + + if (StringUtils.isNotBlank(microServiceInfo.getUrl().trim())) { + if (!RegExpTestUtil.urlRegExpTest(microServiceInfo.getUrl())) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:url is not a valid format(url must be begin with /)"); + + } + } + + + if (RouteUtil.PROTOCOL_LIST.indexOf(microServiceInfo.getProtocol().trim()) == -1) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:Protocol is wrong,value range:(" + + RouteUtil.PROTOCOL_LIST + ")"); + } + + } + + + public static String getAPIRedisPrefixedKey(String routeName, String version, String host,String publish_port,String routeWay){ + String redisPrefixedKey; + if(ROUTEWAY_DOMAIN.equals(routeWay)){ + redisPrefixedKey= RouteUtil.getPrefixedKey4Host(host, APIROUTE, routeName, version); + } + else{ + redisPrefixedKey=RouteUtil.getPrefixedKey(publish_port, APIROUTE, routeName, version); + } + + return redisPrefixedKey; + } + + public static String getRedisPrefixedKey(String routeType,String routeName, String host,String publish_port,String routeWay){ + String redisPrefixedKey; + if(ROUTEWAY_DOMAIN.equals(routeWay)){ + redisPrefixedKey= RouteUtil.getPrefixedKey4Host(host, routeType, routeName); + } + else{ + redisPrefixedKey=RouteUtil.getPrefixedKey(publish_port, routeType, routeName); + } + + return redisPrefixedKey; + } + + public static String getMutiRedisKey(String routeType,String routeWay){ + String redisKey; + if(RouteUtil.ROUTEWAY_DOMAIN.equals(routeWay)){ + redisKey = + RouteUtil.getPrefixedKey4Host("*", routeType, "*"); + + } + else{ + redisKey = + RouteUtil.getPrefixedKey("[^h]*", routeType, "*"); + + } + + return redisKey; + } + + /** + * @Title getRouteNameByns + * @Description TODO(根据服务名和命名空间拆分服务路由名) + * @param serviceName + * @param namespace + * @return + * @return String + */ + public static String getRouteNameByns(String consul_serviceName,String namespace){ + String serviceName=consul_serviceName; + if(StringUtils.isNotBlank(namespace)){ + if(consul_serviceName.endsWith("-"+namespace)){ + serviceName=consul_serviceName.substring(0,consul_serviceName.length()-namespace.length()-1); + } + } + + return serviceName; + } + + public static String getVisualRangeByRouter(String visualRange){ + String[] rangs = StringUtils.split(visualRange, "|"); + if(rangs.length>1){ + String visualRangeMatches=ConfigUtil.getInstance().getVisualRangeMatches(); + if(StringUtils.split(visualRangeMatches, "|").length>1){ + return "0"; + } + else{ + return visualRangeMatches; + } + } + else{ + return visualRange; + } + + } + + + +} 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; + + } + +} |