From 9a0c9790a1dc31dcc2db199b6f0ff76e796c2597 Mon Sep 17 00:00:00 2001 From: Norm Traxler Date: Tue, 27 Nov 2018 22:18:16 +0000 Subject: ND get VM info from Openstack Issue-ID: SDNC-533 Change-Id: If50c4ae02349824a4e179e30ea1ee29d3afe6ab2 Signed-off-by: Norm Traxler --- .../config/application.properties | 27 +- .../config/auth/client-cert-onap.p12 | Bin 0 -> 2556 bytes pomba/network-discovery/config/auth/osauth.json | 18 + .../network-discovery/config/jolt/l3-network.json | 25 ++ pomba/network-discovery/config/jolt/vserver.json | 32 ++ pomba/network-discovery/pom.xml | 18 + pomba/network-discovery/src/main/docker/Dockerfile | 3 +- .../apps/pomba/networkdiscovery/Application.java | 2 +- .../networkdiscovery/ApplicationException.java | 19 +- .../networkdiscovery/EnricherConfiguration.java | 94 ---- .../networkdiscovery/OpenstackConfiguration.java | 108 +++++ .../networkdiscovery/service/OSAuthentication.java | 78 ++++ .../service/SpringServiceImpl.java | 206 ++++----- .../service/rs/RestServiceImpl.java | 11 +- .../service/util/TransformationUtil.java | 99 ++++ .../unittest/service/NetworkDiscoveryTest.java | 169 +++++-- .../unittest/service/TestHttpServletRequest.java | 500 --------------------- .../service/util/TransformationUtilTest.java | 136 ++++++ .../test/resources/jolt/l3network-expected.json | 14 + .../src/test/resources/jolt/l3network-input.json | 32 ++ .../src/test/resources/jolt/vserver-expected.json | 15 + .../src/test/resources/jolt/vserver-input.json | 92 ++++ 22 files changed, 901 insertions(+), 797 deletions(-) create mode 100644 pomba/network-discovery/config/auth/client-cert-onap.p12 create mode 100644 pomba/network-discovery/config/auth/osauth.json create mode 100644 pomba/network-discovery/config/jolt/l3-network.json create mode 100644 pomba/network-discovery/config/jolt/vserver.json delete mode 100644 pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/EnricherConfiguration.java create mode 100644 pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/OpenstackConfiguration.java create mode 100644 pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/OSAuthentication.java create mode 100644 pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/util/TransformationUtil.java delete mode 100644 pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/TestHttpServletRequest.java create mode 100644 pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/util/TransformationUtilTest.java create mode 100644 pomba/network-discovery/src/test/resources/jolt/l3network-expected.json create mode 100644 pomba/network-discovery/src/test/resources/jolt/l3network-input.json create mode 100644 pomba/network-discovery/src/test/resources/jolt/vserver-expected.json create mode 100644 pomba/network-discovery/src/test/resources/jolt/vserver-input.json diff --git a/pomba/network-discovery/config/application.properties b/pomba/network-discovery/config/application.properties index 6dba59d..f6a889e 100644 --- a/pomba/network-discovery/config/application.properties +++ b/pomba/network-discovery/config/application.properties @@ -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 -# :; 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 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 index 0000000..95dec53 --- /dev/null +++ b/pomba/network-discovery/config/auth/osauth.json @@ -0,0 +1,18 @@ +{ + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "name": "%USER%", + "domain": { + "name": "Default" + }, + "password": "%PASSWORD%" + } + } + } + } +} \ 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 index 0000000..0afe4a2 --- /dev/null +++ b/pomba/network-discovery/config/jolt/l3-network.json @@ -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 index 0000000..cc9e26d --- /dev/null +++ b/pomba/network-discovery/config/jolt/vserver.json @@ -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" + } + } + } + +] diff --git a/pomba/network-discovery/pom.xml b/pomba/network-discovery/pom.xml index 24aa3de..18a8587 100644 --- a/pomba/network-discovery/pom.xml +++ b/pomba/network-discovery/pom.xml @@ -50,6 +50,23 @@ limitations under the License. + + + com.bazaarvoice.jolt + jolt-core + 0.1.0 + + + com.bazaarvoice.jolt + json-utils + 0.1.0 + + + commons-io + commons-io + 2.5 + + org.springframework.boot @@ -279,6 +296,7 @@ limitations under the License. *.properties *.xml + **/*.json false diff --git a/pomba/network-discovery/src/main/docker/Dockerfile b/pomba/network-discovery/src/main/docker/Dockerfile index e9be214..45a8c5a 100644 --- a/pomba/network-discovery/src/main/docker/Dockerfile +++ b/pomba/network-discovery/src/main/docker/Dockerfile @@ -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"] diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/Application.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/Application.java index c976678..e7e2208 100644 --- a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/Application.java +++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/Application.java @@ -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 diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/ApplicationException.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/ApplicationException.java index fa29645..98bb2e7 100644 --- a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/ApplicationException.java +++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/ApplicationException.java @@ -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; } diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/EnricherConfiguration.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/EnricherConfiguration.java deleted file mode 100644 index 62ea3f7..0000000 --- a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/EnricherConfiguration.java +++ /dev/null @@ -1,94 +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; - -import java.util.HashMap; -import java.util.Map; -import java.util.StringTokenizer; -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 { - @Autowired - private Environment env; - - @Value("${enricher.url:https://localhost:9505}") - private String url; - - @Value("${enricher.keyStorePath:config/auth/client-cert-onap.p12}") - private String keyStorePath; - - @Value("${enricher.keyStorePassword:OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10}") - private String keyStorePassword; - - @Value("${enricher.connectionTimeout:5000}") - private int connectionTimeout; - - @Value("${enricher.readTimeout:60000}") - private int readTimeout; - - @Value("${enricher.attributeNameMappingList}") - private String enricherAttributeNameMappingList; - - @Bean(name = "enricherClient") - 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)); - } - - @Bean(name = "enricherBaseUrl") - public String getURL() { - return this.url; - } - - @Bean(name = "enricherTypeURLs") - public Map enricherTypeURLs() { - - Map result = new HashMap<>(); - String types = this.env.getProperty("enricher.types"); - if (types == null) { - return result; - } - - 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); - } - - return result; - } - - @Bean(name = "enricherAttributeNameMapping") - public Map 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/OpenstackConfiguration.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/OpenstackConfiguration.java new file mode 100644 index 0000000..ee18397 --- /dev/null +++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/OpenstackConfiguration.java @@ -0,0 +1,108 @@ +/* + * ============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; + +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; + +@Configuration +public class OpenstackConfiguration { + @Autowired + private Environment env; + + @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("${openstack.api.microversion}") + private String apiMicroversion; + + @Value("${openstack.identity.keyStorePath:config/auth/client-cert-onap.p12}") + private String keyStorePath; + + @Value("${openstack.identity.keyStorePassword:OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10}") + private String keyStorePassword; + + @Value("${openstack.connectionTimeout:5000}") + private int connectionTimeout; + + @Value("${openstack.readTimeout:60000}") + private int readTimeout; + + @Bean(name = "openstackClient") + public RestClient restClient() { + return new RestClient().validateServerHostname(false) + .validateServerCertChain(false) + .connectTimeoutMs(this.connectionTimeout) + .readTimeoutMs(this.readTimeout); + } + + @Bean(name = "openstackIdentityUrl") + public String getIdentityURL() { + return this.identityUrl; + } + + @Bean(name = "openstackIdentityUser") + public String getIdentityUser() { + return this.identityUser; + } + + @Bean(name = "openstackIdentityPassword") + public String getIdentityPassword() { + return Password.deobfuscate(this.identityPassword); + } + + @Bean(name = "openstackApiMicroversion") + public String getApiMicroversion() { + return this.apiMicroversion; + } + + @Bean(name = "openstackTypeURLs") + public Map getOpenstackTypeURLs() { + + Map result = new HashMap<>(); + String types = this.env.getProperty("openstack.types"); + if (types == null) { + return result; + } + + StringTokenizer tokenizer = new StringTokenizer(types, ", "); + while (tokenizer.hasMoreTokens()) { + String type = tokenizer.nextToken(); + String openstackUrl = this.env.getProperty("openstack.type." + type + ".url"); + result.put(type, openstackUrl); + } + + return result; + } + +} 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 index 0000000..fed52a0 --- /dev/null +++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/OSAuthentication.java @@ -0,0 +1,78 @@ +/* + * ============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.service; + +import static org.onap.sdnc.apps.pomba.networkdiscovery.ApplicationException.Error.UNAUTHORIZED; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response.Status; + +import org.apache.commons.io.IOUtils; +import org.onap.aai.restclient.client.OperationResult; +import org.onap.aai.restclient.client.RestClient; +import org.onap.logging.ref.slf4j.ONAPLogAdapter; +import org.onap.sdnc.apps.pomba.networkdiscovery.ApplicationException; + +public class OSAuthentication { + + private static final String CONFIG_AUTH_DIR = "config/auth"; + private static final String X_SUBJECT_TOKEN = "X-Subject-Token"; + + private static final String USER_PATTERN = "%USER%"; + private static final String PASSWORD_PATTERN = "%PASSWORD%"; + + private OSAuthentication() { + throw new IllegalStateException("Utility class"); + } + + public static String getToken(String openstackIdentityUrl, String userId, String password, RestClient openstackClient, ONAPLogAdapter adapter) + throws IOException, ApplicationException { + + MultivaluedMap headers = new MultivaluedHashMap<>(); + + String mappingConfigPath = CONFIG_AUTH_DIR + File.separator + "osauth.json"; + + File file = new File(mappingConfigPath); + String payload = IOUtils.toString(new FileInputStream(file), "UTF-8"); + payload = payload.replaceAll(USER_PATTERN, userId); + payload = payload.replaceAll(PASSWORD_PATTERN, password); + + OperationResult result = openstackClient.post(openstackIdentityUrl, payload, headers, + MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON_TYPE); + + adapter.unwrap().info("request at url = {} resulted in http response: {}", openstackIdentityUrl, + result.getResult()); + + String token = result.getHeaders().getFirst(X_SUBJECT_TOKEN); + + if (token == null) { + throw new ApplicationException(UNAUTHORIZED, Status.UNAUTHORIZED); + } + + adapter.unwrap().debug("Got token: {}", token); + + return token; + } + +} diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringServiceImpl.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringServiceImpl.java index 8d0de03..1be8fbc 100644 --- a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringServiceImpl.java +++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/SpringServiceImpl.java @@ -17,16 +17,17 @@ */ 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 enricherTypeURLs; + @Autowired + private String openstackIdentityPassword; + + @Autowired + private String openstackApiMicroversion; - private DocumentBuilder parser; + @javax.annotation.Resource + private Client callbackClient; @javax.annotation.Resource - private Map enricherAttributeNameMapping; + private Map openstackTypeURLs; public SpringServiceImpl() throws ParserConfigurationException { - this.parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); } @Override - public NetworkDiscoveryResponse findbyResourceIdAndType(String transactionId, - String requestId, - String resourceType, - List resourceIds, - String notificationURL, - String notificationAuthorization, - ONAPLogAdapter adapter) throws ApplicationException { + public NetworkDiscoveryResponse findbyResourceIdAndType(String transactionId, String requestId, String resourceType, + List 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> 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> 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 resourceIds, - String notificationURL, - String notificationAuthorization, - String resourceURL, - ONAPLogAdapter adapter) { + public ResourceTask(String transactionId, String requestId, String resourceType, List 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 resources = null; - MessageFormat format = new MessageFormat(SpringServiceImpl.this.enricherBaseUrl + this.resourceURL); + MessageFormat format = new MessageFormat(this.resourceURL); MultivaluedMap 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 attributeList = toAttributeList(result.getResult(), adapter); - resource.setAttributeList(attributeList); - } catch (Exception x) { - resource.setDataQuality(DataQuality.error(x.getMessage())); - } + List 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 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 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); } } diff --git a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestServiceImpl.java b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestServiceImpl.java index 7447e67..0677dcd 100644 --- a/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestServiceImpl.java +++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/rs/RestServiceImpl.java @@ -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 index 0000000..dc17848 --- /dev/null +++ b/pomba/network-discovery/src/main/java/org/onap/sdnc/apps/pomba/networkdiscovery/service/util/TransformationUtil.java @@ -0,0 +1,99 @@ +/* + * Copyright 2014 Bazaarvoice, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.sdnc.apps.pomba.networkdiscovery.service.util; + +import com.bazaarvoice.jolt.Chainr; +import com.bazaarvoice.jolt.JsonUtils; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + +import org.onap.pomba.common.datatypes.DataQuality; +import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.Attribute; + +public class TransformationUtil { + + private static final String CONFIG_JOLT = "config/jolt"; + private static final String EMPTY_STRING = ""; + + public TransformationUtil() { + throw new IllegalStateException("Utility class"); + } + + /** + * Transforms the sourceJson using the jolt specification for the given resourceType. + * + * @param sourceJson + * @param resourceType + * @return + */ + public static String transform(String sourceJson, String resourceType) { + + Object sourceObject = JsonUtils.jsonToObject(sourceJson); + + List chainrSpecJSON = JsonUtils.filepathToList(CONFIG_JOLT + File.separator + resourceType + ".json"); + Chainr chainr = Chainr.fromSpec(chainrSpecJSON); + Object output = chainr.transform(sourceObject); + + return JsonUtils.toJsonString(output); + } + + /** + * Converts the second level of JsonElements from the given json to a list of + * Network Discovery Attributes. + * + * @param json + * @return + */ + public static List toAttributeList(String json) { + + JsonParser parser = new JsonParser(); + JsonElement elem = parser.parse(json); + + Set> entrySet = elem.getAsJsonObject().entrySet(); + + List result = new ArrayList<>(); + + Iterator> iter = entrySet.iterator(); + while (iter.hasNext()) { + Entry next = iter.next(); + + JsonElement vserverElem = next.getValue(); + Set> vserverEntrySet = vserverElem.getAsJsonObject().entrySet(); + Iterator> vserverIter = vserverEntrySet.iterator(); + while (vserverIter.hasNext()) { + Entry vserverNext = vserverIter.next(); + Attribute attr = new Attribute(); + attr.setName(vserverNext.getKey()); + if (vserverNext.getValue().isJsonNull()) { + attr.setValue(EMPTY_STRING); + } else { + attr.setValue(vserverNext.getValue().getAsString()); + } + attr.setDataQuality(DataQuality.ok()); + result.add(attr); + } + } + return result; + } + +} \ No newline at end of file diff --git a/pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/NetworkDiscoveryTest.java b/pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/NetworkDiscoveryTest.java index 1829e6e..18a0a04 100644 --- a/pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/NetworkDiscoveryTest.java +++ b/pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/NetworkDiscoveryTest.java @@ -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 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 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 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 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("\r\n" - + " %s\r\n" - + " 1\r\n" - + " true\r\n" - + " 10.147.112.48\r\n" - + " active\r\n" - + " ACTIVE\r\n" - + " UNKNOWN\r\n" - + " 2017-11-20T04:26:13Z\r\n" - + " .010\r\n" - + " null\r\n" - + " .043\r\n" - + " 2018-06-27 19:41:49 +0000\r\n" - + "", - 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 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 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 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 index 671033b..0000000 --- a/pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/TestHttpServletRequest.java +++ /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 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 getParameterNames() { - // TODO Implement getParameterNames - throw new UnsupportedOperationException("getParameterNames"); - } - - @Override - public String[] getParameterValues(String name) { - // TODO Implement getParameterValues - throw new UnsupportedOperationException("getParameterValues"); - } - - @Override - public Map 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 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 getHeaders(String name) { - // TODO Implement getHeaders - throw new UnsupportedOperationException("getHeaders"); - } - - @Override - public Enumeration 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 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 upgrade(Class 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 index 0000000..968c1cf --- /dev/null +++ b/pomba/network-discovery/src/test/java/org/onap/sdnc/apps/pomba/networkdiscovery/unittest/service/util/TransformationUtilTest.java @@ -0,0 +1,136 @@ +/* + * ============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.util; + +import static org.junit.Assert.assertThat; + +import com.bazaarvoice.jolt.JsonUtils; +import com.bazaarvoice.jolt.exception.JsonUnmarshalException; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hamcrest.CoreMatchers; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.sdnc.apps.pomba.networkdiscovery.datamodel.Attribute; +import org.onap.sdnc.apps.pomba.networkdiscovery.service.util.TransformationUtil; + +public class TransformationUtilTest { + + private static final String TEST_RESOURCES = "src/test/resources/jolt/"; + + @Rule + public ExpectedException expectedEx = ExpectedException.none(); + + @Test + public void testTransformVServer() { + + Object sourceObject = JsonUtils.filepathToObject(TEST_RESOURCES + "vserver-input.json"); + + String resultJson = TransformationUtil.transform(JsonUtils.toJsonString(sourceObject), "vserver"); + + Object expectedObject = JsonUtils.filepathToObject(TEST_RESOURCES + "vserver-expected.json"); + + Assert.assertEquals("Json transformation result does not match expected content", + JsonUtils.toPrettyJsonString(expectedObject), + JsonUtils.toPrettyJsonString(JsonUtils.jsonToObject(resultJson))); + + } + + @Test + public void testTransformL3Network() { + + Object sourceObject = JsonUtils.filepathToObject(TEST_RESOURCES + "l3network-input.json"); + String resultJson = TransformationUtil.transform(JsonUtils.toJsonString(sourceObject), "l3-network"); + + Object expectedObject = JsonUtils.filepathToObject(TEST_RESOURCES + "l3network-expected.json"); + + Assert.assertEquals("Json transformation result does not match expected content", + JsonUtils.toPrettyJsonString(expectedObject), + JsonUtils.toPrettyJsonString(JsonUtils.jsonToObject(resultJson))); + + } + + @Test + public void testTransformFailureFileNotFound() { + + expectedEx.expect(RuntimeException.class); + expectedEx.expectMessage("Unable to load JSON file"); + + TransformationUtil.transform("{}", "foobar"); + } + + @Test + public void testTransformFailureInvalidInputJson() { + + expectedEx.expect(JsonUnmarshalException.class); + expectedEx.expectMessage("Unable to unmarshal JSON"); + + TransformationUtil.transform("xxx", "foobar"); + } + + @Test + public void testToAttributeList() { + Map expectedAttributes = new HashMap(); + expectedAttributes.put("name", "norm_bouygues"); + expectedAttributes.put("hostId", "ea1660efbbedda164379afacdc622305c4b88cebfb84119472d286a8"); + expectedAttributes.put("hostStatus", "UP"); + expectedAttributes.put("id", "2c311eae-f542-4173-8a01-582922abd495"); + expectedAttributes.put("status", "ACTIVE"); + expectedAttributes.put("vmState", "active"); + expectedAttributes.put("hostname", "norm-bouygues"); + expectedAttributes.put("inMaintenance", "true"); + expectedAttributes.put("imageId", "c0022890-d91f-422c-91c5-3866edeae768"); + expectedAttributes.put("tenantId", "15ad36d394e744838e947ca90609f805"); + expectedAttributes.put("host", "Setup-NCSO-OTT-E-C2"); + + Object inputJson = JsonUtils.filepathToObject(TEST_RESOURCES + "vserver-expected.json"); + List resultAttributeList = TransformationUtil.toAttributeList(JsonUtils.toJsonString(inputJson)); + + Map resultAttributes = new HashMap<>(); + + for (Attribute attribute : resultAttributeList) { + resultAttributes.put(attribute.getName(), attribute.getValue()); + } + assertThat(expectedAttributes, CoreMatchers.is(resultAttributes)); + } + + @Test + public void testToAttributeListNullJsonValue() { + Map expectedAttributes = new HashMap(); + expectedAttributes.put("name", ""); + + String inputJson = "{\"server\": { \"name\": null }}"; + + List resultAttributeList = TransformationUtil.toAttributeList(inputJson); + + Map resultAttributes = new HashMap<>(); + + for (Attribute attribute : resultAttributeList) { + resultAttributes.put(attribute.getName(), attribute.getValue()); + } + // assertThat(expectedAttributes, resultAttributes); + assertThat(expectedAttributes, CoreMatchers.is(resultAttributes)); + } + +} 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 index 0000000..be4ad9d --- /dev/null +++ b/pomba/network-discovery/src/test/resources/jolt/l3network-expected.json @@ -0,0 +1,14 @@ +{ + "l3-network": { + "id": "8df84f0a-737a-4628-be9c-c3c78454f9d9", + "name": "NET_503", + "AdminState": true, + "sharedNetwork": true, + "status": "ACTIVE", + "subnets": [ + "d0e6ecad-7bc9-4138-b9e8-e742bdf9afd5" + ], + "tenantId": "c44b872f6830498b88c4989d67b2a6b7", + "host-status": "UNKNOWN" + } +} 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 index 0000000..ebd9504 --- /dev/null +++ b/pomba/network-discovery/src/test/resources/jolt/l3network-input.json @@ -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 index 0000000..53d4a79 --- /dev/null +++ b/pomba/network-discovery/src/test/resources/jolt/vserver-expected.json @@ -0,0 +1,15 @@ +{ + "vserver" : { + "id" : "2c311eae-f542-4173-8a01-582922abd495", + "name" : "norm_bouygues", + "inMaintenance" : true, + "hostname" : "norm-bouygues", + "imageId" : "c0022890-d91f-422c-91c5-3866edeae768", + "status" : "ACTIVE", + "vmState" : "active", + "tenantId" : "15ad36d394e744838e947ca90609f805", + "hostId" : "ea1660efbbedda164379afacdc622305c4b88cebfb84119472d286a8", + "host" : "Setup-NCSO-OTT-E-C2", + "hostStatus" : "UP" + } +} \ 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 index 0000000..faa7ba5 --- /dev/null +++ b/pomba/network-discovery/src/test/resources/jolt/vserver-input.json @@ -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 -- cgit 1.2.3-korg