diff options
author | HuabingZhao <zhao.huabing@zte.com.cn> | 2017-07-04 05:15:15 +0000 |
---|---|---|
committer | HuabingZhao <zhao.huabing@zte.com.cn> | 2017-07-04 05:51:17 +0000 |
commit | 5353f7df61d16d6624ba033627a7d09160fb679c (patch) | |
tree | c5dd805b7c1655589a0edaf0a6a7d54e78fec539 /sdclient | |
parent | a3fa8cc2c6fa2883bc88a8244cbce5cacfd4fadf (diff) |
migrate discovery source codes from OPEN-O
Change-Id: I65396f0ed5f85542e8b17b509fc30073bf7f959e
Signed-off-by: HuabingZhao <zhao.huabing@zte.com.cn>
Diffstat (limited to 'sdclient')
64 files changed, 10556 insertions, 0 deletions
diff --git a/sdclient/discovery-service/dependency-reduced-pom.xml b/sdclient/discovery-service/dependency-reduced-pom.xml new file mode 100644 index 0000000..2efbf10 --- /dev/null +++ b/sdclient/discovery-service/dependency-reduced-pom.xml @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <artifactId>sdclient</artifactId> + <groupId>org.onap.msb.discovery</groupId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <groupId>org.onap.msb.discovery.sdclient</groupId> + <artifactId>discovery-service</artifactId> + <name>onap/msb/discovery/sdclient/discovery-service</name> + <version>0.0.1-SNAPSHOT</version> + <build> + <resources> + <resource> + <directory>src/main/java</directory> + <includes> + <include>**/*.properties</include> + </includes> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <version>2.4</version> + <configuration> + <archive> + <manifest> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + </manifest> + </archive> + </configuration> + </plugin> + <plugin> + <artifactId>maven-shade-plugin</artifactId> + <version>2.3</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <transformers> + <transformer /> + <transformer> + <mainClass>org.onap.msb.sdclient.DiscoverApp</mainClass> + </transformer> + </transformers> + </configuration> + </execution> + </executions> + <configuration> + <createDependencyReducedPom>true</createDependencyReducedPom> + <filters> + <filter> + <artifact>*:*</artifact> + <excludes> + <exclude>META-INF/*.SF</exclude> + <exclude>META-INF/*.DSA</exclude> + <exclude>META-INF/*.RSA</exclude> + </excludes> + </filter> + </filters> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + <exclusions> + <exclusion> + <artifactId>hamcrest-core</artifactId> + <groupId>org.hamcrest</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-junit4</artifactId> + <version>1.5.5</version> + <scope>test</scope> + <exclusions> + <exclusion> + <artifactId>powermock-module-junit4-common</artifactId> + <groupId>org.powermock</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + <version>1.5.5</version> + <scope>test</scope> + <exclusions> + <exclusion> + <artifactId>mockito-all</artifactId> + <groupId>org.mockito</groupId> + </exclusion> + <exclusion> + <artifactId>powermock-api-support</artifactId> + <groupId>org.powermock</groupId> + </exclusion> + </exclusions> + </dependency> + </dependencies> +</project> + diff --git a/sdclient/discovery-service/pom.xml b/sdclient/discovery-service/pom.xml new file mode 100644 index 0000000..22ec3e6 --- /dev/null +++ b/sdclient/discovery-service/pom.xml @@ -0,0 +1,160 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- + + 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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>org.onap.msb.discovery</groupId> + <artifactId>sdclient</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <groupId>org.onap.msb.discovery.sdclient</groupId> + <artifactId>discovery-service</artifactId> + <name>onap/msb/discovery/sdclient/discovery-service</name> + <packaging>jar</packaging> + <version>0.0.1-SNAPSHOT</version> + + + <dependencies> + <dependency> + <groupId>io.dropwizard</groupId> + <artifactId>dropwizard-core</artifactId> + </dependency> + <dependency> + <groupId>io.dropwizard</groupId> + <artifactId>dropwizard-assets</artifactId> + </dependency> + <dependency> + <groupId>io.dropwizard</groupId> + <artifactId>dropwizard-client</artifactId> + </dependency> + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey2-jaxrs</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-junit4</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + <scope>test</scope> + </dependency> + + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>2.4</version> + <configuration> + <archive> + <manifest> + <addDefaultImplementationEntries>true</addDefaultImplementationEntries> + </manifest> + </archive> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>2.3</version> + <configuration> + <createDependencyReducedPom>true</createDependencyReducedPom> + <filters> + <filter> + <artifact>*:*</artifact> + <excludes> + <exclude>META-INF/*.SF</exclude> + <exclude>META-INF/*.DSA</exclude> + <exclude>META-INF/*.RSA</exclude> + </excludes> + </filter> + </filters> + </configuration> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <transformers> + <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> + <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <mainClass>org.onap.msb.sdclient.DiscoverApp</mainClass> + </transformer> + </transformers> + </configuration> + </execution> + </executions> + </plugin> + <!--plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <phase>package</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>io.dropwizard</groupId> + <artifactId>dropwizard-core</artifactId> + <version>${dropwizard.version}</version> + <overWrite>true</overWrite> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin--> + </plugins> + <resources> + <resource> + <directory>src/main/java</directory> + <includes> + <include>**/*.properties</include> + </includes> + </resource> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + </build> +</project> diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverApp.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverApp.java new file mode 100644 index 0000000..7c9185a --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverApp.java @@ -0,0 +1,140 @@ +/** + * 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.sdclient; + +import org.onap.msb.sdclient.resources.MicroServiceResource; +import org.onap.msb.sdclient.wrapper.ConsulClientApp; +import org.onap.msb.sdclient.wrapper.PublishAddressWrapper; +import org.onap.msb.sdclient.wrapper.util.ConfigUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import io.dropwizard.Application; +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; + +public class DiscoverApp extends Application<DiscoverAppConfig> { + + private static final Logger LOGGER = LoggerFactory + .getLogger(DiscoverApp.class); + + public static void main(String[] args) throws Exception { + new DiscoverApp().run(args); + + } + + private DiscoverAppConfig config; + + @Override + public String getName() { + return " MicroService Bus "; + } + + @Override + public void initialize(Bootstrap<DiscoverAppConfig> bootstrap) { +// bootstrap.addBundle(new AssetsBundle("/iui-metrics", +// "/iui/microservices/metrics", "index.html", "iui-metrics")); +// bootstrap.addBundle(new AssetsBundle("/iui-discover", +// "/iui/microservices", "index.html", "iui-microservices")); +// bootstrap.addBundle(new AssetsBundle("/iui-discover", "/iui", +// "index.html", "iui")); + + + } + + @Override + public void run(DiscoverAppConfig configuration, Environment environment) { + + environment.jersey().register(new MicroServiceResource()); + + config=configuration; + + initSwaggerConfig(environment, configuration); + + ConfigUtil.getInstance().initConsulClientInfo(configuration); + + initApiGateWayServiceListen(); + + ConfigUtil.getInstance().initTCP_UDP_portRange(); + + ConfigUtil.getInstance().initConsulRegisterMode(configuration); + + } + + + + private void initSwaggerConfig(Environment environment, + DiscoverAppConfig configuration) { + + environment.jersey().register(new ApiListingResource()); + environment.getObjectMapper().setSerializationInclusion( + JsonInclude.Include.NON_NULL); + + BeanConfig config = new BeanConfig(); + config.setTitle("Service Discovery RESTful API"); + config.setVersion("1.0.0"); + config.setResourcePackage("org.onap.msb.sdclient.resources"); + // 设置swagger里面访问rest api时的basepath + 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.info("getApplicationContextPath: " + basePath); + config.setBasePath(basePath); + config.setScan(true); + } + + + + + + + + + + /** + * @Title initApiGateWayServiceListen + * @Description TODO(开启对consul中ApiGateWay服务的监听和缓存) + * @return void + */ + private void initApiGateWayServiceListen(){ + + String[] consulAddress= ConfigUtil.getInstance().getConsulAddress().split(":"); + ConsulClientApp consulClientApp = new ConsulClientApp(consulAddress[0],Integer.parseInt(consulAddress[1])); + + PublishAddressWrapper.getInstance().setConsulClientApp(consulClientApp); + // 监听服务变化 + //consulClientApp.startHealthNodeListen(DiscoverUtil.APIGATEWAY_SERVINCE_ALL); + //LOGGER.info("start monitor ApiGateWay service--" + DiscoverUtil.CONSUL_ADDRESSS+"--"+DiscoverUtil.APIGATEWAY_SERVINCE); + + } + + + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverAppConfig.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverAppConfig.java new file mode 100644 index 0000000..96576fa --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/DiscoverAppConfig.java @@ -0,0 +1,86 @@ +/** + * 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.sdclient; + +import io.dropwizard.Configuration; + +import javax.validation.Valid; + +import org.hibernate.validator.constraints.NotEmpty; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class DiscoverAppConfig extends Configuration { + @NotEmpty + private String defaultWorkspace = "discover-works"; + + @NotEmpty + private String defaultName = "discover-service"; + + + @Valid + private String consulAdderss; + + @Valid + private String consulRegisterMode; + + + @JsonProperty + public String getConsulRegisterMode() { + return consulRegisterMode; + } + + @JsonProperty + public void setConsulRegisterMode(String consulRegisterMode) { + this.consulRegisterMode = consulRegisterMode; + } + + @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 String getConsulAdderss() { + return consulAdderss; + } + + @JsonProperty + public void setConsulAdderss(String consulAdderss) { + this.consulAdderss = consulAdderss; + } + + + + + + +}
\ No newline at end of file diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/AgentService.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/AgentService.java new file mode 100644 index 0000000..f85e583 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/AgentService.java @@ -0,0 +1,167 @@ +/** + * 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.sdclient.core; + +import java.io.Serializable; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class AgentService implements Serializable { + + + private static final long serialVersionUID = 1L; + + @JsonProperty("ID") + private String id; + + @JsonProperty("Name") + private String name; + + @JsonProperty("Tags") + private List<String> tags; + + @JsonProperty("Address") + private String address; + + @JsonProperty("Port") + private int port; + + @JsonProperty("Check") + @JsonInclude(Include.NON_EMPTY) + private Check check; + + @JsonInclude(Include.NON_EMPTY) + public class Check{ + + @JsonProperty("HTTP") + private String http; + + @JsonProperty("TCP") + private String tcp; + + @JsonProperty("TTL") + private String ttl; + + @JsonProperty("Interval") + private String interval; + + @JsonProperty("Timeout") + private String timeout; + + + private String status="passing"; + + public String getTimeout() { + return timeout; + } + public void setTimeout(String timeout) { + this.timeout = timeout; + } + + public String getHttp() { + return http; + } + public void setHttp(String http) { + this.http = http; + } + public String getTcp() { + return tcp; + } + public void setTcp(String tcp) { + this.tcp = tcp; + } + public String getTtl() { + return ttl; + } + public void setTtl(String ttl) { + this.ttl = ttl; + } + public String getInterval() { + return interval; + } + public void setInterval(String interval) { + this.interval = interval; + } + public String getStatus() { + return status; + } + public void setStatus(String status) { + this.status = status; + } + + + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List<String> getTags() { + return tags; + } + + public void setTags(List<String> tags) { + this.tags = tags; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public Check getCheck() { + return check; + } + + public void setCheck(Check check) { + this.check = check; + } + + public Check createCheck(){ + return new Check(); + + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogNode.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogNode.java new file mode 100644 index 0000000..307fbcb --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogNode.java @@ -0,0 +1,74 @@ +/** + * 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.sdclient.core; + +import java.io.Serializable; +import java.util.List; + +import org.onap.msb.sdclient.wrapper.util.DiscoverUtil; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CatalogNode implements Serializable{ + private static final long serialVersionUID = 1L; + + @JsonProperty("Node") + private String node=DiscoverUtil.EXTERNAL_NODE_NAME; + + @JsonProperty("Address") + private String address="127.0.0.1"; + + @JsonProperty("Service") + private ConsulService service; + + public String getNode() { + return node; + } + + public void setNode(String node) { + this.node = node; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public ConsulService getService() { + return service; + } + + public void setService(ConsulService service) { + this.service = service; + } + + public CatalogNode(){ + + } + + public CatalogNode(ConsulService service){ + this.service = service; + } + + +} + + diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogService.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogService.java new file mode 100644 index 0000000..dd4e2d6 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CatalogService.java @@ -0,0 +1,108 @@ +/** + * 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.sdclient.core; + +import java.io.Serializable; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + + + +@JsonIgnoreProperties(ignoreUnknown = true) +public class CatalogService implements Serializable{ + private static final long serialVersionUID = 1L; + @JsonProperty("Node") + private String node; + + @JsonProperty("Address") + private String address; + + @JsonProperty("ServiceName") + private String serviceName; + + @JsonProperty("ServiceID") + private String serviceId; + + @JsonProperty("ServiceAddress") + private String serviceAddress; + + @JsonProperty("ServicePort") + private int servicePort; + + @JsonProperty("ServiceTags") + private List<String> serviceTags; + + public String getNode() { + return node; + } + + public void setNode(String node) { + this.node = node; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getServiceId() { + return serviceId; + } + + public void setServiceId(String serviceId) { + this.serviceId = serviceId; + } + + public String getServiceAddress() { + return serviceAddress; + } + + public void setServiceAddress(String serviceAddress) { + this.serviceAddress = serviceAddress; + } + + public int getServicePort() { + return servicePort; + } + + public void setServicePort(int servicePort) { + this.servicePort = servicePort; + } + + public List<String> getServiceTags() { + return serviceTags; + } + + public void setServiceTags(List<String> serviceTags) { + this.serviceTags = serviceTags; + } + + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Check.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Check.java new file mode 100644 index 0000000..ffa4683 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Check.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. + */ +package org.onap.msb.sdclient.core; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Check implements Serializable { + + + private static final long serialVersionUID = 1L; + + @JsonProperty("CheckID") + private String checkID; + + @JsonProperty("Name") + private String name; + + @JsonProperty("Status") + private String status; + + public String getCheckID() { + return checkID; + } + + public void setCheckID(String checkID) { + this.checkID = checkID; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + + + +}
\ No newline at end of file diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulResponse.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulResponse.java new file mode 100644 index 0000000..0839e8f --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulResponse.java @@ -0,0 +1,38 @@ +/** + * 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.sdclient.core; + +import java.math.BigInteger; + +public class ConsulResponse<T> { + + private final T response; + private final BigInteger index; + + public ConsulResponse(T response, BigInteger index) { + this.response = response; + this.index = index; + } + + public BigInteger getIndex() { + return index; + } + public T getResponse() { + return response; + } + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulService.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulService.java new file mode 100644 index 0000000..5b5763c --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/ConsulService.java @@ -0,0 +1,84 @@ +/** + * 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.sdclient.core; + +import java.io.Serializable; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ConsulService implements Serializable{ + private static final long serialVersionUID = 1L; + + @JsonProperty("ID") + private String id; + + @JsonProperty("Service") + private String service; + + @JsonProperty("Tags") + private List<String> tags; + + @JsonProperty("Address") + private String address; + + @JsonProperty("Port") + private int port; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getService() { + return service; + } + + public void setService(String service) { + this.service = service; + } + + public List<String> getTags() { + return tags; + } + + public void setTags(List<String> tags) { + this.tags = tags; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + +}
\ No newline at end of file diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CustomDateSerializer.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/CustomDateSerializer.java new file mode 100644 index 0000000..6efeb04 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/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.sdclient.core; + +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/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/HealthService.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/HealthService.java new file mode 100644 index 0000000..f952ee5 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/HealthService.java @@ -0,0 +1,154 @@ +/** + * 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.sdclient.core; + +import java.io.Serializable; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class HealthService implements Serializable { + + + private static final long serialVersionUID = 1L; + + @JsonProperty("Node") + private Node node; + + @JsonProperty("Service") + private Service service; + + @JsonProperty("Checks") + private List<Check> checks; + + + public Node getNode() { + return node; + } + + public void setNode(Node node) { + this.node = node; + } + + public Service getService() { + return service; + } + + public void setService(Service service) { + this.service = service; + } + + public List<Check> getChecks() { + return checks; + } + + public void setChecks(List<Check> checks) { + this.checks = checks; + } + + + + + @JsonIgnoreProperties(ignoreUnknown = true) + public class Service{ + @JsonProperty("ID") + private String id; + + @JsonProperty("Service") + private String service; + + @JsonProperty("Tags") + private List<String> tags; + + @JsonProperty("Address") + private String address; + + @JsonProperty("Port") + private String port; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getService() { + return service; + } + + public void setService(String service) { + this.service = service; + } + + public List<String> getTags() { + return tags; + } + + public void setTags(List<String> tags) { + this.tags = tags; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + } + + @JsonIgnoreProperties(ignoreUnknown = true) + public class Node{ + + @JsonProperty("Node") + private String node; + + @JsonProperty("Address") + private String address; + + public String getNode() { + return node; + } + + public void setNode(String node) { + this.node = node; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + + } + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/KeyVaulePair.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/KeyVaulePair.java new file mode 100644 index 0000000..4fca0ed --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/KeyVaulePair.java @@ -0,0 +1,51 @@ +/** + * 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.sdclient.core; + +import java.io.Serializable; + +public class KeyVaulePair implements Serializable { + private static final long serialVersionUID = 1L; + + private String key; + private String value; + + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + + public KeyVaulePair(){ + + } + + public KeyVaulePair(String key,String value){ + this.key=key; + this.value=value; + + } + + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceFullInfo.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceFullInfo.java new file mode 100644 index 0000000..ec5c52a --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceFullInfo.java @@ -0,0 +1,87 @@ +/** + * 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.sdclient.core; + +import java.io.Serializable; +import java.util.Set; + +import com.google.common.base.Objects; + + +public class MicroServiceFullInfo extends Service<NodeInfo> implements Serializable { + private static final long serialVersionUID = 1L; + + // 状态 0:不可用,待审核 1:可用,审核通过 2:审核失败 + private String status = "1"; + + private boolean is_manual=false; //手动注册:true; 自动注册:false + + private Set<NodeInfo> nodes; + + + public Set<NodeInfo> getNodes() { + return nodes; + } + + public void setNodes(Set<NodeInfo> nodes) { + this.nodes = nodes; + } + + public String getStatus() { + return status; + } + public void setStatus(String status) { + this.status = status; + } + + + public boolean isIs_manual() { + return is_manual; + } + + public void setIs_manual(boolean is_manual) { + this.is_manual = is_manual; + } + + @Override + public int hashCode() { + return Objects.hashCode(getServiceName(),getVersion(),getProtocol(),getNamespace(),getUrl(),getVisualRange(),nodes); + } + + @Override + public boolean equals(Object other) + { + if(this == other) + return true; + if(other instanceof MicroServiceFullInfo) + { + MicroServiceFullInfo that = (MicroServiceFullInfo)other; + return Objects.equal(getServiceName(), that.getServiceName()) + && Objects.equal(getVersion(), that.getVersion()) + && Objects.equal(getProtocol(), that.getProtocol()) + && Objects.equal(getNamespace(), that.getNamespace()) + && Objects.equal(getUrl(), that.getUrl()) + && Objects.equal(getVisualRange(), that.getVisualRange()) + && Objects.equal(nodes.hashCode(), that.nodes.hashCode()); + } else + { + return false; + } + } + + + +}
\ No newline at end of file diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceInfo.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceInfo.java new file mode 100644 index 0000000..d5e8296 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/MicroServiceInfo.java @@ -0,0 +1,46 @@ +/** + * 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.sdclient.core; + +import java.io.Serializable; +import java.util.Set; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +/** + * @ClassName: MicroServiceInfo Bean + * @Description:P2PRouteInfo信息实体类 + * @author 10188044 + * @date 2016-1-19 + */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class MicroServiceInfo extends Service<Node> implements Serializable { + private static final long serialVersionUID = 1L; + + private Set<Node> nodes; + + public Set<Node> getNodes() { + return nodes; + } + + public void setNodes(Set<Node> nodes) { + this.nodes = nodes; + } + + + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Node.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Node.java new file mode 100644 index 0000000..8727248 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Node.java @@ -0,0 +1,149 @@ +/** + * 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.sdclient.core; + +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Node implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(example = "127.0.0.1",required = true) + private String ip; + + @ApiModelProperty(example = "80", required = true) + private String port; + + + //负载均衡策略参数 + @ApiModelProperty(value = "lb node params", allowableValues = "weight,max_fails,fail_timeout", example = "weight=5,max_fails=3,fail_timeout=30s") + private String lb_server_params; + + //健康检查参数 + @ApiModelProperty(value = "health check type", allowableValues = "TTL,HTTP,TCP", example = "TTL") + private String checkType=""; + + @ApiModelProperty(value = "health check URL,applies only to TCP or HTTP", example = "http://localhost:5000/health") + private String checkUrl=""; + + @ApiModelProperty(value = "TCP or HTTP health check Interval,Unit: second", example = "10s") + private String checkInterval; + + @ApiModelProperty(value = "TCP or HTTP health check TimeOut,Unit: second", example = "10s") + private String checkTimeOut; + + @ApiModelProperty(value = "TTL health check Interval,Unit: second", example = "10s") + private String ttl; + + + @ApiModelProperty(value = "Instance HA_role", allowableValues = "active,standby", example = "active") + private String ha_role=""; + + + + + + public String getHa_role() { + return ha_role; + } + + public void setHa_role(String ha_role) { + this.ha_role = ha_role; + } + + 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 String getTtl() { + return ttl; + } + + public void setTtl(String ttl) { + this.ttl = ttl; + } + + public Node(){ + + } + + public Node(String ip,String port){ + this.ip = ip; + this.port = port; + } + + public String getLb_server_params() { + return lb_server_params; + } + + public void setLb_server_params(String lb_server_params) { + this.lb_server_params = lb_server_params; + } + + + public String getCheckType() { + return checkType; + } + + public void setCheckType(String checkType) { + this.checkType = checkType; + } + + public String getCheckUrl() { + return checkUrl; + } + + public void setCheckUrl(String checkUrl) { + this.checkUrl = checkUrl; + } + + public String getCheckInterval() { + return checkInterval; + } + + public void setCheckInterval(String checkInterval) { + this.checkInterval = checkInterval; + } + + public String getCheckTimeOut() { + return checkTimeOut; + } + + public void setCheckTimeOut(String checkTimeOut) { + this.checkTimeOut = checkTimeOut; + } + + + + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeAddress.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeAddress.java new file mode 100644 index 0000000..91b6206 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeAddress.java @@ -0,0 +1,111 @@ +/** + * 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.sdclient.core; + +import io.swagger.annotations.ApiModelProperty; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.Serializable; + +import com.google.common.base.Objects; + +public class NodeAddress implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(required = true) + private String ip; + + @ApiModelProperty(required = true) + private String port; + + + + private PropertyChangeSupport changes = new PropertyChangeSupport(this); + + 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 NodeAddress(String ip,String port){ + this.ip=ip; + this.port=port; + } + + public void setIPandPort(String ip,String port){ + String oldAddress = this.ip+":"+this.port; + String newAddress = ip+":"+port; + this.ip=ip; + this.port=port; + + changes.firePropertyChange("ip", oldAddress, newAddress); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + changes.addPropertyChangeListener(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + changes.removePropertyChangeListener(listener); + } + + public NodeAddress(){ + + } + + @Override + public boolean equals(Object other) + { + if(this == other) + return true; + if(other instanceof NodeAddress) + { + NodeAddress that = (NodeAddress)other; + return Objects.equal(ip, that.ip) && Objects.equal(port, that.port); + } else + { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(ip, port); + } + + @Override + public String toString(){ + return this.ip+":"+this.port; + } + + + + + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeInfo.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeInfo.java new file mode 100644 index 0000000..950c0d8 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/NodeInfo.java @@ -0,0 +1,106 @@ +/** + * 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.sdclient.core; + +import java.util.Date; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.google.common.base.Objects; + +public class NodeInfo extends Node { + + private static final long serialVersionUID = 8955786461351557306L; + + private String nodeId; //node唯一标识 + + private String status; //实例健康检查状态 + + + @JsonSerialize(using = CustomDateSerializer.class) + private Date expiration; + + @JsonSerialize(using = CustomDateSerializer.class) + private Date created_at; + + @JsonSerialize(using = CustomDateSerializer.class) + private Date updated_at; + + + + public Date getExpiration() { + return expiration; + } + + public void setExpiration(Date expiration) { + this.expiration = expiration; + } + + public Date getCreated_at() { + return created_at; + } + + public void setCreated_at(Date created_at) { + this.created_at = created_at; + } + + public Date getUpdated_at() { + return updated_at; + } + + public void setUpdated_at(Date updated_at) { + this.updated_at = updated_at; + } + + public String getNodeId() { + return nodeId; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + @Override + public int hashCode() { + return Objects.hashCode(getIp(),getPort(),getHa_role(),status ); + } + + @Override + public boolean equals(Object other) + { + if(this == other) + return true; + if(other instanceof NodeInfo) + { + NodeInfo that = (NodeInfo)other; + return Objects.equal(getIp(), that.getIp()) + && Objects.equal(getPort(), that.getPort()); + } else + { + return false; + } + } + + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishAddress.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishAddress.java new file mode 100644 index 0000000..ef49b31 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishAddress.java @@ -0,0 +1,95 @@ +/** + * 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.sdclient.core; + +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; + +import com.google.common.base.Objects; + +public class PublishAddress implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "Service Publish IP") + private String ip; + + @ApiModelProperty(value = "Service Publish Port", required = true) + private String port; + + @ApiModelProperty(value = "Service Publish URL,start with /",example = "/api/serviceName/v1", required = true) + private String publish_url; + + 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 PublishAddress(){ + + } + + public PublishAddress(String ip,String port,String publish_url){ + this.ip=ip; + this.port=port; + this.publish_url = publish_url; + } + + public String getPublish_url() { + return publish_url; + } + + public void setPublish_url(String publish_url) { + this.publish_url = publish_url; + } + + @Override + public boolean equals(Object other) + { + if(this == other) + return true; + if(other instanceof PublishAddress) + { + PublishAddress that = (PublishAddress)other; + return Objects.equal(ip, that.ip) && Objects.equal(port, that.port)&& Objects.equal(publish_url, that.publish_url); + } else + { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(ip, port,publish_url); + } + + @Override + public String toString(){ + return this.ip+":"+this.port+this.publish_url; + } + +}
\ No newline at end of file diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishFullAddress.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishFullAddress.java new file mode 100644 index 0000000..03200c3 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/PublishFullAddress.java @@ -0,0 +1,147 @@ +/** + * 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.sdclient.core; + +import io.swagger.annotations.ApiModelProperty; + +import java.io.Serializable; + +import org.apache.commons.lang3.StringUtils; +import org.onap.msb.sdclient.wrapper.consul.model.health.ServiceHealth; + +import com.google.common.base.Objects; + +public class PublishFullAddress implements Serializable { + private static final long serialVersionUID = 1L; + + + @ApiModelProperty(value = "Service Publish IP") + private String ip; + + @ApiModelProperty(value = "Service Publish Domain") + private String domain; + + @ApiModelProperty(value = "Service Publish Port", required = true) + private String port; + + @ApiModelProperty(value = "Service Publish URL,start with /",example = "/api/serviceName/v1", required = true) + private String publish_url; + + @ApiModelProperty(value = "[visual Range]outSystem:0,inSystem:1", allowableValues = "0,1", example = "1", required = true) + private String visualRange; + + @ApiModelProperty(value = "Service Publish Protocol",allowableValues = "http,https",example = "https", required = true) + 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 getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + public String getPublish_url() { + return publish_url; + } + + public void setPublish_url(String publish_url) { + this.publish_url = publish_url; + } + + public String getVisualRange() { + return visualRange; + } + + public void setVisualRange(String visualRange) { + this.visualRange = visualRange; + } + + 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(){ + + } + + public PublishFullAddress(String ip,String port,String publish_url,String visualRange,String publish_protocol ){ + this.ip=ip; + this.port=port; + this.publish_url=publish_url; + this.visualRange=visualRange; + this.publish_protocol=publish_protocol; + } + + @Override + public boolean equals(Object other) + { + if(this == other) + return true; + if(other instanceof PublishFullAddress) + { + PublishFullAddress that = (PublishFullAddress)other; + return Objects.equal(ip, that.ip) + && Objects.equal(domain, that.domain) + && Objects.equal(port, that.port) + && Objects.equal(publish_url, that.publish_url) + && Objects.equal(visualRange, that.visualRange) + && Objects.equal(publish_protocol, that.publish_protocol); + } else + { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(ip, domain,port,publish_url,visualRange,publish_protocol); + } + + @Override + public String toString() { + // TODO Auto-generated method stub + if(StringUtils.isNotBlank(this.domain)){ + return (new StringBuilder().append(this.publish_protocol).append("://").append(this.domain).append(":").append(this.port).append(this.publish_url)).toString(); + } + else { + return (new StringBuilder().append(this.publish_protocol).append("://").append(this.ip).append(":").append(this.port).append(this.publish_url)).toString(); + } + + } + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Service.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Service.java new file mode 100644 index 0000000..9b382b7 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/Service.java @@ -0,0 +1,194 @@ +/** + * 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.sdclient.core; + +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import io.swagger.annotations.ApiModelProperty; + + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Service<T> implements Serializable { + private static final long serialVersionUID = 1L; + // 服务名 + @ApiModelProperty(example = "test",required = true) + private String serviceName; + // 版本号 + @ApiModelProperty(example = "v1", required = true) + private String version=""; + // 服务url + @ApiModelProperty(value = "Target Service URL,start with /",example = "/api/serviceName/v1", required = true) + private String url=""; + + // 服务对应协议,比如REST、UI、MQ、FTP、SNMP、TCP、UDP + @ApiModelProperty(value = "Service Protocol", allowableValues = "REST,UI, HTTP, TCP,UDP", example = "HTTP",required = true) + private String protocol = ""; + + //服务的可见范围 0:系统间 1:系统内 ,可配置多个,以 |分隔 + @ApiModelProperty(value = "[visual Range]interSystem:0,inSystem:1", allowableValues = "0,1", example = "1") + private String visualRange = "1"; + + //负载均衡策略类型 + @ApiModelProperty(value = "lb policy", allowableValues = "round-robin,ip_hash", example = "ip_hash") + private String lb_policy; + + //TCP/UDP协议监听端口 + @ApiModelProperty(hidden = true) + private String publish_port; + + //命名空间 + private String namespace=""; + + //网络平面 + @ApiModelProperty(hidden = true) + private String network_plane_type; + + @ApiModelProperty(hidden = true) + private String host=""; + + @ApiModelProperty(hidden = true) + private String path=""; + + + + + @ApiModelProperty(required = true) + private Set<T> nodes; + + //服务自身属性的键值对 + private List<KeyVaulePair> metadata; + + //自定义标签 + @ApiModelProperty(value = "custom labels", example = "key1:value1") + private List<String> labels; + + + + 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 List<String> getLabels() { + return labels; + } + + public void setLabels(List<String> labels) { + this.labels = labels; + } + + public Set<T> getNodes() { + return nodes; + } + + public void setNodes(Set<T> nodes) { + this.nodes = nodes; + } + + 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 List<KeyVaulePair> getMetadata() { + return metadata; + } + + public void setMetadata(List<KeyVaulePair> metadata) { + this.metadata = metadata; + } + + + 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 getPublish_port() { + return publish_port; + } + + public void setPublish_port(String publish_port) { + this.publish_port = publish_port; + } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + public String getNetwork_plane_type() { + return network_plane_type; + } + + public void setNetwork_plane_type(String network_plane_type) { + this.network_plane_type = network_plane_type; + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/ExtendedInternalServerErrorException.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/ExtendedInternalServerErrorException.java new file mode 100644 index 0000000..93a33a3 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/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.sdclient.core.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/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/ExtendedNotFoundException.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/ExtendedNotFoundException.java new file mode 100644 index 0000000..4acf507 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/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.sdclient.core.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/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/UnprocessableEntityException.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/UnprocessableEntityException.java new file mode 100644 index 0000000..ed7b632 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/core/exception/UnprocessableEntityException.java @@ -0,0 +1,19 @@ +package org.onap.msb.sdclient.core.exception; + +import javax.ws.rs.ClientErrorException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.http.HttpStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class UnprocessableEntityException extends ClientErrorException{ +private static final long serialVersionUID = -8266622745725405656L; +private static final Logger LOGGER = LoggerFactory.getLogger(UnprocessableEntityException.class); + + public UnprocessableEntityException(final String message) { + super(Response.status(HttpStatus.SC_UNPROCESSABLE_ENTITY).entity(message).type(MediaType.TEXT_PLAIN).build()); + LOGGER.warn(message); + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/health/ConsulLinkHealthCheck.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/health/ConsulLinkHealthCheck.java new file mode 100644 index 0000000..9596b4a --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/health/ConsulLinkHealthCheck.java @@ -0,0 +1,58 @@ +/** + * 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.sdclient.health; + +import org.apache.commons.lang3.StringUtils; +import org.onap.msb.sdclient.wrapper.util.HttpClientUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.codahale.metrics.health.HealthCheck; + +public class ConsulLinkHealthCheck extends HealthCheck { + + + private static final Logger LOGGER = LoggerFactory + .getLogger(ConsulLinkHealthCheck.class); + + 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"; + + + @Override + protected Result check() throws Exception { + // TODO Auto-generated method stub + + if(!StringUtils.isBlank(System.getenv("CONSUL_IP"))) + { + CHECK_IP=System.getenv("CONSUL_IP"); + CHECK_URL = "http://"+CHECK_IP+":"+CHECK_PORT+"/v1/status/leader"; + LOGGER.info("check consul URL:"+CHECK_URL); + } + + int resultStatus = HttpClientUtil.httpGetStatus(CHECK_URL); + + if (resultStatus == 200) { + return Result.healthy(); + } else { + return Result + .unhealthy("check consul link {} fail:{}",CHECK_URL,resultStatus); + } + + } + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/resources/MicroServiceResource.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/resources/MicroServiceResource.java new file mode 100644 index 0000000..9b83d6d --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/resources/MicroServiceResource.java @@ -0,0 +1,395 @@ +/** + * 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.sdclient.resources; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +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.sdclient.core.ConsulResponse; +import org.onap.msb.sdclient.core.MicroServiceFullInfo; +import org.onap.msb.sdclient.core.MicroServiceInfo; +import org.onap.msb.sdclient.core.NodeAddress; +import org.onap.msb.sdclient.core.PublishAddress; +import org.onap.msb.sdclient.core.PublishFullAddress; +import org.onap.msb.sdclient.core.exception.ExtendedInternalServerErrorException; +import org.onap.msb.sdclient.health.ConsulLinkHealthCheck; +import org.onap.msb.sdclient.wrapper.ConsulServiceWrapper; +import org.onap.msb.sdclient.wrapper.PublishAddressWrapper; +import org.onap.msb.sdclient.wrapper.util.ConfigUtil; +import org.onap.msb.sdclient.wrapper.util.DiscoverUtil; +import org.onap.msb.sdclient.wrapper.util.JacksonJsonUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.codahale.metrics.annotation.Timed; +import com.codahale.metrics.health.HealthCheck; +import com.codahale.metrics.health.HealthCheck.Result; + +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; + +@Path("/services") +@Api(tags = { "Service Resource" }) +@Produces(MediaType.APPLICATION_JSON) +public class MicroServiceResource { + + + @Context + UriInfo uriInfo; // actual uri info + + + + private static final Logger LOGGER = LoggerFactory.getLogger(MicroServiceResource.class); + + @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 ConsulServiceWrapper.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) MicroServiceInfo microServiceInfo, + @Context HttpServletRequest request, + @ApiParam(value = "createOrUpdate", required = false) @QueryParam("createOrUpdate") @DefaultValue("true") boolean createOrUpdate, + @ApiParam(value = "is_manual", required = false) @QueryParam("is_manual") @DefaultValue("false") boolean is_manual + ) { + + String ip=DiscoverUtil.getRealIp(request); + + try { + LOGGER.info("[POST REQUEST] Request IP:"+ip+",Request Param:[createOrUpdate]"+createOrUpdate+",Request Body:"+JacksonJsonUtil.beanToJson(microServiceInfo)); + } catch (Exception e) { + // TODO Auto-generated catch block + LOGGER.error("[POST REQUEST] beanToJson is wrong:"+e.getMessage()); + } + + MicroServiceFullInfo microServiceFullInfo = + ConsulServiceWrapper.getInstance().saveMicroServiceInstance(microServiceInfo, + createOrUpdate,ip,is_manual); + URI returnURI = + uriInfo.getAbsolutePathBuilder() + .path("/" + microServiceInfo.getServiceName() + "/version/" + + microServiceInfo.getVersion()).build(); + return Response.created(returnURI).entity(microServiceFullInfo).build(); + } + + + + @GET + @Path("/{serviceName}/version/{version}/nodes") + @ApiOperation(value = "get one microservice ", code = HttpStatus.SC_OK, response = MicroServiceFullInfo.class, responseContainer = "List") + @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 List<MicroServiceFullInfo> getMicroServiceNodes( + @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 = "Format key:value,Multiple use ',' split", required = false) @QueryParam("labels") @DefaultValue("") String labels, + @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace, + @ApiParam(value = "if true then only query passing services", required = false) @QueryParam("ifPassStatus") @DefaultValue("true")boolean ifPassStatus + ) { + + return ConsulServiceWrapper.getInstance().getMicroServiceForNodes(serviceName, version,ifPassStatus,labels,namespace); + + + } + + @GET + @Path("/{serviceName}/version/{version}") + @ApiOperation(value = "get one microservice nodes", 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 Response 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, + @ApiParam(value = "Format key:value,Multiple use ',' split", required = false) @QueryParam("labels") @DefaultValue("") String labels, + @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace, + @ApiParam(value = "if true then only query passing services", required = false) @QueryParam("ifPassStatus") @DefaultValue("true")boolean ifPassStatus, + @ApiParam(value = "wait", required = false) @QueryParam("wait") @DefaultValue("") String wait, + @ApiParam(value = "index", required = false) @QueryParam("index") @DefaultValue("") String index) { + + + ConsulResponse<MicroServiceFullInfo> serviceResponse= ConsulServiceWrapper.getInstance().getMicroServiceInstance(serviceName, version,ifPassStatus,wait,index,labels,namespace); + return Response.ok(serviceResponse.getResponse()).header("X-Consul-Index", serviceResponse.getIndex()).build(); + + + } + + @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 = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace, + @ApiParam(value = "microservice Instance Info", required = true) MicroServiceInfo microServiceInfo, + @Context HttpServletRequest request, + @ApiParam(value = "protocol", required = false) @QueryParam("protocol") @DefaultValue("") String protocol, + @ApiParam(value = "is_manual", required = false, hidden = true ) @QueryParam("is_manual") @DefaultValue("false") boolean is_manual) { + + String ip=DiscoverUtil.getRealIp(request); + MicroServiceFullInfo microServiceFullInfo =ConsulServiceWrapper.getInstance().updateMicroServiceInstance(serviceName,version,namespace,microServiceInfo,ip,is_manual); + return Response.created(uriInfo.getAbsolutePathBuilder().build()).entity(microServiceFullInfo).build(); + + } + + @PUT + @Path("/{serviceName}/version/{version}/ttl") + @ApiOperation(value = "passing one microservice health check by ttl", code = HttpStatus.SC_CREATED, response = NodeAddress.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_UNPROCESSABLE_ENTITY, message = "Unprocessable MicroServiceInfo Entity ", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "health check by ttl fail", response = String.class), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Unprocessable CheckNode JSON REQUEST", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Response healthCheckbyTTL( + @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 = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace, + @ApiParam(value = "CheckNode Instance Info", required = true) NodeAddress checkNode) { + + ConsulServiceWrapper.getInstance().healthCheckbyTTL(serviceName,version,namespace,checkNode); + return Response.created(uriInfo.getAbsolutePathBuilder().build()).entity(checkNode).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 = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace, + @ApiParam(value = "ip") @PathParam("ip") String ip, + @ApiParam(value = "port") @PathParam("port") String port, + @ApiParam(value = "protocol", required = false) @QueryParam("protocol") @DefaultValue("") String protocol) { + LOGGER.info("[DELETE NODE REQUEST] serviceName:"+serviceName+",version:"+version+",namespace:"+namespace+",protocol:"+protocol+",ip:"+ip+",port:"+port); + ConsulServiceWrapper.getInstance().deleteMicroServiceInstance(serviceName, version, namespace,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, + @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace, + @ApiParam(value = "protocol", required = false) @QueryParam("protocol") @DefaultValue("") String protocol) { + + LOGGER.info("[DELETE REQUEST] serviceName:"+serviceName+",version:"+version+",namespace:"+namespace+",protocol:"+protocol); + + ConsulServiceWrapper.getInstance().deleteMicroService(serviceName, version,namespace); + + } + + + + + + + + + // @PUT + // @Path("/{serviceName}/version/{version}/status/{status}") + // @ApiOperation(value = "update one microservice's status by serviceName and version", + // response = RouteResult.class) + // @ApiResponses(value = {@ApiResponse(code = 500, message = + // "update microservice status error ")}) + // @Produces(MediaType.APPLICATION_JSON) + // @Timed + // public RouteResult updateMicroServiceStatus( + // @ApiParam(value = "microservice serviceName", required = true) @PathParam("serviceName") + // String serviceName, + // @ApiParam(value = "microservice version", required = false) @PathParam("version") + // @DefaultValue("") String version, + // @ApiParam(value = "microservice status", required = true) @PathParam("status") String status) + // { + // + // return MicroServiceWrapper.getInstance().updateMicroServiceStatus(serviceName, version, + // status); + // + // } + + + @GET + @Path("/{serviceName}/version/{version}/publishaddress") + @ApiOperation(value = "get one microservice's inner publishaddress", code = HttpStatus.SC_OK, response = PublishAddress.class) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "publishaddress 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 publishaddress fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public PublishAddress getPublishaddress( + @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 = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace, + @ApiParam(value = "Waiting time,Scope: 5-300, unit: second", required = false) @QueryParam("wait") @DefaultValue("0") int wait + ) { + + + return PublishAddressWrapper.getInstance().getPublishaddress(serviceName, version,namespace,wait); + + + } + + @GET + @Path("/apigatewayserviceinfo") + @ApiOperation(value = "get apigateway AddressInfo", code = HttpStatus.SC_OK,response = MicroServiceFullInfo.class, responseContainer = "List") + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "apigateway ServiceInfo not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get apigateway ServiceInfo fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Set<MicroServiceFullInfo> getApigatewayServiceInfo( + @ApiParam(value = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace, + @ApiParam(value = "visualRange", required = false) @QueryParam("visualRange") @DefaultValue("1") String visualRange) { + + + return PublishAddressWrapper.getInstance().getApigatewayServiceInfo(namespace, visualRange); + + + } + + @GET + @Path("/{serviceName}/version/{version}/allpublishaddress") + @ApiOperation(value = "get one microservice's all publishaddress", code = HttpStatus.SC_OK, response = PublishFullAddress.class, responseContainer = "List") + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "publishaddress 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 publishaddress fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public Set<PublishFullAddress> getAllPublishaddress( + @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 = "namespace", required = false) @QueryParam("namespace") @DefaultValue("") String namespace, + @ApiParam(value = "outSystem:0,inSystem:1,all:0|1(default)", required = false) @QueryParam("visualRange") @DefaultValue("0|1") String visualRange + ) { + + + return PublishAddressWrapper.getInstance().getAllPublishaddress(serviceName, version, namespace,visualRange); + + + } + + + @GET + @Path("/tcpudpportrange") + @ApiOperation(value = "get tcp and udp port range", code = HttpStatus.SC_OK,response = String.class, responseContainer = "List") + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = "port range not found", response = String.class), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = "get port range fail", response = String.class)}) + @Produces(MediaType.APPLICATION_JSON) + @Timed + public String[] getTCP_UDP_portRange() { + + return new String[]{ConfigUtil.getInstance().getTcpudpPortRangeStart(),ConfigUtil.getInstance().getTcpudpPortRangeEnd()}; + + } + + @GET + @Path("/health") + @ApiOperation(value = "sdclient 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() { + + ArrayList<HealthCheck> healthcheckArray = new ArrayList<HealthCheck>(); + + // consul link check + healthcheckArray.add(new ConsulLinkHealthCheck()); + + // begin check + for (int i = 0; i < healthcheckArray.size(); i++) { + Result rst = healthcheckArray.get(i).execute(); + + if (!rst.isHealthy()) { + LOGGER.warn("health check failed:" + rst.getMessage()); + throw new ExtendedInternalServerErrorException(rst.getMessage()); + } + } + + return Response.ok("sdclient healthy check:ok").build(); + } + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulAgentServiceWrapper.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulAgentServiceWrapper.java new file mode 100644 index 0000000..65a808a --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulAgentServiceWrapper.java @@ -0,0 +1,66 @@ +/** + * 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.sdclient.wrapper; + +import org.apache.commons.lang3.StringUtils; +import org.onap.msb.sdclient.core.AgentService; +import org.onap.msb.sdclient.core.Node; +import org.onap.msb.sdclient.wrapper.util.ConfigUtil; +import org.onap.msb.sdclient.wrapper.util.DiscoverUtil; +import org.onap.msb.sdclient.wrapper.util.HttpClientUtil; +import org.onap.msb.sdclient.wrapper.util.JacksonJsonUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class ConsulAgentServiceWrapper { + + private static ConsulAgentServiceWrapper instance = new ConsulAgentServiceWrapper(); + + private ConsulAgentServiceWrapper() {} + + public static ConsulAgentServiceWrapper getInstance() { + return instance; + } + private static final Logger LOGGER = LoggerFactory.getLogger(ConsulAgentServiceWrapper.class); + + + public synchronized int saveService(AgentService agentService) throws Exception{ + String consulRegisterurl = + (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress()) + .append(DiscoverUtil.CONSUL_AGENT_URL).append("/register")).toString(); + + + int registerResult = + HttpClientUtil.httpPostWithJSON(consulRegisterurl, + JacksonJsonUtil.beanToJson(agentService)); + + return registerResult; + + } + + public synchronized int deleteService(String serviceId) throws Exception{ + String consulDelurl = + (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress()) + .append(DiscoverUtil.CONSUL_AGENT_URL).append("/deregister/").append(serviceId)) + .toString(); + + int delResult = HttpClientUtil.httpPostWithJSON(consulDelurl, ""); + + return delResult; + } + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulCatalogServiceWrapper.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulCatalogServiceWrapper.java new file mode 100644 index 0000000..298dd54 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulCatalogServiceWrapper.java @@ -0,0 +1,84 @@ +/** + * 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.sdclient.wrapper; + +import org.onap.msb.sdclient.core.AgentService; +import org.onap.msb.sdclient.core.CatalogNode; +import org.onap.msb.sdclient.core.ConsulService; +import org.onap.msb.sdclient.wrapper.util.ConfigUtil; +import org.onap.msb.sdclient.wrapper.util.DiscoverUtil; +import org.onap.msb.sdclient.wrapper.util.HttpClientUtil; +import org.onap.msb.sdclient.wrapper.util.JacksonJsonUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConsulCatalogServiceWrapper { + + private static ConsulCatalogServiceWrapper instance = new ConsulCatalogServiceWrapper(); + + private ConsulCatalogServiceWrapper() {} + + public static ConsulCatalogServiceWrapper getInstance() { + return instance; + } + private static final Logger LOGGER = LoggerFactory.getLogger(ConsulAgentServiceWrapper.class); + + + public synchronized int saveService(AgentService agentService) throws Exception{ + String consulRegisterurl = + (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress()) + .append(DiscoverUtil.CONSUL_CATALOG_URL).append("/register")).toString(); + + CatalogNode catalogNode=transformCatalogNode(agentService); + + + int registerResult = + HttpClientUtil.httpPostWithJSON(consulRegisterurl, + JacksonJsonUtil.beanToJson(catalogNode)); + + return registerResult; + + } + + public synchronized int deleteService(String serviceId) throws Exception{ + String consulDelurl = + (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress()) + .append(DiscoverUtil.CONSUL_CATALOG_URL).append("/deregister")) + .toString(); + + String nodeJson="{\"Node\": \""+DiscoverUtil.EXTERNAL_NODE_NAME+"\",\"ServiceID\": \""+serviceId+"\"}"; + + int delResult = HttpClientUtil.httpPostWithJSON(consulDelurl, nodeJson); + + return delResult; + } + + + private CatalogNode transformCatalogNode(AgentService agentService){ + ConsulService consulService=new ConsulService(); + + consulService.setAddress(agentService.getAddress()); + consulService.setId(agentService.getId()); + consulService.setPort(agentService.getPort()); + consulService.setService(agentService.getName()); + consulService.setTags(agentService.getTags()); + + CatalogNode catalogNode=new CatalogNode(consulService); + + return catalogNode; + } + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulClientApp.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulClientApp.java new file mode 100644 index 0000000..5f3fbc4 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulClientApp.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.sdclient.wrapper; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.onap.msb.sdclient.core.KeyVaulePair; +import org.onap.msb.sdclient.core.MicroServiceFullInfo; +import org.onap.msb.sdclient.core.NodeInfo; +import org.onap.msb.sdclient.wrapper.consul.Consul; +import org.onap.msb.sdclient.wrapper.consul.HealthClient; +import org.onap.msb.sdclient.wrapper.consul.cache.HealthCache; +import org.onap.msb.sdclient.wrapper.consul.model.health.Service; +import org.onap.msb.sdclient.wrapper.consul.model.health.ServiceHealth; +import org.onap.msb.sdclient.wrapper.util.DiscoverUtil; +import org.onap.msb.sdclient.wrapper.util.JacksonJsonUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConsulClientApp { + + private final Consul consul; + private final HealthClient healthClient; +// private AtomicReference<List<HealthCache>> cacheList = new AtomicReference<List<HealthCache>>( +// new ArrayList<HealthCache>()); + + + private static final Logger LOGGER = LoggerFactory.getLogger(ConsulClientApp.class); + + public ConsulClientApp(String ip, int port) { + URL url = null; + try { + url = new URL("http", ip, port, ""); + } catch (MalformedURLException e1) { + // TODO Auto-generated catch block + LOGGER.error("start ConsulClientApp throw exception", e1); + throw new RuntimeException(e1); + } + this.consul = Consul.builder().withUrl(url).build(); // connect to Consul on localhost + this.healthClient = consul.healthClient(); + } + + public Consul getConsul() { + return consul; + } + + + + + + /** + * @Title startHealthNodeListen + * @Description TODO(开启某个服务的node变化监听,只返回健康状态服务) + * @param serviceName + * @return + * @return HealthCache + */ + public HealthCache startHealthNodeListen(final String serviceName) { + final HealthCache healthCache = HealthCache.newCache(healthClient, serviceName, 30); + healthCache.addListener(new HealthCache.Listener<String, ServiceHealth>() { + @Override + public void notify(Map<String, ServiceHealth> newValues) { + // do Something with updated server map + LOGGER.info(serviceName + "--new node notify--"); + + + if (newValues.isEmpty()) { + LOGGER.warn(serviceName + "--nodeList is Empty--"); + PublishAddressWrapper.publishApigateWayList.remove(serviceName); + + try { + healthCache.stop(); + LOGGER.info(serviceName + " Node Listen stopped"); + } catch (Exception e) { + LOGGER.error(serviceName + " Node Listen stop throw exception", e); + } + + return; + } + //服务发现变化 + List<MicroServiceFullInfo> nodeAddressList=new ArrayList<MicroServiceFullInfo>(); + for (Map.Entry<String, ServiceHealth> entry : newValues.entrySet()) { + + MicroServiceFullInfo microServiceInfo = new MicroServiceFullInfo(); + + ServiceHealth value = (ServiceHealth) entry.getValue(); + Service service = value.getService(); + + NodeInfo node = new NodeInfo(); + node.setIp(service.getAddress()); + node.setPort(String.valueOf(service.getPort())); + Set<NodeInfo> nodes = new HashSet<NodeInfo>(); + nodes.add(node); + microServiceInfo.setNodes(nodes); + + + microServiceInfo.setServiceName(serviceName); + + try { + List<String> tagList = service.getTags(); + + + for (String tag : tagList) { + + 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) { + microServiceInfo.setNamespace(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); + + List<String> nodeLabels = new ArrayList<String>(); + for (Map.Entry<String, String> labelEntry : labelMap.entrySet()) { + if ("visualRange".equals(labelEntry.getKey())) { + microServiceInfo.setVisualRange(labelEntry.getValue()); + } else if ("network_plane_type".equals(labelEntry.getKey())) { + microServiceInfo.setNetwork_plane_type( labelEntry.getValue()); + } else { + nodeLabels.add(labelEntry.getKey() + ":" + labelEntry.getValue()); + } + + } + + microServiceInfo.setLabels(nodeLabels); + continue; + } + + if (tag.startsWith("\"metadata\"")) { + String ms_metadata_json = "{"+tag.split("\"metadata\":\\{")[1]; + Map<String, String> metadataMap = + (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_metadata_json, Map.class); + + List<KeyVaulePair> ms_metadata = new ArrayList<KeyVaulePair>(); + + + for (Map.Entry<String, String> metadataEntry : metadataMap.entrySet()) { + KeyVaulePair keyVaulePair = new KeyVaulePair(); + keyVaulePair.setKey(metadataEntry.getKey()); + keyVaulePair.setValue(metadataEntry.getValue()); + ms_metadata.add(keyVaulePair); + } + microServiceInfo.setMetadata(ms_metadata); + continue; + } + + } + + + } catch (Exception e) { + LOGGER.error(serviceName + " read tag throw exception", e); + } + + nodeAddressList.add(microServiceInfo); + } + + PublishAddressWrapper.publishApigateWayList.put(serviceName, nodeAddressList); + + } + }); + try { + LOGGER.info(serviceName + " Node Listen start"); +// cacheList.get().add(healthCache); + healthCache.start(); + + } catch (Exception e) { + // TODO Auto-generated catch block + LOGGER.error(serviceName + " Node Listen start throw exception", e); + } + + return healthCache; + } + + + + public static void main(String[] args) { + ConsulClientApp consulTest = new ConsulClientApp("127.0.0.1", 8500); + // 监听服务变化 + consulTest.startHealthNodeListen("apigateway"); + + + } + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulServiceWrapper.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulServiceWrapper.java new file mode 100644 index 0000000..48e783e --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/ConsulServiceWrapper.java @@ -0,0 +1,1946 @@ +/** + * 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.sdclient.wrapper; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang3.StringUtils; +import org.onap.msb.sdclient.core.AgentService; +import org.onap.msb.sdclient.core.CatalogService; +import org.onap.msb.sdclient.core.Check; +import org.onap.msb.sdclient.core.ConsulResponse; +import org.onap.msb.sdclient.core.HealthService; +import org.onap.msb.sdclient.core.HealthService.Service; +import org.onap.msb.sdclient.core.KeyVaulePair; +import org.onap.msb.sdclient.core.MicroServiceFullInfo; +import org.onap.msb.sdclient.core.MicroServiceInfo; +import org.onap.msb.sdclient.core.Node; +import org.onap.msb.sdclient.core.NodeAddress; +import org.onap.msb.sdclient.core.NodeInfo; +import org.onap.msb.sdclient.core.exception.ExtendedInternalServerErrorException; +import org.onap.msb.sdclient.core.exception.ExtendedNotFoundException; +import org.onap.msb.sdclient.core.exception.UnprocessableEntityException; +import org.onap.msb.sdclient.wrapper.util.ConfigUtil; +import org.onap.msb.sdclient.wrapper.util.DiscoverUtil; +import org.onap.msb.sdclient.wrapper.util.HttpClientUtil; +import org.onap.msb.sdclient.wrapper.util.JacksonJsonUtil; +import org.onap.msb.sdclient.wrapper.util.RegExpTestUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.type.TypeReference; + +public class ConsulServiceWrapper { + + + private static ConsulServiceWrapper instance = new ConsulServiceWrapper(); + + + private ConsulServiceWrapper() {} + + public static ConsulServiceWrapper getInstance() { + return instance; + } + private static final Logger LOGGER = LoggerFactory.getLogger(ConsulServiceWrapper.class); + + /** + * Title: getAllMicroServiceInstances Description: 获取全部服务 + * + * @return + * @see com.zte.ums.nfv.eco.hsif.msb.core.IMSBService#getAllMicroServiceInstances() + */ + public List<MicroServiceFullInfo> getAllMicroServiceInstances() { + + String consulServiceUrl = + (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress()) + .append(DiscoverUtil.CONSUL_CATALOG_URL).append("/services")).toString(); + + String resultJson = HttpClientUtil.httpGet(consulServiceUrl); + Map<String, String[]> catalogServiceMap = + (Map<String, String[]>) JacksonJsonUtil.jsonToMapBean(resultJson); + + List<MicroServiceFullInfo> microServiceFullInfoArray = new ArrayList<MicroServiceFullInfo>(); + + if(catalogServiceMap.isEmpty()){ + return microServiceFullInfoArray; + } + + for (Map.Entry<String, String[]> entry : catalogServiceMap.entrySet()) { + Set<String> versionSet = new HashSet<String>(); + + Set<String> nsSet = new HashSet<String>(); + nsSet.add(""); + + String consul_serviceName = entry.getKey().toString(); + String[] tagList = entry.getValue(); + + for (String tag : tagList) { + + if (tag.startsWith("\"base\"")) { + String ms_base_json = tag.split("\"base\":")[1]; + + try { + Map<String, String> baseMap = + (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_base_json, Map.class); + if (baseMap.get("version") != null) { + versionSet.add( baseMap.get("version")); + } + else{ + versionSet.add(""); + } + } catch (Exception e) { + LOGGER.error(e.getMessage()); + } + + continue; + + } + + if (tag.startsWith("\"ns\"")) { + String ms_ns_json = tag.split("\"ns\":")[1]; + + try { + Map<String, String> namespaceMap = + (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_ns_json, Map.class); + if (namespaceMap.get("namespace") != null) { + nsSet.add(namespaceMap.get("namespace")); + } else { + nsSet.add(""); + } + + continue; + + } catch (Exception e) { + // TODO Auto-generated catch block + LOGGER.error(e.getMessage()); + } + + continue; + + } + + + } + + for(String ms_version:versionSet){ + for (String ns : nsSet) { + MicroServiceFullInfo microServiceFullInfo = + getMicroServiceInstanceForAll(consul_serviceName, ms_version, ns); + if (microServiceFullInfo != null && !"consul".equals(microServiceFullInfo.getServiceName())) { + + microServiceFullInfoArray.add(microServiceFullInfo); + } + } + } + + + } + + + return microServiceFullInfoArray; + } + + + + + /** + * @Title getMicroServiceInstanceForAll + * @Description TODO(通过列表遍历获取单个服务信息) + * @param consul_serviceName + * @param version + * @param namespace + * @return + * @return MicroServiceFullInfo + */ + public MicroServiceFullInfo getMicroServiceInstanceForAll(String consul_serviceName, String version, + String namespace) { + + try{ + ConsulResponse consulResponse = getHealthServices(consul_serviceName, false, "", ""); + if (consulResponse == null) { + LOGGER.error( "microservice not found: serviceName-" + consul_serviceName+", namespace-"+namespace); + return null; + } + + String serviceName=consul_serviceName; + if (StringUtils.isNotBlank(namespace)) { + if(consul_serviceName.endsWith("-"+namespace)){ + serviceName=consul_serviceName.substring(0,consul_serviceName.length()-namespace.length()-1); + } + } + + + ConsulResponse serviceResponse = + getMicroServiceInfo(consulResponse,serviceName,version, + false, "",namespace); + return (MicroServiceFullInfo) serviceResponse.getResponse(); + } + catch(Exception e){ + if(StringUtils.isNotBlank(namespace)){ + LOGGER.error("get service List have error:serviceName["+consul_serviceName+"],version["+version+"],namespace["+namespace+"]:"+e.getMessage()); + } + } + + return null; + } + + + /** + * @Title getMicroServiceInstance + * @Description TODO(通过Rest接口获取单个服务信息) + * @param serviceName + * @param version + * @param ifPassStatus + * @param wait + * @param index + * @param labels + * @param namespace + * @return + * @return ConsulResponse + */ + public ConsulResponse getMicroServiceInstance(String serviceName, String version, + boolean ifPassStatus, String wait, String index, String labels, String namespace){ + + if ("null".equals(version)) { + version = ""; + } + + + checkServiceNameAndVersion(serviceName,version); + + if (!RegExpTestUtil.labelRegExpTest(labels)) { + throw new UnprocessableEntityException( + "get MicroServiceInfo FAIL: The label query parameter format is wrong (key:value)"); + } + + String consul_serviceName=getServiceName4Consul(serviceName,namespace); + + ConsulResponse consulResponse = getHealthServices(consul_serviceName, ifPassStatus, wait, index); + if (consulResponse == null) { + String errInfo = "microservice not found: serviceName-" + serviceName+", namespace-"+namespace; + throw new ExtendedNotFoundException(errInfo); + } + + return getMicroServiceInfo(consulResponse,serviceName,version, + ifPassStatus, labels,namespace); + + } + + + + /** + * Title: getMicroServiceInstance Description:获取指定服务信息 + * + * @param serviceName + * @param version + * @return + * @see com.zte.ums.nfv.eco.hsif.msb.core.IMSBService#getMicroServiceInstance(java.lang.String, + * java.lang.String) + */ + + public ConsulResponse getMicroServiceInfo(ConsulResponse consulResponse,String serviceName, String version, + boolean ifPassStatus, String labels, String namespace) { + // TODO Auto-generated method stub + + + + String resultJson = (String) consulResponse.getResponse(); + List<HealthService> healthServiceList = + JacksonJsonUtil.jsonToListBean(resultJson, new TypeReference<List<HealthService>>() {}); + + + if (healthServiceList == null || healthServiceList.size() == 0) { + String errInfo = "microservice not found: serviceName-" + serviceName+", namespace-"+namespace; + throw new ExtendedNotFoundException(errInfo); + + } + + try { + + // label query,format key:value|value2,key2:value2 + boolean islabelQuery = false; + Map<String, String> query_labelMap = new HashMap<String, String>(); + if (StringUtils.isNotBlank(labels)) { + islabelQuery = true; + String[] routeLabels = StringUtils.split(labels, ","); + + for (int i = 0; i < routeLabels.length; i++) { + String[] labelArray = StringUtils.split(routeLabels[i], ":"); + query_labelMap.put(labelArray[0], labelArray[1]); + } + } + + + MicroServiceFullInfo microServiceInfo = new MicroServiceFullInfo(); + Set<NodeInfo> nodes = new HashSet<NodeInfo>(); + Set<String> serviceLabels = new HashSet<String>(); + Set<KeyVaulePair> serviceMetadatas = new HashSet<KeyVaulePair>(); + Set<String> serviceNetworkPlane = new HashSet<String>(); + String nodeNamespace = ""; + + + + for (HealthService healthService : healthServiceList) { + Service service = healthService.getService(); + List<String> tagList = service.getTags(); + + String ms_url = "", ms_version = "", ms_protocol = "", ms_status = "", ms_publish_port = "", ms_is_manual = + "", ms_visualRange = "1", ms_network_plane_type = "",ms_lb_policy="",ms_host="",ms_path=""; + List<KeyVaulePair> ms_metadata = new ArrayList<KeyVaulePair>(); + + List<String> nodeLabels = new ArrayList<String>(); + Map<String, String> labelMap = new HashMap<String, String>(); + + NodeInfo node = new NodeInfo(); + + node.setIp(service.getAddress()); + node.setPort(String.valueOf(service.getPort())); + node.setNodeId(service.getId()); + + + + try { + + 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); + ms_url = (baseMap.get("url") == null ? "" : baseMap.get("url")); + ms_version = (baseMap.get("version") == null ? "" : baseMap.get("version")); + ms_protocol = (baseMap.get("protocol") == null ? "" : baseMap.get("protocol")); + ms_status = (baseMap.get("status") == null ? "1" : baseMap.get("status")); + + if (baseMap.get("publish_port") != null) { + ms_publish_port = (baseMap.get("publish_port")); + } + + if (baseMap.get("is_manual") != null) { + ms_is_manual = baseMap.get("is_manual"); + + } + + if (baseMap.get("ha_role") != null) { + node.setHa_role(baseMap.get("ha_role")); + } + + if (baseMap.get("host") != null) { + ms_host=baseMap.get("host"); + } + + if (baseMap.get("path") != null) { + ms_path=baseMap.get("path"); + } + + continue; + } + + if (tag.startsWith("\"labels\"")) { + String ms_labels_json = "{"+tag.split("\"labels\":\\{")[1]; + labelMap = + (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_labels_json, Map.class); + + + + for (Map.Entry<String, String> labelEntry : labelMap.entrySet()) { + if ("visualRange".equals(labelEntry.getKey())) { + ms_visualRange = labelEntry.getValue(); + } else if ("network_plane_type".equals(labelEntry.getKey())) { + ms_network_plane_type = labelEntry.getValue(); + } else { + nodeLabels.add(labelEntry.getKey() + ":" + labelEntry.getValue()); + } + + } + + + continue; + } + + if (tag.startsWith("\"ns\"")) { + String ms_namespace_json = tag.split("\"ns\":")[1]; + Map<String, String> namespaceMap = + (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_namespace_json, Map.class); + + if (namespaceMap.get("namespace") != null) { + nodeNamespace = namespaceMap.get("namespace"); + } else { + nodeNamespace = ""; + } + + 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) { + ms_lb_policy = lbMap.get("lb_policy"); + if (ms_lb_policy.startsWith("hash") || ms_lb_policy.equals("ip_hash")) { + ms_lb_policy = "ip_hash"; + } + + } + + if (lbMap.get("lb_server_params") != null) { + node.setLb_server_params(lbMap.get("lb_server_params").replace(" ", ",")); + } + + continue; + } + + if (tag.startsWith("\"checks\"")) { + String ms_check_json = tag.split("\"checks\":")[1]; + Map<String, String> checkMap = + (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_check_json, Map.class); + + + //自动注册健康检查 + if (StringUtils.isNotBlank(checkMap.get("ttl"))){ + node.setCheckType("TTL"); + node.setTtl(checkMap.get("ttl")); + } + else if(StringUtils.isNotBlank(checkMap.get("http"))){ + node.setCheckType("HTTP"); + node.setCheckUrl(checkMap.get("http")); + if (checkMap.get("interval") != null) node.setCheckInterval(checkMap.get("interval")); + if (checkMap.get("timeout") != null) node.setCheckTimeOut(checkMap.get("timeout")); + } + else if(StringUtils.isNotBlank(checkMap.get("tcp"))){ + node.setCheckType("TCP"); + node.setCheckUrl(checkMap.get("tcp")); + if (checkMap.get("interval") != null) node.setCheckInterval(checkMap.get("interval")); + if (checkMap.get("timeout") != null) node.setCheckTimeOut(checkMap.get("timeout")); + } + + continue; + } + + if (tag.startsWith("\"metadata\"")) { + String ms_metadata_json = "{"+tag.split("\"metadata\":\\{")[1]; + Map<String, String> metadataMap = + (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_metadata_json, Map.class); + + + + for (Map.Entry<String, String> entry : metadataMap.entrySet()) { + KeyVaulePair keyVaulePair = new KeyVaulePair(); + keyVaulePair.setKey(entry.getKey()); + keyVaulePair.setValue(entry.getValue()); + ms_metadata.add(keyVaulePair); + } + + continue; + } + + + + } + + } catch (Exception e) { + LOGGER.error(serviceName + " read tag throw exception", e); + } + + // 健康检查信息 + List<Check> checks = healthService.getChecks(); + node.setStatus("passing"); + for (Check check : checks) { + if (!"passing".equals(check.getStatus())) { + node.setStatus(check.getStatus()); + break; + } + } + + if (!ms_version.equals(version)) { + continue; + } + + // namespace过滤 + if (!namespace.equals(nodeNamespace)) { + continue; + } + + // 标签过滤 + if (islabelQuery) { + boolean ifMatchLabel = false; + for (Map.Entry<String, String> query_entry : query_labelMap.entrySet()) { + String key = query_entry.getKey(); + String value = query_entry.getValue(); + if (StringUtils.isBlank(labelMap.get(key))) { + continue; + } + + String[] queryTagArray = StringUtils.split(value, "|"); + String[] serviceTagArray = StringUtils.split(labelMap.get(key), "|"); + if (DiscoverUtil.contain(queryTagArray, serviceTagArray)) { + ifMatchLabel = true; + break; + } + + } + + if (!ifMatchLabel) { + continue; + } + } + + + nodes.add(node); + serviceLabels.addAll(nodeLabels); + serviceMetadatas.addAll(ms_metadata); + + String[] network_plane_array=StringUtils.split(ms_network_plane_type, "|"); + for(int i=0;i<network_plane_array.length;i++){ + serviceNetworkPlane.add(network_plane_array[i]); + } + + + + microServiceInfo.setServiceName(serviceName); + microServiceInfo.setUrl(ms_url); + microServiceInfo.setVersion(ms_version); + microServiceInfo.setProtocol(ms_protocol); + microServiceInfo.setStatus(ms_status); + microServiceInfo.setPublish_port(ms_publish_port); + microServiceInfo.setIs_manual(Boolean.parseBoolean(ms_is_manual)); + microServiceInfo.setVisualRange(ms_visualRange); + + microServiceInfo.setLb_policy(ms_lb_policy); + microServiceInfo.setNamespace(namespace); + microServiceInfo.setHost(ms_host); + microServiceInfo.setPath(ms_path); + } + + + if (nodes.isEmpty()) { + + + String errInfo = + "microservice not found: serviceName-" + serviceName + ",version-" + version + + ",namespace-" + namespace + ",labels-" + labels; + throw new ExtendedNotFoundException(errInfo); + + } + + + + microServiceInfo.setLabels(new ArrayList<String>(serviceLabels)); + microServiceInfo.setMetadata(new ArrayList<KeyVaulePair>(serviceMetadatas)); + microServiceInfo.setNodes(nodes); + microServiceInfo.setNetwork_plane_type(StringUtils.join(serviceNetworkPlane.toArray(), "|")); + + + + return new ConsulResponse(microServiceInfo, consulResponse.getIndex()); + + + } catch (ExtendedNotFoundException e) { + throw e; + } catch (Exception e) { + throw new ExtendedInternalServerErrorException(e.getMessage()); + } + + + } + + + + public MicroServiceFullInfo updateMicroServiceInstance(String serviceName, String version, + String namespace, MicroServiceInfo microServiceInfo, String requestIP,boolean is_manual) { + //数据格式效验 + checkMicroServiceInfo(microServiceInfo); + deleteMicroService(serviceName, version,namespace); + return saveMicroServiceInstance(microServiceInfo, true, requestIP,is_manual); + } + + /** + * Title: saveMicroServiceInstance Description: 保存服务信息 + * + * @param microServiceInfo + * @param createOrUpdate true:添加或追加更新 false:覆盖 + * @param requestIP 访问请求IP地址 + * @return + * @see com.zte.ums.nfv.eco.hsif.msb.core.IMSBService#saveMicroServiceInstance(org.onap.msb.sdclient.core.MicroServiceInfo, + * boolean, java.lang.String) + */ + public MicroServiceFullInfo saveMicroServiceInstance(MicroServiceInfo microServiceInfo, + boolean createOrUpdate, String requestIP,boolean is_manual) { + + //数据格式效验 + checkMicroServiceInfo(microServiceInfo); + + String serviceName = microServiceInfo.getServiceName().trim(); + + if (createOrUpdate == false) { + // 覆盖原记录,先删除后添加 + try{ + deleteMicroService(microServiceInfo.getServiceName(), microServiceInfo.getVersion(), + microServiceInfo.getNamespace()); + } + catch (ExtendedNotFoundException e) { + String errInfo = "microservice not found: serviceName-" + microServiceInfo.getServiceName() + ",version-" + microServiceInfo.getVersion()+ " ,namespace-" + microServiceInfo.getNamespace(); + LOGGER.warn(errInfo); + } + + + + } + + Set<Node> nodes = microServiceInfo.getNodes(); + String[] visualRangeArray = StringUtils.split(microServiceInfo.getVisualRange(), "|"); + + try { + + for (Node node : nodes) { + AgentService agentService = new AgentService(); + + if (StringUtils.isBlank(node.getIp())) { + node.setIp(requestIP); + } + + String serverId = + microServiceInfo.getNamespace() + "_" + serviceName + "_" + node.getIp() + "_" + + node.getPort(); + + + List<String> tags = new ArrayList<String>(); + + Map<String, String> baseMap = new HashMap<String, String>(); + Map<String, String> lbMap = new HashMap<String, String>(); + Map<String, String> labelMap = new HashMap<String, String>(); + Map<String, String> metadataMap = new HashMap<String, String>(); + Map<String, String> checkMap = new HashMap<String, String>(); + Map<String, String> nsMap = new HashMap<String, String>(); + //Map<String, String> nodeMap = new HashMap<String, String>(); + + baseMap.put("url", microServiceInfo.getUrl()); + baseMap.put("protocol", microServiceInfo.getProtocol()); + baseMap.put("version", microServiceInfo.getVersion()); + + baseMap.put("status", "1"); + baseMap.put("is_manual", Boolean.toString(is_manual)); + + // TCP和UDP协议保存 nginx端口和负载均衡策略 + if (StringUtils.isNotBlank(microServiceInfo.getPublish_port())) { + baseMap.put("publish_port", microServiceInfo.getPublish_port()); + } + String lb_policy = microServiceInfo.getLb_policy(); + + // 保存服务的负载均衡策略 + if (StringUtils.isNotBlank(lb_policy)) { + switch (lb_policy) { + case "round-robin": + break; + case "ip_hash": + if ("TCP".equals(microServiceInfo.getProtocol()) + || "UDP".equals(microServiceInfo.getProtocol())) { + lbMap.put("lb_policy", "hash $remote_addr"); + } else { + lbMap.put("lb_policy", "ip_hash"); + } + break; + default: + lbMap.put("lb_policy", lb_policy); + break; + } + + } + + if (StringUtils.isNotBlank(node.getLb_server_params())) { + lbMap.put("lb_server_params", node.getLb_server_params().trim().replace(",", " ")); + + } + + if (StringUtils.isNotBlank(node.getHa_role())) { + baseMap.put("ha_role", node.getHa_role()); + } + + if (StringUtils.isNotBlank(microServiceInfo.getHost())) { + baseMap.put("host", microServiceInfo.getHost().toLowerCase()); + } + + if (StringUtils.isNotBlank(microServiceInfo.getPath())) { + baseMap.put("path",microServiceInfo.getPath()); + } + + // 保存健康检查参数 + if (StringUtils.isNotBlank(node.getCheckType())) { + + AgentService.Check check = agentService.createCheck(); + + if ("TTL".equals(node.getCheckType())) { + check.setTtl(node.getTtl()); + checkMap.put("ttl", node.getTtl()); + + } else if ("HTTP".equals(node.getCheckType())) { + check.setInterval(node.getCheckInterval()); + check.setHttp(node.getCheckUrl()); + check.setTimeout(node.getCheckTimeOut()); + + checkMap.put("http", node.getCheckUrl()); + checkMap.put("interval",node.getCheckInterval()); + checkMap.put("timeout", node.getCheckTimeOut()); + } else if ("TCP".equals(node.getCheckType())) { + check.setInterval(node.getCheckInterval()); + check.setTcp(node.getCheckUrl()); + check.setTimeout(node.getCheckTimeOut()); + + checkMap.put("tcp", node.getCheckUrl()); + checkMap.put("interval", node.getCheckInterval()); + checkMap.put("timeout",node.getCheckTimeOut()); + } + + agentService.setCheck(check); + } + + + List<KeyVaulePair> keyVaulePairs = microServiceInfo.getMetadata(); + + if (keyVaulePairs != null && keyVaulePairs.size() > 0) { + for (KeyVaulePair keyVaulePair : keyVaulePairs) { + metadataMap.put(keyVaulePair.getKey(), keyVaulePair.getValue()); + } + } + + // 同步过滤参数组合为json格式存储 + labelMap.put("visualRange", StringUtils.join(visualRangeArray, "|")); + + if (StringUtils.isNotBlank(microServiceInfo.getNetwork_plane_type())) { + labelMap.put("network_plane_type", microServiceInfo.getNetwork_plane_type()); + } + if(microServiceInfo.getLabels()!=null){ + for (String label : microServiceInfo.getLabels()) { + String[] labelArray = StringUtils.split(label, ":"); + if(labelArray.length==2){ + labelMap.put(labelArray[0], labelArray[1]); + } + } + } + + if (StringUtils.isNotBlank(microServiceInfo.getNamespace())) { + nsMap.put("namespace", microServiceInfo.getNamespace()); + } + + + + tags.add("\"base\":" + JacksonJsonUtil.beanToJson(baseMap)); + if(!lbMap.isEmpty()) tags.add("\"lb\":" + JacksonJsonUtil.beanToJson(lbMap)); + if(!checkMap.isEmpty()) tags.add("\"checks\":" + JacksonJsonUtil.beanToJson(checkMap)); + if(!labelMap.isEmpty()) tags.add("\"labels\":" + JacksonJsonUtil.beanToJson(labelMap)); + if(!metadataMap.isEmpty()) tags.add("\"metadata\":" + JacksonJsonUtil.beanToJson(metadataMap)); + if(!nsMap.isEmpty()) tags.add("\"ns\":" + JacksonJsonUtil.beanToJson(nsMap)); + + agentService.setTags(tags); + + agentService.setAddress(node.getIp()); + agentService.setId(serverId); + agentService.setPort(Integer.parseInt(node.getPort())); + + String consul_serviceName=getServiceName4Consul(serviceName,microServiceInfo.getNamespace()); + + + agentService.setName(consul_serviceName); + + int registerResult; + if(DiscoverUtil.CONSUL_REGISTER_MODE.equals(ConfigUtil.getInstance().getConsulRegisterMode())){ + registerResult =ConsulCatalogServiceWrapper.getInstance().saveService(agentService); + } + else{ + registerResult =ConsulAgentServiceWrapper.getInstance().saveService(agentService); + } + + if (registerResult != 200) { + throw new Exception("register consul service fail:" + registerResult); + } + + + + } + + LOGGER.info( "save microservice success: serviceName-" + microServiceInfo.getServiceName() + ",version-" + microServiceInfo.getVersion()+ " ,namespace-" + microServiceInfo.getNamespace()); + + return getMicroServiceInstance(serviceName, microServiceInfo.getVersion(), + microServiceInfo.getNamespace()); + + + } catch (ExtendedNotFoundException e) { + throw e; + } catch (Exception e) { + LOGGER.error("register consul service throw exception", e); + throw new ExtendedInternalServerErrorException(e.getMessage()); + + } + + + + } + + public MicroServiceFullInfo getMicroServiceInstance(String serviceName, String version, + String namespace) { + ConsulResponse serviceResponse = + getMicroServiceInstance(serviceName, version, false, "", "", "", namespace); + return (MicroServiceFullInfo) serviceResponse.getResponse(); + } + + + /** + * Title: deleteMicroService Description: 删除服务信息 + * + * @param serviceName + * @param version + * @see com.zte.ums.nfv.eco.hsif.msb.core.IMSBService#deleteMicroService(java.lang.String, + * java.lang.String) + */ + public void deleteMicroService(String serviceName, String version, String namespace) { + + + if ("null".equals(version)) { + version = ""; + } + + checkServiceNameAndVersion(serviceName,version); + + + String consul_serviceName=getServiceName4Consul(serviceName,namespace); + + List<CatalogService> catalogServiceList = getConsulServices(consul_serviceName, version); + + + if (catalogServiceList == null || catalogServiceList.size() == 0) { + String errInfo = "microservice not found: serviceName-" + serviceName + ",version-" + version+ " ,namespace-" + namespace; + throw new ExtendedNotFoundException(errInfo); + + } + + boolean ifFindServiceForNS = false; + + for (CatalogService catalogService : catalogServiceList) { + + List<String> tagList = catalogService.getServiceTags(); + String serviceNamespace = "",serviceVersion=""; + try { + + for (String tag : tagList) { + + 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) { + serviceNamespace = nsMap.get("namespace"); + } + + continue; + } + + 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("version") != null) { + serviceVersion= baseMap.get("version"); + } + + + continue; + + } + + } + + } catch (Exception e) { + LOGGER.error(serviceName + " read tag throw exception", e); + } + + if (!serviceNamespace.equals(namespace)) { + continue; + } + + if(!serviceVersion.equals(version)){ + continue; + } + ifFindServiceForNS = true; + String serviceID = catalogService.getServiceId(); + try { + + int delResult; + if(DiscoverUtil.CONSUL_REGISTER_MODE.equals(ConfigUtil.getInstance().getConsulRegisterMode())){ + delResult =ConsulCatalogServiceWrapper.getInstance().deleteService(serviceID); + } + else{ + delResult =ConsulAgentServiceWrapper.getInstance().deleteService(serviceID); + } + + if (delResult != 200) { + throw new Exception("delete consul service fail:" + delResult); + } + + + } catch (Exception e) { + LOGGER.error("delete consul service throw exception", e); + throw new ExtendedInternalServerErrorException(e.getMessage()); + + } + + } + + + if (!ifFindServiceForNS) { + String errInfo = + "microservice not found: serviceName-" + serviceName + ",version-" + version + + ",namespace-" + namespace; + throw new ExtendedNotFoundException(errInfo); + } + + LOGGER.info("microservice delete success: serviceName-" + serviceName + ",version-" + version + + ",namespace-" + namespace); + + } + + /** + * Title: deleteMicroServiceInstance Description: 刪除服务的节点信息 + * + * @param serviceName + * @param version + * @param ip + * @param port + * @see com.zte.ums.nfv.eco.hsif.msb.core.IMSBService#deleteMicroServiceInstance(java.lang.String, + * java.lang.String, java.lang.String, java.lang.String) + */ + public void deleteMicroServiceInstance(String serviceName, String version, String namespace, + String ip, String port) { + if ("null".equals(version)) { + version = ""; + } + + 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"); + } + + String consul_serviceName=getServiceName4Consul(serviceName,namespace); + + List<CatalogService> catalogServiceList = getConsulServices(consul_serviceName, version); + + + if (catalogServiceList == null || catalogServiceList.size() == 0) { + String errInfo = "microservice not found: serviceName-" + serviceName + ",version-" + version; + LOGGER.warn(errInfo); + throw new ExtendedNotFoundException(errInfo); + + } + + String node = "", serviceID = ""; + boolean ifFindBNode = false; + + + for (CatalogService catalogService : catalogServiceList) { + + String serviceAddress = catalogService.getServiceAddress(); + String servicePort = String.valueOf(catalogService.getServicePort()); + + + + List<String> tagList = catalogService.getServiceTags(); + String ms_version = "", ms_namespace = ""; + try { + + 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("version") != null) { + ms_version = baseMap.get("version"); + } + + + } + + 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) { + ms_namespace = nsMap.get("namespace"); + } + + + } + } + + } catch (Exception e) { + LOGGER.error(serviceName + " read tag throw exception", e); + } + if (serviceAddress.equals(ip) && servicePort.equals(port) && ms_version.equals(version) + && ms_namespace.equals(namespace)) { + node = catalogService.getNode(); + serviceID = catalogService.getServiceId(); + ifFindBNode = true; + break; + } + + + } + + if (!ifFindBNode) { + throw new ExtendedNotFoundException("delete MicroServiceInfo FAIL: node-" + ip + ":" + port + + " namespace-" + namespace + " not found "); + } + + + + try { + int delResult; + if(DiscoverUtil.CONSUL_REGISTER_MODE.equals(ConfigUtil.getInstance().getConsulRegisterMode())){ + delResult =ConsulCatalogServiceWrapper.getInstance().deleteService(serviceID); + } + else{ + delResult =ConsulAgentServiceWrapper.getInstance().deleteService(serviceID); + } + + if (delResult != 200) { + throw new Exception("delete consul service fail:" + delResult); + } + + + } catch (Exception e) { + LOGGER.error("delete consul service throw exception", e); + throw new ExtendedInternalServerErrorException(e.getMessage()); + + } + + } + + /** + * @Title getConsulServices + * @Description TODO(通过方法:根据服务名\版本号获取consul服务信息) + * @param serviceName + * @return + * @return List<CatalogService> + */ + private List<CatalogService> getConsulServices(String serviceName, String version) { + // serviceName = serviceName.replace("/", "*"); + String consulServiceUrl = + (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress()) + .append(DiscoverUtil.CONSUL_CATALOG_URL).append("/service/").append(serviceName)) + .toString(); + + String resultJson = HttpClientUtil.httpGet(consulServiceUrl); + List<CatalogService> catalogServiceList = + (List<CatalogService>) JacksonJsonUtil.jsonToListBean(resultJson); + + for (CatalogService catalogService : catalogServiceList) { + + + List<String> tagList = catalogService.getServiceTags(); + String ms_version = ""; + try { + 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("version") != null) { + ms_version = baseMap.get("version"); + } + + break; + + } + } + } catch (Exception e) { + LOGGER.error(serviceName + " read tag throw exception", e); + } + if (!ms_version.equals(version)) { + catalogServiceList.remove(catalogService); + break; + } + + + } + return catalogServiceList; + } + + /** + * @Title getHealthServices + * @Description TODO(通过方法:根据服务名获取consul服务健康检查信息) + * @param serviceName + * @return List<HealthService> + */ + private ConsulResponse getHealthServices(String serviceName, boolean ifPassStatus, String wait, + String index) { + // serviceName = serviceName.replace("/", "*"); + StringBuilder healthServiceUrlBuilder = + new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress()) + .append(DiscoverUtil.CONSUL_HEALTH_URL).append(serviceName); + + if (ifPassStatus) { + healthServiceUrlBuilder.append("?passing"); + } + + if (StringUtils.isNotBlank(wait) && StringUtils.isNotBlank(index)) { + if (ifPassStatus) { + healthServiceUrlBuilder.append("&wait=").append(wait).append("&index=").append(index); + } else { + healthServiceUrlBuilder.append("?wait=").append(wait).append("&index=").append(index); + } + } + + return HttpClientUtil.httpWaitGet(healthServiceUrlBuilder.toString()); + + } + + + + public void healthCheckbyTTL(String serviceName, String version, String namespace, + NodeAddress checkNode) { + // TODO Auto-generated method stub + if ("null".equals(version)) { + version = ""; + } + + checkServiceNameAndVersion(serviceName,version); + + + if (!RegExpTestUtil.ipRegExpTest(checkNode.getIp())) { + throw new UnprocessableEntityException("healthCheck by TTL FAIL:IP(" + checkNode.getIp() + + ")is not a valid IP address"); + } + + if (!RegExpTestUtil.portRegExpTest(checkNode.getPort())) { + throw new UnprocessableEntityException("healthCheck by TTL FAIL:Port(" + checkNode.getPort() + + ")is not a valid Port address"); + } + + String consul_serviceName=getServiceName4Consul(serviceName,namespace); + + List<CatalogService> catalogServiceList = getConsulServices(consul_serviceName, version); + + + if (catalogServiceList == null || catalogServiceList.size() == 0) { + String errInfo = "microservice not found: serviceName-" + serviceName + ",version-" + version; + LOGGER.warn(errInfo); + throw new ExtendedNotFoundException(errInfo); + + } + + + boolean ifFindBNode = false; + + + for (CatalogService catalogService : catalogServiceList) { + + String serviceAddress = catalogService.getServiceAddress(); + String servicePort = String.valueOf(catalogService.getServicePort()); + boolean ifttlCheck = false; + + + List<String> tagList = catalogService.getServiceTags(); + String ms_version = "", ms_namespace = ""; + try { + + 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("version") != null) { + ms_version = baseMap.get("version"); + } + } + + 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) { + ms_namespace = nsMap.get("namespace"); + } + } + + + if (tag.startsWith("\"checks\"")) { + String ms_check_json = tag.split("\"checks\":")[1]; + Map<String, String> checkMap = + (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_check_json, Map.class); + + //自动注册健康检查 + if (StringUtils.isNotBlank(checkMap.get("ttl"))){ + ifttlCheck=true; + } + } + } + + } catch (Exception e) { + LOGGER.error(serviceName + " read tag throw exception", e); + } + + + + + if (serviceAddress.equals(checkNode.getIp()) && servicePort.equals(checkNode.getPort()) && ms_version.equals(version) + && ms_namespace.equals(namespace)) { + if(!ifttlCheck){ + throw new ExtendedNotFoundException("healthCheck by TTL FAIL: Service is not enabled TTL health check "); + } + ifFindBNode = true; + break; + } + + + } + + + + if (!ifFindBNode) { + throw new ExtendedNotFoundException("healthCheck by TTL FAIL: node-" + checkNode.getIp() + ":" + checkNode.getPort() + + " namespace-" + namespace + " not found "); + } + + + + + + try { + String checkID = + (new StringBuilder().append("service:").append(namespace).append("_").append(serviceName) + .append("_").append(checkNode.getIp()).append("_").append(checkNode.getPort())) + .toString(); + + String consulServiceUrl = + (new StringBuilder().append("http://").append(ConfigUtil.getInstance().getConsulAddress()) + .append(DiscoverUtil.CONSUL_AGENT_TTL_URL).append(checkID)).toString(); + + String result= HttpClientUtil.httpGet(consulServiceUrl); + if("CheckID does not have associated TTL".equals(result)){ + throw new ExtendedNotFoundException("healthCheck by TTL FAIL: Service is not enabled TTL health check "); + } + + } + catch (ExtendedInternalServerErrorException e) { + throw e; + } + catch (Exception e) { + throw new ExtendedInternalServerErrorException("healthCheck by TTL FAIL:" + e.getMessage()); + } + + + + } + +// public MicroServiceFullInfo getApigatewayServiceInfo4Host(String namespace){ +// return getMicroServiceInstance(DiscoverUtil.APIGATEWAY_SERVINCE, "v1", namespace); +// } +// + + + + + + public List<MicroServiceFullInfo> getMicroServiceForNodes(String serviceName, String version, boolean ifPassStatus,String labels,String namespace){ + // TODO Auto-generated method stub + if ("null".equals(version)) { + version = ""; + } + + checkServiceNameAndVersion(serviceName,version); + + if (!RegExpTestUtil.labelRegExpTest(labels)) { + throw new UnprocessableEntityException( + "get MicroServiceInfo FAIL: The label query parameter format is wrong (key:value)"); + } + + + String consul_serviceName=getServiceName4Consul(serviceName,namespace); + + ConsulResponse consulResponse = getHealthServices(consul_serviceName, ifPassStatus, "", ""); + if (consulResponse == null) { + String errInfo = "microservice not found: serviceName-" + serviceName; + throw new ExtendedNotFoundException(errInfo); + } + String resultJson = (String) consulResponse.getResponse(); + List<HealthService> healthServiceList = + JacksonJsonUtil.jsonToListBean(resultJson, new TypeReference<List<HealthService>>() {}); + + + if (healthServiceList == null || healthServiceList.size() == 0) { + String errInfo = "microservice not found: serviceName-" + serviceName; + throw new ExtendedNotFoundException(errInfo); + } + + try { + + // label query,format key:value|value2,key2:value2 + boolean islabelQuery = false; + Map<String, String> query_labelMap = new HashMap<String, String>(); + if (StringUtils.isNotBlank(labels)) { + islabelQuery = true; + String[] routeLabels = StringUtils.split(labels, ","); + + for (int i = 0; i < routeLabels.length; i++) { + String[] labelArray = StringUtils.split(routeLabels[i], ":"); + query_labelMap.put(labelArray[0], labelArray[1]); + } + } + + List<MicroServiceFullInfo> microServiceInfoList=new ArrayList<MicroServiceFullInfo>(); + + + + for (HealthService healthService : healthServiceList) { + + Set<NodeInfo> nodes = new HashSet<NodeInfo>(); + Set<String> serviceLabels = new HashSet<String>(); + String nodeNamespace = ""; + MicroServiceFullInfo microServiceInfo = new MicroServiceFullInfo(); + + Service service = healthService.getService(); + List<String> tagList = service.getTags(); + + String ms_url = "", ms_version = "", ms_protocol = "", ms_status = "", ms_publish_port = "", ms_is_manual = + "", ms_visualRange = "1", ms_network_plane_type = "",ms_lb_policy="",ms_host="",ms_path=""; + List<KeyVaulePair> ms_metadata = new ArrayList<KeyVaulePair>(); + + List<String> nodeLabels = new ArrayList<String>(); + Map<String, String> labelMap = new HashMap<String, String>(); + + NodeInfo node = new NodeInfo(); + + node.setIp(service.getAddress()); + node.setPort(String.valueOf(service.getPort())); + node.setNodeId(service.getId()); + + + + try { + + 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); + ms_url = (baseMap.get("url") == null ? "" : baseMap.get("url")); + ms_version = (baseMap.get("version") == null ? "" : baseMap.get("version")); + ms_protocol = (baseMap.get("protocol") == null ? "" : baseMap.get("protocol")); + ms_status = (baseMap.get("status") == null ? "1" : baseMap.get("status")); + + if (baseMap.get("publish_port") != null) { + ms_publish_port = (baseMap.get("publish_port")); + } + + if (baseMap.get("is_manual") != null) { + ms_is_manual = baseMap.get("is_manual"); + + } + + if (baseMap.get("ha_role") != null) { + node.setHa_role(baseMap.get("ha_role")); + } + + if (baseMap.get("host") != null) { + ms_host=baseMap.get("host"); + } + + if (baseMap.get("path") != null) { + ms_path=baseMap.get("path"); + } + + continue; + } + + if (tag.startsWith("\"labels\"")) { + String ms_labels_json = "{"+tag.split("\"labels\":\\{")[1]; + labelMap = + (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_labels_json, Map.class); + + + + for (Map.Entry<String, String> labelEntry : labelMap.entrySet()) { + if ("visualRange".equals(labelEntry.getKey())) { + ms_visualRange = labelEntry.getValue(); + } else if ("network_plane_type".equals(labelEntry.getKey())) { + ms_network_plane_type = labelEntry.getValue(); + } else { + nodeLabels.add(labelEntry.getKey() + ":" + labelEntry.getValue()); + } + + } + + + continue; + } + + if (tag.startsWith("\"ns\"")) { + String ms_namespace_json = tag.split("\"ns\":")[1]; + Map<String, String> namespaceMap = + (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_namespace_json, Map.class); + + if (namespaceMap.get("namespace") != null) { + nodeNamespace = namespaceMap.get("namespace"); + } else { + nodeNamespace = ""; + } + + 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) { + ms_lb_policy = lbMap.get("lb_policy"); + if (ms_lb_policy.startsWith("hash") || ms_lb_policy.equals("ip_hash")) { + ms_lb_policy = "ip_hash"; + } + + } + + if (lbMap.get("lb_server_params") != null) { + node.setLb_server_params(lbMap.get("lb_server_params").replace(" ", ",")); + } + + continue; + } + + if (tag.startsWith("\"checks\"")) { + String ms_check_json = tag.split("\"checks\":")[1]; + Map<String, String> checkMap = + (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_check_json, Map.class); + + + //自动注册健康检查 + if (StringUtils.isNotBlank(checkMap.get("ttl"))){ + node.setCheckType("TTL"); + node.setTtl(checkMap.get("ttl")); + } + else if(StringUtils.isNotBlank(checkMap.get("http"))){ + node.setCheckType("HTTP"); + node.setCheckUrl(checkMap.get("http")); + if (checkMap.get("interval") != null) node.setCheckInterval(checkMap.get("interval")); + if (checkMap.get("timeout") != null) node.setCheckTimeOut(checkMap.get("timeout")); + } + else if(StringUtils.isNotBlank(checkMap.get("tcp"))){ + node.setCheckType("TCP"); + node.setCheckUrl(checkMap.get("tcp")); + if (checkMap.get("interval") != null) node.setCheckInterval(checkMap.get("interval")); + if (checkMap.get("timeout") != null) node.setCheckTimeOut(checkMap.get("timeout")); + } + + continue; + } + + if (tag.startsWith("\"metadata\"")) { + String ms_metadata_json = "{"+tag.split("\"metadata\":\\{")[1]; + Map<String, String> metadataMap = + (Map<String, String>) JacksonJsonUtil.jsonToBean(ms_metadata_json, Map.class); + + + + for (Map.Entry<String, String> entry : metadataMap.entrySet()) { + KeyVaulePair keyVaulePair = new KeyVaulePair(); + keyVaulePair.setKey(entry.getKey()); + keyVaulePair.setValue(entry.getValue()); + ms_metadata.add(keyVaulePair); + } + + continue; + } + + + + } + + } catch (Exception e) { + LOGGER.error(serviceName + " read tag throw exception", e); + } + + // 健康检查信息 + List<Check> checks = healthService.getChecks(); + node.setStatus("passing"); + for (Check check : checks) { + if (!"passing".equals(check.getStatus())) { + node.setStatus(check.getStatus()); + break; + } + } + + if (!ms_version.equals(version)) { + continue; + } + + // namespace过滤 + if (!namespace.equals(nodeNamespace)) { + continue; + } + + // 标签过滤 + if (islabelQuery) { + boolean ifMatchLabel = false; + for (Map.Entry<String, String> query_entry : query_labelMap.entrySet()) { + String key = query_entry.getKey(); + String value = query_entry.getValue(); + if (StringUtils.isBlank(labelMap.get(key))) { + continue; + } + + String[] queryTagArray = StringUtils.split(value, "|"); + String[] serviceTagArray = StringUtils.split(labelMap.get(key), "|"); + if (DiscoverUtil.contain(queryTagArray, serviceTagArray)) { + ifMatchLabel = true; + break; + } + + } + + if (!ifMatchLabel) { + continue; + } + } + + + nodes.add(node); + serviceLabels.addAll(nodeLabels); + + microServiceInfo.setServiceName(serviceName); + microServiceInfo.setUrl(ms_url); + microServiceInfo.setVersion(ms_version); + microServiceInfo.setProtocol(ms_protocol); + microServiceInfo.setStatus(null); + microServiceInfo.setPublish_port(ms_publish_port); + microServiceInfo.setIs_manual(Boolean.parseBoolean(ms_is_manual)); + microServiceInfo.setVisualRange(ms_visualRange); + microServiceInfo.setNetwork_plane_type(ms_network_plane_type); + microServiceInfo.setLb_policy(ms_lb_policy); + microServiceInfo.setHost(ms_host); + microServiceInfo.setPath(ms_path); + + microServiceInfo.setMetadata(ms_metadata); + microServiceInfo.setNamespace(namespace); + microServiceInfo.setLabels(new ArrayList<String>(serviceLabels)); + microServiceInfo.setNodes(nodes); + + microServiceInfoList.add(microServiceInfo); + } + + + + if (microServiceInfoList.size() == 0) { + String errInfo = + "microservice not found: serviceName-" + serviceName + ",version-" + version + + ",namespace-" + namespace + ",labels-" + labels; + throw new ExtendedNotFoundException(errInfo); + } + + + + + + return microServiceInfoList; + + + } catch (ExtendedNotFoundException e) { + throw e; + } catch (Exception e) { + throw new ExtendedInternalServerErrorException(e.getMessage()); + } + } + + + private String getServiceName4Consul(String serviceName,String namespace){ + String consul_serviceName; + + if (StringUtils.isNotBlank(namespace)) { +// if (DiscoverUtil.APIGATEWAY_SERVINCE_DEFAULT.equals(namespace)) { +// consul_serviceName=serviceName; +// }else{ + consul_serviceName=serviceName+"-"+namespace; +// } + } + else{ + consul_serviceName=serviceName; + } + return consul_serviceName; + } + + + + + + + private void checkMicroServiceInfo(MicroServiceInfo microServiceInfo){ + + if (StringUtils.isBlank(microServiceInfo.getServiceName()) + || StringUtils.isBlank(microServiceInfo.getProtocol())) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL: Some required fields are empty"); + } + + if(microServiceInfo.getNodes()==null || microServiceInfo.getNodes().size() == 0){ + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL: Nodes fields are empty"); + } + + if (!RegExpTestUtil.serviceNameRegExpTest(microServiceInfo.getServiceName().trim())) { + throw new UnprocessableEntityException("register MicroServiceInfo FAIL:ServiceName(" + + microServiceInfo.getServiceName() + ") format error"); + } + + if (StringUtils.isNotBlank(microServiceInfo.getHost())) { + if (!RegExpTestUtil.serviceNameRegExpTest(microServiceInfo.getHost().trim())) { + throw new UnprocessableEntityException("register MicroServiceInfo host (" + + microServiceInfo.getHost() + ") format error"); + } + } + + if (StringUtils.isNotBlank(microServiceInfo.getLb_policy())) { + if (!DiscoverUtil.checkExist(DiscoverUtil.LB_POLICY_LIST, microServiceInfo.getLb_policy() + .trim(), ",")) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:lb_policy is wrong,value range:(" + + DiscoverUtil.LB_POLICY_LIST + ")"); + } + + } + + 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())) { + + String url=microServiceInfo.getUrl(); + if(!"/".equals(url)){ + if(!url.startsWith("/")){ + url="/"+url; + microServiceInfo.setUrl(url); + } + + if(url.endsWith("/")){ + url=url.substring(0, url.length()-1); + microServiceInfo.setUrl(url); + } + } + + if (!RegExpTestUtil.urlRegExpTest(url)) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:url ("+url+") is not a valid format"); + } + + } + else{ + microServiceInfo.setUrl("/"); + } + + + if (StringUtils.isNotBlank(microServiceInfo.getPath())) { + + String path=microServiceInfo.getPath(); + if(!"/".equals(path)){ + if(!path.startsWith("/")){ + path="/"+path; + microServiceInfo.setPath(path); + } + + if(path.endsWith("/")){ + path=path.substring(0, path.length()-1); + microServiceInfo.setPath(path); + } + } + + if (!RegExpTestUtil.urlRegExpTest(path)) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:path ("+path+") is not a valid format"); + + } + + + + } + + + for (Node node : microServiceInfo.getNodes()) { + + if (StringUtils.isNotBlank(node.getIp())) { + 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(node.getLb_server_params())) { + try { + String[] lb_server_params_array = node.getLb_server_params().split(","); + for (int i = 0; i < lb_server_params_array.length; i++) { + String params = lb_server_params_array[i].split("=")[0]; + if (!DiscoverUtil.checkExist(DiscoverUtil.LB_PARAMS_LIST, params, ",")) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:lb_server_params is wrong:" + + lb_server_params_array[i]); + } + } + } catch (Exception e) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:lb_server_params'format is wrong:" + + node.getLb_server_params()); + } + + } + + if (StringUtils.isNotBlank(node.getCheckType())) { + if (!DiscoverUtil.checkExist(DiscoverUtil.CHECK_TYPE_LIST, node.getCheckType().trim(), ",")) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:checkType is wrong,value range:(" + + DiscoverUtil.CHECK_TYPE_LIST + ")"); + } + + + if ("HTTP".equals(node.getCheckType()) || "TCP".equals(node.getCheckType())) { + String checkUrl=node.getCheckUrl(); + if (StringUtils.isBlank(checkUrl)) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:checkUrl field is empty"); + } + + if("HTTP".equals(node.getCheckType())){ + + + if(RegExpTestUtil.httpUrlRegExpTest(checkUrl)){ + if(!checkUrl.startsWith("http://")){ + checkUrl="http://"+checkUrl; + node.setCheckUrl(checkUrl); + } + } + else{ + if(!checkUrl.startsWith("/")){ + checkUrl="/"+checkUrl; + } + checkUrl="http://"+node.getIp()+":"+node.getPort()+checkUrl; + node.setCheckUrl(checkUrl); + } + } + + + } + + } + + if (StringUtils.isNotBlank(node.getHa_role())) { + if (!DiscoverUtil + .checkExist(DiscoverUtil.CHECK_HA_ROLE_LIST, node.getHa_role().trim(), ",")) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:ha_role is wrong,value range:(" + + DiscoverUtil.CHECK_HA_ROLE_LIST + ")"); + } + } + + + } + + + + String[] visualRangeArray = StringUtils.split(microServiceInfo.getVisualRange(), "|"); + for (int i = 0; i < visualRangeArray.length; i++) { + if (!DiscoverUtil.checkExist(DiscoverUtil.VISUAL_RANGE_LIST, visualRangeArray[i], ",")) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:type is wrong,value range:(" + + DiscoverUtil.VISUAL_RANGE_LIST + ")"); + } + } + + microServiceInfo.setProtocol(microServiceInfo.getProtocol().toUpperCase()); + if (!DiscoverUtil.checkExist(DiscoverUtil.PROTOCOL_LIST, microServiceInfo.getProtocol().trim(), + ",")) { + throw new UnprocessableEntityException( + "register MicroServiceInfo FAIL:Protocol is wrong,value range:(" + + DiscoverUtil.PROTOCOL_LIST + ")"); + } + + if (microServiceInfo.getLabels()!=null) { + for (String label : microServiceInfo.getLabels()) { + if (!RegExpTestUtil.labelRegExpTest(label)) { + throw new UnprocessableEntityException("register MicroServiceInfo FAIL:label[" + label + + "] is not a valid format(key:value)"); + } + } + } + + + + // 判断自定义发布端口 + if (StringUtils.isNotBlank(microServiceInfo.getPublish_port())) { + + if(DiscoverUtil.checkExist(DiscoverUtil.HTTP_PROTOCOL, microServiceInfo.getProtocol())){ + + if(microServiceInfo.getPublish_port().contains("|")){ + + String[] publishPortArray = StringUtils.split(microServiceInfo.getPublish_port(), "|"); + + int portNum=publishPortArray.length; + + //判断端口格式 + for (int i = 0; i < portNum; i++) { + if (!RegExpTestUtil.portRegExpTest(publishPortArray[i])) { + throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Public Port(" + +publishPortArray[i] + ")is not a valid Port address"); + } + } + + //判断端口数量 + if(portNum==0 || portNum>2){ + throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Public Port num is wrong:"+portNum); + } + else if(portNum==2){ + //判断端口值是否一样 + if(publishPortArray[0].equals(publishPortArray[1])){ + throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Two ports have the same value :"+publishPortArray[0]); + } + } + else if(portNum==1){ + throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Two ports have one null value"); + } + } + else{ + if (!RegExpTestUtil.portRegExpTest(microServiceInfo.getPublish_port())) { + throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Public Port(" + + microServiceInfo.getPublish_port() + ")is not a valid Port address"); + } + } + + } + else if("TCP".equals(microServiceInfo.getProtocol()) || "UDP".equals(microServiceInfo.getProtocol())){ + if (!RegExpTestUtil.portRegExpTest(microServiceInfo.getPublish_port())) { + throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Public Port(" + + microServiceInfo.getPublish_port() + ")is not a valid Port address"); + } + + int tcpUdpPortRangeStart= Integer.parseInt(ConfigUtil.getInstance().getTcpudpPortRangeStart()); + int tcpUdpPortRangeEnd= Integer.parseInt(ConfigUtil.getInstance().getTcpudpPortRangeEnd()); + int iPublishPort=Integer.parseInt(microServiceInfo.getPublish_port()); + + if(iPublishPort>tcpUdpPortRangeEnd || iPublishPort <tcpUdpPortRangeStart){ + throw new UnprocessableEntityException("register MicroServiceInfo FAIL:Public_Port Range (" + + tcpUdpPortRangeStart + "-"+tcpUdpPortRangeEnd+")"); + } + + } + else{ + microServiceInfo.setPublish_port(""); + } + + + + + + } + + //检查同名不同协议注册 + try{ + List<MicroServiceFullInfo> serviceList= getMicroServiceForNodes(microServiceInfo.getServiceName(),microServiceInfo.getVersion(), false,"",microServiceInfo.getNamespace()); + if(serviceList!=null && serviceList.size()>0){ + for(MicroServiceFullInfo service:serviceList){ + if(!service.getProtocol().equalsIgnoreCase(microServiceInfo.getProtocol())){ + throw new UnprocessableEntityException("register MicroServiceInfo FAIL:There is a same service ,but different protocol--" + + service.getProtocol()); + } + + } + } + } + catch(ExtendedNotFoundException e){ +// LOGGER.info("register MicroServiceInfo CHECK ok for protocol:service is not fond"); + } + + + } + + + private void checkServiceNameAndVersion(String serviceName,String version){ + if (StringUtils.isBlank(serviceName)) { + throw new UnprocessableEntityException( + "check MicroServiceInfo FAIL:serviceName can't be empty"); + } + + if (!RegExpTestUtil.serviceNameRegExpTest(serviceName)) { + throw new UnprocessableEntityException("check MicroServiceInfo FAIL:ServiceName(" + + serviceName + ") format error"); + } + + if (StringUtils.isNotBlank(version)) { + if (!RegExpTestUtil.versionRegExpTest(version)) { + throw new UnprocessableEntityException( + "check MicroServiceInfo FAIL:version is not a valid format"); + } + } + } + + + + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/PublishAddressWrapper.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/PublishAddressWrapper.java new file mode 100644 index 0000000..a6e1037 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/PublishAddressWrapper.java @@ -0,0 +1,875 @@ +/** + * 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.sdclient.wrapper; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.apache.commons.lang3.StringUtils; +import org.onap.msb.sdclient.core.KeyVaulePair; +import org.onap.msb.sdclient.core.MicroServiceFullInfo; +import org.onap.msb.sdclient.core.NodeInfo; +import org.onap.msb.sdclient.core.PublishAddress; +import org.onap.msb.sdclient.core.PublishFullAddress; +import org.onap.msb.sdclient.core.exception.ExtendedNotFoundException; +import org.onap.msb.sdclient.core.exception.UnprocessableEntityException; +import org.onap.msb.sdclient.wrapper.util.DiscoverUtil; +import org.onap.msb.sdclient.wrapper.util.RegExpTestUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PublishAddressWrapper { + + private static PublishAddressWrapper instance = new PublishAddressWrapper(); + + + private PublishAddressWrapper() {} + + public static PublishAddressWrapper getInstance() { + return instance; + } + + private final String ROUTE_DEFAULT_WAY = "ip"; + + private final String ROUTE_IP = "ip"; + + private final String ROUTE_DOMAIN = "domain"; + + private final String ROUTE_DEFAULT_SUBDOMAIN = "openpalette.zte.com.cn"; + + private final String METADATA_ROUTE_WAY = "routeWay"; + + private final String METADATA_ROUTE_SUBDOMAIN = "routeSubdomain"; + + + + private static final Logger LOGGER = LoggerFactory.getLogger(PublishAddressWrapper.class); + + public static volatile Map<String, List<MicroServiceFullInfo>> publishApigateWayList = + new HashMap<String, List<MicroServiceFullInfo>>(); + + private ConsulClientApp consulClientApp; + + + ExecutorService exec = Executors.newCachedThreadPool(); + + + public void setConsulClientApp(ConsulClientApp consulClientApp) { + this.consulClientApp = consulClientApp; + } + + + + /** + * @Title getAllPublishaddress + * @Description TODO(get all publishaddresss list by service,rest-interface master methods) + * @param serviceName + * @param version + * @param namespace + * @param visualRange + * @return + * @return List<PublishFullAddress> + */ + public Set<PublishFullAddress> getAllPublishaddress(String serviceName, String version, + String namespace, String visualRange) { + + if ("null".equals(version)) { + version = ""; + } + + + // 1.Check input parameter format efficacy + checkServiceInputFormat(serviceName, version, visualRange); + + + + // 2.get service Info + MicroServiceFullInfo serviceInfo = + ConsulServiceWrapper.getInstance().getMicroServiceInstance(serviceName, version, namespace); + + if (!DiscoverUtil.checkExist(DiscoverUtil.PUBLISH_PROTOCOL, serviceInfo.getProtocol())) { + throw new ExtendedNotFoundException("This service's Protocol (" + serviceInfo.getProtocol() + + ") is not published to apigateway"); + } + + if ("TCP".equals(serviceInfo.getProtocol()) || "UDP".equals(serviceInfo.getProtocol())) { + if (StringUtils.isBlank(serviceInfo.getPublish_port())) { + throw new ExtendedNotFoundException("This service's Protocol (" + + serviceInfo.getProtocol() + ") is not published to apigateway"); + } + } + + Set<PublishFullAddress> publishFullAddressList = new HashSet<PublishFullAddress>(); + + // 3.get in-system apigateway publish address (visualRange=1) + if (DiscoverUtil.checkVisualRangeIn(visualRange)) { + Set<PublishFullAddress> publishFullAddressInList = + getPublishFullAddress(namespace, DiscoverUtil.VISUAL_RANGE_IN, serviceInfo); + if (publishFullAddressInList != null && publishFullAddressInList.size() > 0) { + publishFullAddressList.addAll(publishFullAddressInList); + } + + } + + // 4.get out-system apigateway publish address (visualRange=0) + if (DiscoverUtil.checkVisualRangeOut(visualRange)) { + Set<PublishFullAddress> publishFullAddressOutList = + getPublishFullAddress(namespace, DiscoverUtil.VISUAL_RANGE_OUT, serviceInfo); + if (publishFullAddressOutList != null && publishFullAddressOutList.size() > 0) { + publishFullAddressList.addAll(publishFullAddressOutList); + } + } + + if (publishFullAddressList.size() > 0) { + return publishFullAddressList; + } + + throw new ExtendedNotFoundException("This service's publish Address is not found"); + } + + /** + * @Title getApigatewayServiceInfo + * @Description TODO(get one apigatewayServiceInfo by namespace,rest-interface master methods) + * @param namespace + * @param visualRange + * @return + * @return List<MicroServiceFullInfo> + */ + public Set<MicroServiceFullInfo> getApigatewayServiceInfo(String namespace, String visualRange) { + + if (!DiscoverUtil.checkExist(DiscoverUtil.VISUAL_RANGE_LIST, visualRange, ",")) { + throw new UnprocessableEntityException( + "get ApigatewayServiceInfo FAIL:visualRange is wrong,value range:(" + + DiscoverUtil.VISUAL_RANGE_LIST + ")"); + } + + List<MicroServiceFullInfo> apigatewayList; + + if (DiscoverUtil.checkVisualRangeIn(visualRange)) { + apigatewayList = getApiGateWayFromCache(DiscoverUtil.APIGATEWAY_SERVINCE, namespace); + + } else { + apigatewayList = getApiGateWayFromCache(DiscoverUtil.ROUTER_SERVINCE, namespace); + + if (apigatewayList != null) { + if (StringUtils.isNotBlank(System.getenv("ROUTER_IP"))) { + for (MicroServiceFullInfo routerInfo : apigatewayList) { + for (NodeInfo node : routerInfo.getNodes()) { + node.setIp(System.getenv("ROUTER_IP")); + } + + } + } + } + } + + + if (apigatewayList == null || apigatewayList.isEmpty()) { + throw new ExtendedNotFoundException("This service's publish Address is not found"); + } + else{ + Set<MicroServiceFullInfo> apigatewaySet= new HashSet<MicroServiceFullInfo>(apigatewayList); + return apigatewaySet; + } + + + + } + + + + /** + * @Title convert2PublishFullAddress + * @Description TODO(convert to PublishFullAddress from MicroServiceFullInfo ) + * @param apigatewayInfo + * @param serviceInfo + * @return List<PublishFullAddress> + */ + private List<PublishFullAddress> convert2PublishFullAddress(MicroServiceFullInfo apigatewayInfo, + MicroServiceFullInfo serviceInfo) { + + List<PublishFullAddress> publishFullAddressList = new ArrayList<PublishFullAddress>(); + + + + String routeWay = this.ROUTE_DEFAULT_WAY, routeSubdomain = this.ROUTE_DEFAULT_SUBDOMAIN; + + List<KeyVaulePair> metadata = apigatewayInfo.getMetadata(); + if (metadata != null) { + + for (KeyVaulePair keyVaulePair : metadata) { + if (this.METADATA_ROUTE_WAY.equals(keyVaulePair.getKey())) { + routeWay = keyVaulePair.getValue(); + } + if (this.METADATA_ROUTE_SUBDOMAIN.equals(keyVaulePair.getKey())) { + routeSubdomain = keyVaulePair.getValue(); + } + } + } + + NodeInfo apigatewayNode = (NodeInfo) apigatewayInfo.getNodes().toArray()[0]; + + String[] routeWays = StringUtils.split(routeWay, DiscoverUtil.SPLIT_LINE); + for (int i = 0; i < routeWays.length; i++) { + PublishFullAddress publishFullAddress = new PublishFullAddress(); + // set service publish visualRange + publishFullAddress.setVisualRange(apigatewayInfo.getVisualRange()); + if (this.ROUTE_IP.equals(routeWays[i])) { + // ----routeWay:ip----- + + // set service publish ip + publishFullAddress.setIp(apigatewayNode.getIp()); + if (DiscoverUtil.VISUAL_RANGE_OUT.equals(apigatewayInfo.getVisualRange())) { + if (StringUtils.isNotBlank(System.getenv("ROUTER_IP"))) { + publishFullAddress.setIp(System.getenv("ROUTER_IP")); + } + } + + + + // set service publish url + publishFullAddress.setPublish_url(getPublishUrl4IP(serviceInfo)); + + // set service port + if (DiscoverUtil.VISUAL_RANGE_IN.equals(apigatewayInfo.getVisualRange())) { + publishFullAddress.setPort(apigatewayNode.getPort()); + publishFullAddress.setPublish_protocol("http"); + publishFullAddressList.add(publishFullAddress); + } + else{ + + String[] publishPorts = + StringUtils.split(serviceInfo.getPublish_port(), DiscoverUtil.SPLIT_LINE); + if (publishPorts.length == 2) { + // multiPublishPort: https|http + publishFullAddress.setPort(publishPorts[0]); + publishFullAddress.setPublish_protocol("https"); + publishFullAddressList.add(publishFullAddress); + + + PublishFullAddress publishFullAddress2 = + new PublishFullAddress(publishFullAddress.getIp(), publishPorts[1], + publishFullAddress.getPublish_url(), publishFullAddress.getVisualRange(), "http"); + publishFullAddressList.add(publishFullAddress2); + + } else { + // single Port + + if (StringUtils.isNotBlank(serviceInfo.getPublish_port())) { + publishFullAddress.setPort(serviceInfo.getPublish_port()); + publishFullAddress.setPublish_protocol("https"); + } else { + publishFullAddress.setPort(apigatewayNode.getPort()); + publishFullAddress.setPublish_protocol("http"); + } + + if ("TCP".equals(serviceInfo.getProtocol()) || "UDP".equals(serviceInfo.getProtocol())) { + publishFullAddress.setPublish_protocol(serviceInfo.getProtocol()); + } + + publishFullAddressList.add(publishFullAddress); + + } + } + + + } else if (this.ROUTE_DOMAIN.equals(routeWays[i])) { + // ----routeWay:domain----- + + // set service domain + String host = getHost4Domain(serviceInfo); + publishFullAddress.setDomain(host + "." + routeSubdomain); + + + if ("TCP".equals(serviceInfo.getProtocol()) || "UDP".equals(serviceInfo.getProtocol())) { + publishFullAddress.setPort(serviceInfo.getPublish_port()); + publishFullAddress.setPublish_protocol(serviceInfo.getProtocol()); + } else { + publishFullAddress.setPublish_protocol("http"); + publishFullAddress.setPort(apigatewayNode.getPort()); + } + + // set service publish url + publishFullAddress.setPublish_url(getPublishUrl4Domain(serviceInfo)); + + + publishFullAddressList.add(publishFullAddress); + } + + + + } + + return publishFullAddressList; + } + + + /** + * @Title getPublishFullAddress + * @Description TODO(get PublishFullAddress List for namespace and visualRange) + * @param namespace + * @param visualRange + * @param serviceInfo + * @return List<PublishFullAddress> + */ + private Set<PublishFullAddress> getPublishFullAddress(String namespace, String visualRange, + MicroServiceFullInfo serviceInfo) { + + if (DiscoverUtil.checkVisualRangeIn(visualRange)) { + if (!DiscoverUtil.checkVisualRangeIn(serviceInfo.getVisualRange())) { + return null; + } + } else { + if (!DiscoverUtil.checkVisualRangeOut(serviceInfo.getVisualRange())) { + return null; + } + } + + + Set<PublishFullAddress> publishFullAddressList = new HashSet<PublishFullAddress>(); + List<MicroServiceFullInfo> apigatewayList = getApigatewayInfo4Service(namespace, visualRange); + if (apigatewayList != null && !apigatewayList.isEmpty()) { + for (MicroServiceFullInfo apigatewayInfo : apigatewayList) { + if (isPublish2apigateway(apigatewayInfo, serviceInfo)) { + publishFullAddressList.addAll(convert2PublishFullAddress(apigatewayInfo, serviceInfo)); + } + } + } + return publishFullAddressList; + } + + + + private String getHost4Domain(MicroServiceFullInfo serviceInfo) { + String host = ""; + if (StringUtils.isNotBlank(serviceInfo.getHost())) { + host = serviceInfo.getHost(); + } else { + if (StringUtils.isNotBlank(serviceInfo.getNamespace())) { + host = + serviceInfo.getServiceName() + DiscoverUtil.SERVICENAME_LINE_NAMESPACE + + serviceInfo.getNamespace(); + } else { + host = serviceInfo.getServiceName(); + } + } + + return host; + } + + private String getPublishPort(MicroServiceFullInfo apigatewayInfo, + MicroServiceFullInfo serviceInfo) { + + NodeInfo node = (NodeInfo) apigatewayInfo.getNodes().toArray()[0]; + String port = ""; + + if ("TCP".equals(serviceInfo.getProtocol()) || "UDP".equals(serviceInfo.getProtocol())) { + return serviceInfo.getPublish_port(); + } + + if (DiscoverUtil.VISUAL_RANGE_IN.equals(apigatewayInfo.getVisualRange())) { + port = node.getPort(); + } else { + if (StringUtils.isNotBlank(serviceInfo.getPublish_port())) { + port = serviceInfo.getPublish_port(); + } else { + port = node.getPort(); + } + } + + return port; + + } + + + + private String getPublishUrl4Domain(MicroServiceFullInfo serviceInfo) { + String publish_url = "/"; + if (StringUtils.isNotBlank(serviceInfo.getPath()) && !"/".equals(serviceInfo.getPath())) { + publish_url = serviceInfo.getPath(); + } else { + publish_url = serviceInfo.getUrl(); + } + return publish_url; + } + + private String getPublishUrl4IP(MicroServiceFullInfo serviceInfo) { + + String publish_url = "/"; + if (StringUtils.isNotBlank(serviceInfo.getPath()) && !"/".equals(serviceInfo.getPath())) { + publish_url = serviceInfo.getPath(); + } else { + String versionUrl = ""; + String serviceNameUrl = serviceInfo.getServiceName(); + + if (StringUtils.isNotBlank(serviceInfo.getVersion())) { + versionUrl = "/" + serviceInfo.getVersion(); + } + switch (serviceInfo.getProtocol()) { + case "REST": + publish_url = "/api/" + serviceNameUrl + versionUrl; + break; + case "UI": + publish_url = "/iui/" + serviceNameUrl; + break; + case "HTTP": + publish_url = "/" + serviceNameUrl + versionUrl; + break; + case "PORTAL": + publish_url = "/" + serviceNameUrl + versionUrl; + break; + case "TCP": + publish_url = serviceInfo.getUrl(); + break; + case "UDP": + publish_url = serviceInfo.getUrl(); + break; + } + } + + return publish_url; + } + + + private void checkServiceInputFormat(String serviceName, String version, String visualRange) { + if (StringUtils.isBlank(serviceName)) { + throw new UnprocessableEntityException("serviceName can't be empty"); + } + + if (!RegExpTestUtil.serviceNameRegExpTest(serviceName)) { + throw new UnprocessableEntityException("get MicroServiceInfo FAIL:ServiceName(" + + serviceName + ") format error"); + } + + if (StringUtils.isNotBlank(version)) { + if (!RegExpTestUtil.versionRegExpTest(version)) { + throw new UnprocessableEntityException("version (" + version + ") is not a valid format"); + } + } + + if (!DiscoverUtil.checkVisualRangeIn(visualRange) + && !DiscoverUtil.checkVisualRangeOut(visualRange)) { + throw new UnprocessableEntityException( + "get ApigatewayServiceInfo FAIL:visualRange is wrong,value range:(" + + DiscoverUtil.VISUAL_RANGE_LIST + ")"); + } + } + + + /** + * @Title getApigatewayInfo4Service + * @Description TODO(get apigatewayServiceInfo List by namespaces[all & service-namespace]) + * @param namespace + * @param visualRange + * @return + * @return List<MicroServiceFullInfo> + */ + private List<MicroServiceFullInfo> getApigatewayInfo4Service(String namespace, String visualRange) { + + String apigatewayName; + if (DiscoverUtil.checkVisualRangeIn(visualRange)) { + apigatewayName = DiscoverUtil.APIGATEWAY_SERVINCE; + } else { + apigatewayName = DiscoverUtil.ROUTER_SERVINCE; + } + + + String apigateway_ns; + if (StringUtils.isBlank(namespace)) { + apigateway_ns = DiscoverUtil.APIGATEWAY_SERVINCE_DEFAULT; + } else { + apigateway_ns = namespace; + } + + String[] apigateway_ns_array = {DiscoverUtil.APIGATEWAY_SERVINCE_ALL, apigateway_ns}; + List<MicroServiceFullInfo> apigatewayList4Service = new ArrayList<MicroServiceFullInfo>(); + for (int i = 0; i < apigateway_ns_array.length; i++) { + List<MicroServiceFullInfo> apigatewayList = + getApiGateWayFromCache(apigatewayName, apigateway_ns_array[i]); + if (apigatewayList != null) { + apigatewayList4Service.addAll(apigatewayList); + } + } + + return apigatewayList4Service; + + } + + + private boolean isPublish2apigateway(MicroServiceFullInfo apigatewayInfo, + MicroServiceFullInfo serviceInfo) { + return isPublishByNetwork_plane_typeMatches(apigatewayInfo.getNetwork_plane_type(), + serviceInfo.getNetwork_plane_type()) + && isPublishByRouteLabels(apigatewayInfo.getLabels(), serviceInfo.getLabels()); + } + + /** + * Determine whether the service needs to publish to apigateway TODO: according to the + * service_network_plane filter conditions + * + * @param String + * @return + */ + + private boolean isPublishByNetwork_plane_typeMatches(String apigateway_network_plane, + String service_network_plane) { + + if (StringUtils.isBlank(apigateway_network_plane)) + return true; + String[] routeNetwork_plane_typeArray = StringUtils.split(apigateway_network_plane, "|"); + String[] serviceVisualRangeArray = StringUtils.split(service_network_plane, "|"); + if (DiscoverUtil.contain(serviceVisualRangeArray, routeNetwork_plane_typeArray)) { + return true; + } + + return false; + } + + + /** + * Determine whether the service needs to publish to apigateway TODO: according to the labels + * filter conditions + * + * @param labelMap + * @return + */ + private boolean isPublishByRouteLabels(List<String> apigatewayLabels, List<String> serviceLabels) { + if (apigatewayLabels == null || apigatewayLabels.isEmpty()) { + return true; + } + + Map<String, String> apigateway_labelMap = new HashMap<String, String>(); + Map<String, String> service_labelMap = new HashMap<String, String>(); + for (String label : apigatewayLabels) { + String[] labelArray = label.split(":"); + apigateway_labelMap.put(labelArray[0], labelArray[1]); + } + + for (String label : serviceLabels) { + String[] labelArray = label.split(":"); + service_labelMap.put(labelArray[0], labelArray[1]); + } + + for (Map.Entry<String, String> entry : apigateway_labelMap.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue(); + + // Multiple values match + String[] routeLalelsArray = StringUtils.split(value, "|"); + if (StringUtils.isBlank(service_labelMap.get(key))) { + continue; + } + + String[] serviceLabelsArray = StringUtils.split(service_labelMap.get(key), "|"); + + if (DiscoverUtil.contain(routeLalelsArray, serviceLabelsArray)) { + return true; + } + + } + + return false; + } + + + + private List<MicroServiceFullInfo> getApiGateWayFromCache(String apigatewayName, + String apigatewayNamespace) { + String apigatewayConsulName = + apigatewayName + DiscoverUtil.SERVICENAME_LINE_NAMESPACE + apigatewayNamespace; + if (publishApigateWayList.get(apigatewayConsulName) == null) { + + try { + List<MicroServiceFullInfo> apigatewayList = + ConsulServiceWrapper.getInstance().getMicroServiceForNodes(apigatewayName, "v1", true, + "", apigatewayNamespace); + if (!apigatewayList.isEmpty()) { + consulClientApp.startHealthNodeListen(apigatewayConsulName); + return apigatewayList; + } + } catch (ExtendedNotFoundException e) { + LOGGER.warn("ApiGateWay Info not found:[serviceName]" + apigatewayName + ",[namespace]" + + apigatewayNamespace); + } + + } else { + return publishApigateWayList.get(apigatewayConsulName); + } + + return null; + } + + + public PublishAddress getPublishaddress(String serviceName, String version, String namespace, + int wait) { + if ("null".equals(version)) { + version = ""; + } + + // 1.Check input parameter format efficacy + checkServiceInputFormat(serviceName, version, DiscoverUtil.VISUAL_RANGE_IN); + + + MicroServiceFullInfo microServiceFullInfo = + ConsulServiceWrapper.getInstance().getMicroServiceInstance(serviceName, version, namespace); + + if (!DiscoverUtil.checkVisualRangeIn(microServiceFullInfo.getVisualRange())) { + throw new ExtendedNotFoundException("This service is not published internally"); + } + + if (!DiscoverUtil.checkExist(DiscoverUtil.PUBLISH_PROTOCOL, microServiceFullInfo.getProtocol())) { + throw new ExtendedNotFoundException("This service's Protocol (" + + microServiceFullInfo.getProtocol() + ") is not published to apigateway"); + } + + List<PublishAddress> publishaddress_all = new ArrayList<PublishAddress>(); + List<PublishAddress> publishaddress_ns = new ArrayList<PublishAddress>(); + + List<MicroServiceFullInfo> apigatewayList_in_all = + getApiGateWayFromCache(DiscoverUtil.APIGATEWAY_SERVINCE, "all"); + if (apigatewayList_in_all != null && !apigatewayList_in_all.isEmpty()) { + for (MicroServiceFullInfo apigateway : apigatewayList_in_all) { + if (isPublish2apigateway(apigateway, microServiceFullInfo)) { + publishaddress_all.add(convert2PublishAddress(apigateway, microServiceFullInfo)); + } + } + } + + + + String apigateway_ns; + if (StringUtils.isBlank(namespace)) { + apigateway_ns = DiscoverUtil.APIGATEWAY_SERVINCE_DEFAULT; + } else { + apigateway_ns = namespace; + } + + List<MicroServiceFullInfo> apigatewayList_in_ns = + getApiGateWayFromCache(DiscoverUtil.APIGATEWAY_SERVINCE, apigateway_ns); + if (apigatewayList_in_ns != null && !apigatewayList_in_ns.isEmpty()) { + for (MicroServiceFullInfo apigateway : apigatewayList_in_ns) { + if (isPublish2apigateway(apigateway, microServiceFullInfo)) { + publishaddress_ns.add(convert2PublishAddress(apigateway, microServiceFullInfo)); + } + } + } + + + + // 即时返回 + if (wait < 5) { + if (publishaddress_ns.size() > 0) { + return publishaddress_ns.get(0); + } else if (publishaddress_all.size() > 0) { + return publishaddress_all.get(0); + } + + + throw new ExtendedNotFoundException("This service's publish address is not found"); + } + + if (wait > 300) { + wait = 300; + } + + + // get service publish url + String publish_url = "/"; + if (StringUtils.isNotBlank(microServiceFullInfo.getPath())) { + publish_url = microServiceFullInfo.getPath(); + } else { + String versionUrl = ""; + String serviceNameUrl = microServiceFullInfo.getServiceName(); + + + if (StringUtils.isNotBlank(microServiceFullInfo.getVersion())) { + versionUrl = "/" + microServiceFullInfo.getVersion(); + } + switch (microServiceFullInfo.getProtocol()) { + case "REST": + publish_url = "/api/" + serviceNameUrl + versionUrl; + break; + case "UI": + publish_url = "/iui/" + serviceNameUrl; + break; + case "HTTP": + publish_url = "/" + serviceNameUrl + versionUrl; + break; + case "TCP": + publish_url = microServiceFullInfo.getUrl(); + break; + case "UDP": + publish_url = microServiceFullInfo.getUrl(); + break; + } + } + + // 延迟监听返回 + Future<PublishAddress> f = exec.submit(new TimeTask(namespace, publish_url)); + try { + return f.get(wait, TimeUnit.SECONDS); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + LOGGER.error(e.getMessage()); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + LOGGER.error(e.getMessage()); + } catch (TimeoutException e) { + // 定义超时后的状态修改 + // LOGGER.error(e.getMessage()); + LOGGER.error(e.getMessage()); + } finally { + + f.cancel(true); + } + + if (publishaddress_ns.size() > 0) { + return publishaddress_ns.get(0); + } else if (publishaddress_all.size() > 0) { + return publishaddress_all.get(0); + } + + throw new ExtendedNotFoundException("This service's apigatewayInfo is not found"); + + } + + + private PublishAddress convert2PublishAddress(MicroServiceFullInfo apigatewayInfo, + MicroServiceFullInfo serviceInfo) { + PublishAddress publishAddress = new PublishAddress(); + + NodeInfo node = (NodeInfo) apigatewayInfo.getNodes().toArray()[0]; + publishAddress.setIp(node.getIp()); + + if (DiscoverUtil.VISUAL_RANGE_IN.equals(apigatewayInfo.getVisualRange())) { + publishAddress.setPort(node.getPort()); + } else { + if (StringUtils.isNotBlank(serviceInfo.getPublish_port())) { + publishAddress.setPort(serviceInfo.getPublish_port()); + } else { + publishAddress.setPort(node.getPort()); + } + } + + + // get service publish url + String publish_url = "/"; + if (StringUtils.isNotBlank(serviceInfo.getPath())) { + publish_url = serviceInfo.getPath(); + } else { + String versionUrl = ""; + String serviceNameUrl = serviceInfo.getServiceName(); + + + if (StringUtils.isNotBlank(serviceInfo.getVersion())) { + versionUrl = "/" + serviceInfo.getVersion(); + } + switch (serviceInfo.getProtocol()) { + case "REST": + publish_url = "/api/" + serviceNameUrl + versionUrl; + break; + case "UI": + publish_url = "/iui/" + serviceNameUrl; + break; + case "HTTP": + publish_url = "/" + serviceNameUrl + versionUrl; + break; + case "TCP": + publish_url = serviceInfo.getUrl(); + break; + case "UDP": + publish_url = serviceInfo.getUrl(); + break; + } + } + + publishAddress.setPublish_url(publish_url); + + + return publishAddress; + } + + + + public class TimeTask implements Callable<PublishAddress> { + + private String namespace; + private String publish_url; + + @Override + public PublishAddress call() throws Exception { + + + while (true) { + List<PublishAddress> oldAddress = getApigatewayListFromCache(namespace, publish_url); + + + Thread.sleep(2000); + // LOGGER.info("oldAddress:"+oldAddress); + List<PublishAddress> newAddress = getApigatewayListFromCache(namespace, publish_url); + if (!oldAddress.equals(newAddress)) { + // LOGGER.info("CHANGED:"+oldAddress+"-"+apigatewayAddress); + + return newAddress.get(0); + } + } + + } + + TimeTask(String namespace, String publish_url) { + this.namespace = namespace; + this.publish_url = publish_url; + } + + } + + private List<PublishAddress> getApigatewayListFromCache(String namespace, String publish_url) { + List<PublishAddress> fullAddress = new ArrayList<PublishAddress>(); + String apigatewayName4ns = + DiscoverUtil.APIGATEWAY_SERVINCE + DiscoverUtil.SERVICENAME_LINE_NAMESPACE + namespace; + if (publishApigateWayList.get(apigatewayName4ns) != null) { + List<MicroServiceFullInfo> publishaddress4ns = publishApigateWayList.get(apigatewayName4ns); + for (MicroServiceFullInfo address : publishaddress4ns) { + NodeInfo node = (NodeInfo) address.getNodes().toArray()[0]; + fullAddress.add(new PublishAddress(node.getIp(), node.getPort(), publish_url)); + } + + } else { + if (publishApigateWayList.get(DiscoverUtil.APIGATEWAY_SERVINCE_ALL) != null) { + List<MicroServiceFullInfo> publishaddress4all = + publishApigateWayList.get(DiscoverUtil.APIGATEWAY_SERVINCE_ALL); + for (MicroServiceFullInfo address : publishaddress4all) { + NodeInfo node = (NodeInfo) address.getNodes().toArray()[0]; + fullAddress.add(new PublishAddress(node.getIp(), node.getPort(), publish_url)); + } + } + } + + return fullAddress; + } + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/Consul.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/Consul.java new file mode 100644 index 0000000..db12cb6 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/Consul.java @@ -0,0 +1,281 @@ +/** + * 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.sdclient.wrapper.consul; + +import java.net.MalformedURLException; +import java.net.URL; + +import javax.net.ssl.SSLContext; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; + +import org.onap.msb.sdclient.wrapper.consul.util.Jackson; +import org.onap.msb.sdclient.wrapper.consul.util.ObjectMapperContextResolver; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.guava.GuavaModule; +import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import com.google.common.net.HostAndPort; + +/** + * Client for interacting with the Consul HTTP API. + * + * @author rfast + */ +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 final HealthClient healthClient; + + + /** + * Private constructor. + * + * @param url The full URL of a running Consul instance. + * @param builder JAX-RS client builder instance. + */ + private Consul(String url, ClientBuilder builder, ObjectMapper mapper) { + + if (!FluentIterable.from(builder.getConfiguration().getClasses()) + .filter(new Predicate<Class<?>>() { + @Override + public boolean apply(final Class<?> clazz) { + return JacksonJaxbJsonProvider.class.isAssignableFrom(clazz); + } + }).first().isPresent()) { + builder.register(JacksonJaxbJsonProvider.class); + } + final Client client = builder + .register(new ObjectMapperContextResolver(mapper)) + .build(); + + + this.healthClient = new HealthClient(client.target(url).path("v1").path("health")); + + + +// agentClient.ping(); + } + + /** + * Creates a new client given a complete URL. + * + * @deprecated Use {@link Consul.Builder} + * + * @param url The Consul API URL. + * @param builder The JAX-RS client builder instance. + * @return A new client. + */ + @Deprecated + public static Consul newClient(String url, ClientBuilder builder, ObjectMapper mapper) { + return new Consul(url, builder, mapper); + } + + /** + * Creates a new client given a host and a port. + * + * @deprecated Use {@link Consul.Builder} + * + * @param host The Consul API hostname or IP. + * @param port The Consul port. + * @param builder The JAX-RS client builder instance. + * @return A new client. + */ + @Deprecated + public static Consul newClient(String host, int port, ClientBuilder builder, ObjectMapper mapper) { + try { + return new Consul(new URL("http", host, port, "").toString(), builder, mapper); + } catch (MalformedURLException e) { + throw new ConsulException("Bad Consul URL", e); + } + } + + /** + * Creates a new client given a host and a port. + * + * @deprecated Use {@link Consul.Builder} + * + * @param host The Consul API hostname or IP. + * @param port The Consul port. + * @return A new client. + */ + @Deprecated + public static Consul newClient(String host, int port) { + return newClient(host, port, ClientBuilder.newBuilder(), Jackson.MAPPER); + } + + /** + * Creates a new client given a host and a port. + * + * @deprecated Use {@link Consul.Builder} + * + * @return A new client. + */ + @Deprecated + public static Consul newClient() { + return newClient(DEFAULT_HTTP_HOST, DEFAULT_HTTP_PORT); + } + + + + public HealthClient healthClient() { + return healthClient; + } + /** + * Creates a new {@link Builder} object. + * + * @return A new Consul builder. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builder for {@link Consul} client objects. + */ + public static class Builder { + private URL url; + private Optional<SSLContext> sslContext = Optional.absent(); + private ObjectMapper objectMapper = Jackson.MAPPER; + private ClientBuilder clientBuilder = ClientBuilder.newBuilder(); + + { + try { + url = new URL("http", "localhost", 8500, ""); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + + /** + * Constructs a new builder. + */ + Builder() { + + } + + /** + * Sets the URL from a {@link URL} object. + * + * @param url The Consul agent URL. + * @return The builder. + */ + public Builder withUrl(URL url) { + this.url = url; + + return this; + } + + /** + * Sets the URL from a {@link HostAndPort} object. + * + * @param hostAndPort The Consul agent host and port. + * @return The builder. + */ + public Builder withHostAndPort(HostAndPort hostAndPort) { + try { + this.url = new URL("http", hostAndPort.getHostText(), hostAndPort.getPort(), ""); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + + return this; + } + + /** + * Sets the URL from a string. + * + * @param url The Consul agent URL. + * @return The builder. + */ + public Builder withUrl(String url) { + try { + this.url = new URL(url); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + + return this; + } + + /** + * Sets the {@link SSLContext} for the client. + * + * @param sslContext The SSL context for HTTPS agents. + * @return The builder. + */ + public Builder withSslContext(SSLContext sslContext) { + this.sslContext = Optional.of(sslContext); + + return this; + } + + /** + * Sets the {@link ObjectMapper} for the client. + * + * @param objectMapper The {@link ObjectMapper} to use. + * @return The builder. + */ + public Builder withObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + + objectMapper.registerModule(new GuavaModule()); + + return this; + } + + /** + * Sets the JAX-RS {@link ClientBuilder} to use. + * + * @param clientBuilder The JAX-RS builder. + * @return This builder. + */ + public Builder withClientBuilder(ClientBuilder clientBuilder) { + this.clientBuilder = clientBuilder; + + return this; + } + + /** + * Constructs a new {@link Consul} client. + * + * @return A new Consul client. + */ + public Consul build() { + if (this.sslContext.isPresent()) { + this.clientBuilder.sslContext(this.sslContext.get()); + } + + return new Consul(this.url.toExternalForm(), this.clientBuilder, this.objectMapper); + } + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/ConsulException.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/ConsulException.java new file mode 100644 index 0000000..b76aa38 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/ConsulException.java @@ -0,0 +1,41 @@ +/** + * 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.sdclient.wrapper.consul; + +/** + * Wraps an exception thrown whilst interacting with the Consul API. + */ +public class ConsulException extends RuntimeException { + + /** + * Constructs an instance of this class. + * + * @param message The exception message. + */ + public ConsulException(String message) { + super(message); + } + + /** + * Constructs an instance of this class. + * + * @param message The exception message. + * @param throwable The wrapped {@link java.lang.Throwable} object. + */ + public ConsulException(String message, Throwable throwable) { + super(message, throwable); + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/HealthClient.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/HealthClient.java new file mode 100644 index 0000000..61f7cbd --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/HealthClient.java @@ -0,0 +1,246 @@ +/** + * 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.sdclient.wrapper.consul; + +import static org.onap.msb.sdclient.wrapper.consul.util.ClientUtil.response; + +import java.util.List; + +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.GenericType; + +import org.onap.msb.sdclient.wrapper.consul.async.ConsulResponseCallback; +import org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse; +import org.onap.msb.sdclient.wrapper.consul.model.health.ServiceHealth; +import org.onap.msb.sdclient.wrapper.consul.option.CatalogOptions; +import org.onap.msb.sdclient.wrapper.consul.option.QueryOptions; + +/** + * HTTP Client for /v1/health/ endpoints. + */ +public class HealthClient { + + + private static final GenericType<List<ServiceHealth>> TYPE_SERVICE_HEALTH_LIST = + new GenericType<List<ServiceHealth>>() {}; + + private final WebTarget webTarget; + + /** + * Constructs an instance of this class. + * + * @param webTarget The {@link javax.ws.rs.client.WebTarget} to base requests from. + */ + HealthClient(WebTarget webTarget) { + this.webTarget = webTarget; + } + + + + /** + * Retrieves the healthchecks for all healthy service instances. + * + * GET /v1/health/service/{service}?passing + * + * @param service The service to query. + * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of + * {@link com.orbitz.consul.model.health.HealthCheck} objects. + */ + public ConsulResponse<List<ServiceHealth>> getHealthyServiceInstances(String service) { + return getHealthyServiceInstances(service, null, QueryOptions.BLANK); + } + + /** + * Retrieves the healthchecks for all healthy service instances in a given datacenter. + * + * GET /v1/health/service/{service}?dc={datacenter}&passing + * + * @param service The service to query. + * @param catalogOptions The catalog specific options to use. + * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of + * {@link com.orbitz.consul.model.health.HealthCheck} objects. + */ + public ConsulResponse<List<ServiceHealth>> getHealthyServiceInstances(String service, CatalogOptions catalogOptions) { + return getHealthyServiceInstances(service, catalogOptions, QueryOptions.BLANK); + } + + /** + * Retrieves the healthchecks for all healthy service instances with {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}. + * + * GET /v1/health/service/{service}?passing + * + * @param service The service to query. + * @param queryOptions The Query Options to use. + * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of + * {@link com.orbitz.consul.model.health.HealthCheck} objects. + */ + public ConsulResponse<List<ServiceHealth>> getHealthyServiceInstances(String service, QueryOptions queryOptions) { + return getHealthyServiceInstances(service, null, queryOptions); + } + + /** + * Retrieves the healthchecks for all healthy service instances in a given datacenter with + * {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}. + * + * GET /v1/health/service/{service}?dc={datacenter}&passing + * + * @param service The service to query. + * @param catalogOptions The catalog specific options to use. + * @param queryOptions The Query Options to use. + * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of + * {@link com.orbitz.consul.model.health.HealthCheck} objects. + */ + public ConsulResponse<List<ServiceHealth>> getHealthyServiceInstances(String service, CatalogOptions catalogOptions, + QueryOptions queryOptions) { + return response(webTarget.path("service").path(service).queryParam("passing", "true"), + catalogOptions, queryOptions, TYPE_SERVICE_HEALTH_LIST); + } + + /** + * Asynchronously retrieves the healthchecks for all healthy service instances in a given + * datacenter with {@link org.onap.msb.sdclient.wrapper.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) { + response(webTarget.path("service").path(service).queryParam("passing", "true"), + catalogOptions, queryOptions, TYPE_SERVICE_HEALTH_LIST, callback); + } + + /** + * Asynchronously retrieves the healthchecks for all healthy service instances in a given + * datacenter with {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}. + * + * GET /v1/health/service/{service}?dc={datacenter}&passing + * + * Experimental. + * + * @param service The service to query. + * @param queryOptions The Query Options to use. + * @param callback Callback implemented by callee to handle results. + */ + public void getHealthyServiceInstances(String service, QueryOptions queryOptions, + ConsulResponseCallback<List<ServiceHealth>> callback) { + response(webTarget.path("service").path(service).queryParam("passing", "true"), + CatalogOptions.BLANK, queryOptions, TYPE_SERVICE_HEALTH_LIST, callback); + } + + /** + * Retrieves the healthchecks for all nodes. + * + * GET /v1/health/service/{service} + * + * @param service The service to query. + * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of + * {@link com.orbitz.consul.model.health.HealthCheck} objects. + */ + public ConsulResponse<List<ServiceHealth>> getAllServiceInstances(String service) { + return getAllServiceInstances(service, null, QueryOptions.BLANK); + } + + /** + * Retrieves the healthchecks for all nodes in a given datacenter. + * + * GET /v1/health/service/{service}?dc={datacenter} + * + * @param service The service to query. + * @param catalogOptions The catalog specific options to use. + * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of + * {@link com.orbitz.consul.model.health.HealthCheck} objects. + */ + public ConsulResponse<List<ServiceHealth>> getAllServiceInstances(String service, CatalogOptions catalogOptions) { + return getAllServiceInstances(service, catalogOptions, QueryOptions.BLANK); + } + + /** + * Retrieves the healthchecks for all nodes with {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}. + * + * GET /v1/health/service/{service} + * + * @param service The service to query. + * @param queryOptions The Query Options to use. + * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of + * {@link com.orbitz.consul.model.health.HealthCheck} objects. + */ + public ConsulResponse<List<ServiceHealth>> getAllServiceInstances(String service, QueryOptions queryOptions) { + return getAllServiceInstances(service, null, queryOptions); + } + + /** + * Retrieves the healthchecks for all nodes in a given datacenter with + * {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}. + * + * GET /v1/health/service/{service}?dc={datacenter} + * + * @param service The service to query. + * @param catalogOptions The catalog specific options to use. + * @param queryOptions The Query Options to use. + * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing a list of + * {@link com.orbitz.consul.model.health.HealthCheck} objects. + */ + public ConsulResponse<List<ServiceHealth>> getAllServiceInstances(String service, CatalogOptions catalogOptions, + QueryOptions queryOptions) { + return response(webTarget.path("service").path(service), catalogOptions, queryOptions, + TYPE_SERVICE_HEALTH_LIST); + } + + /** + * Asynchronously retrieves the healthchecks for all nodes in a given + * datacenter with {@link org.onap.msb.sdclient.wrapper.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) { + response(webTarget.path("service").path(service), catalogOptions, queryOptions, + TYPE_SERVICE_HEALTH_LIST, callback); + } + + /** + * Asynchronously retrieves the healthchecks for all nodes in a given + * datacenter with {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}. + * + * GET /v1/health/service/{service}?dc={datacenter} + * + * Experimental. + * + * @param service The service to query. + * @param queryOptions The Query Options to use. + * @param callback Callback implemented by callee to handle results. + */ + public void getAllServiceInstances(String service, QueryOptions queryOptions, + ConsulResponseCallback<List<ServiceHealth>> callback) { + response(webTarget.path("service").path(service), CatalogOptions.BLANK, + queryOptions, TYPE_SERVICE_HEALTH_LIST, callback); + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/async/ConsulResponseCallback.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/async/ConsulResponseCallback.java new file mode 100644 index 0000000..33fcb48 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/async/ConsulResponseCallback.java @@ -0,0 +1,41 @@ +/** + * 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.sdclient.wrapper.consul.async; + +import org.onap.msb.sdclient.wrapper.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 org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse}. + * + * @param consulResponse The Consul response. + */ + void onComplete(ConsulResponse<T> consulResponse); + + /** + * Callback for an unsuccessful request. + * + * @param throwable The exception thrown. + */ + void onFailure(Throwable throwable); +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/ConsulCache.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/ConsulCache.java new file mode 100644 index 0000000..60e4a0a --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/ConsulCache.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.sdclient.wrapper.consul.cache; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; + +import org.onap.msb.sdclient.wrapper.consul.async.ConsulResponseCallback; +import org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse; +import org.onap.msb.sdclient.wrapper.consul.option.QueryOptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigInteger; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +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 static com.google.common.base.Preconditions.checkState; + +/** + * A cache structure that can provide an up-to-date read-only + * map backed by consul data + * + * @param <V> + */ +public class ConsulCache<K, V> { + + enum State {latent, starting, started, stopped } + + private final static Logger LOGGER = LoggerFactory.getLogger(ConsulCache.class); + + private final AtomicReference<BigInteger> latestIndex = new AtomicReference<BigInteger>(null); + private final AtomicReference<ImmutableMap<K, V>> lastResponse = new AtomicReference<ImmutableMap<K, V>>(ImmutableMap.<K, V>of()); + 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<K, V>> listeners = new CopyOnWriteArrayList<Listener<K, V>>(); + + private final Function<V, K> keyConversion; + private final CallbackConsumer<V> callBackConsumer; + private final ConsulResponseCallback<List<V>> responseCallback; + + ConsulCache( + Function<V, K> keyConversion, + CallbackConsumer<V> callbackConsumer) { + this(keyConversion, callbackConsumer, 10, TimeUnit.SECONDS); + } + + ConsulCache( + Function<V, K> keyConversion, + CallbackConsumer<V> callbackConsumer, + final long backoffDelayQty, + final TimeUnit backoffDelayUnit) { + + this.keyConversion = keyConversion; + this.callBackConsumer = callbackConsumer; + + this.responseCallback = new ConsulResponseCallback<List<V>>() { + @Override + public void onComplete(ConsulResponse<List<V>> consulResponse) { + + if (!isRunning()) { + return; + } + updateIndex(consulResponse); + ImmutableMap<K, V> full = convertToMap(consulResponse); + + boolean changed = !full.equals(lastResponse.get()); +// LOGGER.info("node changed:"+changed+"----"+full); + if (changed) { + // changes + lastResponse.set(full); + } + + if (changed) { + for (Listener<K, V> l : listeners) { + l.notify(full); + } + } + + if (state.compareAndSet(State.starting, State.started)) { + initLatch.countDown(); + } + runCallback(); + } + + @Override + public void onFailure(Throwable throwable) { + + if (!isRunning()) { + return; + } + LOGGER.error(String.format("Error getting response from consul. will retry in %d %s", backoffDelayQty, backoffDelayUnit), throwable); + + executorService.schedule(new Runnable() { + @Override + public void run() { + runCallback(); + } + }, backoffDelayQty, backoffDelayUnit); + } + }; + } + + 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); + } + + public ImmutableMap<K, V> getMap() { + return lastResponse.get(); + } + + @VisibleForTesting + ImmutableMap<K, V> convertToMap(final ConsulResponse<List<V>> response) { + if (response == null || response.getResponse() == null || response.getResponse().isEmpty()) { + return ImmutableMap.of(); + } + + final ImmutableMap.Builder<K, V> builder = ImmutableMap.builder(); + final Set<K> keySet = new HashSet<>(); + for (final V v : response.getResponse()) { + final K key = keyConversion.apply(v); + if (key != null) { + if (!keySet.contains(key)) { + builder.put(key, v); + } else { + System.out.println(key.toString()); + LOGGER.warn("Duplicate service encountered. May differ by tags. Try using more specific tags? " + key.toString()); + } + } + keySet.add(key); + } + return builder.build(); + } + + private void updateIndex(ConsulResponse<List<V>> consulResponse) { + if (consulResponse != null && consulResponse.getIndex() != null) { + this.latestIndex.set(consulResponse.getIndex()); + } + } + + protected static QueryOptions watchParams(BigInteger index, 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<V> { + void consume(BigInteger index, ConsulResponseCallback<List<V>> callback); + } + + /** + * Implementers can register a listener to receive + * a new map when it changes + * + * @param <V> + */ + public interface Listener<K, V> { + void notify(Map<K, V> newValues); + } + + public boolean addListener(Listener<K, V> listener) { + boolean added = listeners.add(listener); + if (state.get() == State.started) { + listener.notify(lastResponse.get()); + } + return added; + } + + public boolean removeListener(Listener<K, V> listener) { + return listeners.remove(listener); + } + + @VisibleForTesting + protected State getState() { + return state.get(); + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/HealthCache.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/HealthCache.java new file mode 100644 index 0000000..3a60cee --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/cache/HealthCache.java @@ -0,0 +1,69 @@ +/** + * 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.sdclient.wrapper.consul.cache; + +import java.math.BigInteger; +import java.util.List; + +import org.onap.msb.sdclient.wrapper.consul.HealthClient; +import org.onap.msb.sdclient.wrapper.consul.async.ConsulResponseCallback; +import org.onap.msb.sdclient.wrapper.consul.model.health.ServiceHealth; + +import com.google.common.base.Function; + +public class HealthCache extends ConsulCache<String, ServiceHealth>{ + + private final String serviceName; + + private HealthCache(Function<ServiceHealth, String> keyConversion, + ConsulCache.CallbackConsumer<ServiceHealth> callbackConsumer,String serviceName) { + super(keyConversion, callbackConsumer); + this.serviceName=serviceName; + // TODO Auto-generated constructor stub + } + + + public static HealthCache newCache( + final HealthClient healthClient, + final String serviceName, + final int watchSeconds){ + Function<ServiceHealth,String> keyExtractor = new Function<ServiceHealth, String>() { + @Override + public String apply(ServiceHealth input) { + //return input.getKey().substring(rootPath.length() + 1); + return input.getService().getId(); + } + }; + + final CallbackConsumer<ServiceHealth> callbackConsumer = new CallbackConsumer<ServiceHealth>() { + @Override + public void consume(BigInteger index, ConsulResponseCallback<List<ServiceHealth>> callback) { + healthClient.getHealthyServiceInstances(serviceName, watchParams(index, watchSeconds),callback); + } + }; + + + return new HealthCache(keyExtractor, callbackConsumer,serviceName); + + + } + + public String getServiceName(){ + return this.serviceName; + } + + +}
\ No newline at end of file diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/ConsulResponse.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/ConsulResponse.java new file mode 100644 index 0000000..7a704e5 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/ConsulResponse.java @@ -0,0 +1,79 @@ +/** + * 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.sdclient.wrapper.consul.model; + +import com.google.common.base.Objects; + +import java.math.BigInteger; + +public class ConsulResponse<T> { + + private final T response; + private final long lastContact; + private final boolean knownLeader; + private final BigInteger index; + + public ConsulResponse(T response, long lastContact, boolean knownLeader, BigInteger index) { + this.response = response; + this.lastContact = lastContact; + this.knownLeader = knownLeader; + this.index = index; + } + + public T getResponse() { + return response; + } + + public long getLastContact() { + return lastContact; + } + + public boolean isKnownLeader() { + return knownLeader; + } + + public BigInteger getIndex() { + return index; + } + + @Override + public String toString() { + return "ConsulResponse{" + + "response=" + response + + ", lastContact=" + lastContact + + ", knownLeader=" + knownLeader + + ", index=" + index + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ConsulResponse that = (ConsulResponse) o; + + return Objects.equal(this.response, that.response) && + Objects.equal(this.lastContact, that.lastContact) && + Objects.equal(this.knownLeader, that.knownLeader) && + Objects.equal(this.index, that.index); + } + + @Override + public int hashCode() { + return Objects.hashCode(response, lastContact, knownLeader, index); + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableNode.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableNode.java new file mode 100644 index 0000000..c40c8cf --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableNode.java @@ -0,0 +1,265 @@ +/** + * 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.sdclient.wrapper.consul.model.health; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import java.util.List; +import javax.annotation.Generated; + +/** + * Immutable implementation of {@link Node}. + * <p> + * Use the builder to create immutable instances: + * {@code ImmutableNode.builder()}. + */ +@SuppressWarnings("all") +@Generated({"Immutables.generator", "Node"}) +@JsonIgnoreProperties(ignoreUnknown = true) +public final class ImmutableNode extends Node { + private final String node; + private final String address; + + private ImmutableNode(String node, String address) { + this.node = node; + this.address = address; + } + + /** + * @return The value of the {@code node} attribute + */ + @JsonProperty(value = "Node") + @Override + public String getNode() { + return node; + } + + /** + * @return The value of the {@code address} attribute + */ + @JsonProperty(value = "Address") + @Override + public String getAddress() { + return address; + } + + /** + * Copy the current immutable object by setting a value for the {@link Node#getNode() node} attribute. + * An equals check used to prevent copying of the same value by returning {@code this}. + * @param value A new value for node + * @return A modified copy of the {@code this} object + */ + public final ImmutableNode withNode(String value) { + if (this.node.equals(value)) return this; + return new ImmutableNode(Preconditions.checkNotNull(value, "node"), this.address); + } + + /** + * Copy the current immutable object by setting a value for the {@link Node#getAddress() address} attribute. + * An equals check used to prevent copying of the same value by returning {@code this}. + * @param value A new value for address + * @return A modified copy of the {@code this} object + */ + public final ImmutableNode withAddress(String value) { + if (this.address.equals(value)) return this; + return new ImmutableNode(this.node, Preconditions.checkNotNull(value, "address")); + } + + /** + * This instance is equal to all instances of {@code ImmutableNode} that have equal attribute values. + * @return {@code true} if {@code this} is equal to {@code another} instance + */ + @Override + public boolean equals(Object another) { + if (this == another) return true; + return another instanceof ImmutableNode + && equalTo((ImmutableNode) another); + } + + private boolean equalTo(ImmutableNode another) { + return node.equals(another.node) + && address.equals(another.address); + } + + /** + * Computes a hash code from attributes: {@code node}, {@code address}. + * @return hashCode value + */ + @Override + public int hashCode() { + int h = 31; + h = h * 17 + node.hashCode(); + h = h * 17 + address.hashCode(); + return h; + } + + /** + * Prints the immutable value {@code Node...} with all non-generated + * and non-auxiliary attribute values. + * @return A string representation of the value + */ + @Override + public String toString() { + return MoreObjects.toStringHelper("Node") + .add("node", node) + .add("address", address) + .toString(); + } + + /** + * Utility type used to correctly read immutable object from JSON representation. + * @deprecated Do not use this type directly, it exists only for the <em>Jackson</em>-binding infrastructure + */ + @Deprecated + @JsonDeserialize + static final class Json extends Node { + String node; + String address; + @JsonProperty(value = "Node") + public void setNode(String node) { + this.node = node; + } + @JsonProperty(value = "Address") + public void setAddress(String address) { + this.address = address; + } + @Override + public String getNode() { throw new UnsupportedOperationException(); } + @Override + public String getAddress() { throw new UnsupportedOperationException(); } + } + + /** + * @param json A JSON-bindable data structure + * @return An immutable value type + * @deprecated Do not use this method directly, it exists only for the <em>Jackson</em>-binding infrastructure + */ + @Deprecated + @JsonCreator + static ImmutableNode fromJson(Json json) { + ImmutableNode.Builder builder = ImmutableNode.builder(); + if (json.node != null) { + builder.node(json.node); + } + if (json.address != null) { + builder.address(json.address); + } + return builder.build(); + } + + /** + * Creates an immutable copy of a {@link Node} value. + * Uses accessors to get values to initialize the new immutable instance. + * If an instance is already immutable, it is returned as is. + * @param instance The instance to copy + * @return A copied immutable Node instance + */ + public static ImmutableNode copyOf(Node instance) { + if (instance instanceof ImmutableNode) { + return (ImmutableNode) instance; + } + return ImmutableNode.builder() + .from(instance) + .build(); + } + + /** + * Creates a builder for {@link ImmutableNode ImmutableNode}. + * @return A new ImmutableNode builder + */ + public static ImmutableNode.Builder builder() { + return new ImmutableNode.Builder(); + } + + /** + * Builds instances of type {@link ImmutableNode ImmutableNode}. + * Initialize attributes and then invoke the {@link #build()} method to create an + * immutable instance. + * <p><em>{@code Builder} is not thread-safe and generally should not be stored in a field or collection, + * but instead used immediately to create instances.</em> + */ + public static final class Builder { + private static final long INIT_BIT_NODE = 0x1L; + private static final long INIT_BIT_ADDRESS = 0x2L; + private long initBits = 0x3; + + private String node; + private String address; + + private Builder() { + } + + /** + * Fill a builder with attribute values from the provided {@code Node} instance. + * Regular attribute values will be replaced with those from the given instance. + * Absent optional values will not replace present values. + * @param instance The instance from which to copy values + * @return {@code this} builder for use in a chained invocation + */ + public final Builder from(Node instance) { + Preconditions.checkNotNull(instance, "instance"); + node(instance.getNode()); + address(instance.getAddress()); + return this; + } + + /** + * Initializes the value for the {@link Node#getNode() node} attribute. + * @param node The value for node + * @return {@code this} builder for use in a chained invocation + */ + public final Builder node(String node) { + this.node = Preconditions.checkNotNull(node, "node"); + initBits &= ~INIT_BIT_NODE; + return this; + } + + /** + * Initializes the value for the {@link Node#getAddress() address} attribute. + * @param address The value for address + * @return {@code this} builder for use in a chained invocation + */ + public final Builder address(String address) { + this.address = Preconditions.checkNotNull(address, "address"); + initBits &= ~INIT_BIT_ADDRESS; + return this; + } + + /** + * Builds a new {@link ImmutableNode ImmutableNode}. + * @return An immutable instance of Node + * @throws java.lang.IllegalStateException if any required attributes are missing + */ + public ImmutableNode build() throws IllegalStateException { + if (initBits != 0) { + throw new IllegalStateException(formatRequiredAttributesMessage()); + } + return new ImmutableNode(node, address); + } + + private String formatRequiredAttributesMessage() { + List<String> attributes = Lists.newArrayList(); + if ((initBits & INIT_BIT_NODE) != 0) attributes.add("node"); + if ((initBits & INIT_BIT_ADDRESS) != 0) attributes.add("address"); + return "Cannot build Node, some of required attributes are not set " + attributes; + } + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableService.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableService.java new file mode 100644 index 0000000..20da538 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ImmutableService.java @@ -0,0 +1,477 @@ +/** + * 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.sdclient.wrapper.consul.model.health; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import java.util.List; +import javax.annotation.Generated; + +/** + * Immutable implementation of {@link Service}. + * <p> + * Use the builder to create immutable instances: + * {@code ImmutableService.builder()}. + */ +@SuppressWarnings("all") +@Generated({"Immutables.generator", "Service"}) +@JsonIgnoreProperties(ignoreUnknown = true) +public final class ImmutableService extends Service { + private final String id; + private final String service; + private final ImmutableList<String> tags; + private final String address; + private final int port; + + private ImmutableService( + String id, + String service, + ImmutableList<String> tags, + String address, + int port) { + this.id = id; + this.service = service; + this.tags = tags; + this.address = address; + this.port = port; + } + + /** + * @return The value of the {@code id} attribute + */ + @JsonProperty(value = "ID") + @Override + public String getId() { + return id; + } + + /** + * @return The value of the {@code service} attribute + */ + @JsonProperty(value = "Service") + @Override + public String getService() { + return service; + } + + /** + * @return The value of the {@code tags} attribute + */ + @JsonProperty(value = "Tags") + @JsonDeserialize(as = ImmutableList.class, contentAs = String.class) + @Override + public ImmutableList<String> getTags() { + return tags; + } + + /** + * @return The value of the {@code address} attribute + */ + @JsonProperty(value = "Address") + @Override + public String getAddress() { + return address; + } + + /** + * @return The value of the {@code port} attribute + */ + @JsonProperty(value = "Port") + @Override + public int getPort() { + return port; + } + + /** + * Copy the current immutable object by setting a value for the {@link Service#getId() id} attribute. + * An equals check used to prevent copying of the same value by returning {@code this}. + * @param value A new value for id + * @return A modified copy of the {@code this} object + */ + public final ImmutableService withId(String value) { + if (this.id.equals(value)) return this; + return new ImmutableService( + Preconditions.checkNotNull(value, "id"), + this.service, + this.tags, + this.address, + this.port); + } + + /** + * Copy the current immutable object by setting a value for the {@link Service#getService() service} attribute. + * An equals check used to prevent copying of the same value by returning {@code this}. + * @param value A new value for service + * @return A modified copy of the {@code this} object + */ + public final ImmutableService withService(String value) { + if (this.service.equals(value)) return this; + return new ImmutableService( + this.id, + Preconditions.checkNotNull(value, "service"), + this.tags, + this.address, + this.port); + } + + /** + * Copy the current immutable object with elements that replace the content of {@link Service#getTags() tags}. + * @param elements The elements to set + * @return A modified copy of {@code this} object + */ + public final ImmutableService withTags(String... elements) { + ImmutableList<String> newValue = ImmutableList.copyOf(elements); + return new ImmutableService(this.id, this.service, newValue, this.address, this.port); + } + + /** + * Copy the current immutable object with elements that replace the content of {@link Service#getTags() tags}. + * A shallow reference equality check is used to prevent copying of the same value by returning {@code this}. + * @param elements An iterable of tags elements to set + * @return A modified copy of {@code this} object + */ + public final ImmutableService withTags(Iterable<String> elements) { + if (this.tags == elements) return this; + ImmutableList<String> newValue = ImmutableList.copyOf(elements); + return new ImmutableService(this.id, this.service, newValue, this.address, this.port); + } + + /** + * Copy the current immutable object by setting a value for the {@link Service#getAddress() address} attribute. + * An equals check used to prevent copying of the same value by returning {@code this}. + * @param value A new value for address + * @return A modified copy of the {@code this} object + */ + public final ImmutableService withAddress(String value) { + if (this.address.equals(value)) return this; + return new ImmutableService( + this.id, + this.service, + this.tags, + Preconditions.checkNotNull(value, "address"), + this.port); + } + + /** + * Copy the current immutable object by setting a value for the {@link Service#getPort() port} attribute. + * A value equality check is used to prevent copying of the same value by returning {@code this}. + * @param value A new value for port + * @return A modified copy of the {@code this} object + */ + public final ImmutableService withPort(int value) { + if (this.port == value) return this; + return new ImmutableService(this.id, this.service, this.tags, this.address, value); + } + + /** + * This instance is equal to all instances of {@code ImmutableService} that have equal attribute values. + * @return {@code true} if {@code this} is equal to {@code another} instance + */ + @Override + public boolean equals(Object another) { + if (this == another) return true; + return another instanceof ImmutableService + && equalTo((ImmutableService) another); + } + + private boolean equalTo(ImmutableService another) { + return id.equals(another.id) + && service.equals(another.service) + && tags.equals(another.tags) + && address.equals(another.address) + && port == another.port; + } + + /** + * Computes a hash code from attributes: {@code id}, {@code service}, {@code tags}, {@code address}, {@code port}. + * @return hashCode value + */ + @Override + public int hashCode() { + int h = 31; + h = h * 17 + id.hashCode(); + h = h * 17 + service.hashCode(); + h = h * 17 + tags.hashCode(); + h = h * 17 + address.hashCode(); + h = h * 17 + port; + return h; + } + + /** + * Prints the immutable value {@code Service...} with all non-generated + * and non-auxiliary attribute values. + * @return A string representation of the value + */ + @Override + public String toString() { + return MoreObjects.toStringHelper("Service") + .add("id", id) + .add("service", service) + .add("tags", tags) + .add("address", address) + .add("port", port) + .toString(); + } + + /** + * Utility type used to correctly read immutable object from JSON representation. + * @deprecated Do not use this type directly, it exists only for the <em>Jackson</em>-binding infrastructure + */ + @Deprecated + @JsonDeserialize + static final class Json extends Service { + String id; + String service; + List<String> tags = ImmutableList.of(); + String address; + Integer port; + @JsonProperty(value = "ID") + public void setId(String id) { + this.id = id; + } + @JsonProperty(value = "Service") + public void setService(String service) { + this.service = service; + } + @JsonProperty(value = "Tags") + @JsonDeserialize(as = ImmutableList.class, contentAs = String.class) + public void setTags(List<String> tags) { + this.tags = tags; + } + @JsonProperty(value = "Address") + public void setAddress(String address) { + this.address = address; + } + @JsonProperty(value = "Port") + public void setPort(int port) { + this.port = port; + } + @Override + public String getId() { throw new UnsupportedOperationException(); } + @Override + public String getService() { throw new UnsupportedOperationException(); } + @Override + public List<String> getTags() { throw new UnsupportedOperationException(); } + @Override + public String getAddress() { throw new UnsupportedOperationException(); } + @Override + public int getPort() { throw new UnsupportedOperationException(); } + } + + /** + * @param json A JSON-bindable data structure + * @return An immutable value type + * @deprecated Do not use this method directly, it exists only for the <em>Jackson</em>-binding infrastructure + */ + @Deprecated + @JsonCreator + static ImmutableService fromJson(Json json) { + ImmutableService.Builder builder = ImmutableService.builder(); + if (json.id != null) { + builder.id(json.id); + } + if (json.service != null) { + builder.service(json.service); + } + if (json.tags != null) { + builder.addAllTags(json.tags); + } + if (json.address != null) { + builder.address(json.address); + } + if (json.port != null) { + builder.port(json.port); + } + return builder.build(); + } + + /** + * Creates an immutable copy of a {@link Service} value. + * Uses accessors to get values to initialize the new immutable instance. + * If an instance is already immutable, it is returned as is. + * @param instance The instance to copy + * @return A copied immutable Service instance + */ + public static ImmutableService copyOf(Service instance) { + if (instance instanceof ImmutableService) { + return (ImmutableService) instance; + } + return ImmutableService.builder() + .from(instance) + .build(); + } + + /** + * Creates a builder for {@link ImmutableService ImmutableService}. + * @return A new ImmutableService builder + */ + public static ImmutableService.Builder builder() { + return new ImmutableService.Builder(); + } + + /** + * Builds instances of type {@link ImmutableService ImmutableService}. + * Initialize attributes and then invoke the {@link #build()} method to create an + * immutable instance. + * <p><em>{@code Builder} is not thread-safe and generally should not be stored in a field or collection, + * but instead used immediately to create instances.</em> + */ + public static final class Builder { + private static final long INIT_BIT_ID = 0x1L; + private static final long INIT_BIT_SERVICE = 0x2L; + private static final long INIT_BIT_ADDRESS = 0x4L; + private static final long INIT_BIT_PORT = 0x8L; + private long initBits = 0xf; + + private String id; + private String service; + private ImmutableList.Builder<String> tagsBuilder = ImmutableList.builder(); + private String address; + private int port; + + private Builder() { + } + + /** + * Fill a builder with attribute values from the provided {@code Service} instance. + * Regular attribute values will be replaced with those from the given instance. + * Absent optional values will not replace present values. + * Collection elements and entries will be added, not replaced. + * @param instance The instance from which to copy values + * @return {@code this} builder for use in a chained invocation + */ + public final Builder from(Service instance) { + Preconditions.checkNotNull(instance, "instance"); + id(instance.getId()); + service(instance.getService()); + addAllTags(instance.getTags()); + address(instance.getAddress()); + port(instance.getPort()); + return this; + } + + /** + * Initializes the value for the {@link Service#getId() id} attribute. + * @param id The value for id + * @return {@code this} builder for use in a chained invocation + */ + public final Builder id(String id) { + this.id = Preconditions.checkNotNull(id, "id"); + initBits &= ~INIT_BIT_ID; + return this; + } + + /** + * Initializes the value for the {@link Service#getService() service} attribute. + * @param service The value for service + * @return {@code this} builder for use in a chained invocation + */ + public final Builder service(String service) { + this.service = Preconditions.checkNotNull(service, "service"); + initBits &= ~INIT_BIT_SERVICE; + return this; + } + + /** + * Adds one element to {@link Service#getTags() tags} list. + * @param element A tags element + * @return {@code this} builder for use in a chained invocation + */ + public final Builder addTags(String element) { + tagsBuilder.add(element); + return this; + } + + /** + * Adds elements to {@link Service#getTags() tags} list. + * @param elements An array of tags elements + * @return {@code this} builder for use in a chained invocation + */ + public final Builder addTags(String... elements) { + tagsBuilder.add(elements); + return this; + } + + /** + * Sets or replaces all elements for {@link Service#getTags() tags} list. + * @param elements An iterable of tags elements + * @return {@code this} builder for use in a chained invocation + */ + public final Builder tags(Iterable<String> elements) { + tagsBuilder = ImmutableList.builder(); + return addAllTags(elements); + } + + /** + * Adds elements to {@link Service#getTags() tags} list. + * @param elements An iterable of tags elements + * @return {@code this} builder for use in a chained invocation + */ + public final Builder addAllTags(Iterable<String> elements) { + tagsBuilder.addAll(elements); + return this; + } + + /** + * Initializes the value for the {@link Service#getAddress() address} attribute. + * @param address The value for address + * @return {@code this} builder for use in a chained invocation + */ + public final Builder address(String address) { + this.address = Preconditions.checkNotNull(address, "address"); + initBits &= ~INIT_BIT_ADDRESS; + return this; + } + + /** + * Initializes the value for the {@link Service#getPort() port} attribute. + * @param port The value for port + * @return {@code this} builder for use in a chained invocation + */ + public final Builder port(int port) { + this.port = port; + initBits &= ~INIT_BIT_PORT; + return this; + } + + /** + * Builds a new {@link ImmutableService ImmutableService}. + * @return An immutable instance of Service + * @throws java.lang.IllegalStateException if any required attributes are missing + */ + public ImmutableService build() throws IllegalStateException { + if (initBits != 0) { + throw new IllegalStateException(formatRequiredAttributesMessage()); + } + return new ImmutableService(id, service, tagsBuilder.build(), address, port); + } + + private String formatRequiredAttributesMessage() { + List<String> attributes = Lists.newArrayList(); + if ((initBits & INIT_BIT_ID) != 0) attributes.add("id"); + if ((initBits & INIT_BIT_SERVICE) != 0) attributes.add("service"); + if ((initBits & INIT_BIT_ADDRESS) != 0) attributes.add("address"); + if ((initBits & INIT_BIT_PORT) != 0) attributes.add("port"); + return "Cannot build Service, some of required attributes are not set " + attributes; + } + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Node.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Node.java new file mode 100644 index 0000000..839dc46 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Node.java @@ -0,0 +1,34 @@ +/** + * 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.sdclient.wrapper.consul.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; + + +@JsonSerialize(as = ImmutableNode.class) +@JsonDeserialize(as = ImmutableNode.class) +@JsonIgnoreProperties(ignoreUnknown = true) +public abstract class Node { + + @JsonProperty("Node") + public abstract String getNode(); + + @JsonProperty("Address") + public abstract String getAddress(); +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Service.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Service.java new file mode 100644 index 0000000..0cb04ea --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/Service.java @@ -0,0 +1,47 @@ +/** + * 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.sdclient.wrapper.consul.model.health; + +import java.util.List; + +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; + + +@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(); +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ServiceHealth.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ServiceHealth.java new file mode 100644 index 0000000..91f3c7d --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/model/health/ServiceHealth.java @@ -0,0 +1,70 @@ +/** + * 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.sdclient.wrapper.consul.model.health; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Objects; + + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ServiceHealth { + + @JsonProperty("Node") + public Node node; + + @JsonProperty("Service") + public Service service; + + public Node getNode() { + return node; + } + + public void setNode(Node node) { + this.node = node; + } + + public Service getService() { + return service; + } + + public void setService(Service service) { + this.service = service; + } + + @Override + public boolean equals(Object other) + { + if(this == other) + return true; + if(other instanceof ServiceHealth) + { + ServiceHealth that = (ServiceHealth)other; + return Objects.equal(node, that.node) && Objects.equal(service, that.service); + } else + { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(node, service); + } + + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/CatalogOptions.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/CatalogOptions.java new file mode 100644 index 0000000..e608c0f --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/CatalogOptions.java @@ -0,0 +1,38 @@ +/** + * 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.sdclient.wrapper.consul.option; + +import static org.onap.msb.sdclient.wrapper.consul.option.Options.optionallyAdd; + +import javax.ws.rs.client.WebTarget; + +import com.google.common.base.Optional; + + +public abstract class CatalogOptions implements ParamAdder { + + public abstract Optional<String> getDatacenter(); + public abstract Optional<String> getTag(); + + public static final CatalogOptions BLANK = ImmutableCatalogOptions.builder().build(); + + @Override + public final WebTarget apply(final WebTarget input) { + WebTarget added = optionallyAdd(input, "dc", getDatacenter()); + added = optionallyAdd(added, "tag", getTag()); + return added; + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ConsistencyMode.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ConsistencyMode.java new file mode 100644 index 0000000..b60fa0b --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ConsistencyMode.java @@ -0,0 +1,20 @@ +/** + * 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.sdclient.wrapper.consul.option; + +public enum ConsistencyMode { + DEFAULT, STALE, CONSISTENT +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableCatalogOptions.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableCatalogOptions.java new file mode 100644 index 0000000..2a87f8a --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableCatalogOptions.java @@ -0,0 +1,250 @@ +/** + * 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.sdclient.wrapper.consul.option; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import javax.annotation.Generated; + +/** + * Immutable implementation of {@link CatalogOptions}. + * <p> + * Use the builder to create immutable instances: + * {@code ImmutableCatalogOptions.builder()}. + */ +@SuppressWarnings("all") +@Generated({"Immutables.generator", "CatalogOptions"}) +public final class ImmutableCatalogOptions extends CatalogOptions { + private final Optional<String> datacenter; + private final Optional<String> tag; + + private ImmutableCatalogOptions( + Optional<String> datacenter, + Optional<String> tag) { + this.datacenter = datacenter; + this.tag = tag; + } + + /** + * @return The value of the {@code datacenter} attribute + */ + @Override + public Optional<String> getDatacenter() { + return datacenter; + } + + /** + * @return The value of the {@code tag} attribute + */ + @Override + public Optional<String> getTag() { + return tag; + } + + /** + * Copy the current immutable object by setting a <i>present</i> value for the optional {@link CatalogOptions#getDatacenter() datacenter} attribute. + * @param value The value for datacenter + * @return A modified copy of {@code this} object + */ + public final ImmutableCatalogOptions withDatacenter(String value) { + Optional<String> newValue = Optional.of(value); + return new ImmutableCatalogOptions(newValue, this.tag); + } + + /** + * Copy the current immutable object by setting an optional value for the {@link CatalogOptions#getDatacenter() datacenter} attribute. + * A shallow reference equality check on the optional value is used to prevent copying of the same value by returning {@code this}. + * @param optional A value for datacenter + * @return A modified copy of {@code this} object + */ + public final ImmutableCatalogOptions withDatacenter(Optional<String> optional) { + Optional<String> value = Preconditions.checkNotNull(optional, "datacenter"); + if (this.datacenter == value) return this; + return new ImmutableCatalogOptions(value, this.tag); + } + + /** + * Copy the current immutable object by setting a <i>present</i> value for the optional {@link CatalogOptions#getTag() tag} attribute. + * @param value The value for tag + * @return A modified copy of {@code this} object + */ + public final ImmutableCatalogOptions withTag(String value) { + Optional<String> newValue = Optional.of(value); + return new ImmutableCatalogOptions(this.datacenter, newValue); + } + + /** + * Copy the current immutable object by setting an optional value for the {@link CatalogOptions#getTag() tag} attribute. + * A shallow reference equality check on the optional value is used to prevent copying of the same value by returning {@code this}. + * @param optional A value for tag + * @return A modified copy of {@code this} object + */ + public final ImmutableCatalogOptions withTag(Optional<String> optional) { + Optional<String> value = Preconditions.checkNotNull(optional, "tag"); + if (this.tag == value) return this; + return new ImmutableCatalogOptions(this.datacenter, value); + } + + /** + * This instance is equal to all instances of {@code ImmutableCatalogOptions} that have equal attribute values. + * @return {@code true} if {@code this} is equal to {@code another} instance + */ + @Override + public boolean equals(Object another) { + if (this == another) return true; + return another instanceof ImmutableCatalogOptions + && equalTo((ImmutableCatalogOptions) another); + } + + private boolean equalTo(ImmutableCatalogOptions another) { + return datacenter.equals(another.datacenter) + && tag.equals(another.tag); + } + + /** + * Computes a hash code from attributes: {@code datacenter}, {@code tag}. + * @return hashCode value + */ + @Override + public int hashCode() { + int h = 31; + h = h * 17 + datacenter.hashCode(); + h = h * 17 + tag.hashCode(); + return h; + } + + /** + * Prints the immutable value {@code CatalogOptions...} with all non-generated + * and non-auxiliary attribute values. + * @return A string representation of the value + */ + @Override + public String toString() { + return MoreObjects.toStringHelper("CatalogOptions") + .add("datacenter", datacenter) + .add("tag", tag) + .toString(); + } + + /** + * Creates an immutable copy of a {@link CatalogOptions} value. + * Uses accessors to get values to initialize the new immutable instance. + * If an instance is already immutable, it is returned as is. + * @param instance The instance to copy + * @return A copied immutable CatalogOptions instance + */ + public static ImmutableCatalogOptions copyOf(CatalogOptions instance) { + if (instance instanceof ImmutableCatalogOptions) { + return (ImmutableCatalogOptions) instance; + } + return ImmutableCatalogOptions.builder() + .from(instance) + .build(); + } + + /** + * Creates a builder for {@link ImmutableCatalogOptions ImmutableCatalogOptions}. + * @return A new ImmutableCatalogOptions builder + */ + public static ImmutableCatalogOptions.Builder builder() { + return new ImmutableCatalogOptions.Builder(); + } + + /** + * Builds instances of type {@link ImmutableCatalogOptions ImmutableCatalogOptions}. + * Initialize attributes and then invoke the {@link #build()} method to create an + * immutable instance. + * <p><em>{@code Builder} is not thread-safe and generally should not be stored in a field or collection, + * but instead used immediately to create instances.</em> + */ + public static final class Builder { + private Optional<String> datacenter = Optional.absent(); + private Optional<String> tag = Optional.absent(); + + private Builder() { + } + + /** + * Fill a builder with attribute values from the provided {@code CatalogOptions} instance. + * Regular attribute values will be replaced with those from the given instance. + * Absent optional values will not replace present values. + * @param instance The instance from which to copy values + * @return {@code this} builder for use in a chained invocation + */ + public final Builder from(CatalogOptions instance) { + Preconditions.checkNotNull(instance, "instance"); + Optional<String> datacenterOptional = instance.getDatacenter(); + if (datacenterOptional.isPresent()) { + datacenter(datacenterOptional); + } + Optional<String> tagOptional = instance.getTag(); + if (tagOptional.isPresent()) { + tag(tagOptional); + } + return this; + } + + /** + * Initializes the optional value {@link CatalogOptions#getDatacenter() datacenter} to datacenter. + * @param datacenter The value for datacenter + * @return {@code this} builder for chained invocation + */ + public final Builder datacenter(String datacenter) { + this.datacenter = Optional.of(datacenter); + return this; + } + + /** + * Initializes the optional value {@link CatalogOptions#getDatacenter() datacenter} to datacenter. + * @param datacenter The value for datacenter + * @return {@code this} builder for use in a chained invocation + */ + public final Builder datacenter(Optional<String> datacenter) { + this.datacenter = Preconditions.checkNotNull(datacenter, "datacenter"); + return this; + } + + /** + * Initializes the optional value {@link CatalogOptions#getTag() tag} to tag. + * @param tag The value for tag + * @return {@code this} builder for chained invocation + */ + public final Builder tag(String tag) { + this.tag = Optional.of(tag); + return this; + } + + /** + * Initializes the optional value {@link CatalogOptions#getTag() tag} to tag. + * @param tag The value for tag + * @return {@code this} builder for use in a chained invocation + */ + public final Builder tag(Optional<String> tag) { + this.tag = Preconditions.checkNotNull(tag, "tag"); + return this; + } + + /** + * Builds a new {@link ImmutableCatalogOptions ImmutableCatalogOptions}. + * @return An immutable instance of CatalogOptions + * @throws java.lang.IllegalStateException if any required attributes are missing + */ + public ImmutableCatalogOptions build() throws IllegalStateException { + return new ImmutableCatalogOptions(datacenter, tag); + } + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableQueryOptions.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableQueryOptions.java new file mode 100644 index 0000000..6c4db6b --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ImmutableQueryOptions.java @@ -0,0 +1,530 @@ +/** + * 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.sdclient.wrapper.consul.option; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.primitives.Booleans; +import java.math.BigInteger; +import java.util.ArrayList; +import javax.annotation.Generated; + +/** + * Immutable implementation of {@link QueryOptions}. + * <p> + * Use the builder to create immutable instances: + * {@code ImmutableQueryOptions.builder()}. + */ +@SuppressWarnings("all") +@Generated({"Immutables.generator", "QueryOptions"}) +public final class ImmutableQueryOptions extends QueryOptions { + private final Optional<String> wait; + private final Optional<String> token; + private final Optional<BigInteger> index; + private final Optional<String> near; + private final ConsistencyMode consistencyMode; + private final boolean isBlocking; + private final boolean hasToken; + + private ImmutableQueryOptions(ImmutableQueryOptions.Builder builder) { + this.wait = builder.wait; + this.token = builder.token; + this.index = builder.index; + this.near = builder.near; + if (builder.consistencyMode != null) { + initShim.consistencyMode(builder.consistencyMode); + } + this.consistencyMode = initShim.getConsistencyMode(); + this.isBlocking = initShim.isBlocking(); + this.hasToken = initShim.hasToken(); + this.initShim = null; + } + + private ImmutableQueryOptions( + Optional<String> wait, + Optional<String> token, + Optional<BigInteger> index, + Optional<String> near, + ConsistencyMode consistencyMode) { + this.wait = wait; + this.token = token; + this.index = index; + this.near = near; + this.consistencyMode = consistencyMode; + initShim.consistencyMode(consistencyMode); + this.isBlocking = initShim.isBlocking(); + this.hasToken = initShim.hasToken(); + this.initShim = null; + } + + private static final int STAGE_INITIALIZING = -1; + private static final int STAGE_UNINITIALIZED = 0; + private static final int STAGE_INITIALIZED = 1; + private volatile InitShim initShim = new InitShim(); + + private final class InitShim { + private ConsistencyMode consistencyMode; + private byte consistencyModeStage; + + ConsistencyMode getConsistencyMode() { + if (consistencyModeStage == STAGE_INITIALIZING) throw new IllegalStateException(formatInitCycleMessage()); + if (consistencyModeStage == STAGE_UNINITIALIZED) { + consistencyModeStage = STAGE_INITIALIZING; + this.consistencyMode = Preconditions.checkNotNull(ImmutableQueryOptions.super.getConsistencyMode(), "consistencyMode"); + consistencyModeStage = STAGE_INITIALIZED; + } + return consistencyMode; + } + + ConsistencyMode consistencyMode(ConsistencyMode value) { + this.consistencyMode = value; + consistencyModeStage = STAGE_INITIALIZED; + return value; + } + private boolean isBlocking; + private byte isBlockingStage; + + boolean isBlocking() { + if (isBlockingStage == STAGE_INITIALIZING) throw new IllegalStateException(formatInitCycleMessage()); + if (isBlockingStage == STAGE_UNINITIALIZED) { + isBlockingStage = STAGE_INITIALIZING; + this.isBlocking = ImmutableQueryOptions.super.isBlocking(); + isBlockingStage = STAGE_INITIALIZED; + } + return isBlocking; + } + private boolean hasToken; + private byte hasTokenStage; + + boolean hasToken() { + if (hasTokenStage == STAGE_INITIALIZING) throw new IllegalStateException(formatInitCycleMessage()); + if (hasTokenStage == STAGE_UNINITIALIZED) { + hasTokenStage = STAGE_INITIALIZING; + this.hasToken = ImmutableQueryOptions.super.hasToken(); + hasTokenStage = STAGE_INITIALIZED; + } + return hasToken; + } + + private String formatInitCycleMessage() { + ArrayList<String> attributes = Lists.newArrayList(); + if (consistencyModeStage == STAGE_INITIALIZING) attributes.add("consistencyMode"); + if (isBlockingStage == STAGE_INITIALIZING) attributes.add("isBlocking"); + if (hasTokenStage == STAGE_INITIALIZING) attributes.add("hasToken"); + return "Cannot build QueryOptions, attribute initializers form cycle" + attributes; + } + } + + /** + * @return The value of the {@code wait} attribute + */ + @Override + public Optional<String> getWait() { + return wait; + } + + /** + * @return The value of the {@code token} attribute + */ + @Override + public Optional<String> getToken() { + return token; + } + + /** + * @return The value of the {@code index} attribute + */ + @Override + public Optional<BigInteger> getIndex() { + return index; + } + + /** + * @return The value of the {@code near} attribute + */ + @Override + public Optional<String> getNear() { + return near; + } + + /** + * @return The value of the {@code consistencyMode} attribute + */ + @Override + public ConsistencyMode getConsistencyMode() { + return initShim != null + ? initShim.getConsistencyMode() + : consistencyMode; + } + + /** + * @return The computed-at-construction value of the {@code isBlocking} attribute + */ + @Override + public boolean isBlocking() { + return initShim != null + ? initShim.isBlocking() + : isBlocking; + } + + /** + * @return The computed-at-construction value of the {@code hasToken} attribute + */ + @Override + public boolean hasToken() { + return initShim != null + ? initShim.hasToken() + : hasToken; + } + + /** + * Copy the current immutable object by setting a <i>present</i> value for the optional {@link QueryOptions#getWait() wait} attribute. + * @param value The value for wait + * @return A modified copy of {@code this} object + */ + public final ImmutableQueryOptions withWait(String value) { + Optional<String> newValue = Optional.of(value); + return validate(new ImmutableQueryOptions(newValue, this.token, this.index, this.near, this.consistencyMode)); + } + + /** + * Copy the current immutable object by setting an optional value for the {@link QueryOptions#getWait() wait} attribute. + * A shallow reference equality check on the optional value is used to prevent copying of the same value by returning {@code this}. + * @param optional A value for wait + * @return A modified copy of {@code this} object + */ + public final ImmutableQueryOptions withWait(Optional<String> optional) { + Optional<String> value = Preconditions.checkNotNull(optional, "wait"); + if (this.wait == value) return this; + return validate(new ImmutableQueryOptions(value, this.token, this.index, this.near, this.consistencyMode)); + } + + /** + * Copy the current immutable object by setting a <i>present</i> value for the optional {@link QueryOptions#getToken() token} attribute. + * @param value The value for token + * @return A modified copy of {@code this} object + */ + public final ImmutableQueryOptions withToken(String value) { + Optional<String> newValue = Optional.of(value); + return validate(new ImmutableQueryOptions(this.wait, newValue, this.index, this.near, this.consistencyMode)); + } + + /** + * Copy the current immutable object by setting an optional value for the {@link QueryOptions#getToken() token} attribute. + * A shallow reference equality check on the optional value is used to prevent copying of the same value by returning {@code this}. + * @param optional A value for token + * @return A modified copy of {@code this} object + */ + public final ImmutableQueryOptions withToken(Optional<String> optional) { + Optional<String> value = Preconditions.checkNotNull(optional, "token"); + if (this.token == value) return this; + return validate(new ImmutableQueryOptions(this.wait, value, this.index, this.near, this.consistencyMode)); + } + + /** + * Copy the current immutable object by setting a <i>present</i> value for the optional {@link QueryOptions#getIndex() index} attribute. + * @param value The value for index + * @return A modified copy of {@code this} object + */ + public final ImmutableQueryOptions withIndex(BigInteger value) { + Optional<BigInteger> newValue = Optional.of(value); + return validate(new ImmutableQueryOptions(this.wait, this.token, newValue, this.near, this.consistencyMode)); + } + + /** + * Copy the current immutable object by setting an optional value for the {@link QueryOptions#getIndex() index} attribute. + * A shallow reference equality check on the optional value is used to prevent copying of the same value by returning {@code this}. + * @param optional A value for index + * @return A modified copy of {@code this} object + */ + public final ImmutableQueryOptions withIndex(Optional<BigInteger> optional) { + Optional<BigInteger> value = Preconditions.checkNotNull(optional, "index"); + if (this.index == value) return this; + return validate(new ImmutableQueryOptions(this.wait, this.token, value, this.near, this.consistencyMode)); + } + + /** + * Copy the current immutable object by setting a <i>present</i> value for the optional {@link QueryOptions#getNear() near} attribute. + * @param value The value for near + * @return A modified copy of {@code this} object + */ + public final ImmutableQueryOptions withNear(String value) { + Optional<String> newValue = Optional.of(value); + return validate(new ImmutableQueryOptions(this.wait, this.token, this.index, newValue, this.consistencyMode)); + } + + /** + * Copy the current immutable object by setting an optional value for the {@link QueryOptions#getNear() near} attribute. + * A shallow reference equality check on the optional value is used to prevent copying of the same value by returning {@code this}. + * @param optional A value for near + * @return A modified copy of {@code this} object + */ + public final ImmutableQueryOptions withNear(Optional<String> optional) { + Optional<String> value = Preconditions.checkNotNull(optional, "near"); + if (this.near == value) return this; + return validate(new ImmutableQueryOptions(this.wait, this.token, this.index, value, this.consistencyMode)); + } + + /** + * Copy the current immutable object by setting a value for the {@link QueryOptions#getConsistencyMode() consistencyMode} attribute. + * A shallow reference equality check is used to prevent copying of the same value by returning {@code this}. + * @param value A new value for consistencyMode + * @return A modified copy of the {@code this} object + */ + public final ImmutableQueryOptions withConsistencyMode(ConsistencyMode value) { + if (this.consistencyMode == value) return this; + return validate(new ImmutableQueryOptions( + this.wait, + this.token, + this.index, + this.near, + Preconditions.checkNotNull(value, "consistencyMode"))); + } + + /** + * This instance is equal to all instances of {@code ImmutableQueryOptions} that have equal attribute values. + * @return {@code true} if {@code this} is equal to {@code another} instance + */ + @Override + public boolean equals(Object another) { + if (this == another) return true; + return another instanceof ImmutableQueryOptions + && equalTo((ImmutableQueryOptions) another); + } + + private boolean equalTo(ImmutableQueryOptions another) { + return wait.equals(another.wait) + && token.equals(another.token) + && index.equals(another.index) + && near.equals(another.near) + && consistencyMode.equals(another.consistencyMode) + && isBlocking == another.isBlocking + && hasToken == another.hasToken; + } + + /** + * Computes a hash code from attributes: {@code wait}, {@code token}, {@code index}, {@code near}, {@code consistencyMode}, {@code isBlocking}, {@code hasToken}. + * @return hashCode value + */ + @Override + public int hashCode() { + int h = 31; + h = h * 17 + wait.hashCode(); + h = h * 17 + token.hashCode(); + h = h * 17 + index.hashCode(); + h = h * 17 + near.hashCode(); + h = h * 17 + consistencyMode.hashCode(); + h = h * 17 + Booleans.hashCode(isBlocking); + h = h * 17 + Booleans.hashCode(hasToken); + return h; + } + + /** + * Prints the immutable value {@code QueryOptions...} with all non-generated + * and non-auxiliary attribute values. + * @return A string representation of the value + */ + @Override + public String toString() { + return MoreObjects.toStringHelper("QueryOptions") + .add("wait", wait) + .add("token", token) + .add("index", index) + .add("near", near) + .add("consistencyMode", consistencyMode) + .add("isBlocking", isBlocking) + .add("hasToken", hasToken) + .toString(); + } + + private static ImmutableQueryOptions validate(ImmutableQueryOptions instance) { + instance.validate(); + return instance; + } + + /** + * Creates an immutable copy of a {@link QueryOptions} value. + * Uses accessors to get values to initialize the new immutable instance. + * If an instance is already immutable, it is returned as is. + * @param instance The instance to copy + * @return A copied immutable QueryOptions instance + */ + public static ImmutableQueryOptions copyOf(QueryOptions instance) { + if (instance instanceof ImmutableQueryOptions) { + return (ImmutableQueryOptions) instance; + } + return ImmutableQueryOptions.builder() + .from(instance) + .build(); + } + + /** + * Creates a builder for {@link ImmutableQueryOptions ImmutableQueryOptions}. + * @return A new ImmutableQueryOptions builder + */ + public static ImmutableQueryOptions.Builder builder() { + return new ImmutableQueryOptions.Builder(); + } + + /** + * Builds instances of type {@link ImmutableQueryOptions ImmutableQueryOptions}. + * Initialize attributes and then invoke the {@link #build()} method to create an + * immutable instance. + * <p><em>{@code Builder} is not thread-safe and generally should not be stored in a field or collection, + * but instead used immediately to create instances.</em> + */ + public static final class Builder { + private Optional<String> wait = Optional.absent(); + private Optional<String> token = Optional.absent(); + private Optional<BigInteger> index = Optional.absent(); + private Optional<String> near = Optional.absent(); + private ConsistencyMode consistencyMode; + + private Builder() { + } + + /** + * Fill a builder with attribute values from the provided {@code QueryOptions} instance. + * Regular attribute values will be replaced with those from the given instance. + * Absent optional values will not replace present values. + * @param instance The instance from which to copy values + * @return {@code this} builder for use in a chained invocation + */ + public final Builder from(QueryOptions instance) { + Preconditions.checkNotNull(instance, "instance"); + Optional<String> waitOptional = instance.getWait(); + if (waitOptional.isPresent()) { + wait(waitOptional); + } + Optional<String> tokenOptional = instance.getToken(); + if (tokenOptional.isPresent()) { + token(tokenOptional); + } + Optional<BigInteger> indexOptional = instance.getIndex(); + if (indexOptional.isPresent()) { + index(indexOptional); + } + Optional<String> nearOptional = instance.getNear(); + if (nearOptional.isPresent()) { + near(nearOptional); + } + consistencyMode(instance.getConsistencyMode()); + return this; + } + + /** + * Initializes the optional value {@link QueryOptions#getWait() wait} to wait. + * @param wait The value for wait + * @return {@code this} builder for chained invocation + */ + public final Builder wait(String wait) { + this.wait = Optional.of(wait); + return this; + } + + /** + * Initializes the optional value {@link QueryOptions#getWait() wait} to wait. + * @param wait The value for wait + * @return {@code this} builder for use in a chained invocation + */ + public final Builder wait(Optional<String> wait) { + this.wait = Preconditions.checkNotNull(wait, "wait"); + return this; + } + + /** + * Initializes the optional value {@link QueryOptions#getToken() token} to token. + * @param token The value for token + * @return {@code this} builder for chained invocation + */ + public final Builder token(String token) { + this.token = Optional.of(token); + return this; + } + + /** + * Initializes the optional value {@link QueryOptions#getToken() token} to token. + * @param token The value for token + * @return {@code this} builder for use in a chained invocation + */ + public final Builder token(Optional<String> token) { + this.token = Preconditions.checkNotNull(token, "token"); + return this; + } + + /** + * Initializes the optional value {@link QueryOptions#getIndex() index} to index. + * @param index The value for index + * @return {@code this} builder for chained invocation + */ + public final Builder index(BigInteger index) { + this.index = Optional.of(index); + return this; + } + + /** + * Initializes the optional value {@link QueryOptions#getIndex() index} to index. + * @param index The value for index + * @return {@code this} builder for use in a chained invocation + */ + public final Builder index(Optional<BigInteger> index) { + this.index = Preconditions.checkNotNull(index, "index"); + return this; + } + + /** + * Initializes the optional value {@link QueryOptions#getNear() near} to near. + * @param near The value for near + * @return {@code this} builder for chained invocation + */ + public final Builder near(String near) { + this.near = Optional.of(near); + return this; + } + + /** + * Initializes the optional value {@link QueryOptions#getNear() near} to near. + * @param near The value for near + * @return {@code this} builder for use in a chained invocation + */ + public final Builder near(Optional<String> near) { + this.near = Preconditions.checkNotNull(near, "near"); + return this; + } + + /** + * Initializes the value for the {@link QueryOptions#getConsistencyMode() consistencyMode} attribute. + * <p><em>If not set, this attribute will have a default value as returned by the initializer of {@link QueryOptions#getConsistencyMode() consistencyMode}.</em> + * @param consistencyMode The value for consistencyMode + * @return {@code this} builder for use in a chained invocation + */ + public final Builder consistencyMode(ConsistencyMode consistencyMode) { + this.consistencyMode = Preconditions.checkNotNull(consistencyMode, "consistencyMode"); + return this; + } + + /** + * Builds a new {@link ImmutableQueryOptions ImmutableQueryOptions}. + * @return An immutable instance of QueryOptions + * @throws java.lang.IllegalStateException if any required attributes are missing + */ + public ImmutableQueryOptions build() throws IllegalStateException { + return ImmutableQueryOptions.validate(new ImmutableQueryOptions(this)); + } + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/Options.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/Options.java new file mode 100644 index 0000000..5d412df --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/Options.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.sdclient.wrapper.consul.option; + +import com.google.common.base.Optional; + +import javax.ws.rs.client.WebTarget; + +public class Options { + private Options(){}; + + static <T> WebTarget optionallyAdd(WebTarget input, String key, Optional<T> val) { + return val.isPresent() ? input.queryParam(key, val.get()) : input; + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ParamAdder.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ParamAdder.java new file mode 100644 index 0000000..e5f6d44 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/ParamAdder.java @@ -0,0 +1,22 @@ +/** + * 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.sdclient.wrapper.consul.option; + +import com.google.common.base.Function; + +import javax.ws.rs.client.WebTarget; + +public interface ParamAdder extends Function<WebTarget, WebTarget> {} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/QueryOptions.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/QueryOptions.java new file mode 100644 index 0000000..3a09b82 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/option/QueryOptions.java @@ -0,0 +1,99 @@ +/** + * 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.sdclient.wrapper.consul.option; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.onap.msb.sdclient.wrapper.consul.option.Options.optionallyAdd; + +import java.math.BigInteger; + +import javax.ws.rs.client.WebTarget; + +import com.google.common.base.Optional; + +/** + * Container for common query options used by the Consul API. + */ + +public abstract class QueryOptions implements ParamAdder { + + public static final QueryOptions BLANK = ImmutableQueryOptions.builder().build(); + + public abstract Optional<String> getWait(); + public abstract Optional<String> getToken(); + public abstract Optional<BigInteger> getIndex(); + public abstract Optional<String> getNear(); + + + public ConsistencyMode getConsistencyMode() { + return ConsistencyMode.DEFAULT; + } + + + public boolean isBlocking() { + return getWait().isPresent(); + } + + + public boolean hasToken() { + return getToken().isPresent(); + } + + + void validate() { + if (isBlocking()) { + checkArgument(getIndex().isPresent(), "If wait is specified, index must also be specified"); + } + } + + public static ImmutableQueryOptions.Builder blockSeconds(int seconds, BigInteger index) { + return blockBuilder("s", seconds, index); + } + + public static ImmutableQueryOptions.Builder blockMinutes(int minutes, BigInteger index) { + return blockBuilder("m", minutes, index); + } + + private static ImmutableQueryOptions.Builder blockBuilder(String identifier, int qty, BigInteger index) { + return ImmutableQueryOptions.builder() + .wait(String.format("%s%s", qty, identifier)) + .index(index); + } + + @Override + public WebTarget apply(WebTarget input) { + + WebTarget added = input; + switch (getConsistencyMode()) { + case CONSISTENT: + added = added.queryParam("consistent", ""); + break; + case STALE: + added = added.queryParam("stale", ""); + break; + } + + if (isBlocking()) { + added = added.queryParam("wait", getWait().get()) + .queryParam("index", String.valueOf(getIndex().get())); + } + + added = optionallyAdd(added, "token", getToken()); + added = optionallyAdd(added, "near", getToken()); + + return added; + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ClientUtil.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ClientUtil.java new file mode 100644 index 0000000..7e3b7a2 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ClientUtil.java @@ -0,0 +1,246 @@ +/** + * 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.sdclient.wrapper.consul.util; + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +import javax.ws.rs.ServerErrorException; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.InvocationCallback; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.onap.msb.sdclient.wrapper.consul.ConsulException; +import org.onap.msb.sdclient.wrapper.consul.async.ConsulResponseCallback; +import org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse; +import org.onap.msb.sdclient.wrapper.consul.option.CatalogOptions; +import org.onap.msb.sdclient.wrapper.consul.option.ParamAdder; +import org.onap.msb.sdclient.wrapper.consul.option.QueryOptions; + +import java.math.BigInteger; +import java.util.List; +import java.util.Map; + +/** + * A collection of stateless utility methods for use in constructing + * requests and responses to the Consul HTTP API. + */ +public class ClientUtil { + + /** + * Applies all key/values from the params map to query string parameters. + * + * @param webTarget The JAX-RS target to apply the query parameters. + * @param params Map of parameters. + * @return The new target with the parameters applied. + */ + public static WebTarget queryParams(WebTarget webTarget, Map<String, String> params) { + WebTarget target = webTarget; + + if(params != null) { + for(Map.Entry<String, String> entry : params.entrySet()) { + target = target.queryParam(entry.getKey(), entry.getValue()); + } + } + + return target; + } + + /** + * Given a {@link org.onap.msb.sdclient.wrapper.consul.option.ParamAdder} object, adds the + * appropriate query string parameters to the request being built. + * + * @param webTarget The base {@link javax.ws.rs.client.WebTarget}. + * @param paramAdder will add specific params to the target. + * @return A {@link javax.ws.rs.client.WebTarget} with all appropriate query + * string parameters. + */ + public static WebTarget addParams(WebTarget webTarget, ParamAdder paramAdder) { + return paramAdder == null ? webTarget : paramAdder.apply(webTarget); + } + + /** + * Generates a {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} for a specific datacenter, + * set of {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}, and a result type. + * + * @param target The base {@link javax.ws.rs.client.WebTarget}. + * @param catalogOptions Catalog specific options to use. + * @param queryOptions The Query Options to use. + * @param type The generic type to marshall the resulting data to. + * @param <T> The result type. + * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse}. + */ + public static <T> ConsulResponse<T> response(WebTarget target, CatalogOptions catalogOptions, + QueryOptions queryOptions, + GenericType<T> type) { + target = addParams(target, catalogOptions); + target = addParams(target, queryOptions); + + return response(target, type); + } + + /** + * Generates a {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} for a specific datacenter, + * set of {@link org.onap.msb.sdclient.wrapper.consul.option.QueryOptions}, and a result type. + * + * @param target The base {@link javax.ws.rs.client.WebTarget}. + * @param catalogOptions Catalog specific options to use. + * @param queryOptions The Query Options to use. + * @param type The generic type to marshall the resulting data to. + * @param <T> The result type. + */ + public static <T> void response(WebTarget target, CatalogOptions catalogOptions, + QueryOptions queryOptions, + GenericType<T> type, + ConsulResponseCallback<T> callback) { + + target = addParams(target, catalogOptions); + target = addParams(target, queryOptions); + + response(target, type, callback); + } + + /** + * Given a {@link javax.ws.rs.client.WebTarget} object and a type to marshall + * the result JSON into, complete the HTTP GET request. + * + * @param webTarget The JAX-RS target. + * @param responseType The class to marshall the JSON into. + * @param <T> The class to marshall the JSON into. + * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} containing the result. + */ + public static <T> ConsulResponse<T> response(WebTarget webTarget, GenericType<T> responseType) { + Response response = webTarget.request().accept(MediaType.APPLICATION_JSON_TYPE).get(); + + return consulResponse(responseType, response); + } + + /** + * Given a {@link javax.ws.rs.client.WebTarget} object and a type to marshall + * the result JSON into, complete the HTTP GET request. + * + * @param webTarget The JAX-RS target. + * @param responseType The class to marshall the JSON into. + * @param callback The callback object to handle the result on a different thread. + * @param <T> The class to marshall the JSON into. + */ + public static <T> void response(WebTarget webTarget, final GenericType<T> responseType, + final ConsulResponseCallback<T> callback) { + webTarget.request().accept(MediaType.APPLICATION_JSON_TYPE).async().get(new InvocationCallback<Response>() { + + @Override + public void completed(Response response) { + try { + callback.onComplete(consulResponse(responseType, response)); + } catch (Exception ex) { + callback.onFailure(ex); + } + } + + @Override + public void failed(Throwable throwable) { + callback.onFailure(throwable); + } + }); + } + + /** + * Extracts Consul specific headers and adds them to a {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} + * object, which also contains the returned JSON entity. + * + * @param responseType The class to marshall the JSON to. + * @param response The HTTP response. + * @param <T> The class to marshall the JSON to. + * @return A {@link org.onap.msb.sdclient.wrapper.consul.model.ConsulResponse} object. + */ + private static <T> ConsulResponse<T> consulResponse(GenericType<T> responseType, Response response) { + handleErrors(response); + + String indexHeaderValue = response.getHeaderString("X-Consul-Index"); + String lastContactHeaderValue = response.getHeaderString("X-Consul-Lastcontact"); + String knownLeaderHeaderValue = response.getHeaderString("X-Consul-Knownleader"); + + BigInteger index = new BigInteger(indexHeaderValue); + long lastContact = lastContactHeaderValue == null ? -1 : Long.parseLong(lastContactHeaderValue); + boolean knownLeader = knownLeaderHeaderValue == null ? false : Boolean.valueOf(knownLeaderHeaderValue); + + ConsulResponse<T> consulResponse = new ConsulResponse<T>(readResponse(response, responseType), lastContact, knownLeader, index); + + response.close(); + + return consulResponse; + } + + /** + * Converts a {@link Response} object to the generic type provided, or an empty + * representation if appropriate + * + * @param response response + * @param responseType response type + * @param <T> + * @return the re + */ + @SuppressWarnings("unchecked") + private static <T> T readResponse(Response response, GenericType<T> responseType) { + if (response.getStatus() == Response.Status.NOT_FOUND.getStatusCode()) { + // would be nice I knew a better way to do this + if (responseType.getRawType() == List.class) { + return (T) ImmutableList.of(); + } else if (responseType.getRawType() == Optional.class) { + return (T) Optional.absent(); + } else if(responseType.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 " + responseType.getRawType()); + } + } + return response.readEntity(responseType); + } + + /** + * Since Consul returns plain text when an error occurs, check for + * unsuccessful HTTP status code, and throw an exception with the text + * from Consul as the message. + * + * @param response The HTTP response. + */ + public static void handleErrors(Response response) { + + if (response.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL + || response.getStatus() == Response.Status.NOT_FOUND.getStatusCode()) { + // not an error + return; + } + + try { + final String message = response.hasEntity() ? response.readEntity(String.class) : null; + if (response.getStatusInfo().getFamily() == Response.Status.Family.SERVER_ERROR) { + throw new ServerErrorException(message, response); + } else { + throw new WebApplicationException(message, response); + } + } catch (Exception e) { + throw new ConsulException(e.getLocalizedMessage(), e); + } finally { + response.close(); + } + } +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/Jackson.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/Jackson.java new file mode 100644 index 0000000..95af542 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/Jackson.java @@ -0,0 +1,33 @@ +/** + * 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.sdclient.wrapper.consul.util; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.guava.GuavaModule; + +public class Jackson { + + public static final ObjectMapper MAPPER = newObjectMapper(); + + private static ObjectMapper newObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new GuavaModule()); + return mapper; + } + + private Jackson() {} + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ObjectMapperContextResolver.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ObjectMapperContextResolver.java new file mode 100644 index 0000000..95247b5 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/consul/util/ObjectMapperContextResolver.java @@ -0,0 +1,34 @@ +/** + * 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.sdclient.wrapper.consul.util; + +import javax.ws.rs.ext.ContextResolver; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> { + + private final ObjectMapper objectMapper; + public ObjectMapperContextResolver(final ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + @Override + public ObjectMapper getContext(final Class<?> type) { + return objectMapper; + } + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/ConfigUtil.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/ConfigUtil.java new file mode 100644 index 0000000..454a07a --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/ConfigUtil.java @@ -0,0 +1,140 @@ +/** + * 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.sdclient.wrapper.util; + +import org.apache.commons.lang3.StringUtils; +import org.onap.msb.sdclient.DiscoverAppConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @ClassName: ConfigUtil + * @Description: TODO(服务发现配置项工具类) + * @author tanghua10186366 + * @date 2017年1月23日 + * + */ +public class ConfigUtil { + + private static ConfigUtil instance = new ConfigUtil(); + + + private ConfigUtil() {} + + public static ConfigUtil getInstance() { + return instance; + } + + + private String tcpudpPortRangeStart= DiscoverUtil.TCP_UDP_PORT_RANGE_START; + + private String tcpudpPortRangeEnd=DiscoverUtil.TCP_UDP_PORT_RANGE_END; + + private String consulAddress = DiscoverUtil.CONSUL_ADDRESSS; + + private String consulRegisterMode=DiscoverUtil.CONSUL_REGISTER_MODE; + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigUtil.class); + + public void initConsulClientInfo(DiscoverAppConfig config) { + + + String env_CONSUL_IP = System.getenv("CONSUL_IP"); + + + if (StringUtils.isNotBlank(env_CONSUL_IP)) { + String consul_port = DiscoverUtil.CONSUL_DEFAULT_PORT; + try { + consul_port = config.getConsulAdderss().split(":")[1]; + } catch (Exception e) { + LOGGER.error("initConsulClientInfo throw err:" + e.getMessage()); + } + + consulAddress = env_CONSUL_IP + ":" + consul_port; + } else if (StringUtils.isNotBlank(config.getConsulAdderss())) { + { + consulAddress = config.getConsulAdderss(); + } + + + LOGGER.info("init Discover CONSUL ADDRESSS:" + consulAddress); + + + } + } + + public void initTCP_UDP_portRange(){ + + String env_TCP_UDP_PORT_RANGE_START=System.getenv("TCP_UDP_PORT_RANGE_START"); + String env_TCP_UDP_PORT_RANGE_END=System.getenv("TCP_UDP_PORT_RANGE_END"); + + + if(StringUtils.isNotBlank(env_TCP_UDP_PORT_RANGE_START)) + { + tcpudpPortRangeStart=env_TCP_UDP_PORT_RANGE_START; + } + + + if(StringUtils.isNotBlank(env_TCP_UDP_PORT_RANGE_END)) + { + tcpudpPortRangeEnd=env_TCP_UDP_PORT_RANGE_END; + } + + LOGGER.info("init TCP_UDP portRange:"+ tcpudpPortRangeStart+"-"+tcpudpPortRangeEnd); + + } + + public void initConsulRegisterMode(DiscoverAppConfig config){ + + String env_CONSUL_REGISTER_MODE=System.getenv("CONSUL_REGISTER_MODE"); + + if(StringUtils.isNotBlank(env_CONSUL_REGISTER_MODE)) + { + consulRegisterMode=env_CONSUL_REGISTER_MODE; + } + else{ + if(StringUtils.isNotBlank(config.getConsulRegisterMode())){ + consulRegisterMode=config.getConsulRegisterMode(); + } + } + + LOGGER.info("init Consul Register Mode:"+consulRegisterMode); + + } + + + + public String getConsulAddress() { + return consulAddress; + } + + public String getTcpudpPortRangeStart() { + return tcpudpPortRangeStart; + } + + + public String getTcpudpPortRangeEnd() { + return tcpudpPortRangeEnd; + } + + + public String getConsulRegisterMode() { + return consulRegisterMode; + } + + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/DiscoverUtil.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/DiscoverUtil.java new file mode 100644 index 0000000..fb61294 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/DiscoverUtil.java @@ -0,0 +1,153 @@ +/** + * 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.sdclient.wrapper.util; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; + +/** +* @ClassName: ApiRouteUtil +* @Description: TODO(ApiRoute工具类) +* @author tanghua10186366 +* @date 2015年9月29日 下午3:19:51 +* +*/ +public class DiscoverUtil { + + + public static final String CONSUL_DEFAULT_PORT="8500"; + + public static final String APIGATEWAY_SERVINCE = "apigateway"; + + public static final String ROUTER_SERVINCE = "router"; + + public static final String APIGATEWAY_SERVINCE_ALL = "all"; + + public static final String APIGATEWAY_SERVINCE_DEFAULT = "default"; + + public static final String VISUAL_RANGE_IN = "1"; + + public static final String VISUAL_RANGE_OUT = "0"; + + public static final String SERVICENAME_LINE_NAMESPACE="-"; + + public static final String SPLIT_LINE="|"; + + public static final String EXTERNAL_NODE_NAME="externalService"; + + + public static final String REQUEST_SUCCESS = "SUCCESS"; + + public static final String REQUEST_FAIL = "FAIL"; + + public static final String VISUAL_RANGE_LIST="0,1"; + + public static final String PROTOCOL_LIST="REST,HTTP,MQ,FTP,SNMP,UI,TCP,UDP,PORTAL"; + + public static final String LB_POLICY_LIST="round-robin,ip_hash,least_conn,client_custom"; + + public static final String LB_PARAMS_LIST="weight,max_fails,fail_timeout"; + + public static final String CHECK_TYPE_LIST="HTTP,TCP,TTL"; + + public static final String CHECK_HA_ROLE_LIST="active,standby"; + + public static final String CONSUL_CATALOG_URL="/v1/catalog"; + + public static final String CONSUL_AGENT_URL="/v1/agent/service"; + + public static final String CONSUL_AGENT_TTL_URL="/v1/agent/check/pass/"; + + public static final String CONSUL_HEALTH_URL="/v1/health/service/"; + + public static final String[] PUBLISH_PROTOCOL={"TCP","UDP","HTTP","REST","UI","PORTAL"}; + + public static final String[] HTTP_PROTOCOL={"HTTP","REST","UI","PORTAL"}; + + public static final String TCP_UDP_PORT_RANGE_START="28001"; + + public static final String TCP_UDP_PORT_RANGE_END="30000"; + + public static final String CONSUL_ADDRESSS="127.0.0.1:8500"; + + public static final String CONSUL_REGISTER_MODE="catalog"; + +// public static boolean isProtocol_tcp_udp(String protocol){ +// return "TCP".equals(protocol) || "UDP".equals(protocol); +// } +// + + public static String getRealIp(HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) { + // 多次反向代理后会有多个ip值,第一个ip才是真实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(); + + } + + public static boolean checkVisualRangeIn(String visualRange){ + return checkExist(visualRange,DiscoverUtil.VISUAL_RANGE_IN, "|"); + } + + public static boolean checkVisualRangeOut(String visualRange){ + return checkExist(visualRange,DiscoverUtil.VISUAL_RANGE_OUT, "|"); + } + + public static boolean checkExist(String list,String value,String separator){ + String[] listArray=StringUtils.split(list, separator); + + for(int i=0;i<listArray.length;i++){ + if(value.equals(listArray[i])) return true; + } + return false; + } + + public static boolean checkExist(String[] list,String value){ + for(int i=0;i<list.length;i++){ + if(value.equals(list[i])) 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; + + } + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/HttpClientUtil.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/HttpClientUtil.java new file mode 100644 index 0000000..7d06d15 --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/HttpClientUtil.java @@ -0,0 +1,218 @@ +/** + * 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.sdclient.wrapper.util; + +import java.io.IOException; +import java.math.BigInteger; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.NameValuePair; +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.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.onap.msb.sdclient.core.ConsulResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HttpClientUtil { + + private static final Logger logger = LoggerFactory + .getLogger(HttpClientUtil.class); + + public static int httpPostWithJSON(String url, String params) { + int result = 0; + CloseableHttpClient httpClient = HttpClients.createDefault(); + HttpPost httpPost = new HttpPost(url); + httpPost.addHeader("Content-type", "application/json; charset=utf-8"); + httpPost.setHeader("Accept", "application/json"); + httpPost.setEntity(new StringEntity(params, Charset.forName("UTF-8"))); + try { + CloseableHttpResponse res = httpClient.execute(httpPost); + result = res.getStatusLine().getStatusCode(); + if (res.getStatusLine().getStatusCode() != 200) { + logger.error(String.valueOf(result)); + } + res.close(); + } catch (IOException e) { + String errorMsg = url + ":httpPostWithJSON connect faild"; + } finally { + try { + httpClient.close(); + } catch (IOException e) { + String errorMsg = url + ":close httpClient faild"; + } + } + + return result; + + } + + public static void delete(String url, String parameter) throws Exception { + String result = null; + String baseUrl; + if (parameter != null) { + List<NameValuePair> params = new ArrayList<NameValuePair>(); + params.add(new BasicNameValuePair("serviceName", parameter)); + baseUrl = url + "?" + URLEncodedUtils.format(params, "UTF-8"); + } else { + baseUrl = url; + } + + CloseableHttpClient httpClient = HttpClients.createDefault(); + ; + try { + + HttpDelete httpDelete = new HttpDelete(baseUrl); + CloseableHttpResponse res = httpClient.execute(httpDelete); + + if (res.getStatusLine().getStatusCode() != 200) { + throw new Exception("delete fail"); + } + + res.close(); + } catch (IOException e) { + String errorMsg = baseUrl + ":delete connect faild"; + } finally { + try { + httpClient.close(); + } catch (IOException e) { + String errorMsg = baseUrl + ":close httpClient faild"; + } + } + + } + + 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); + + res.getLastHeader("X-Consul-Index"); + result = EntityUtils.toString(res.getEntity()); + if (res.getStatusLine().getStatusCode() != 200) { + logger.error(result); + } + res.close(); + } catch (ClientProtocolException e) { + String errorMsg = url + ":httpGetWithJSON connect faild"; + logger.error(errorMsg); + } catch (IOException e) { + String errorMsg = url + ":httpGetWithJSON connect faild"; + logger.error(errorMsg); + } finally { + try { + httpClient.close(); + } catch (IOException e) { + String errorMsg = url + ":close httpClient faild"; + logger.error(errorMsg); + } + } + + return result; + + } + + @SuppressWarnings("unchecked") + public static <T> ConsulResponse<T> httpWaitGet(String url) { + 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); + String result = EntityUtils.toString(res.getEntity()); + + if (res.getStatusLine().getStatusCode() != 200) { + logger.error(result); + } else { + String indexHeaderValue = res.getLastHeader("X-Consul-Index") + .getValue(); + BigInteger index = new BigInteger(indexHeaderValue); + + return new ConsulResponse<T>((T) result, index); + + } + + res.close(); + } catch (ClientProtocolException e) { + String errorMsg = url + ":httpGetWithJSON connect faild " + + e.getMessage(); + logger.error(errorMsg); + } catch (IOException e) { + String errorMsg = url + ":httpGetWithJSON connect faild " + + e.getMessage(); + logger.error(errorMsg); + } finally { + try { + httpClient.close(); + } catch (IOException e) { + String errorMsg = url + ":close httpClient faild " + + e.getMessage(); + logger.error(errorMsg); + } + } + + return null; + + } + + 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/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/JacksonJsonUtil.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/JacksonJsonUtil.java new file mode 100644 index 0000000..47eac9b --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/JacksonJsonUtil.java @@ -0,0 +1,171 @@ +/** + * 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.sdclient.wrapper.util; + +import java.util.List; +import java.util.Map; + +import org.onap.msb.sdclient.core.CatalogService; +import org.onap.msb.sdclient.core.HealthService; +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 static ObjectMapper mapper; + + /** + * 获取ObjectMapper实例 + * @param createNew 方式:true,新实例;false,存在的mapper实例 + * @return + */ + public static synchronized ObjectMapper getMapperInstance() { + if (mapper == null) { + mapper = new ObjectMapper(); + } + return mapper; + } + + /** + * 将java对象转换成json字符串 + * @param obj 准备转换的对象 + * @return json字符串 + * @throws Exception + */ + public static String beanToJson(Object obj) throws Exception { + String json=null; + try { + ObjectMapper objectMapper = getMapperInstance(); + objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); + json =objectMapper.writeValueAsString(obj); + } catch (Exception e) { + logger.error("Class beanToJson faild:"+e.getMessage()); + throw new Exception("Class beanToJson faild:"+e.getMessage()); + } + return json; + } + + + + /** + * 将json字符串转换成java对象 + * @param json 准备转换的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:"+e.getMessage()); + throw new Exception(cls+" JsonTobean faild:"+e.getMessage()); + } + return vo; + } + + + + + /** + * 将json字符串转换成java集合对象 + * @param json 准备转换的json字符串 + * @param cls 准备转换的类 + * @return + * @throws Exception + */ + public static List<CatalogService> jsonToListBean(String json) { + List<CatalogService> vo =null; + try { + + ObjectMapper objectMapper = getMapperInstance(); + + + vo = objectMapper.readValue(json, new TypeReference<List<CatalogService>>() {}); + + } catch (Exception e) { + String errorMsg =" JsonTobean faild:"+e.getMessage(); + logger.error(errorMsg); + } + return vo; + } + + 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; + } + + + + + + /** + * 将json字符串转换成java集合对象 + * @param json 准备转换的json字符串 + * @param cls 准备转换的类 + * @return + * @throws Exception + */ + public static Map<String,String[]> jsonToMapBean(String json) { + Map<String,String[]> vo =null; + try { + + ObjectMapper objectMapper = getMapperInstance(); + + + vo = objectMapper.readValue(json, new TypeReference<Map<String,String[]>>() {}); + + } catch (Exception e) { + String errorMsg =" JsonTobean faild"; + logger.error(errorMsg); + } + return vo; + } + + + public static void main(String[] args) { + String json="[{\"Node\":{\"Node\":\"A23179111\",\"Address\":\"10.74.44.27\",\"CreateIndex\":3,\"ModifyIndex\":318},\"Service\":{\"ID\":\"oo_10.74.56.36_5656\",\"Service\":\"oo\",\"Tags\":[\"url:/root\",\"protocol:REST\",\"version:\",\"visualRange:0|1\",\"ttl:-1\",\"status:1\",\"lb_policy:client_custom\",\"lb_server_params:weight=1 max_fails=1 fail_timeout=16s\",\"checkType:TCP\",\"checkInterval:10\",\"checkUrl:10.56.23.63:8989\"],\"Address\":\"10.74.56.36\",\"Port\":5656,\"EnableTagOverride\":false,\"CreateIndex\":314,\"ModifyIndex\":318},\"Checks\":[{\"Node\":\"A23179111\",\"CheckID\":\"serfHealth\",\"Name\":\"Serf Health Status\",\"Status\":\"passing\",\"Notes\":\"\",\"Output\":\"Agent alive and reachable\",\"ServiceID\":\"\",\"ServiceName\":\"\",\"CreateIndex\":3,\"ModifyIndex\":3},{\"Node\":\"A23179111\",\"CheckID\":\"service:oo_10.74.56.36_5656\",\"Name\":\"Service 'oo' check\",\"Status\":\"critical\",\"Notes\":\"\",\"Output\":\"\",\"ServiceID\":\"oo_10.74.56.36_5656\",\"ServiceName\":\"oo\",\"CreateIndex\":314,\"ModifyIndex\":318}]},{\"Node\":{\"Node\":\"A23179111\",\"Address\":\"10.74.44.27\",\"CreateIndex\":3,\"ModifyIndex\":318},\"Service\":{\"ID\":\"oo_10.78.36.36_111\",\"Service\":\"oo\",\"Tags\":[\"url:/root\",\"protocol:REST\",\"version:\",\"visualRange:0|1\",\"ttl:-1\",\"status:1\",\"lb_policy:client_custom\"],\"Address\":\"10.78.36.36\",\"Port\":111,\"EnableTagOverride\":false,\"CreateIndex\":315,\"ModifyIndex\":315},\"Checks\":[{\"Node\":\"A23179111\",\"CheckID\":\"serfHealth\",\"Name\":\"Serf Health Status\",\"Status\":\"passing\",\"Notes\":\"\",\"Output\":\"Agent alive and reachable\",\"ServiceID\":\"\",\"ServiceName\":\"\",\"CreateIndex\":3,\"ModifyIndex\":3}]}]"; + List<HealthService> list=jsonToListBean(json,new TypeReference<List<HealthService>>() { + }); + System.out.println(list); + + } + + + + +} diff --git a/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/RegExpTestUtil.java b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/RegExpTestUtil.java new file mode 100644 index 0000000..0203dee --- /dev/null +++ b/sdclient/discovery-service/src/main/java/org/onap/msb/sdclient/wrapper/util/RegExpTestUtil.java @@ -0,0 +1,117 @@ +/** + * 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.sdclient.wrapper.util; + +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; + +public class RegExpTestUtil { + + public static boolean httpUrlRegExpTest(String url){ + + + + String httpUrlReg = "^(|http:\\/\\/)(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(httpUrlReg, url); + +} + + 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}$"; + if(Pattern.matches(hostReg, port)){ + int iport=Integer.parseInt(port); + if(iport>=1 && iport<=65535) return true; + } + + return false; + + } + +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 serviceNameRegExpTest(String serviceName){ + + String serviceNameReg = "^([0-9a-zA-Z]|-|_)*$"; + return Pattern.matches(serviceNameReg, serviceName); + +} + +public static boolean apiRouteUrlRegExpTest(String url){ + + String urlReg = "^\\/api\\/.*$"; + return Pattern.matches(urlReg, url); + +} + +public static boolean labelRegExpTest(String label){ + + String labelReg = "^\\S+:\\S+$"; + String[] labelArray=StringUtils.split(label,","); + for(int i=0;i<labelArray.length;i++){ + if(!Pattern.matches(labelReg, labelArray[i])){ + return false; + } + } + return true; + +} + + + public static void main(String[] args) { + + System.out.println(httpUrlRegExpTest("/wqew")); + } +} diff --git a/sdclient/discovery-standalone/pom.xml b/sdclient/discovery-standalone/pom.xml new file mode 100644 index 0000000..431d480 --- /dev/null +++ b/sdclient/discovery-standalone/pom.xml @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <groupId>org.onap.msb.discovery</groupId> + <artifactId>sdclient</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <groupId>org.onap.msb.discovery.sdclient</groupId> + <artifactId>discovery-standalone</artifactId> + <name>onap/msb/discovery/sdclient/discovery-standalone</name> + <packaging>pom</packaging> + <version>0.0.1-SNAPSHOT</version> + + <properties> + <packageid>discovery-standalone</packageid> + <outputdir>target/assembly/</outputdir> + </properties> + + <dependencies> + <dependency> + <groupId>org.onap.msb.discovery.sdclient</groupId> + <artifactId>discovery-service</artifactId> + <version>${project.version}</version> + <optional>true</optional> + </dependency> + </dependencies> + <build> + + <plugins> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>copy-resources</id> + <phase>process-resources</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>${outputdir}</outputDirectory> + <includeEmptyDirs>true</includeEmptyDirs> + <resources> + <resource> + <directory>src/assembly/resources/</directory> + <filtering>false</filtering> + <includes> + <include>**/*</include> + </includes> + </resource> + </resources> + <overwrite>true</overwrite> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.8</version> + <executions> + <execution> + <id>copy-jar</id> + <goals> + <goal>copy</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <artifactItems> + <artifactItem> + <groupId>org.onap.msb.discovery.sdclient</groupId> + <artifactId>discovery-service</artifactId> + <type>jar</type> + <overWrite>true</overWrite> + <outputDirectory>${outputdir}/discover/</outputDirectory> + <destFileName>discovery-service.jar</destFileName> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-antrun-plugin</artifactId> + <executions> + <execution> + <id>distribution</id> + <phase>package</phase> + <goals> + <goal>run</goal> + </goals> + <configuration> + <target name="distribution"> + <zip destfile="${version.output}/${packageid}-${project.version}.zip" update="true"> + <zipfileset dir="target/assembly/" includes="**"/> + </zip> + <attachartifact file="${version.output}/${packageid}-${project.version}.zip" type="zip"/> + + </target> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project> + diff --git a/sdclient/discovery-standalone/src/assembly/resources/discover/conf/discover.yml b/sdclient/discovery-standalone/src/assembly/resources/discover/conf/discover.yml new file mode 100644 index 0000000..8236cae --- /dev/null +++ b/sdclient/discovery-standalone/src/assembly/resources/discover/conf/discover.yml @@ -0,0 +1,61 @@ +#
+# 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.
+#
+
+defaultWorkspace: ../discovery-works
+
+defaultName: ${DW_DEFAULT_NAME:-Stranger}
+
+# the consul address
+consulAdderss: 127.0.0.1:8500
+
+# the consul way:catalog|agent
+consulRegisterMode: agent
+
+# use the simple server factory if you only want to run on a single port
+server:
+ type: simple
+ rootPath: '/api/microservices/v1/*'
+ applicationContextPath: /
+ adminContextPath: /admin
+ connector:
+ type: http
+ port: 8076
+
+# Logging settings.
+logging:
+
+ # The default level of all loggers. Can be OFF, ERROR, WARN, INFO, DEBUG, TRACE, or ALL.
+ level: ALL
+
+ # Logger-specific levels.
+ loggers:
+
+ # Sets the level for 'com.example.app' to DEBUG.
+ com.example: DEBUG
+
+ appenders:
+ - type: console
+ threshold: INFO
+ timeZone: UTC
+ logFormat: "%d{yyyy-MM-dd HH:mm:ss SSS} %-5p [%c][%t] - %m%n"
+ - type: file
+ threshold: INFO
+ logFormat: "%d{yyyy-MM-dd HH:mm:ss SSS} %-5p [%c][%t] - %m%n"
+ currentLogFilename: ../discover-works/logs/msb-discover.log
+ archivedLogFilenamePattern: ../discover-works/logs/zip/msb-discover-%d{yyyy-MM-dd}.log.gz
+ archivedFileCount: 7
+ timeZone: UTC
+
diff --git a/sdclient/discovery-standalone/src/assembly/resources/discover/run.sh b/sdclient/discovery-standalone/src/assembly/resources/discover/run.sh new file mode 100644 index 0000000..fd86036 --- /dev/null +++ b/sdclient/discovery-standalone/src/assembly/resources/discover/run.sh @@ -0,0 +1,79 @@ +#!/bin/sh +# +# 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. +# + + +DIRNAME=`dirname $0` +RUNHOME=`cd $DIRNAME/; pwd` +echo @RUNHOME@ $RUNHOME + +if [ -f "$RUNHOME/setenv.sh" ]; then + . "$RUNHOME/setenv.sh" +else +echo "can not found $RUNHOME/setenv.sh" +fi + +# set CONSUL_IP in ha mode +if [ -n "${HA_MODE}" ]; then + export CONSUL_IP=`cat /root/consul.ip` + export CONSUL_REGISTER_MODE="catalog" +fi + +echo ================== ENV_INFO ============================================= +echo @RUNHOME@ $RUNHOME +echo @JAVA_HOME@ $JAVA_HOME +echo @Main_Class@ $Main_Class +echo @APP_INFO@ $APP_INFO +echo @Main_JAR@ $Main_JAR +echo @Main_Conf@ $Main_Conf +echo @CONSUL_IP@ ${CONSUL_IP} +echo ========================================================================== + +echo start $APP_INFO ... + +JAVA="$JAVA_HOME/bin/java" + +JAVA_VERSION=`$JAVA -version 2>&1 |awk 'NR==1{ sub(/"/,""); print substr($3,1,3)}'` +echo @JAVA_VERSION@ $JAVA_VERSION + +MAXIMUM_HEAP_SIZE=128m +echo @MAXIMUM_HEAP_SIZE@ ${MAXIMUM_HEAP_SIZE} + +if [ $JAVA_VERSION = "1.8" ] +then + JAVA_OPTS="-Xms16m -Xmx${MAXIMUM_HEAP_SIZE} -XX:+UseSerialGC -XX:MaxMetaspaceSize=64m -XX:NewRatio=2" +else + JAVA_OPTS="-Xms16m -Xmx${MAXIMUM_HEAP_SIZE} -XX:+UseSerialGC -XX:MaxPermSize=64m -XX:NewRatio=2" +fi + +port=8789 + +CLASS_PATH="$RUNHOME/:$RUNHOME/$Main_JAR" + +echo ================== RUN_INFO ============================================= +echo @JAVA_HOME@ $JAVA_HOME +echo @JAVA@ $JAVA +echo @JAVA_OPTS@ $JAVA_OPTS +echo @CLASS_PATH@ $CLASS_PATH +echo @EXT_DIRS@ $EXT_DIRS +echo ========================================================================== + +cd $RUNHOME +echo @JAVA@ $JAVA +echo @JAVA_CMD@ +"$JAVA" $JAVA_OPTS -classpath "$CLASS_PATH" $Main_Class server "$RUNHOME/$Main_Conf" + + diff --git a/sdclient/discovery-standalone/src/assembly/resources/discover/setenv.sh b/sdclient/discovery-standalone/src/assembly/resources/discover/setenv.sh new file mode 100644 index 0000000..92a8752 --- /dev/null +++ b/sdclient/discovery-standalone/src/assembly/resources/discover/setenv.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# +# 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. +# + + +Main_Class="org.onap.msb.sdclient.DiscoverApp" +Main_JAR="discovery-service.jar" +Main_Conf="conf/discover.yml" +APP_INFO="msb-discovery-service" diff --git a/sdclient/discovery-standalone/src/assembly/resources/discover/stop.sh b/sdclient/discovery-standalone/src/assembly/resources/discover/stop.sh new file mode 100644 index 0000000..e4f57c0 --- /dev/null +++ b/sdclient/discovery-standalone/src/assembly/resources/discover/stop.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# 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. +# + + +DIRNAME=`dirname $0` +RUNHOME=`cd $DIRNAME/; pwd` +echo @RUNHOME@ $RUNHOME + + +if [ -f "$RUNHOME/setenv.sh" ]; then + . "$RUNHOME/setenv.sh" +else +echo "can not found $RUNHOME/setenv.sh" +fi + + +echo ================== ENV_INFO ============================================= +echo RUNHOME=$RUNHOME +echo JAVA_BASE=$JAVA_BASE +echo Main_Class=$Main_Class +echo APP_INFO=$APP_INFO +echo ========================================================================== + + +cd $RUNHOME; pwd + +function save_app_pid(){ + app_id=`ps -ef | grep $Main_Class| grep $RUNHOME | grep -v grep | awk '{print $2}'` + echo @app_id@ $app_id +} + +function kill_app_process(){ + ps -p $app_id + if [ $? == 0 ]; then + kill -9 $app_id + fi +} + +save_app_pid; +echo @C_CMD@ kill -9 $app_id +kill_app_process; + + + + diff --git a/sdclient/pom.xml b/sdclient/pom.xml new file mode 100644 index 0000000..6b92ecd --- /dev/null +++ b/sdclient/pom.xml @@ -0,0 +1,301 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.onap.msb.discovery</groupId> + <artifactId>msb-discovery-parent</artifactId> + <version>0.0.1-SNAPSHOT</version> + </parent> + + <groupId>org.onap.msb.discovery</groupId> + <artifactId>sdclient</artifactId> + <version>0.0.1-SNAPSHOT</version> + <name>onap/msb/discovery/sdclient</name> + <packaging>pom</packaging> + + <modules> + <module>discovery-service</module> + <module>discovery-standalone</module> + </modules> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + + <!-- Java Versions --> + <!-- FIXME: confirm these two are picked by maven-compiler-plugin --> + <maven.compiler.source>1.7</maven.compiler.source> + <maven.compiler.target>1.7</maven.compiler.target> + <java.version.source>${maven.compiler.source}</java.version.source> + <java.version.target>${maven.compiler.target}</java.version.target> + + + <!-- dependency version --> + <dropwizard.version>0.8.0</dropwizard.version> + <swagger.version>1.5.3</swagger.version> + <lombok.version>1.16.4</lombok.version> + + <jetty.version>9.2.9.v20150224</jetty.version> + <jackson-version>2.7.9</jackson-version> + <jersey.version>2.16</jersey.version> + <slf4j.version>1.7.12</slf4j.version> + <logback.version>1.1.3</logback.version> + <!-- <httpclient.version>4.5</httpclient.version> --> + + + <guava.version>18.0</guava.version> + <annotation-api.version>1.2</annotation-api.version> + + <junit.version>4.11</junit.version> + <powermock.version>1.5.5</powermock.version> + + </properties> + + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>${guava.version}</version> + </dependency> +<!-- <dependency> + <groupId>javax.ws.rs</groupId> + <artifactId>javax.ws.rs-api</artifactId> + <version>${rs-api.version}</version> + </dependency> --> +<!-- <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>${commons-lang3.version}</version> + </dependency> --> + <dependency> + <groupId>javax.annotation</groupId> + <artifactId>javax.annotation-api</artifactId> + <version>${annotation-api.version}</version> + </dependency> + + + + <dependency> + <groupId>com.fasterxml.jackson.jaxrs</groupId> + <artifactId>jackson-jaxrs-base</artifactId> + <version>${jackson-version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.jaxrs</groupId> + <artifactId>jackson-jaxrs-json-provider</artifactId> + <version>${jackson-version}</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-guava</artifactId> + <version>${jackson-version}</version> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-client</artifactId> + <version>${jersey.version}</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-junit4</artifactId> + <version>${powermock.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + <version>${powermock.version}</version> + <scope>test</scope> + </dependency> + + <!-- Supporting Libraries --> + <dependency> + <groupId>io.dropwizard</groupId> + <artifactId>dropwizard-core</artifactId> + <version>${dropwizard.version}</version> + </dependency> + + <dependency> + <groupId>io.dropwizard</groupId> + <artifactId>dropwizard-assets</artifactId> + <version>${dropwizard.version}</version> + </dependency> + + + <dependency> + <groupId>io.dropwizard</groupId> + <artifactId>dropwizard-client</artifactId> + <version>${dropwizard.version}</version> + </dependency> + + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey2-jaxrs</artifactId> + <version>${swagger.version}</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + <version>${lombok.version}</version> + </dependency> + <!--jersey --> + <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-multipart</artifactId> + <version>${jersey.version}</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-servlet-core</artifactId> + <version>${jersey.version}</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.core</groupId> + <artifactId>jersey-common</artifactId> + <version>${jersey.version}</version> + </dependency> + + <!--jackson --> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <version>${jackson-version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>2.7.9.1</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + <version>${jackson-version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-xml</artifactId> + <version>${jackson-version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-yaml</artifactId> + <version>${jackson-version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.module</groupId> + <artifactId>jackson-module-jaxb-annotations</artifactId> + <version>${jackson-version}</version> + </dependency> + + <!--jetty --> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-io</artifactId> + <version>${jetty.version}</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-util</artifactId> + <version>${jetty.version}</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-http</artifactId> + <version>${jetty.version}</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-client</artifactId> + <version>${jetty.version}</version> + </dependency> +<!-- <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-continuation</artifactId> + <version>${jetty.version}</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-jmx</artifactId> + <version>${jetty.version}</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-webapp</artifactId> + <version>${jetty.version}</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-xml</artifactId> + <version>${jetty.version}</version> + </dependency> --> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlet</artifactId> + <version>${jetty.version}</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-security</artifactId> + <version>${jetty.version}</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <version>${jetty.version}</version> + </dependency> + <!-- logger --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <version>${logback.version}</version> + </dependency> + + + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-core</artifactId> + <version>${logback.version}</version> + </dependency> + + </dependencies> + </dependencyManagement> +</project>
\ No newline at end of file |