ND get VM info from Openstack 53/73753/2
authorNorm Traxler <normant@amdocs.com>
Tue, 27 Nov 2018 22:18:16 +0000 (22:18 +0000)
committerNorm Traxler <norman.traxler@amdocs.com>
Wed, 28 Nov 2018 19:24:42 +0000 (14:24 -0500)
Issue-ID: SDNC-533

Change-Id: If50c4ae02349824a4e179e30ea1ee29d3afe6ab2
Signed-off-by: Norm Traxler <normant@amdocs.com>
21 files changed:
pomba/network-discovery/config/application.properties
pomba/network-discovery/config/auth/client-cert-onap.p12 [new file with mode: 0644]
pomba/network-discovery/config/auth/osauth.json [new file with mode: 0644]
pomba/network-discovery/config/jolt/l3-network.json [new file with mode: 0644]
pomba/network-discovery/config/jolt/vserver.json [new file with mode: 0644]
pomba/network-discovery/pom.xml
pomba/network-discovery/src/main/docker/Dockerfile
pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/Application.java
pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/ApplicationException.java
pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/OpenstackConfiguration.java [moved from pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/EnricherConfiguration.java with 56% similarity]
pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/OSAuthentication.java [new file with mode: 0644]
pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringServiceImpl.java
pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestServiceImpl.java
pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/util/TransformationUtil.java [new file with mode: 0644]
pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/NetworkDiscoveryTest.java
pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/TestHttpServletRequest.java [deleted file]
pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/util/TransformationUtilTest.java [new file with mode: 0644]
pomba/network-discovery/src/test/resources/jolt/l3network-expected.json [new file with mode: 0644]
pomba/network-discovery/src/test/resources/jolt/l3network-input.json [new file with mode: 0644]
pomba/network-discovery/src/test/resources/jolt/vserver-expected.json [new file with mode: 0644]
pomba/network-discovery/src/test/resources/jolt/vserver-input.json [new file with mode: 0644]

index 6dba59d..f6a889e 100644 (file)
@@ -22,20 +22,13 @@ server.context_parameters.p-name=value #context parameter with p-name as key and
 basicAuth.username=admin
 basicAuth.password=OBF:1u2a1toa1w8v1tok1u30
 
-enricher.types = vserver, l3-network
-enricher.type.vserver.url    = /enricher/v11/cloud-infrastructure/vservers/vserver/{0}?sot=!aai
-enricher.type.l3-network.url = /enricher/v11/network/l3-networks/l3-network/{0}?sot=!aai
-
-# Mapping from Enricher Attribute name to POMBA Attribute name in the format
-#   <Enricher Attribute Name>:<Pomba Attribute Name>;  and separated by semicolon ";"
-# for example,
-#          vserser-id:id;
-# means Attribute name "vserer-id" from Enricher will be converted to "id" in POMBA.
-enricher.attributeNameMappingList=Id:id;id:id;vserver-id:id;name:name;locked:inMaintenance; \
-            hostname:hostName;status:status;vm_state:vmState;vm-state:vmState;admin_state_up:adminState; \
-            favor.disk:flavorDisk;flavor.ephemeral:flavorEphemoral;flavor.extra_specs.hw.cpu_model:flavorHwCpuModel; \
-            flavor.extra_specs.hw.cpu_policy:flavorHwCpuPolicy;flavor.extra_specs.hw.mem_page_size:flavorHwMemPageSize; \
-            flavor.original_name:flavorOriginalName;flavor.ram:flavorRam;flavor.swap:flavorSwag;flavorvcpus:flavorVcpus; \
-            image.id:imageId;hostId:hostId;host:host;host_status:hostStatus;security_group.name:securityGroupName; \
-            serverName:serverName;metadata.myservername:otherServerName;shared:sharedNetwork;subnets:subnets; \
-            userId:userId;tenant_id:tenantId
\ No newline at end of file
+openstack.identity.url = http://10.69.36.11:5000/v3/auth/tokens
+openstack.identity.user = ralph
+openstack.identity.password = OBF:1w951ugg1vun1uha1w8l
+
+openstack.types = vserver, l3-network
+openstack.type.vserver.url    = http://10.69.36.11:8774/v2.1/servers/{0}
+openstack.type.l3-network.url = http://10.69.36.11:9696/v2.0/networks/{0}
+
+openstack.api.microversion = 2.42
+
diff --git a/pomba/network-discovery/config/auth/client-cert-onap.p12 b/pomba/network-discovery/config/auth/client-cert-onap.p12
new file mode 100644 (file)
index 0000000..dbf4fca
Binary files /dev/null and b/pomba/network-discovery/config/auth/client-cert-onap.p12 differ
diff --git a/pomba/network-discovery/config/auth/osauth.json b/pomba/network-discovery/config/auth/osauth.json
new file mode 100644 (file)
index 0000000..95dec53
--- /dev/null
@@ -0,0 +1,18 @@
+{\r
+    "auth": {\r
+        "identity": {\r
+            "methods": [\r
+                "password"\r
+            ],\r
+            "password": {\r
+                "user": {\r
+                    "name": "%USER%",\r
+                    "domain": {\r
+                        "name": "Default"\r
+                    },\r
+                    "password": "%PASSWORD%"\r
+                }\r
+            } \r
+        }\r
+    }\r
+}
\ No newline at end of file
diff --git a/pomba/network-discovery/config/jolt/l3-network.json b/pomba/network-discovery/config/jolt/l3-network.json
new file mode 100644 (file)
index 0000000..0afe4a2
--- /dev/null
@@ -0,0 +1,25 @@
+[
+  {
+    "operation": "shift",
+    "spec": {
+      "network": {
+        "id": "l3-network.id",
+        "name": "l3-network.name",
+        "admin_state_up": "l3-network.AdminState",
+        "shared": "l3-network.sharedNetwork",
+        "status": "l3-network.status",
+        "subnets": "l3-network.subnets",
+        "tenant_id": "l3-network.tenantId"
+      }
+    }
+  },
+  {
+    "operation": "default",
+    "spec": {
+      "*": {
+        "host-status": "UNKNOWN"
+      }
+    }
+  }
+
+]
diff --git a/pomba/network-discovery/config/jolt/vserver.json b/pomba/network-discovery/config/jolt/vserver.json
new file mode 100644 (file)
index 0000000..cc9e26d
--- /dev/null
@@ -0,0 +1,32 @@
+[
+  {
+    "operation": "shift",
+    "spec": {
+      "server": {
+        "id": "vserver.id",
+        "name": "vserver.name",
+        "locked":  "vserver.inMaintenance",
+        "OS-EXT-SRV-ATTR:hostname":  "vserver.hostname",
+        "image": {
+            "id": "vserver.imageId"
+        },
+        
+        "status": "vserver.status",
+        "OS-EXT-STS:vm_state": "vserver.vmState",
+        "tenant_id": "vserver.tenantId",
+        "hostId": "vserver.hostId",
+        "OS-EXT-SRV-ATTR:host": "vserver.host",      
+        "host_status": "vserver.hostStatus"
+      }
+    }
+  },
+  {
+    "operation": "default",
+    "spec": {
+      "*": {
+        "hostStatus": "UNKNOWN"
+      }
+    }
+  }
+
+]
index 24aa3de..18a8587 100644 (file)
@@ -50,6 +50,23 @@ limitations under the License.
     </dependencyManagement>
 
     <dependencies>
+        <!-- Jolt transformation dependencies -->
+        <dependency>
+            <groupId>com.bazaarvoice.jolt</groupId>
+            <artifactId>jolt-core</artifactId>
+            <version>0.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.bazaarvoice.jolt</groupId>
+            <artifactId>json-utils</artifactId>
+            <version>0.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.5</version>
+        </dependency>
+
         <!-- Springframework dependencies -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -279,6 +296,7 @@ limitations under the License.
                                             <includes>
                                                 <include>*.properties</include>
                                                 <include>*.xml</include>
