Fix snapshot dependency and security 91/37991/2
authorDenes Nemeth <denes.nemeth@nokia.com>
Fri, 23 Mar 2018 07:43:06 +0000 (08:43 +0100)
committerDenes Nemeth <denes.nemeth@nokia.com>
Fri, 23 Mar 2018 07:50:40 +0000 (08:50 +0100)
Change-Id: Ief922144c5c9cd46a147fb697279d947f667889e
Signed-off-by: Denes Nemeth <denes.nemeth@nokia.com>
Issue-ID: VFC-728

13 files changed:
nokiav2/deployment/src/main/resources/Dockerfile
nokiav2/docs/integration.rst
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/SelfRegistrationManager.java
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/LcmApi.java
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/RealConfig.java
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/SecurityConfig.java
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/JobManager.java
nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/TestRealConfig.java
nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/TestSecurityConfig.java
nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestJobManager.java
nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestSelfRegistrationManager.java
nokiav2/driverwar/pom.xml
nokiav2/generatedapis/src/main/resources/msb.json [new file with mode: 0644]

index 2ad7209..eb13714 100755 (executable)
@@ -6,12 +6,13 @@ COPY LICENSE ./ONAP_LICENSE
 COPY application.properties .
 RUN sed -i 's/enabled=1/enabled=0/' /etc/yum/pluginconf.d/fastestmirror.conf
 RUN sed -i 's|#baseurl=http://mirror.centos.org/centos|baseurl=http://mirrors.ocf.berkeley.edu/centos|' /etc/yum.repos.d/*.repo
-RUN yum -y update
-RUN yum -y install java-1.8.0-openjdk-headless wget
-# Debugging tools withing the container
-RUN yum -y install mc vim tcpdump net-tools nc strace telnet unzip xmlstarlet
+RUN yum -y update && \
+    yum -y install java-1.8.0-openjdk-headless wget && \
+    yum -y install mc vim tcpdump net-tools nc strace telnet unzip xmlstarlet && \
+    yum clean all
 RUN wget -q -O driver.war "https://nexus.onap.org/service/local/artifact/maven/redirect?r=staging&g=org.onap.vfc.nfvo.driver.vnfm.svnfm.nokiav2&a=driverwar&v=${VERSION}&e=war"
+#Can be used for local builds
+#COPY driver.war .
 ENV JAVA_HOME /usr/lib/jvm/jre
-RUN yum clean all
 EXPOSE 8089
 ENTRYPOINT /service/docker-entrypoint.sh
index c2722c5..2c02b75 100644 (file)
@@ -119,7 +119,7 @@ Add the VNFM driver to ONAP
 +-----------------+-----------------------------------+
 | version         | v1                                |
 +-----------------+-----------------------------------+
-| URL             | https://<cbamIp>:443/vnfm/lcm/v3  |
+| URL             | https://<cbamIp>:443/vnfm/lcm/v3/ |
 +-----------------+-----------------------------------+
 | VIM             | <cloudOwner>_<cloudRegionId>      |
 +-----------------+-----------------------------------+
@@ -152,5 +152,5 @@ Start the driver (fill in values)
    export IMAGE_ID=<imageId>
    export CBAM_PASSWORD=<onapPassword>
    export CBAM_USERNAME=<onapUsername>
-   docker run --name vfc_nokia -p 8089:8089 -e "MSB_IP=$MULTI_NODE_IP" -e "CONFIGURE=kuku" -e "EXTERNAL_IP=$MULTI_NODE_IP" -e "CBAM_CATALOG_URL=https://$CBAM_IP:443/api/catalog/adapter" -e "CBAM_LCN_URL=https://$CBAM_IP:443/vnfm/lcn/v3" -e "CBAM_KEYCLOAK_URL=https://$CBAM_IP:443/auth" -e "CBAM_USERNAME=$CBAM_USERNAME" -e "CBAM_PASSWORD=$CBAM_PASSWORD" -e "VNFM_ID=$VNFM_ID" -d --stop-timeout 300 $IMAGE_ID
+   docker run --name vfc_nokia -p 8089:8089 -e "MSB_IP=$MULTI_NODE_IP" -e "CONFIGURE=kuku" -e "EXTERNAL_IP=$MULTI_NODE_IP" -e "CBAM_CATALOG_URL=https://$CBAM_IP:443/api/catalog/adapter/" -e "CBAM_LCN_URL=https://$CBAM_IP:443/vnfm/lcn/v3/" -e "CBAM_KEYCLOAK_URL=https://$CBAM_IP:443/auth/" -e "CBAM_USERNAME=$CBAM_USERNAME" -e "CBAM_PASSWORD=$CBAM_PASSWORD" -e "VNFM_ID=$VNFM_ID" -d --stop-timeout 300 $IMAGE_ID
 
index 6d569e2..92064b1 100644 (file)
@@ -139,7 +139,7 @@ public class SelfRegistrationManager {
         microServiceInfo.setVisualRange(INTERNAL_SERVICE);
         microServiceInfo.setServiceName(SERVICE_NAME);
         microServiceInfo.setVersion(DRIVER_VERSION);
-        microServiceInfo.setEnable_ssl(true);
+        microServiceInfo.setEnable_ssl(false);
         Node node = new Node();
         microServiceInfo.setNodes(new HashSet<>());
         microServiceInfo.getNodes().add(node);
index 5a7bd74..be78aa0 100644 (file)
@@ -65,8 +65,6 @@ public class LcmApi {
     @ResponseBody
     public VnfInstantiateResponse instantiateVnf(@RequestBody VnfInstantiateRequest request, @PathVariable("vnfmId") String vnfmId, HttpServletResponse httpResponse) {
         logger.info("REST: Instantiate VNF");
-        //FIXME
-
         VnfInstantiateResponse response = lifecycleManager.createAndInstantiate(vnfmId, request, httpResponse);
         httpResponse.setStatus(SC_CREATED);
         return response;
index ddf7df3..f9b2e39 100644 (file)
@@ -16,6 +16,7 @@
 package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring;
 
 import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
+import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.converter.HttpMessageConverter;
 import org.springframework.http.converter.json.GsonHttpMessageConverter;
@@ -36,11 +37,10 @@ public class RealConfig {
      *
      * @return the message converter
      */