+                                                <include>**/*.json</include>   
                                             </includes>
                                             <filtering>false</filtering>
                                         </resource>
index e9be214..45a8c5a 100644 (file)
@@ -6,6 +6,7 @@ ARG MICROSERVICE_HOME=/opt/app/
 RUN mkdir -p $MICROSERVICE_HOME
 RUN mkdir -p $MICROSERVICE_HOME/config/
 RUN mkdir -p $MICROSERVICE_HOME/config/auth/
+RUN mkdir -p $MICROSERVICE_HOME/config/jolt/
 RUN mkdir -p $MICROSERVICE_HOME/lib/
 RUN mkdir -p $MICROSERVICE_HOME/bin/
 
@@ -17,4 +18,4 @@ RUN chmod 755 $MICROSERVICE_HOME/config/*
 RUN chmod 755 $MICROSERVICE_HOME/lib/*
 RUN chmod 755 $MICROSERVICE_HOME/bin/*
 
-CMD ["/opt/app/bin/startService.sh"]
\ No newline at end of file
+CMD ["/opt/app/bin/startService.sh"]
index c976678..e7e2208 100644 (file)
@@ -38,7 +38,7 @@ public class Application extends SpringBootServletInitializer {
         return application.sources(Application.class);
     }
 
-    public static void main(String[] args) throws Exception {
+    public static void main(String[] args) {
         SpringApplication.run(Application.class, args);
     }
 }
\ No newline at end of file
index fa29645..98bb2e7 100644 (file)
@@ -45,11 +45,7 @@ public class ApplicationException extends Exception {
     private static final long serialVersionUID = -4874149714911165454L;
 
     private final Status httpStatus;
-    private String responseCode;
-
-    public ApplicationException(String message) {
-        this(message, Status.INTERNAL_SERVER_ERROR);
-    }
+    private final String responseCode;
 
     public ApplicationException(Error errorCode, Status httpStatus, Object... args) {
         super(errorCode.getMessage(args));
@@ -61,19 +57,6 @@ public class ApplicationException extends Exception {
         this.httpStatus = httpStatus;
     }
 
-    public ApplicationException(String message, Status httpStatus) {
-        super(message);
-        if (httpStatus == null) {
-            throw new NullPointerException("httpStatus");
-        }
-        this.httpStatus = httpStatus;
-    }
-
-    public ApplicationException(String message, Exception cause) {
-        super(message, cause);
-        this.httpStatus = Status.INTERNAL_SERVER_ERROR;
-    }
-
     public Status getHttpStatus() {
         return this.httpStatus;
     }
@@ -20,58 +20,77 @@ package org.onap.sdnc.apps.pomba.networkdiscovery;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.StringTokenizer;
+
+import org.eclipse.jetty.util.security.Password;
 import org.onap.aai.restclient.client.RestClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.core.env.Environment;
-import com.google.common.base.Splitter;
 
 @Configuration
-public class EnricherConfiguration {
+public class OpenstackConfiguration {
     @Autowired
     private Environment env;
 
-    @Value("${enricher.url:https://localhost:9505}")
-    private String url;
+    @Value("${openstack.identity.url:http://localhost:5000/v3}")
+    private String identityUrl;
+
+    @Value("${openstack.identity.user}")
+    private String identityUser;
+
+    @Value("${openstack.identity.password}")
+    private String identityPassword;
 
-    @Value("${enricher.keyStorePath:config/auth/client-cert-onap.p12}")
+    @Value("${openstack.api.microversion}")
+    private String apiMicroversion;
+
+    @Value("${openstack.identity.keyStorePath:config/auth/client-cert-onap.p12}")
     private String keyStorePath;
 
-    @Value("${enricher.keyStorePassword:OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10}")
+    @Value("${openstack.identity.keyStorePassword:OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10}")
     private String keyStorePassword;
 
-    @Value("${enricher.connectionTimeout:5000}")
+    @Value("${openstack.connectionTimeout:5000}")
     private int connectionTimeout;
 
-    @Value("${enricher.readTimeout:60000}")
+    @Value("${openstack.readTimeout:60000}")
     private int readTimeout;
 
-    @Value("${enricher.attributeNameMappingList}")
-    private String enricherAttributeNameMappingList;
-
-    @Bean(name = "enricherClient")
+    @Bean(name = "openstackClient")
     public RestClient restClient() {
         return new RestClient().validateServerHostname(false)
                         .validateServerCertChain(false)
                         .connectTimeoutMs(this.connectionTimeout)
-                        .readTimeoutMs(this.readTimeout)
-                        .clientCertFile(this.keyStorePath)
-                        .clientCertPassword(org.eclipse.jetty.util.security.Password.deobfuscate(
-                                        this.keyStorePassword));
+                        .readTimeoutMs(this.readTimeout);
+    }
+
+    @Bean(name = "openstackIdentityUrl")
+    public String getIdentityURL() {
+        return this.identityUrl;
+    }
+
+    @Bean(name = "openstackIdentityUser")
+    public String getIdentityUser() {
+        return this.identityUser;
     }
 
-    @Bean(name = "enricherBaseUrl")
-    public String getURL() {
-        return this.url;
+    @Bean(name = "openstackIdentityPassword")
+    public String getIdentityPassword() {
+        return Password.deobfuscate(this.identityPassword);
     }
 
-    @Bean(name = "enricherTypeURLs")
-    public Map<String, String> enricherTypeURLs() {
+    @Bean(name = "openstackApiMicroversion")
+    public String getApiMicroversion() {
+        return this.apiMicroversion;
+    }
+
+    @Bean(name = "openstackTypeURLs")
+    public Map<String, String> getOpenstackTypeURLs() {
 
         Map<String, String> result = new HashMap<>();
-        String types = this.env.getProperty("enricher.types");
+        String types = this.env.getProperty("openstack.types");
         if (types == null) {
             return result;
         }
@@ -79,16 +98,11 @@ public class EnricherConfiguration {
         StringTokenizer tokenizer = new StringTokenizer(types, ", ");
         while (tokenizer.hasMoreTokens()) {
             String type = tokenizer.nextToken();
-            String enricherUrl = this.env.getProperty("enricher.type." + type + ".url");
-            result.put(type, enricherUrl);
+            String openstackUrl = this.env.getProperty("openstack.type." + type + ".url");
+            result.put(type, openstackUrl);
         }
 
         return result;
     }
 
-    @Bean(name = "enricherAttributeNameMapping")
-    public Map<String, String> getAttributeNameMap() {
-        String noWhiteSpaceString = enricherAttributeNameMappingList.replaceAll("\\s", "");
-        return (Splitter.on(";").withKeyValueSeparator(":").split(noWhiteSpaceString));
-    }
 }
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/OSAuthentication.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/OSAuthentication.java
new file mode 100644 (file)
index 0000000..fed52a0
--- /dev/null
@@ -0,0 +1,78 @@
+/*\r
+ * ============LICENSE_START===================================================\r
+ * Copyright (c) 2018 Amdocs\r
+ * ============================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *        http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * ============LICENSE_END=====================================================\r
+ */\r
+package org.onap.sdnc.apps.pomba.networkdiscovery.service;\r
+\r
+import static org.onap.sdnc.apps.pomba.networkdiscovery.ApplicationException.Error.UNAUTHORIZED;\r
+\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+\r
+import javax.ws.rs.core.MediaType;\r
+import javax.ws.rs.core.MultivaluedHashMap;\r
+import javax.ws.rs.core.MultivaluedMap;\r
+import javax.ws.rs.core.Response.Status;\r
+\r
+import org.apache.commons.io.IOUtils;\r
+import org.onap.aai.restclient.client.OperationResult;\r
+import org.onap.aai.restclient.client.RestClient;\r
+import org.onap.logging.ref.slf4j.ONAPLogAdapter;\r
+import org.onap.sdnc.apps.pomba.networkdiscovery.ApplicationException;\r
+\r
+public class OSAuthentication {\r
+\r
+    private static final String CONFIG_AUTH_DIR = "config/auth";\r
+    private static final String X_SUBJECT_TOKEN = "X-Subject-Token";\r
+\r
+    private static final String USER_PATTERN = "%USER%";    \r
+    private static final String PASSWORD_PATTERN = "%PASSWORD%";\r
+\r
+    private OSAuthentication() {\r
+        throw new IllegalStateException("Utility class");\r
+    }\r
+\r
+       public static String getToken(String openstackIdentityUrl, String userId, String password, RestClient openstackClient, ONAPLogAdapter adapter)\r
+                       throws IOException, ApplicationException {\r
+\r
+               MultivaluedMap<String, String> headers = new MultivaluedHashMap<>();\r
+\r
+               String mappingConfigPath = CONFIG_AUTH_DIR + File.separator + "osauth.json";\r
+\r
+               File file = new File(mappingConfigPath);\r
+               String payload = IOUtils.toString(new FileInputStream(file), "UTF-8");\r
+        payload = payload.replaceAll(USER_PATTERN, userId);\r
+               payload = payload.replaceAll(PASSWORD_PATTERN, password);\r
+\r
+               OperationResult result = openstackClient.post(openstackIdentityUrl, payload, headers,\r
+                               MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE);\r
+\r
+               adapter.unwrap().info("request at url = {} resulted in http response: {}", openstackIdentityUrl,\r
+                               result.getResult());\r
+\r
+               String token = result.getHeaders().getFirst(X_SUBJECT_TOKEN);\r
+               \r
+               if (token == null) {\r
+                   throw new ApplicationException(UNAUTHORIZED, Status.UNAUTHORIZED);\r
+               }\r
+\r
+               adapter.unwrap().debug("Got token: {}", token);\r
+\r
+               return token;\r
+       }\r
+\r
+}\r
index 8d0de03..1be8fbc 100644 (file)
  */
 package org.onap.sdnc.apps.pomba.networkdiscovery.service;
 
+import com.bazaarvoice.jolt.JsonUtils;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
 import java.io.IOException;
-import java.io.StringReader;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+
 import javax.annotation.PreDestroy;
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.Entity;
@@ -37,13 +38,13 @@ import javax.ws.rs.core.MultivaluedHashMap;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+
 import org.onap.aai.restclient.client.OperationResult;
 import org.onap.aai.restclient.client.RestClient;
 import org.onap.logging.ref.slf4j.ONAPLogAdapter;
 import org.onap.logging.ref.slf4j.ONAPLogAdapter.RequestBuilder;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
 import org.onap.logging.ref.slf4j.ONAPLogConstants.InvocationMode;
 import org.onap.pomba.common.datatypes.DataQuality;
 import org.onap.sdnc.apps.pomba.networkdiscovery.ApplicationException;
@@ -51,64 +52,56 @@ import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.Attribute;
 import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.NetworkDiscoveryNotification;
 import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.NetworkDiscoveryResponse;
 import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.Resource;