-    //FIXME? @Bean
+    @Bean
     public HttpMessageConverters customConverters() {
         Collection<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
         GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter();
-        //FIXME gsonHttpMessageConverter.setGson(new ApiClient().getAdapterBuilder().build()..getJSON().getGson());
         messageConverters.add(gsonHttpMessageConverter);
         return new HttpMessageConverters(true, messageConverters);
     }
index e3dd071..708376d 100644 (file)
@@ -18,6 +18,7 @@ package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring;
 
 import org.springframework.context.annotation.Configuration;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 
@@ -45,4 +46,18 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
                 .permitAll();
     }
 
+    /**
+     * Does not configure security, but solves the https://pivotal.io/security/cve-2017-4995
+     * "The fix ensures that by default only explicitly mapped classes will be deserialized.
+     * The effect of using explicitly mapped classes is to create a whitelist which works with all
+     * supported versions of Jackson. If users explicitly opt into global default typing, the previous
+     * potentially dangerous configuration is restored."
+     *
+     * @param web the web security configuration
+     */
+    @Override
+    public void configure(WebSecurity web) throws Exception {
+        web.ignoring().anyRequest();
+    }
+
 }
index 085231f..0d078d0 100644 (file)
@@ -22,6 +22,7 @@ import com.google.gson.JsonElement;
 import com.nokia.cbam.lcm.v32.api.OperationExecutionsApi;
 import com.nokia.cbam.lcm.v32.api.VnfsApi;
 import com.nokia.cbam.lcm.v32.model.OperationExecution;
+import com.nokia.cbam.lcm.v32.model.OperationType;
 import com.nokia.cbam.lcm.v32.model.VnfInfo;
 import org.apache.http.HttpStatus;
 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.SelfRegistrationManager;
@@ -284,14 +285,17 @@ public class JobManager {
     }
 
     private boolean isCurrentOperationTriggeredByJob(String jobId, OperationExecutionsApi cbamOperationExecutionApi, OperationExecution operationExecution) {
-
+        if(OperationType.MODIFY_INFO.equals(operationExecution.getOperationType())){
+            //the modify info is never triggered by an external job
+            return false;
+        }
         try {
             Object operationParams = cbamOperationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(operationExecution.getId(), NOKIA_LCM_API_VERSION).blockingFirst();
             if (extractOnapJobId(operationParams).equals(jobId)) {
                 return true;
             }
         } catch (Exception e) {
-            throw buildFatalFailure(logger, "Unable to retrieve operation parameters", e);
+            throw buildFatalFailure(logger, "Unable to retrieve operation parameters of operation with " + operationExecution.getId() + " identifier", e);
         }
         return false;
     }
@@ -312,7 +316,7 @@ public class JobManager {
                 return of(cbamLcmApi.vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION).blockingFirst());
             }
         } catch (Exception e) {
-            throw buildFatalFailure(logger, "Unable to retrieve VNF", e);
+            throw buildFatalFailure(logger, "Unable to retrieve VNF with " + vnfId + " identifier", e);
         }
     }
 }