-import org.onap.sdnc.apps.pomba.networkdiscovery.service.rs.RestService;
+import org.onap.sdnc.apps.pomba.networkdiscovery.service.util.TransformationUtil;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
 
 @Service
 public class SpringServiceImpl implements SpringService {
-    private static final String ENRICHER_HEADER_APPLICATION = "X-FromAppId";
-    private static final String ENRICHER_HEADER_TRANSACTION = "X-TransactionId";
-
+    private static final String OPENSTACK_HEADER_TOKEN = "X-Auth-Token";
+    private static final String OPENSTACK_HEADER_API_VERSION = "X-OpenStack-Nova-API-Version";
     private static final int DEFAULT_WORKER_THREADS = 3;
 
     private ExecutorService executor = Executors.newFixedThreadPool(
-                    Integer.getInteger("discovery.threads", DEFAULT_WORKER_THREADS),
-                    new ThreadFactoryBuilder().setNameFormat("discovery-worker-%d").build());
+            Integer.getInteger("discovery.threads", DEFAULT_WORKER_THREADS),
+            new ThreadFactoryBuilder().setNameFormat("discovery-worker-%d").build());
 
     @Autowired
-    private RestClient enricherClient;
+    private RestClient openstackClient;
 
     @Autowired
-    private String enricherBaseUrl;
+    private String openstackIdentityUrl;
 
-    @javax.annotation.Resource
-    private Client callbackClient;
+    @Autowired
+    private String openstackIdentityUser;
 
-    @javax.annotation.Resource
-    private Map<String, String> enricherTypeURLs;
+    @Autowired
+    private String openstackIdentityPassword;
+
+    @Autowired
+    private String openstackApiMicroversion;
 
-    private DocumentBuilder parser;
+    @javax.annotation.Resource
+    private Client callbackClient;
 
     @javax.annotation.Resource
-    private Map<String, String> enricherAttributeNameMapping;
+    private Map<String, String> openstackTypeURLs;
 
     public SpringServiceImpl() throws ParserConfigurationException {
-        this.parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
     }
 
     @Override