index 6caeb3a..6bcce07 100644 (file)
 
 package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring;
 
-import com.nokia.cbam.lcm.v32.model.VnfIdentifierCreationNotification;
-import com.nokia.cbam.lcm.v32.model.VnfIdentifierDeletionNotification;
-import com.nokia.cbam.lcm.v32.model.VnfInfoAttributeValueChangeNotification;
-import com.nokia.cbam.lcm.v32.model.VnfLifecycleChangeNotification;
+import com.nokia.cbam.lcm.v32.model.*;
+import junit.framework.TestCase;
 import org.junit.Test;
 import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpInputMessage;
 import org.springframework.http.MediaType;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.mock.http.MockHttpInputMessage;
+import org.springframework.mock.http.MockHttpOutputMessage;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import static junit.framework.TestCase.assertEquals;
 
 public class TestRealConfig {
 
@@ -38,6 +46,17 @@ public class TestRealConfig {
         converters.getConverters().get(0).canRead(VnfInfoAttributeValueChangeNotification.class, MediaType.APPLICATION_JSON);
         converters.getConverters().get(0).canRead(VnfLifecycleChangeNotification.class, MediaType.APPLICATION_JSON);
         converters.getConverters().get(0).canRead(String.class, MediaType.APPLICATION_JSON);
+
+        HttpMessageConverter<VnfLifecycleChangeNotification> httpMessageConverter = (HttpMessageConverter<VnfLifecycleChangeNotification>) converters.getConverters().get(0);
+        MockHttpOutputMessage out = new MockHttpOutputMessage();
+        VnfLifecycleChangeNotification not = new VnfLifecycleChangeNotification();
+        not.setNotificationType(VnfNotificationType.VNFLIFECYCLECHANGENOTIFICATION);
+        not.setVnfInstanceId("vnfId");
+        httpMessageConverter.write(not, MediaType.APPLICATION_JSON, out);
+        String write = out.getBodyAsString();
+        HttpInputMessage x = new MockHttpInputMessage(write.getBytes());
+        VnfLifecycleChangeNotification deserialized = (VnfLifecycleChangeNotification) httpMessageConverter.read(VnfLifecycleChangeNotification.class, x);
+        assertEquals("vnfId", deserialized.getVnfInstanceId());
     }
 
 }
index 5d0d88b..39a8e64 100644 (file)
@@ -21,6 +21,7 @@ import org.mockito.Mockito;
 import org.springframework.security.config.annotation.ObjectPostProcessor;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
 import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
 import org.springframework.security.web.util.matcher.AnyRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
@@ -38,7 +39,7 @@ public class TestSecurityConfig {
      * this can only fully be tested from CT by starting the web service
      */
     @Test
-    public void testSpringBootApplicationInit() throws Exception {
+    public void testNoHttpSecurity() throws Exception {
         HttpSecurity http = new HttpSecurity(Mockito.mock(ObjectPostProcessor.class), Mockito.mock(AuthenticationManagerBuilder.class), new HashMap<>());
         //when
         new SecurityConfig().configure(http);
@@ -48,4 +49,19 @@ public class TestSecurityConfig {
         assertTrue(AnyRequestMatcher.class.isAssignableFrom(requestMatchers.get(0).getClass()));
     }
 
+    /**
+     * verify that no web security is performed
+     * this can only fully be tested from CT by starting the web service
+     */
+    @Test
+    public void testNoWebSecurity() throws Exception {
+        WebSecurity webSecurity = new WebSecurity(Mockito.mock(ObjectPostProcessor.class));
+        WebSecurity.IgnoredRequestConfigurer ignorer = Mockito.mock(WebSecurity.IgnoredRequestConfigurer.class);
+        ReflectionTestUtils.setField(webSecurity, "ignoredRequestRegistry", ignorer);
+        //when
+        new SecurityConfig().configure(webSecurity);
+        //verify
+        Mockito.verify(ignorer).anyRequest();
+    }
+
 }
index ee20653..bed2540 100644 (file)
@@ -425,7 +425,7 @@ public class TestJobManager extends TestBase {
             fail();
         } catch (RuntimeException e) {
             assertEquals(expectedException, e.getCause());
-            verify(logger).error("Unable to retrieve operation parameters", expectedException);
+            verify(logger).error("Unable to retrieve operation parameters of operation with " + operation.getId() +" identifier", expectedException);
         }
         assertTrue(jobManager.hasOngoingJobs());
     }
@@ -447,7 +447,7 @@ public class TestJobManager extends TestBase {
             fail();
         } catch (RuntimeException e) {
             assertEquals(expectedException, e.getCause());
-            verify(logger).error("Unable to retrieve VNF", expectedException);
+            verify(logger).error("Unable to retrieve VNF with myVnfId identifier", expectedException);
         }
         assertTrue(jobManager.hasOngoingJobs());
     }