-    public NetworkDiscoveryResponse findbyResourceIdAndType(String transactionId,
-                    String requestId,
-                    String resourceType,
-                    List<String> resourceIds,
-                    String notificationURL,
-                    String notificationAuthorization,
-                    ONAPLogAdapter adapter) throws ApplicationException {
+    public NetworkDiscoveryResponse findbyResourceIdAndType(String transactionId, String requestId, String resourceType,
+            List<String> resourceIds, String notificationURL, String notificationAuthorization, ONAPLogAdapter adapter)
+            throws ApplicationException {
 
         NetworkDiscoveryResponse response = new NetworkDiscoveryResponse();
         response.setRequestId(requestId);
 
-        String enricherURL = this.enricherTypeURLs.get(resourceType);
+        String openstackURL = this.openstackTypeURLs.get(resourceType);
         // check if resourceType is supported
-        if (enricherURL == null) {
+        if (openstackURL == null) {
             // don't know what to do with this - return empty response
             response.setCode(Status.NO_CONTENT.getStatusCode());
             response.setMessage("Unsupported resourceType " + resourceType);
@@ -118,7 +111,7 @@ public class SpringServiceImpl implements SpringService {
 
         // schedule discovery of specified resources
         Runnable task = new ResourceTask(transactionId, requestId, resourceType, resourceIds, notificationURL,
-                        notificationAuthorization, enricherURL, adapter);
+                notificationAuthorization, openstackURL, adapter);
         this.executor.submit(task);
 
         response.setCode(Status.ACCEPTED.getStatusCode());
@@ -132,65 +125,29 @@ public class SpringServiceImpl implements SpringService {
         this.executor.shutdown();
     }
 
-    private void sendNotification(String url, String authorization, Object notification, ONAPLogAdapter adapter) {
+    private void sendNotification(String url, String transactionId, String authorization, Object notification,
+            ONAPLogAdapter adapter) {
 
         Invocation.Builder request = this.callbackClient.target(url).request().accept(MediaType.TEXT_PLAIN_TYPE);
 
         if (authorization != null) {
             request.header(HttpHeaders.AUTHORIZATION, authorization);
+            request.header(ONAPLogConstants.Headers.REQUEST_ID, transactionId);
         }
         Logger log = adapter.unwrap();
         adapter.invoke(new RequestBuilderWrapper(request), InvocationMode.SYNCHRONOUS);
         try {
-            // native client marshaller doesn't skip null fields
-            // so manually marshal notification to json
-
-            if (log.isDebugEnabled()) {
-                StringBuilder debugRequest = new StringBuilder("REQUEST:\n");
-                debugRequest.append("URL: ").append(url).append("\n");
-                debugRequest.append("Payload: ").append(notification).append("\n");
-                // if (headers != null) {
-                // debugRequest.append("Headers: ");
-                // for (Entry<String, List<String>> header : headers.entrySet())
-                // {
-                // debugRequest.append("\n\t").append(header.getKey()).append(":");
-                // for (String headerEntry : header.getValue()) {
-                // debugRequest.append("\"").append(headerEntry).append("\" ");
-                // }
-                // }
-                // }
-                log.debug(debugRequest.toString());
-            }
+            adapter.unwrap().info("Posting notfication to url = {} , payload: {}", url,
+                    JsonUtils.toJsonString(Entity.json(notification).getEntity()));
 
             Response result = request.post(Entity.json(notification));
 
-            adapter.unwrap().info("request at url = {} resulted in http response: {}", url,
-                            result.getStatusInfo().getStatusCode() + " " + result.getStatusInfo().getReasonPhrase());
-
-            if (log.isDebugEnabled()) {
-                StringBuilder debugResponse = new StringBuilder("RESPONSE:\n");
-                debugResponse.append("Result: ").append(result.getStatus()).append("\n");
-                String content = result.hasEntity() ? result.getEntity().toString() : null;
-                if (result.getStatus() >= 300) {
-                    debugResponse.append("Failure Cause: ").append(content).append("\n");
-                } else {
-                    debugResponse.append("Payload: ").append(content).append("\n");
-                }
-                if (result.getHeaders() != null) {
-                    debugResponse.append("Headers: ");
-                    for (Entry<String, List<Object>> header : result.getHeaders().entrySet()) {
-                        debugResponse.append("\n\t").append(header.getKey()).append(":");
-                        for (Object headerEntry : header.getValue()) {
-                            debugResponse.append("\"").append(headerEntry).append("\" ");
-                        }
-                    }
-                }
-                log.debug(debugResponse.toString());
-            }
+            adapter.unwrap().info("request at url = {} resulted in http status {} and response: {}", url,
+                    result.getStatus(), result.getEntity());
 
         } catch (Exception x) {
             log.error("Error during {} operation to endpoint at url = {} with error = {}", "POST", url,
-                            x.getLocalizedMessage());
+                    x.getLocalizedMessage());
         }
     }
 
@@ -204,14 +161,8 @@ public class SpringServiceImpl implements SpringService {
         private final String resourceURL;
         private final ONAPLogAdapter adapter;
 
-        public ResourceTask(String transactionId,
-                        String requestId,
-                        String resourceType,
-                        List<String> resourceIds,
-                        String notificationURL,
-                        String notificationAuthorization,
-                        String resourceURL,
-                        ONAPLogAdapter adapter) {
+        public ResourceTask(String transactionId, String requestId, String resourceType, List<String> resourceIds,
+                String notificationURL, String notificationAuthorization, String resourceURL, ONAPLogAdapter adapter) {
             this.transactionId = transactionId;
             this.requestId = requestId;
             this.resourceType = resourceType;
@@ -224,19 +175,45 @@ public class SpringServiceImpl implements SpringService {
 
         @Override
         public void run() {
+            try {
+                runResourceDiscoveryTask();
+            } catch (Exception e) {
+                Logger log = adapter.unwrap();
+                log.error("Failure in resource task", e);
+
+                // Try to send out a notification of the failure:
+                NetworkDiscoveryNotification notification = new NetworkDiscoveryNotification();
+                notification.setRequestId(this.requestId);
+                notification.setCode(Status.INTERNAL_SERVER_ERROR.getStatusCode());
+                notification.setMessage(e.getMessage());
+                notification.setAckFinalIndicator(true);
+
+                // call client back with resource details
+                sendNotification(this.notificationURL, this.transactionId, this.notificationAuthorization, notification,
+                        adapter);
+            }
+        }
+
+        private void runResourceDiscoveryTask() throws IOException, ApplicationException {
+
+            String token = OSAuthentication.getToken(openstackIdentityUrl, openstackIdentityUser,
+                    openstackIdentityPassword, openstackClient, adapter);
+
             NetworkDiscoveryNotification notification = new NetworkDiscoveryNotification();
             notification.setRequestId(this.requestId);
 
             List<Resource> resources = null;
-            MessageFormat format = new MessageFormat(SpringServiceImpl.this.enricherBaseUrl + this.resourceURL);
+            MessageFormat format = new MessageFormat(this.resourceURL);
             MultivaluedMap<String, String> headers = new MultivaluedHashMap<>();
-            headers.add(ENRICHER_HEADER_APPLICATION, RestService.SERVICE_NAME);
-            headers.add(ENRICHER_HEADER_TRANSACTION, this.transactionId);
+            headers.add(OPENSTACK_HEADER_TOKEN, token);
+            headers.add(OPENSTACK_HEADER_API_VERSION, openstackApiMicroversion);
 
             for (String resourceId : this.resourceIds) {
                 String url = format.format(new Object[] { resourceId });
-                OperationResult result = SpringServiceImpl.this.enricherClient.get(url, headers,
-                                MediaType.APPLICATION_XML_TYPE);
+                OperationResult result = SpringServiceImpl.this.openstackClient.get(url, headers,
+                        MediaType.APPLICATION_JSON_TYPE);
+
+                adapter.unwrap().info("Openstack GET result: {}", result.getResult());
 
                 Resource resource = new Resource();
                 resource.setType(this.resourceType);
@@ -248,13 +225,13 @@ public class SpringServiceImpl implements SpringService {
                 resources.add(resource);
 
                 if (result.wasSuccessful()) {
+                    String transformedOutput = TransformationUtil.transform(result.getResult(), this.resourceType);
+
+                    adapter.unwrap().info("Jolt transformed output: {}", transformedOutput);
+
                     resource.setDataQuality(DataQuality.ok());
-                    try {
-                        List<Attribute> attributeList = toAttributeList(result.getResult(), adapter);
-                        resource.setAttributeList(attributeList);
-                    } catch (Exception x) {
-                        resource.setDataQuality(DataQuality.error(x.getMessage()));
-                    }
+                    List<Attribute> attributeList = TransformationUtil.toAttributeList(transformedOutput);
+                    resource.setAttributeList(attributeList);
                 } else {
                     resource.setDataQuality(DataQuality.error(result.getFailureCause()));
                 }
@@ -264,37 +241,8 @@ public class SpringServiceImpl implements SpringService {
             notification.setAckFinalIndicator(true);
 
             // call client back with resource details
-            sendNotification(this.notificationURL, this.notificationAuthorization, notification, adapter);
-        }
-
-        private List<Attribute> toAttributeList(String xml, ONAPLogAdapter adapter) throws SAXException, IOException {
-            Logger log = adapter.unwrap();
-            Document doc = parser.parse(new InputSource(new StringReader(xml)));
-            NodeList children = doc.getDocumentElement().getChildNodes();
-            List<Attribute> result = new ArrayList<>();
-            for (int i = 0; i < children.getLength(); i++) {
-                Node child = children.item(i);
-                if (child.getNodeType() == Node.ELEMENT_NODE) {
-
-                    // remove white space before conversion
-                    String attributeName = ((Element) child).getTagName().replaceAll("\\s", "");
-
-                    // If the incoming attribute name is not listed in the
-                    // attributeNameMapping, then this attribute will be removed.
-                    String newName = enricherAttributeNameMapping.get(attributeName);
-                    if (newName != null) {
-                        Attribute attr = new Attribute();
-                        attr.setName(newName);
-                        attr.setValue(((Element) child).getTextContent());
-                        attr.setDataQuality(DataQuality.ok());
-                        result.add(attr);
-                    } else {
-                        log.debug("[" + ((Element) child).getTagName()
-                                + "] was removed due to not listed in enricherAttributeNameMapping.");
-                    }
-                }
-            }
-            return result;
+            sendNotification(this.notificationURL, this.transactionId, this.notificationAuthorization, notification,
+                    adapter);
         }
 
     }
index 7447e67..0677dcd 100644 (file)
@@ -64,14 +64,13 @@ public class RestServiceImpl implements RestService {
                                             String notificationURL) throws ApplicationException {
 
         ONAPLogAdapter adapter = new ONAPLogAdapter(log);
-        adapter.getServiceDescriptor().setServiceName(SERVICE_NAME);
-        adapter.entering(request);
+
         try {
+            adapter.getServiceDescriptor().setServiceName(SERVICE_NAME);
+            adapter.entering(request);
 
             if (version == null) {
-                // only unit tests can pass null here
-                // url matching will guarantee non-null in real server
-                version = "v1";
+                throw new ApplicationException(MISSING_PARAM, Status.BAD_REQUEST, "version");
             }
 
             if (authorization == null || !this.basicAuthHeader.equals(authorization)) {
@@ -95,7 +94,7 @@ public class RestServiceImpl implements RestService {
 
             if (transactionId == null || transactionId.isEmpty()) {
                 transactionId = UUID.randomUUID().toString();
-                log.debug("transactionId is missing; using newly generated value: " + transactionId);
+                log.debug("transactionId is missing; using newly generated value: {}", transactionId);
             }
 
             // just reuse received Authorization header in callback
diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/util/TransformationUtil.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/util/TransformationUtil.java
new file mode 100644 (file)
index 0000000..dc17848
--- /dev/null
@@ -0,0 +1,99 @@
+/*\r
+ * Copyright 2014 Bazaarvoice, Inc.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.onap.sdnc.apps.pomba.networkdiscovery.service.util;\r
+\r
+import com.bazaarvoice.jolt.Chainr;\r
+import com.bazaarvoice.jolt.JsonUtils;\r
+import com.google.gson.JsonElement;\r
+import com.google.gson.JsonParser;\r
+\r
+import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map.Entry;\r
+import java.util.Set;\r
+\r
+import org.onap.pomba.common.datatypes.DataQuality;\r
+import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.Attribute;\r
+\r
+public class TransformationUtil {\r
+\r
+    private static final String CONFIG_JOLT = "config/jolt";\r
+    private static final String EMPTY_STRING = "";\r
+\r
+    public TransformationUtil() {\r
+        throw new IllegalStateException("Utility class");\r
+    }\r
+\r
+    /**\r
+     * Transforms the sourceJson using the jolt specification for the given resourceType.\r
+     * \r
+     * @param sourceJson\r
+     * @param resourceType\r
+     * @return\r
+     */\r
+    public static String transform(String sourceJson, String resourceType) {\r
+\r
+        Object sourceObject = JsonUtils.jsonToObject(sourceJson);\r
+\r
+        List<Object> chainrSpecJSON = JsonUtils.filepathToList(CONFIG_JOLT + File.separator + resourceType + ".json");\r
+        Chainr chainr = Chainr.fromSpec(chainrSpecJSON);\r
+        Object output = chainr.transform(sourceObject);\r
+\r
+        return JsonUtils.toJsonString(output);\r
+    }\r
+\r
+    /**\r
+     * Converts the second level of JsonElements from the given json to a list of\r
+     * Network Discovery Attributes.\r
+     * \r
+     * @param json\r
+     * @return\r
+     */\r
+    public static List<Attribute> toAttributeList(String json) {\r
+\r
+        JsonParser parser = new JsonParser();\r
+        JsonElement elem = parser.parse(json);\r
+\r
+        Set<Entry<String, JsonElement>> entrySet = elem.getAsJsonObject().entrySet();\r
+\r
+        List<Attribute> result = new ArrayList<>();\r
+\r
+        Iterator<Entry<String, JsonElement>> iter = entrySet.iterator();\r
+        while (iter.hasNext()) {\r
+            Entry<String, JsonElement> next = iter.next();\r
+\r
+            JsonElement vserverElem = next.getValue();\r
+            Set<Entry<String, JsonElement>> vserverEntrySet = vserverElem.getAsJsonObject().entrySet();\r
+            Iterator<Entry<String, JsonElement>> vserverIter = vserverEntrySet.iterator();\r
+            while (vserverIter.hasNext()) {\r
+                Entry<String, JsonElement> vserverNext = vserverIter.next();\r
+                Attribute attr = new Attribute();\r
+                attr.setName(vserverNext.getKey());\r
+                if (vserverNext.getValue().isJsonNull()) {\r
+                    attr.setValue(EMPTY_STRING);\r
+                } else {\r
+                    attr.setValue(vserverNext.getValue().getAsString());\r
+                }\r
+                attr.setDataQuality(DataQuality.ok());\r
+                result.add(attr);\r
+            }\r
+        }\r
+        return result;\r
+    }\r
+\r
+}
\ No newline at end of file
index 1829e6e..18a0a04 100644 (file)
@@ -20,7 +20,7 @@ package org.onap.sdnc.apps.pomba.networkdiscovery.unittest.service;
 
 import static com.github.tomakehurst.wiremock.client.WireMock.get;
 import static com.github.tomakehurst.wiremock.client.WireMock.ok;
-import static com.github.tomakehurst.wiremock.client.WireMock.okTextXml;
+import static com.github.tomakehurst.wiremock.client.WireMock.okJson;
 import static com.github.tomakehurst.wiremock.client.WireMock.post;
 import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
 import static org.junit.Assert.assertEquals;
@@ -28,13 +28,16 @@ import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import com.bazaarvoice.jolt.JsonUtils;
 import com.fasterxml.jackson.databind.AnnotationIntrospector;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
+import com.github.tomakehurst.wiremock.client.WireMock;
 import com.github.tomakehurst.wiremock.junit.WireMockRule;
 import com.github.tomakehurst.wiremock.stubbing.ServeEvent;
 import com.github.tomakehurst.wiremock.verification.LoggedRequest;
+
 import java.net.URISyntaxException;
 import java.text.MessageFormat;
 import java.util.ArrayList;
@@ -42,16 +45,19 @@ import java.util.Arrays;
 import java.util.Base64;
 import java.util.List;
 import java.util.UUID;
+
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
+
 import org.eclipse.jetty.util.security.Password;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mockito;
 import org.onap.logging.ref.slf4j.ONAPLogConstants;
 import org.onap.pomba.common.datatypes.DataQuality;
 import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.Attribute;
@@ -64,7 +70,6 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
 import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
 import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.core.env.Environment;
 import org.springframework.test.context.TestPropertySource;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 import org.springframework.test.context.web.WebAppConfiguration;
@@ -73,11 +78,13 @@ import org.springframework.test.context.web.WebAppConfiguration;
 @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
 @WebAppConfiguration
 @SpringBootTest
-@TestPropertySource(properties = { "enricher.url=http://localhost:9505",
+@TestPropertySource(properties = { "openstack.type.vserver.url=http://localhost:8774/v2.1/servers/{0}",
+        "openstack.identity.url=http://localhost:5000/v3/auth/tokens",
         "enricher.keyStorePath=src/test/resources/client-cert-onap.p12",
         "enricher.keyStorePassword=OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10",
         "basicAuth.username=admin",
         "basicAuth.password=OBF:1u2a1toa1w8v1tok1u30" })
+
 public class NetworkDiscoveryTest {
     private static final String V1 = "v1";
     private static final String APP = "junit";
@@ -87,11 +94,12 @@ public class NetworkDiscoveryTest {
 
     private static final String AUTH = "Basic " + Base64.getEncoder().encodeToString((
             "admin:" + Password.deobfuscate("OBF:1u2a1toa1w8v1tok1u30")).getBytes());
-    @Autowired
-    private Environment environment;
 
     @Rule
-    public WireMockRule enricherRule = new WireMockRule(wireMockConfig().port(9505));
+    public WireMockRule identityRule = new WireMockRule(wireMockConfig().port(5000));
+
+    @Rule
+    public WireMockRule openstackRule = new WireMockRule(wireMockConfig().port(8774));
 
     @Rule
     public WireMockRule callbackRule = new WireMockRule(wireMockConfig().dynamicPort());
@@ -101,7 +109,10 @@ public class NetworkDiscoveryTest {
 
     private String transactionId = UUID.randomUUID().toString();
     private String requestId = UUID.randomUUID().toString();
-    private HttpServletRequest httpRequest = new TestHttpServletRequest();
+    private HttpServletRequest httpRequest = Mockito.mock(HttpServletRequest.class);
+    
+    private static final String TEST_RESOURCES = "src/test/resources/jolt/";
+
 
     public NetworkDiscoveryTest() throws URISyntaxException {
 
@@ -138,6 +149,18 @@ public class NetworkDiscoveryTest {
         assertNull(response.getHeaderString(HttpHeaders.WWW_AUTHENTICATE));
     }
 
+    @Test
+    public void testNoVersion() throws Exception {
+        // no Authorization header
+        String authorization = "Basic " + Base64.getEncoder().encodeToString("aaa:bbb".getBytes());
+        List<String> resourceIds = Arrays.asList(UUID.randomUUID().toString());
+        Response response = this.service.findbyResourceIdAndType(this.httpRequest, null, authorization, APP,
+                this.transactionId, this.requestId, RESOURCE_TYPE_VSERVER, resourceIds, getCallbackUrl());
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+        // should get WWW-Authenticate header in response
+        assertTrue(((String) response.getEntity()).contains("version"));
+    }
+
     @Test
     public void testVerifyAppId() throws Exception {
         // no X-FromAppId header
@@ -150,7 +173,6 @@ public class NetworkDiscoveryTest {
 
     @Test
     public void testVerifyRequestId() throws Exception {
-        // no X-FromAppId header
         List<String> resourceIds = Arrays.asList(UUID.randomUUID().toString());
         Response response = this.service.findbyResourceIdAndType(this.httpRequest, V1, AUTH, APP, this.transactionId,
                         null, RESOURCE_TYPE_VSERVER, resourceIds, getCallbackUrl());
@@ -160,7 +182,6 @@ public class NetworkDiscoveryTest {
 
     @Test
     public void testVerifyNotificationUrl() throws Exception {
-        // no X-FromAppId header
         List<String> resourceIds = Arrays.asList(UUID.randomUUID().toString());
         Response response = this.service.findbyResourceIdAndType(this.httpRequest, V1, AUTH, APP, this.transactionId,
                         this.requestId, RESOURCE_TYPE_VSERVER, resourceIds, null);
@@ -199,32 +220,32 @@ public class NetworkDiscoveryTest {
         assertTrue(((String) response.getEntity()).contains("resourceType"));
     }
 
+    @Test
+    public void testVerifyInternalError() throws Exception {
+        // no request
+        List<String> resourceIds = Arrays.asList(UUID.randomUUID().toString());
+        Response response = this.service.findbyResourceIdAndType(null, V1, AUTH, APP, this.transactionId,
+                        this.requestId, null, resourceIds, getCallbackUrl());
+        assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
+    }
+
     @Test
     public void testDiscoverVserver() throws Exception {
         String vserverId = UUID.randomUUID().toString();
 
-        String resourcePath = MessageFormat.format(
-                        this.environment.getProperty("enricher.type.vserver.url"),
-                        new Object[] { vserverId });
-
-        String enricherPayload = String.format("<vserver xmlns=\"http://org.onap.aai.inventory/v11\">\r\n"
-                        + "   <vserver-id>%s</vserver-id>\r\n"
-                        + "   <power-state>1</power-state>\r\n"
-                        + "   <locked>true</locked>\r\n"
-                        + "   <hostname>10.147.112.48</hostname>\r\n"
-                        + "   <vm-state>active</vm-state>\r\n"
-                        + "   <status>ACTIVE</status>\r\n"
-                        + "   <host-status>UNKNOWN</host-status>\r\n"
-                        + "   <updated>2017-11-20T04:26:13Z</updated>\r\n"
-                        + "   <disk-allocation-gb>.010</disk-allocation-gb>\r\n"
-                        + "   <memory-usage-mb>null</memory-usage-mb>\r\n"
-                        + "   <cpu-util-percent>.043</cpu-util-percent>\r\n"
-                        + "   <retrieval-timestamp>2018-06-27 19:41:49 +0000</retrieval-timestamp>\r\n"
-                        + "</vserver>",
-                        vserverId);
-
-        this.enricherRule.stubFor(get(resourcePath).willReturn(okTextXml(enricherPayload)));
+        String resourcePath = MessageFormat.format("/v2.1/servers/{0}",
+                new Object[] { vserverId });
 
+        String identityPath = "/v3/auth/tokens";
+      
+        Object sourceObject = JsonUtils.filepathToObject(TEST_RESOURCES + "vserver-input.json");
+
+        String openstackApiResponse = JsonUtils.toJsonString(sourceObject);
+
+        this.openstackRule.stubFor(get(resourcePath).willReturn(okJson(openstackApiResponse)));
+
+        this.identityRule.stubFor(post(identityPath).willReturn(okJson("{}").withHeader("X-Subject-Token", "tokenId")));
+        
         this.callbackRule.stubFor(post(CALLBACK_PATH).willReturn(ok("Acknowledged")));
 
         Response response = this.service.findbyResourceIdAndType(this.httpRequest, V1, AUTH, APP, null, this.requestId,
@@ -259,9 +280,57 @@ public class NetworkDiscoveryTest {
 
         verifyAttribute(vserver.getAttributeList(), "status", "ACTIVE");
         verifyAttribute(vserver.getAttributeList(), "inMaintenance", "true");
-        verifyAttribute(vserver.getAttributeList(), "hostName", "10.147.112.48");
+        verifyAttribute(vserver.getAttributeList(), "hostname", "norm-bouygues");
         verifyAttribute(vserver.getAttributeList(), "vmState", "active");
     }
+    
+    @Test
+    public void testDiscoverVserverFailure() throws Exception {
+        String vserverId = UUID.randomUUID().toString();
+
+        String resourcePath = MessageFormat.format("/v2.1/servers/{0}",
+                new Object[] { vserverId });
+
+        String identityPath = "/v3/auth/tokens";
+        this.openstackRule.stubFor(get(resourcePath).willReturn(WireMock.notFound()));
+
+        this.identityRule.stubFor(post(identityPath).willReturn(okJson("{}").withHeader("X-Subject-Token", "tokenId")));
+        
+        this.callbackRule.stubFor(post(CALLBACK_PATH).willReturn(ok("Acknowledged")));
+
+        Response response = this.service.findbyResourceIdAndType(this.httpRequest, V1, AUTH, APP, null, this.requestId,
+                        RESOURCE_TYPE_VSERVER, Arrays.asList(vserverId), getCallbackUrl());
+
+        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+        NetworkDiscoveryResponse entity = (NetworkDiscoveryResponse) response.getEntity();
+        assertEquals(requestId, entity.getRequestId());
+        assertEquals(Status.ACCEPTED.getStatusCode(), entity.getCode().intValue());
+        assertEquals(Boolean.FALSE, entity.getAckFinalIndicator());
+
+        List<ServeEvent> events = waitForRequests(this.callbackRule, 1, 10);
+        LoggedRequest notificationRequest = events.get(0).getRequest();
+        assertEquals(AUTH, notificationRequest.getHeader(HttpHeaders.AUTHORIZATION));
+        String notificationJson = notificationRequest.getBodyAsString();
+
+        ObjectMapper mapper = new ObjectMapper();
+        AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
+        mapper.setAnnotationIntrospector(introspector);
+        NetworkDiscoveryNotification notification = mapper.readValue(notificationJson,
+                        NetworkDiscoveryNotification.class);
+
+        assertEquals(requestId, notification.getRequestId());
+        assertEquals(Status.OK.getStatusCode(), notification.getCode().intValue());
+        assertEquals(Boolean.TRUE, notification.getAckFinalIndicator());
+
+        assertEquals(1, notification.getResources().size());
+        Resource vserver = notification.getResources().get(0);
+        assertEquals(vserverId, vserver.getId());
+        assertEquals("vserver", vserver.getType());
+        assertEquals(DataQuality.Status.error, vserver.getDataQuality().getStatus());
+        assertNull(vserver.getAttributeList());
+    }
+
 
     /**
      * Verify API returns a final response indicating no discovery possible.
@@ -276,9 +345,47 @@ public class NetworkDiscoveryTest {
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
         NetworkDiscoveryResponse entity = (NetworkDiscoveryResponse) response.getEntity();
+        System.err.println("entity:" + entity);
         assertEquals(Boolean.TRUE, entity.getAckFinalIndicator());
         assertEquals(Status.NO_CONTENT.getStatusCode(), entity.getCode().intValue());
     }
+    
+    @Test
+    public void testLoginFailure() throws Exception {
+        String vserverId = UUID.randomUUID().toString();
+
+        String identityPath = "/v3/auth/tokens";
+      
+        this.identityRule.stubFor(post(identityPath).willReturn(WireMock.unauthorized()));
+        
+        this.callbackRule.stubFor(post(CALLBACK_PATH).willReturn(ok("Acknowledged")));
+
+        Response response = this.service.findbyResourceIdAndType(this.httpRequest, V1, AUTH, APP, null, this.requestId,
+                        RESOURCE_TYPE_VSERVER, Arrays.asList(vserverId), getCallbackUrl());
+
+        assertEquals(Status.OK.getStatusCode(), response.getStatus());
+        NetworkDiscoveryResponse entity = (NetworkDiscoveryResponse) response.getEntity();
+        assertEquals(requestId, entity.getRequestId());
+        assertEquals(Status.ACCEPTED.getStatusCode(), entity.getCode().intValue());
+        assertEquals(Boolean.FALSE, entity.getAckFinalIndicator());
+
+        List<ServeEvent> events = waitForRequests(this.callbackRule, 1, 10);
+        LoggedRequest notificationRequest = events.get(0).getRequest();
+        assertEquals(AUTH, notificationRequest.getHeader(HttpHeaders.AUTHORIZATION));
+        String notificationJson = notificationRequest.getBodyAsString();
+
+        ObjectMapper mapper = new ObjectMapper();
+        AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
+        mapper.setAnnotationIntrospector(introspector);
+        NetworkDiscoveryNotification notification = mapper.readValue(notificationJson,
+                        NetworkDiscoveryNotification.class);
+
+        assertEquals(requestId, notification.getRequestId());
+        assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), notification.getCode().intValue());
+        assertEquals(Boolean.TRUE, notification.getAckFinalIndicator());
+        assertNull(notification.getResources());
+    }
+
 
     private void verifyAttribute(List<Attribute> attributeList, String attrName, String attrValue) {
         for (Attribute attr : attributeList) {
diff --git a/pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/TestHttpServletRequest.java b/pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/TestHttpServletRequest.java
deleted file mode 100644 (file)
index 671033b..0000000
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- *  ============LICENSE_START===================================================
- * Copyright (c) 2018 Amdocs
- * ============================================================================
- * 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.
- * ============LICENSE_END=====================================================
- */
-
-package org.onap.sdnc.apps.pomba.networkdiscovery.unittest.service;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.security.Principal;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.Locale;
-import java.util.Map;
-import javax.servlet.AsyncContext;
-import javax.servlet.DispatcherType;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletInputStream;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpUpgradeHandler;
-import javax.servlet.http.Part;
-
-public class TestHttpServletRequest implements HttpServletRequest {
-    @Override
-    public String getHeader(String name) {
-        return null;
-    }
-
-    @Override
-    public String getRemoteAddr() {
-        return "localhost";
-    }
-
-    @Override
-    public String getServerName() {
-        return "localhost";
-    }
-
-    @Override
-    public String getRequestURI() {
-        return "/test";
-    }
-
-
-    @Override
-    public Object getAttribute(String name) {
-        // TODO Implement getAttribute
-        throw new UnsupportedOperationException("getAttribute");
-    }
-
-    @Override
-    public Enumeration<String> getAttributeNames() {
-        // TODO Implement getAttributeNames
-        throw new UnsupportedOperationException("getAttributeNames");
-    }
-
-    @Override
-    public String getCharacterEncoding() {
-        // TODO Implement getCharacterEncoding
-        throw new UnsupportedOperationException("getCharacterEncoding");
-    }
-
-    @Override
-    public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
-        // TODO Implement setCharacterEncoding
-        throw new UnsupportedOperationException("setCharacterEncoding");
-    }
-
-    @Override
-    public int getContentLength() {
-        // TODO Implement getContentLength
-        throw new UnsupportedOperationException("getContentLength");
-    }
-
-    @Override
-    public long getContentLengthLong() {
-        // TODO Implement getContentLengthLong
-        throw new UnsupportedOperationException("getContentLengthLong");
-    }
-
-    @Override
-    public String getContentType() {
-        // TODO Implement getContentType
-        throw new UnsupportedOperationException("getContentType");
-    }
-
-    @Override
-    public ServletInputStream getInputStream() throws IOException {
-        // TODO Implement getInputStream
-        throw new UnsupportedOperationException("getInputStream");
-    }
-
-    @Override
-    public String getParameter(String name) {
-        // TODO Implement getParameter
-        throw new UnsupportedOperationException("getParameter");
-    }
-
-    @Override
-    public Enumeration<String> getParameterNames() {
-        // TODO Implement getParameterNames
-        throw new UnsupportedOperationException("getParameterNames");
-    }
-
-    @Override
-    public String[] getParameterValues(String name) {
-        // TODO Implement getParameterValues
-        throw new UnsupportedOperationException("getParameterValues");
-    }
-
-    @Override
-    public Map<String, String[]> getParameterMap() {
-        // TODO Implement getParameterMap
-        throw new UnsupportedOperationException("getParameterMap");
-    }
-
-    @Override
-    public String getProtocol() {
-        // TODO Implement getProtocol
-        throw new UnsupportedOperationException("getProtocol");
-    }
-
-    @Override
-    public String getScheme() {
-        // TODO Implement getScheme
-        throw new UnsupportedOperationException("getScheme");
-    }
-
-    @Override
-    public int getServerPort() {
-        // TODO Implement getServerPort
-        throw new UnsupportedOperationException("getServerPort");
-    }
-
-    @Override
-    public BufferedReader getReader() throws IOException {
-        // TODO Implement getReader
-        throw new UnsupportedOperationException("getReader");
-    }
-
-    @Override
-    public String getRemoteHost() {
-        // TODO Implement getRemoteHost
-        throw new UnsupportedOperationException("getRemoteHost");
-    }
-
-    @Override
-    public void setAttribute(String name, Object obj) {
-        // TODO Implement setAttribute
-        throw new UnsupportedOperationException("setAttribute");
-    }
-
-    @Override
-    public void removeAttribute(String name) {
-        // TODO Implement removeAttribute
-        throw new UnsupportedOperationException("removeAttribute");
-    }
-
-    @Override
-    public Locale getLocale() {
-        // TODO Implement getLocale
-        throw new UnsupportedOperationException("getLocale");
-    }
-
-    @Override
-    public Enumeration<Locale> getLocales() {
-        // TODO Implement getLocales
-        throw new UnsupportedOperationException("getLocales");
-    }
-
-    @Override
-    public boolean isSecure() {
-        // TODO Implement isSecure
-        throw new UnsupportedOperationException("isSecure");
-    }
-
-    @Override
-    public RequestDispatcher getRequestDispatcher(String path) {
-        // TODO Implement getRequestDispatcher
-        throw new UnsupportedOperationException("getRequestDispatcher");
-    }
-
-    @Override
-    public String getRealPath(String path) {
-        // TODO Implement getRealPath
-        throw new UnsupportedOperationException("getRealPath");
-    }
-
-    @Override
-    public int getRemotePort() {
-        // TODO Implement getRemotePort
-        throw new UnsupportedOperationException("getRemotePort");
-    }
-
-    @Override
-    public String getLocalName() {
-        // TODO Implement getLocalName
-        throw new UnsupportedOperationException("getLocalName");
-    }
-
-    @Override
-    public String getLocalAddr() {
-        // TODO Implement getLocalAddr
-        throw new UnsupportedOperationException("getLocalAddr");
-    }
-
-    @Override
-    public int getLocalPort() {
-        // TODO Implement getLocalPort
-        throw new UnsupportedOperationException("getLocalPort");
-    }
-
-    @Override
-    public ServletContext getServletContext() {
-        // TODO Implement getServletContext
-        throw new UnsupportedOperationException("getServletContext");
-    }
-
-    @Override
-    public AsyncContext startAsync() throws IllegalStateException {
-        // TODO Implement startAsync
-        throw new UnsupportedOperationException("startAsync");
-    }
-
-    @Override
-    public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse)
-            throws IllegalStateException {
-        // TODO Implement startAsync
-        throw new UnsupportedOperationException("startAsync");
-    }
-
-    @Override
-    public boolean isAsyncStarted() {
-        // TODO Implement isAsyncStarted
-        throw new UnsupportedOperationException("isAsyncStarted");
-    }
-
-    @Override
-    public boolean isAsyncSupported() {
-        // TODO Implement isAsyncSupported
-        throw new UnsupportedOperationException("isAsyncSupported");
-    }
-
-    @Override
-    public AsyncContext getAsyncContext() {
-        // TODO Implement getAsyncContext
-        throw new UnsupportedOperationException("getAsyncContext");
-    }
-
-    @Override
-    public DispatcherType getDispatcherType() {
-        // TODO Implement getDispatcherType
-        throw new UnsupportedOperationException("getDispatcherType");
-    }
-
-    @Override
-    public String getAuthType() {
-        // TODO Implement getAuthType
-        throw new UnsupportedOperationException("getAuthType");
-    }
-
-    @Override
-    public Cookie[] getCookies() {
-        // TODO Implement getCookies
-        throw new UnsupportedOperationException("getCookies");
-    }
-
-    @Override
-    public long getDateHeader(String name) {
-        // TODO Implement getDateHeader
-        throw new UnsupportedOperationException("getDateHeader");
-    }
-
-    @Override
-    public Enumeration<String> getHeaders(String name) {
-        // TODO Implement getHeaders
-        throw new UnsupportedOperationException("getHeaders");
-    }
-
-    @Override
-    public Enumeration<String> getHeaderNames() {
-        // TODO Implement getHeaderNames
-        throw new UnsupportedOperationException("getHeaderNames");
-    }
-
-    @Override
-    public int getIntHeader(String name) {
-        // TODO Implement getIntHeader
-        throw new UnsupportedOperationException("getIntHeader");
-    }
-
-    @Override
-    public String getMethod() {
-        // TODO Implement getMethod
-        throw new UnsupportedOperationException("getMethod");
-    }
-
-    @Override
-    public String getPathInfo() {
-        // TODO Implement getPathInfo
-        throw new UnsupportedOperationException("getPathInfo");
-    }
-
-    @Override
-    public String getPathTranslated() {
-        // TODO Implement getPathTranslated
-        throw new UnsupportedOperationException("getPathTranslated");
-    }
-
-    @Override
-    public String getContextPath() {
-        // TODO Implement getContextPath
-        throw new UnsupportedOperationException("getContextPath");
-    }
-
-    @Override
-    public String getQueryString() {
-        // TODO Implement getQueryString
-        throw new UnsupportedOperationException("getQueryString");
-    }
-
-    @Override
-    public String getRemoteUser() {
-        // TODO Implement getRemoteUser
-        throw new UnsupportedOperationException("getRemoteUser");
-    }
-
-    @Override
-    public boolean isUserInRole(String role) {
-        // TODO Implement isUserInRole
-        throw new UnsupportedOperationException("isUserInRole");
-    }
-
-    @Override
-    public Principal getUserPrincipal() {
-        // TODO Implement getUserPrincipal
-        throw new UnsupportedOperationException("getUserPrincipal");
-    }
-
-    @Override
-    public String getRequestedSessionId() {
-        // TODO Implement getRequestedSessionId
-        throw new UnsupportedOperationException("getRequestedSessionId");
-    }
-
-    @Override
-    public StringBuffer getRequestURL() {
-        // TODO Implement getRequestURL
-        throw new UnsupportedOperationException("getRequestURL");
-    }
-
-    @Override
-    public String getServletPath() {
-        // TODO Implement getServletPath
-        throw new UnsupportedOperationException("getServletPath");
-    }
-
-    @Override
-    public HttpSession getSession(boolean create) {
-        // TODO Implement getSession
-        throw new UnsupportedOperationException("getSession");
-    }
-
-    @Override
-    public HttpSession getSession() {
-        // TODO Implement getSession
-        throw new UnsupportedOperationException("getSession");
-    }
-
-    @Override
-    public String changeSessionId() {
-        // TODO Implement changeSessionId
-        throw new UnsupportedOperationException("changeSessionId");
-    }
-
-    @Override
-    public boolean isRequestedSessionIdValid() {
-        // TODO Implement isRequestedSessionIdValid
-        throw new UnsupportedOperationException("isRequestedSessionIdValid");
-    }
-
-    @Override
-    public boolean isRequestedSessionIdFromCookie() {
-        // TODO Implement isRequestedSessionIdFromCookie
-        throw new UnsupportedOperationException("isRequestedSessionIdFromCookie");
-    }
-
-    @Override
-    public boolean isRequestedSessionIdFromURL() {
-        // TODO Implement isRequestedSessionIdFromURL
-        throw new UnsupportedOperationException("isRequestedSessionIdFromURL");
-    }
-
-    @Override
-    public boolean isRequestedSessionIdFromUrl() {
-        // TODO Implement isRequestedSessionIdFromUrl
-        throw new UnsupportedOperationException("isRequestedSessionIdFromUrl");
-    }
-
-    @Override
-    public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
-        // TODO Implement authenticate
-        throw new UnsupportedOperationException("authenticate");
-    }
-
-    @Override
-    public void login(String username, String password) throws ServletException {
-        // TODO Implement login
-        throw new UnsupportedOperationException("login");
-    }
-
-    @Override
-    public void logout() throws ServletException {
-        // TODO Implement logout
-        throw new UnsupportedOperationException("logout");
-    }
-
-    @Override
-    public Collection<Part> getParts() throws IOException, ServletException {
-        // TODO Implement getParts
-        throw new UnsupportedOperationException("getParts");
-    }
-
-    @Override
-    public Part getPart(String name) throws IOException, ServletException {
-        // TODO Implement getPart
-        throw new UnsupportedOperationException("getPart");
-    }
-
-    @Override
-    public <T extends HttpUpgradeHandler> T upgrade(Class<T> httpUpgradeHandlerClass)
-            throws IOException, ServletException {
-        // TODO Implement upgrade
-        throw new UnsupportedOperationException("upgrade");
-    }
-    /////////////////////////////////////////////////////////////////////////////
-    // Constants
-    /////////////////////////////////////////////////////////////////////////////
-
-    /////////////////////////////////////////////////////////////////////////////
-    // Class variables
-    /////////////////////////////////////////////////////////////////////////////
-
-    /////////////////////////////////////////////////////////////////////////////
-    // Instance variables
-    /////////////////////////////////////////////////////////////////////////////
-
-    /////////////////////////////////////////////////////////////////////////////
-    // Constructors
-    /////////////////////////////////////////////////////////////////////////////
-
-    /////////////////////////////////////////////////////////////////////////////
-    // Public methods
-    /////////////////////////////////////////////////////////////////////////////
-
-    /////////////////////////////////////////////////////////////////////////////
-    // [interface name] implementation
-    /////////////////////////////////////////////////////////////////////////////
-
-    /////////////////////////////////////////////////////////////////////////////
-    // [super class] override methods
-    /////////////////////////////////////////////////////////////////////////////
-
-    /////////////////////////////////////////////////////////////////////////////
-    // Package protected methods
-    /////////////////////////////////////////////////////////////////////////////
-
-    /////////////////////////////////////////////////////////////////////////////
-    // Protected methods
-    /////////////////////////////////////////////////////////////////////////////
-
-    /////////////////////////////////////////////////////////////////////////////
-    // Private methods
-    /////////////////////////////////////////////////////////////////////////////
-
-    /////////////////////////////////////////////////////////////////////////////
-    // Inner classes
-    /////////////////////////////////////////////////////////////////////////////
-}
diff --git a/pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/util/TransformationUtilTest.java b/pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/util/TransformationUtilTest.java
new file mode 100644 (file)
index 0000000..968c1cf
--- /dev/null
@@ -0,0 +1,136 @@
+/*\r
+ * ============LICENSE_START===================================================\r
+ * Copyright (c) 2018 Amdocs\r
+ * ============================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *        http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * ============LICENSE_END=====================================================\r
+ */\r
+\r
+package org.onap.sdnc.apps.pomba.networkdiscovery.unittest.service.util;\r
+\r
+import static org.junit.Assert.assertThat;\r
+\r
+import com.bazaarvoice.jolt.JsonUtils;\r
+import com.bazaarvoice.jolt.exception.JsonUnmarshalException;\r
+\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.hamcrest.CoreMatchers;\r
+import org.junit.Assert;\r
+import org.junit.Rule;\r
+import org.junit.Test;\r
+import org.junit.rules.ExpectedException;\r
+import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.Attribute;\r
+import org.onap.sdnc.apps.pomba.networkdiscovery.service.util.TransformationUtil;\r
+\r
+public class TransformationUtilTest {\r
+\r
+    private static final String TEST_RESOURCES = "src/test/resources/jolt/";\r
+\r
+    @Rule\r
+    public ExpectedException expectedEx = ExpectedException.none();\r
+\r
+    @Test\r
+    public void testTransformVServer() {\r
+\r
+        Object sourceObject = JsonUtils.filepathToObject(TEST_RESOURCES + "vserver-input.json");\r
+\r
+        String resultJson = TransformationUtil.transform(JsonUtils.toJsonString(sourceObject), "vserver");\r
+\r
+        Object expectedObject = JsonUtils.filepathToObject(TEST_RESOURCES + "vserver-expected.json");\r
+\r
+        Assert.assertEquals("Json transformation result does not match expected content",\r
+                JsonUtils.toPrettyJsonString(expectedObject),\r
+                JsonUtils.toPrettyJsonString(JsonUtils.jsonToObject(resultJson)));\r
+\r
+    }\r
+\r
+    @Test\r
+    public void testTransformL3Network() {\r
+\r
+        Object sourceObject = JsonUtils.filepathToObject(TEST_RESOURCES + "l3network-input.json");\r
+        String resultJson = TransformationUtil.transform(JsonUtils.toJsonString(sourceObject), "l3-network");\r
+\r
+        Object expectedObject = JsonUtils.filepathToObject(TEST_RESOURCES + "l3network-expected.json");\r
+\r
+        Assert.assertEquals("Json transformation result does not match expected content",\r
+                JsonUtils.toPrettyJsonString(expectedObject),\r
+                JsonUtils.toPrettyJsonString(JsonUtils.jsonToObject(resultJson)));\r
+\r
+    }\r
+\r
+    @Test\r
+    public void testTransformFailureFileNotFound() {\r
+\r
+        expectedEx.expect(RuntimeException.class);\r
+        expectedEx.expectMessage("Unable to load JSON file");\r
+\r
+        TransformationUtil.transform("{}", "foobar");\r
+    }\r
+\r
+    @Test\r
+    public void testTransformFailureInvalidInputJson() {\r
+\r
+        expectedEx.expect(JsonUnmarshalException.class);\r
+        expectedEx.expectMessage("Unable to unmarshal JSON");\r
+\r
+        TransformationUtil.transform("xxx", "foobar");\r
+    }\r
+\r
+    @Test\r
+    public void testToAttributeList() {\r
+        Map<String, String> expectedAttributes = new HashMap<String, String>();\r
+        expectedAttributes.put("name", "norm_bouygues");\r
+        expectedAttributes.put("hostId", "ea1660efbbedda164379afacdc622305c4b88cebfb84119472d286a8");\r
+        expectedAttributes.put("hostStatus", "UP");\r
+        expectedAttributes.put("id", "2c311eae-f542-4173-8a01-582922abd495");\r
+        expectedAttributes.put("status", "ACTIVE");\r
+        expectedAttributes.put("vmState", "active");\r
+        expectedAttributes.put("hostname", "norm-bouygues");\r
+        expectedAttributes.put("inMaintenance", "true");\r
+        expectedAttributes.put("imageId", "c0022890-d91f-422c-91c5-3866edeae768");\r
+        expectedAttributes.put("tenantId", "15ad36d394e744838e947ca90609f805");\r
+        expectedAttributes.put("host", "Setup-NCSO-OTT-E-C2");\r
+\r
+        Object inputJson = JsonUtils.filepathToObject(TEST_RESOURCES + "vserver-expected.json");\r
+        List<Attribute> resultAttributeList = TransformationUtil.toAttributeList(JsonUtils.toJsonString(inputJson));\r
+\r
+        Map<String, String> resultAttributes = new HashMap<>();\r
+\r
+        for (Attribute attribute : resultAttributeList) {\r
+            resultAttributes.put(attribute.getName(), attribute.getValue());\r
+        }\r
+        assertThat(expectedAttributes, CoreMatchers.is(resultAttributes));\r
+    }\r
+\r
+    @Test\r
+    public void testToAttributeListNullJsonValue() {\r
+        Map<String, String> expectedAttributes = new HashMap<String, String>();\r
+        expectedAttributes.put("name", "");\r
+\r
+        String inputJson = "{\"server\": { \"name\": null }}";\r
+\r
+        List<Attribute> resultAttributeList = TransformationUtil.toAttributeList(inputJson);\r
+\r
+        Map<String, String> resultAttributes = new HashMap<>();\r
+\r
+        for (Attribute attribute : resultAttributeList) {\r
+            resultAttributes.put(attribute.getName(), attribute.getValue());\r
+        }\r
+       // assertThat(expectedAttributes, resultAttributes);\r
+        assertThat(expectedAttributes, CoreMatchers.is(resultAttributes));\r
+    }\r
+\r
+}\r
diff --git a/pomba/network-discovery/src/test/resources/jolt/l3network-expected.json b/pomba/network-discovery/src/test/resources/jolt/l3network-expected.json
new file mode 100644 (file)
index 0000000..be4ad9d
--- /dev/null
@@ -0,0 +1,14 @@
+{\r
+       "l3-network": {\r
+               "id": "8df84f0a-737a-4628-be9c-c3c78454f9d9",\r
+               "name": "NET_503",\r
+               "AdminState": true,\r
+               "sharedNetwork": true,\r
+               "status": "ACTIVE",\r
+               "subnets": [\r
+                       "d0e6ecad-7bc9-4138-b9e8-e742bdf9afd5"\r
+               ],\r
+               "tenantId": "c44b872f6830498b88c4989d67b2a6b7",\r
+               "host-status": "UNKNOWN"\r
+       }\r
+}\r
diff --git a/pomba/network-discovery/src/test/resources/jolt/l3network-input.json b/pomba/network-discovery/src/test/resources/jolt/l3network-input.json
new file mode 100644 (file)
index 0000000..ebd9504
--- /dev/null
@@ -0,0 +1,32 @@
+{
+    "network": {
+        "provider:physical_network": "public",
+        "ipv6_address_scope": null,
+        "revision_number": 9,
+        "port_security_enabled": true,
+        "mtu": 1500,
+        "id": "8df84f0a-737a-4628-be9c-c3c78454f9d9",
+        "router:external": true,
+        "availability_zone_hints": [],
+        "availability_zones": [
+            "nova"
+        ],
+        "ipv4_address_scope": null,
+        "shared": true,
+        "project_id": "c44b872f6830498b88c4989d67b2a6b7",
+        "status": "ACTIVE",
+        "subnets": [
+            "d0e6ecad-7bc9-4138-b9e8-e742bdf9afd5"
+        ],
+        "description": "",
+        "tags": [],
+        "updated_at": "2018-10-03T21:15:10Z",
+        "is_default": false,
+        "provider:segmentation_id": 503,
+        "name": "NET_503",
+        "admin_state_up": true,
+        "tenant_id": "c44b872f6830498b88c4989d67b2a6b7",
+        "created_at": "2018-03-20T16:49:01Z",
+        "provider:network_type": "vlan"
+    }
+}
\ No newline at end of file
diff --git a/pomba/network-discovery/src/test/resources/jolt/vserver-expected.json b/pomba/network-discovery/src/test/resources/jolt/vserver-expected.json
new file mode 100644 (file)
index 0000000..53d4a79
--- /dev/null
@@ -0,0 +1,15 @@
+{\r
+  "vserver" : {\r
+    "id" : "2c311eae-f542-4173-8a01-582922abd495",\r
+    "name" : "norm_bouygues",\r
+    "inMaintenance" : true,\r
+    "hostname" : "norm-bouygues",\r
+    "imageId" : "c0022890-d91f-422c-91c5-3866edeae768",\r
+    "status" : "ACTIVE",\r
+    "vmState" : "active",\r
+    "tenantId" : "15ad36d394e744838e947ca90609f805",\r
+    "hostId" : "ea1660efbbedda164379afacdc622305c4b88cebfb84119472d286a8",\r
+    "host" : "Setup-NCSO-OTT-E-C2",\r
+    "hostStatus" : "UP"\r
+  }\r
+}
\ No newline at end of file
diff --git a/pomba/network-discovery/src/test/resources/jolt/vserver-input.json b/pomba/network-discovery/src/test/resources/jolt/vserver-input.json
new file mode 100644 (file)
index 0000000..faa7ba5
--- /dev/null
@@ -0,0 +1,92 @@
+{
+    "server": {
+        "OS-EXT-STS:task_state": null,
+        "addresses": {
+            "NET_502": [
+                {
+                    "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:a5:c5:19",
+                    "version": 4,
+                    "addr": "10.69.36.133",
+                    "OS-EXT-IPS:type": "fixed"
+                },
+                {
+                    "OS-EXT-IPS-MAC:mac_addr": "fa:16:3e:50:05:f4",
+                    "version": 4,
+                    "addr": "10.69.36.137",
+                    "OS-EXT-IPS:type": "fixed"
+                }
+            ]
+        },
+        "links": [
+            {
+                "href": "http://10.69.36.11:8774/v2.1/servers/2c311eae-f542-4173-8a01-582922abd495",
+                "rel": "self"
+            },
+            {
+                "href": "http://10.69.36.11:8774/servers/2c311eae-f542-4173-8a01-582922abd495",
+                "rel": "bookmark"
+            }
+        ],
+        "image": {
+            "id": "c0022890-d91f-422c-91c5-3866edeae768",
+            "links": [
+                {
+                    "href": "http://10.69.36.11:8774/images/c0022890-d91f-422c-91c5-3866edeae768",
+                    "rel": "bookmark"
+                }
+            ]
+        },
+        "OS-EXT-SRV-ATTR:user_data": null,
+        "OS-EXT-STS:vm_state": "active",
+        "OS-EXT-SRV-ATTR:instance_name": "instance-000009ca",
+        "OS-EXT-SRV-ATTR:root_device_name": "/dev/vda",
+        "OS-SRV-USG:launched_at": "2018-08-20T15:10:09.000000",
+        "flavor": {
+            "id": "786f55b2-7c94-4089-b89d-96353567c9d8",
+            "links": [
+                {
+                    "href": "http://10.69.36.11:8774/flavors/786f55b2-7c94-4089-b89d-96353567c9d8",
+                    "rel": "bookmark"
+                }
+            ]
+        },
+        "id": "2c311eae-f542-4173-8a01-582922abd495",
+        "security_groups": [
+            {
+                "name": "default"
+            },
+            {
+                "name": "default"
+            }
+        ],
+        "OS-SRV-USG:terminated_at": null,
+        "os-extended-volumes:volumes_attached": [],
+        "user_id": "bdaf4fcde1574450bfa488b3221033d8",
+        "OS-EXT-SRV-ATTR:hostname": "norm-bouygues",
+        "OS-DCF:diskConfig": "AUTO",
+        "accessIPv4": "",
+        "accessIPv6": "",
+        "OS-EXT-SRV-ATTR:reservation_id": "r-wo1numj9",
+        "progress": 0,
+        "OS-EXT-STS:power_state": 1,
+        "OS-EXT-AZ:availability_zone": "nova",
+        "metadata": {},
+        "status": "ACTIVE",
+        "OS-EXT-SRV-ATTR:ramdisk_id": "",
+        "updated": "2018-11-15T15:28:09Z",
+        "hostId": "ea1660efbbedda164379afacdc622305c4b88cebfb84119472d286a8",
+        "OS-EXT-SRV-ATTR:host": "Setup-NCSO-OTT-E-C2",
+        "description": "norm_bouygues",
+        "tags": [],
+        "key_name": "normant-test-key",
+        "OS-EXT-SRV-ATTR:kernel_id": "",
+        "locked": true,
+        "OS-EXT-SRV-ATTR:hypervisor_hostname": "Setup-NCSO-OTT-E-C2",
+        "name": "norm_bouygues",
+        "OS-EXT-SRV-ATTR:launch_index": 0,
+        "created": "2018-08-20T15:09:32Z",
+        "tenant_id": "15ad36d394e744838e947ca90609f805",
+        "host_status": "UP",
+        "config_drive": ""
+    }
+}
\ No newline at end of file