index e4960b2..ffbda14 100644 (file)
@@ -127,6 +127,7 @@ public class TestSelfRegistrationManager extends TestBase {
         assertEquals(SelfRegistrationManager.SERVICE_NAME, microserviceRequest.getServiceName());
         assertEquals("/api/NokiaSVNFM/v1", microserviceRequest.getUrl());
         assertEquals("v1", microserviceRequest.getVersion());
+        assertEquals(false, microserviceRequest.isEnable_ssl());
         //1 means internal service to ONAP
         assertEquals("1", microserviceRequest.getVisualRange());
     }
index 2d07812..ebec707 100644 (file)
         <version>${spring.boot.version}</version>
         <configuration>
           <mainClass>org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.NokiaSvnfmApplication</mainClass>
-          <layout>ZIP</layout>
+          <layout>WAR</layout>
         </configuration>
+        <executions>
+        <execution>
+          <goals>
+            <goal>repackage</goal>
+          </goals>
+        </execution>
+      </executions>
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
diff --git a/nokiav2/generatedapis/src/main/resources/msb.json b/nokiav2/generatedapis/src/main/resources/msb.json
new file mode 100644 (file)
index 0000000..633e3b7
--- /dev/null
@@ -0,0 +1,1255 @@
+{
+  "swagger": "2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "Service Discovery RESTful API"
+  },
+  "basePath": "/api/microservices/v1",
+  "tags": [
+    {
+      "name": "Service Resource"
+    }
+  ],
+  "paths": {
+    "/services": {
+      "get": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "get all microservices ",
+        "description": "",
+        "operationId": "getMicroService",
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [],
+        "responses": {
+          "200": {
+            "description": "successful operation",
+            "schema": {
+              "type": "array",
+              "items": {
+                "$ref": "#/definitions/MicroServiceFullInfo"
+              }
+            }
+          },
+          "500": {
+            "description": "get microservice List  fail",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      },
+      "post": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "add one microservice ",
+        "description": "",
+        "operationId": "addMicroService",
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "in": "body",
+            "name": "body",
+            "description": "MicroServiceInfo Instance Info",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/MicroServiceInfo"
+            }
+          },
+          {
+            "name": "createOrUpdate",
+            "in": "query",
+            "description": "createOrUpdate",
+            "required": false,
+            "type": "boolean",
+            "default": "true"
+          },
+          {
+            "name": "is_manual",
+            "in": "query",
+            "description": "is_manual",
+            "required": false,
+            "type": "boolean",
+            "default": "false"
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "successful operation",
+            "schema": {
+              "$ref": "#/definitions/MicroServiceFullInfo"
+            }
+          },
+          "422": {
+            "description": "Unprocessable MicroServiceInfo Entity ",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "400": {
+            "description": "Unprocessable MicroServiceInfo JSON REQUEST",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "500": {
+            "description": "add microservice fail",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      }
+    },
+    "/services/apigatewayserviceinfo": {
+      "get": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "get apigateway AddressInfo",
+        "description": "",
+        "operationId": "getApigatewayServiceInfo",
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "name": "namespace",
+            "in": "query",
+            "description": "namespace",
+            "required": false,
+            "type": "string"
+          },
+          {
+            "name": "visualRange",
+            "in": "query",
+            "description": "visualRange",
+            "required": false,
+            "type": "string",
+            "default": "1"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "successful operation",
+            "schema": {
+              "type": "array",
+              "items": {
+                "$ref": "#/definitions/MicroServiceFullInfo"
+              }
+            }
+          },
+          "500": {
+            "description": "get apigateway ServiceInfo fail",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "404": {
+            "description": "apigateway ServiceInfo not found",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      }
+    },
+    "/services/health": {
+      "get": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "sdclient healthy check ",
+        "description": "",
+        "operationId": "health",
+        "produces": [
+          "text/plain"
+        ],
+        "parameters": [],
+        "responses": {
+          "200": {
+            "description": "successful operation",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "500": {
+            "description": "check fail",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      }
+    },
+    "/services/tcpudpportrange": {
+      "get": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "get tcp and udp port range",
+        "description": "",
+        "operationId": "getTCP_UDP_portRange",
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [],
+        "responses": {
+          "200": {
+            "description": "successful operation",
+            "schema": {
+              "type": "array",
+              "items": {
+                "type": "string"
+              }
+            }
+          },
+          "500": {
+            "description": "get port range fail",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "404": {
+            "description": "port range not found",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      }
+    },
+    "/services/{serviceName}/version/{version}": {
+      "get": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "get one microservice nodes",
+        "description": "",
+        "operationId": "getMicroService",
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "name": "serviceName",
+            "in": "path",
+            "description": "microservice serviceName",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "version",
+            "in": "path",
+            "description": "microservice version,if the version is empty, please enter \"null\"",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "labels",
+            "in": "query",
+            "description": "Format key:value,Multiple use ',' split",
+            "required": false,
+            "type": "string"
+          },
+          {
+            "name": "namespace",
+            "in": "query",
+            "description": "namespace",
+            "required": false,
+            "type": "string"
+          },
+          {
+            "name": "ifPassStatus",
+            "in": "query",
+            "description": "if true then only query passing services",
+            "required": false,
+            "type": "boolean",
+            "default": "true"
+          },
+          {
+            "name": "wait",
+            "in": "query",
+            "description": "wait",
+            "required": false,
+            "type": "string"
+          },
+          {
+            "name": "index",
+            "in": "query",
+            "description": "index",
+            "required": false,
+            "type": "string"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "successful operation",
+            "schema": {
+              "$ref": "#/definitions/MicroServiceFullInfo"
+            }
+          },
+          "422": {
+            "description": "Unprocessable MicroServiceInfo Entity ",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "500": {
+            "description": "get microservice fail",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "404": {
+            "description": "microservice not found",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      },
+      "put": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "update one microservice by serviceName and version",
+        "description": "",
+        "operationId": "updateMicroService",
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "name": "serviceName",
+            "in": "path",
+            "description": "microservice serviceName",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "version",
+            "in": "path",
+            "description": "microservice version,if the version is empty, please enter \"null\"",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "namespace",
+            "in": "query",
+            "description": "namespace",
+            "required": false,
+            "type": "string"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "microservice Instance Info",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/MicroServiceInfo"
+            }
+          },
+          {
+            "name": "protocol",
+            "in": "query",
+            "description": "protocol",
+            "required": false,
+            "type": "string"
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "successful operation",
+            "schema": {
+              "$ref": "#/definitions/MicroServiceFullInfo"
+            }
+          },
+          "422": {
+            "description": "Unprocessable MicroServiceInfo Entity ",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "400": {
+            "description": "Unprocessable MicroServiceInfo JSON REQUEST",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "500": {
+            "description": "update microservice fail",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      },
+      "delete": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "delete one full microservice by serviceName and version",
+        "description": "",
+        "operationId": "deleteMicroService",
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "name": "serviceName",
+            "in": "path",
+            "description": "microservice serviceName",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "version",
+            "in": "path",
+            "description": "microservice version,if the version is empty, please enter \"null\"",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "namespace",
+            "in": "query",
+            "description": "namespace",
+            "required": false,
+            "type": "string"
+          },
+          {
+            "name": "protocol",
+            "in": "query",
+            "description": "protocol",
+            "required": false,
+            "type": "string"
+          }
+        ],
+        "responses": {
+          "422": {
+            "description": "Unprocessable MicroServiceInfo Entity ",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "500": {
+            "description": "delete microservice fail",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "204": {
+            "description": "delete microservice succeed "
+          },
+          "404": {
+            "description": "microservice not found",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      }
+    },
+    "/services/{serviceName}/version/{version}/allpublishaddress": {
+      "get": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "get one microservice's all publishaddress",
+        "description": "",
+        "operationId": "getAllPublishaddress",
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "name": "serviceName",
+            "in": "path",
+            "description": "microservice serviceName",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "version",
+            "in": "path",
+            "description": "microservice version,if the version is empty, please enter \"null\"",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "namespace",
+            "in": "query",
+            "description": "namespace",
+            "required": false,
+            "type": "string"
+          },
+          {
+            "name": "visualRange",
+            "in": "query",
+            "description": "outSystem:0,inSystem:1,all:0|1(default)",
+            "required": false,
+            "type": "string",
+            "default": "0|1"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "successful operation",
+            "schema": {
+              "type": "array",
+              "items": {
+                "$ref": "#/definitions/PublishFullAddress"
+              }
+            }
+          },
+          "422": {
+            "description": "Unprocessable MicroServiceInfo Entity ",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "500": {
+            "description": "get publishaddress fail",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "404": {
+            "description": "publishaddress not found",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      }
+    },
+    "/services/{serviceName}/version/{version}/nodes": {
+      "get": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "get one microservice ",
+        "description": "",
+        "operationId": "getMicroServiceNodes",
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "name": "serviceName",
+            "in": "path",
+            "description": "microservice serviceName",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "version",
+            "in": "path",
+            "description": "microservice version,if the version is empty, please enter \"null\"",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "labels",
+            "in": "query",
+            "description": "Format key:value,Multiple use ',' split",
+            "required": false,
+            "type": "string"
+          },
+          {
+            "name": "namespace",
+            "in": "query",
+            "description": "namespace",
+            "required": false,
+            "type": "string"
+          },
+          {
+            "name": "ifPassStatus",
+            "in": "query",
+            "description": "if true then only query passing services",
+            "required": false,
+            "type": "boolean",
+            "default": "true"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "successful operation",
+            "schema": {
+              "type": "array",
+              "items": {
+                "$ref": "#/definitions/MicroServiceFullInfo"
+              }
+            }
+          },
+          "422": {
+            "description": "Unprocessable MicroServiceInfo Entity ",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "500": {
+            "description": "get microservice fail",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "404": {
+            "description": "microservice not found",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      }
+    },
+    "/services/{serviceName}/version/{version}/nodes/{ip}/{port}": {
+      "delete": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "delete single node by serviceName and version and node",
+        "description": "",
+        "operationId": "deleteNode",
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "name": "serviceName",
+            "in": "path",
+            "description": "microservice serviceName",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "version",
+            "in": "path",
+            "description": "microservice version,if the version is empty, please enter \"null\"",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "namespace",
+            "in": "query",
+            "description": "namespace",
+            "required": false,
+            "type": "string"
+          },
+          {
+            "name": "ip",
+            "in": "path",
+            "description": "ip",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "port",
+            "in": "path",
+            "description": "port",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "protocol",
+            "in": "query",
+            "description": "protocol",
+            "required": false,
+            "type": "string"
+          }
+        ],
+        "responses": {
+          "422": {
+            "description": "Unprocessable MicroServiceInfo Entity ",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "500": {
+            "description": "delete node fail",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "204": {
+            "description": "delete node succeed "
+          },
+          "404": {
+            "description": "node not found",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      }
+    },
+    "/services/{serviceName}/version/{version}/publishaddress": {
+      "get": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "get one microservice's inner publishaddress",
+        "description": "",
+        "operationId": "getPublishaddress",
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "name": "serviceName",
+            "in": "path",
+            "description": "microservice serviceName",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "version",
+            "in": "path",
+            "description": "microservice version,if the version is empty, please enter \"null\"",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "namespace",
+            "in": "query",
+            "description": "namespace",
+            "required": false,
+            "type": "string"
+          },
+          {
+            "name": "wait",
+            "in": "query",
+            "description": "Waiting time,Scope: 5-300, unit: second",
+            "required": false,
+            "type": "integer",
+            "default": "0",
+            "format": "int32"
+          }
+        ],
+        "responses": {
+          "200": {
+            "description": "successful operation",
+            "schema": {
+              "$ref": "#/definitions/PublishAddress"
+            }
+          },
+          "422": {
+            "description": "Unprocessable MicroServiceInfo Entity ",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "500": {
+            "description": "get publishaddress fail",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "404": {
+            "description": "publishaddress not found",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      }
+    },
+    "/services/{serviceName}/version/{version}/ttl": {
+      "put": {
+        "tags": [
+          "Service Resource"
+        ],
+        "summary": "passing one microservice health check by ttl",
+        "description": "",
+        "operationId": "healthCheckbyTTL",
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "name": "serviceName",
+            "in": "path",
+            "description": "microservice serviceName",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "version",
+            "in": "path",
+            "description": "microservice version,if the version is empty, please enter \"null\"",
+            "required": true,
+            "type": "string"
+          },
+          {
+            "name": "namespace",
+            "in": "query",
+            "description": "namespace",
+            "required": false,
+            "type": "string"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "CheckNode Instance Info",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/NodeAddress"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "successful operation",
+            "schema": {
+              "$ref": "#/definitions/NodeAddress"
+            }
+          },
+          "422": {
+            "description": "Unprocessable MicroServiceInfo Entity ",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "400": {
+            "description": "Unprocessable CheckNode JSON REQUEST",
+            "schema": {
+              "type": "string"
+            }
+          },
+          "500": {
+            "description": "health check by ttl fail",
+            "schema": {
+              "type": "string"
+            }
+          }
+        }
+      }
+    }
+  },
+  "definitions": {
+    "PublishAddress": {
+      "type": "object",
+      "required": [
+        "port",
+        "publish_url"
+      ],
+      "properties": {
+        "ip": {
+          "type": "string",
+          "description": "Service Publish IP"
+        },
+        "port": {
+          "type": "string",
+          "description": "Service Publish Port"
+        },
+        "publish_url": {
+          "type": "string",
+          "example": "/api/serviceName/v1",
+          "description": "Service Publish URL,start with /"
+        }
+      }
+    },
+    "PublishFullAddress": {
+      "type": "object",
+      "required": [
+        "port",
+        "publish_protocol",
+        "publish_url",
+        "visualRange"
+      ],
+      "properties": {
+        "ip": {
+          "type": "string",
+          "description": "Service Publish IP"
+        },
+        "domain": {
+          "type": "string",
+          "description": "Service Publish Domain"
+        },
+        "port": {
+          "type": "string",
+          "description": "Service Publish Port"
+        },
+        "publish_url": {
+          "type": "string",
+          "example": "/api/serviceName/v1",
+          "description": "Service Publish URL,start with /"
+        },
+        "visualRange": {
+          "type": "string",
+          "example": "1",
+          "description": "[visual Range]outSystem:0,inSystem:1",
+          "enum": [
+            "0",
+            "1"
+          ]
+        },
+        "publish_protocol": {
+          "type": "string",
+          "example": "https",
+          "description": "Service Publish Protocol",
+          "enum": [
+            "http",
+            "https"
+          ]
+        }
+      }
+    },
+    "MicroServiceFullInfo": {
+      "type": "object",
+      "required": [
+        "protocol",
+        "serviceName",
+        "url",
+        "version"
+      ],
+      "properties": {
+        "serviceName": {
+          "type": "string",
+          "example": "test"
+        },
+        "version": {
+          "type": "string",
+          "example": "v1"
+        },
+        "url": {
+          "type": "string",
+          "example": "/api/serviceName/v1",
+          "description": "Target Service URL,start with /"
+        },
+        "protocol": {
+          "type": "string",
+          "example": "HTTP",
+          "description": "Service Protocol",
+          "enum": [
+            "REST",
+            "UI",
+            "HTTP",
+            "TCP",
+            "UDP"
+          ]
+        },
+        "visualRange": {
+          "type": "string",
+          "example": "1",
+          "description": "[visual Range]interSystem:0,inSystem:1",
+          "enum": [
+            "0",
+            "1"
+          ]
+        },
+        "lb_policy": {
+          "type": "string",
+          "example": "ip_hash",
+          "description": "lb policy",
+          "enum": [
+            "round-robin",
+            "ip_hash"
+          ]
+        },
+        "namespace": {
+          "type": "string"
+        },
+        "enable_ssl": {
+          "type": "boolean",
+          "example": "false",
+          "description": "enable ssl",
+          "default": false
+        },
+        "nodes": {
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/NodeInfo"
+          }
+        },
+        "metadata": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/KeyVaulePair"
+          }
+        },
+        "labels": {
+          "type": "array",
+          "example": "key1:value1",
+          "description": "custom labels",
+          "items": {
+            "type": "string"
+          }
+        },
+        "status": {
+          "type": "string"
+        },
+        "is_manual": {
+          "type": "boolean",
+          "default": false
+        }
+      }
+    },
+    "NodeInfo": {
+      "type": "object",
+      "required": [
+        "ip",
+        "port"
+      ],
+      "properties": {
+        "ip": {
+          "type": "string",
+          "example": "127.0.0.1"
+        },
+        "port": {
+          "type": "string",
+          "example": "80"
+        },
+        "lb_server_params": {
+          "type": "string",
+          "example": "weight=5,max_fails=3,fail_timeout=30s",
+          "description": "lb node params",
+          "enum": [
+            "weight",
+            "max_fails",
+            "fail_timeout"
+          ]
+        },
+        "checkType": {
+          "type": "string",
+          "example": "TTL",
+          "description": "health check type",
+          "enum": [
+            "TTL",
+            "HTTP",
+            "TCP"
+          ]
+        },
+        "checkUrl": {
+          "type": "string",
+          "example": "http://localhost:5000/health",
+          "description": "health check URL,applies only to TCP or HTTP"
+        },
+        "checkInterval": {
+          "type": "string",
+          "example": "10s",
+          "description": "TCP or HTTP health check Interval,Unit: second"
+        },
+        "checkTimeOut": {
+          "type": "string",
+          "example": "10s",
+          "description": "TCP or HTTP health check TimeOut,Unit: second"
+        },
+        "ttl": {
+          "type": "string",
+          "example": "10s",
+          "description": "TTL health check Interval,Unit: second"
+        },
+        "ha_role": {
+          "type": "string",
+          "example": "active",
+          "description": "Instance HA_role",
+          "enum": [
+            "active",
+            "standby"
+          ]
+        },
+        "nodeId": {
+          "type": "string"
+        },
+        "status": {
+          "type": "string"
+        },
+        "expiration": {
+          "type": "string",
+          "format": "date-time"
+        },
+        "created_at": {
+          "type": "string",
+          "format": "date-time"
+        },
+        "updated_at": {
+          "type": "string",
+          "format": "date-time"
+        }
+      }
+    },
+    "Node": {
+      "type": "object",
+      "required": [
+        "ip",
+        "port"
+      ],
+      "properties": {
+        "ip": {
+          "type": "string",
+          "example": "127.0.0.1"
+        },
+        "port": {
+          "type": "string",
+          "example": "80"
+        },
+        "lb_server_params": {
+          "type": "string",
+          "example": "weight=5,max_fails=3,fail_timeout=30s",
+          "description": "lb node params",
+          "enum": [
+            "weight",
+            "max_fails",
+            "fail_timeout"
+          ]
+        },
+        "checkType": {
+          "type": "string",
+          "example": "TTL",
+          "description": "health check type",
+          "enum": [
+            "TTL",
+            "HTTP",
+            "TCP"
+          ]
+        },
+        "checkUrl": {
+          "type": "string",
+          "example": "http://localhost:5000/health",
+          "description": "health check URL,applies only to TCP or HTTP"
+        },
+        "checkInterval": {
+          "type": "string",
+          "example": "10s",
+          "description": "TCP or HTTP health check Interval,Unit: second"
+        },
+        "checkTimeOut": {
+          "type": "string",
+          "example": "10s",
+          "description": "TCP or HTTP health check TimeOut,Unit: second"
+        },
+        "ttl": {
+          "type": "string",
+          "example": "10s",
+          "description": "TTL health check Interval,Unit: second"
+        },
+        "ha_role": {
+          "type": "string",
+          "example": "active",
+          "description": "Instance HA_role",
+          "enum": [
+            "active",
+            "standby"
+          ]
+        }
+      }
+    },
+    "MicroServiceInfo": {
+      "type": "object",
+      "required": [
+        "protocol",
+        "serviceName",
+        "url",
+        "version"
+      ],
+      "properties": {
+        "serviceName": {
+          "type": "string",
+          "example": "test"
+        },
+        "version": {
+          "type": "string",
+          "example": "v1"
+        },
+        "url": {
+          "type": "string",
+          "example": "/api/serviceName/v1",
+          "description": "Target Service URL,start with /"
+        },
+        "protocol": {
+          "type": "string",
+          "example": "HTTP",
+          "description": "Service Protocol",
+          "enum": [
+            "REST",
+            "UI",
+            "HTTP",
+            "TCP",
+            "UDP"
+          ]
+        },
+        "visualRange": {
+          "type": "string",
+          "example": "1",
+          "description": "[visual Range]interSystem:0,inSystem:1",
+          "enum": [
+            "0",
+            "1"
+          ]
+        },
+        "lb_policy": {
+          "type": "string",
+          "example": "ip_hash",
+          "description": "lb policy",
+          "enum": [
+            "round-robin",
+            "ip_hash"
+          ]
+        },
+        "namespace": {
+          "type": "string"
+        },
+        "enable_ssl": {
+          "type": "boolean",
+          "example": "false",
+          "description": "enable ssl",
+          "default": false
+        },
+        "nodes": {
+          "type": "array",
+          "uniqueItems": true,
+          "items": {
+            "$ref": "#/definitions/Node"
+          }
+        },
+        "metadata": {
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/KeyVaulePair"
+          }
+        },
+        "labels": {
+          "type": "array",
+          "example": "key1:value1",
+          "description": "custom labels",
+          "items": {
+            "type": "string"
+          }
+        }
+      }
+    },
+    "NodeAddress": {
+      "type": "object",
+      "required": [
+        "ip",
+        "port"
+      ],
+      "properties": {
+        "ip": {
+          "type": "string"
+        },
+        "port": {
+          "type": "string"
+        }
+      }
+    },
+    "KeyVaulePair": {
+      "type": "object",
+      "properties": {
+        "key": {
+          "type": "string"
+        },
+        "value": {
+          "type": "string"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file