[SDNC-1416]VNF CRUD Operations 45/115045/4
authorHaddox, Anthony (ah0647) <ah0647@att.com>
Wed, 18 Nov 2020 16:25:23 +0000 (16:25 +0000)
committerDan Timoney <dtimoney@att.com>
Thu, 19 Nov 2020 18:39:40 +0000 (18:39 +0000)
Add database CRUD operations for several VNF related containers

Signed-off-by: Haddox, Anthony (ah0647) <ah0647@att.com>
Issue-ID: SDNC-1416
Change-Id: If85f3a1df76d5aba42b3bbd76475edad5275a9bf

ms/generic-resource-api/pom.xml
ms/generic-resource-api/src/main/java/org/onap/sdnc/apps/ms/gra/controllers/ConfigApiController.java
ms/generic-resource-api/src/test/java/org/onap/sdnc/apps/ms/gra/controllers/ConfigApiServicesControllerTest.java
ms/generic-resource-api/src/test/resources/vnf-data.json [new file with mode: 0644]
ms/generic-resource-api/src/test/resources/vnf-level-oper-status.json [new file with mode: 0644]
ms/generic-resource-api/src/test/resources/vnf-onap-model-info.json [new file with mode: 0644]
ms/generic-resource-api/src/test/resources/vnf-vnf-networks-network-role.json [new file with mode: 0644]
ms/generic-resource-api/src/test/resources/vnf-vnf-networks.json [new file with mode: 0644]

index cc6471d..6a34388 100644 (file)
             <artifactId>derby</artifactId>
             <scope>test</scope>
         </dependency>
+        <!-- Necessary to run tests with coverage in IntelliJ -->
+        <dependency>
+            <groupId>org.junit.platform</groupId>
+            <artifactId>junit-platform-launcher</artifactId>
+            <version>1.6.2</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
index 5695cfc..26b6dcf 100644 (file)
@@ -44,11 +44,14 @@ import org.springframework.stereotype.Controller;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.validation.Valid;
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @Controller
 @ComponentScan(basePackages = {"org.onap.sdnc.apps.ms.gra.*"})
@@ -797,4 +800,706 @@ public class ConfigApiController implements ConfigApi {
         }
     }
 
+    /**
+     * Deletes VNF data from the Config table specified Service Instance.
+     * <p>
+     * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/
+     * @param serviceInstanceId the Service Instance ID to perform the delete on
+     * @param vnfId the VNF ID of the VNF to delete
+     * @return HttpStatus.NO_CONTENT (204) on successful delete
+     *         <p>
+     *         HttpStatus.BAD_REQUEST (400) if unmarshalling Service Data from
+     *         the database fails, there is no VNF data for {@code vnfId}, or
+     *         writing Service Data back to the database fails.
+     *         <p>
+     *         HttpStatus.NOT_FOUND (404) if {@code serviceInstanceId} does
+     *         not exist.
+     */
+    @Override
+    public ResponseEntity<Void> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdDelete(String serviceInstanceId, String vnfId) throws RestException {
+        log.info("DELETE | VNF Data for ({})", vnfId);
+
+        /* The logic may need to be moved inside of this check or this check
+         * may need to be removed.
+         */
+        if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) {
+            log.info("Something with header.");
+        } else {
+            log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated");
+        }
+
+        List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId);
+        ConfigServices data;
+        if((services == null) || (services.isEmpty())) {
+            log.info("Could not find data for ({}).", serviceInstanceId);
+            // Or throw the data not found error?
+            throw new RestProtocolException("data-missing", "Service Instance ID not found.", HttpStatus.NOT_FOUND.value());
+        } else {
+            data = services.get(0);
+        }
+
+        GenericResourceApiServicedataServiceData svcData;
+        try {
+            svcData = objectMapper.readValue(data.getSvcData(), GenericResourceApiServicedataServiceData.class);
+        } catch(JsonProcessingException e) {
+            // Or throw the data not found error?
+            log.error("Could not map service data for ({})", serviceInstanceId);
+            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+        }
+        if(svcData == null) {
+            // Or throw the data not found error?
+            log.info("Could not find Service Data for ({}).", serviceInstanceId);
+            throw new RestProtocolException("data-missing", "Service data not found.", HttpStatus.NOT_FOUND.value());
+        }
+
+        GenericResourceApiServicedataServicedataVnfs vnfs = svcData.getVnfs();
+        if(vnfs == null) {
+            // Or throw the data not found error?
+            log.info("VNF List not found for ({}).", serviceInstanceId);
+            throw new RestProtocolException("data-missing", "VNFs not found.", HttpStatus.NOT_FOUND.value());
+        }
+
+        Stream<GenericResourceApiServicedataServicedataVnfsVnf> vnfStream = svcData.getVnfs().getVnf().stream();
+        if(vnfStream.noneMatch(targetVnf -> targetVnf.getVnfId().equals(vnfId))) {
+            // Data was not found
+            log.error("Did not find VNF ({}) in data.", vnfId);
+            throw new RestProtocolException("data-missing", "VNF ID not found.", HttpStatus.NOT_FOUND.value());
+        }
+        // Recreate the stream per Sonar?
+        vnfStream = svcData.getVnfs().getVnf().stream();
+        svcData.getVnfs().setVnf(vnfStream.filter(targetVnf -> !targetVnf.getVnfId().equals(vnfId)).collect(Collectors.toList()));
+
+        // Map and save the new data
+        try {
+            data.setSvcData(objectMapper.writeValueAsString(svcData));
+            configServicesRepository.save(data);
+            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+        } catch(JsonProcessingException e) {
+            log.error("Error mapping object to JSON", e);
+            // Should probably be a 500 INTERNAL_SERVICE_ERROR
+            throw new RestProtocolException("internal-service-error", "Failed to save data.", HttpStatus.BAD_REQUEST.value());
+        }
+    }
+
+    /**
+     * Extracts VNF data from the Config table specified Service Instance.
+     * <p>
+     * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/
+     * @param serviceInstanceId the Service Instance ID to lookup data for
+     * @param vnfId the VNF ID of the VNF to return
+     * @return HttpStatus.OK (200) if the data is found.
+     * @throws RestException if the data does not exist.
+     */
+    @Override
+    public ResponseEntity<GenericResourceApiServicedataServicedataVnfsVnf> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdGet(String serviceInstanceId, String vnfId) throws RestException {
+        log.info("GET | VNF Data for ({})", vnfId);
+        if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) {
+            if(getAcceptHeader().get().contains("application/json")) {
+            }
+        } else {
+            log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated");
+        }
+        List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId);
+        if((services == null) || (services.isEmpty())) {
+            throw new RestProtocolException("data-missing", "No service entry found", HttpStatus.NOT_FOUND.value());
+        }
+
+        Optional<GenericResourceApiServicedataServicedataVnfsVnf> vnf = getVnfObject(services.get(0), vnfId);
+        if(vnf.isPresent()) {
+            return new ResponseEntity<>(vnf.get(), HttpStatus.OK);
+        } else {
+            log.info("No information found for {}", vnfId);
+            throw new RestApplicationException("data-missing", "Request could not be completed because the relevant data model content does not exist", HttpStatus.NOT_FOUND.value());
+        }
+    }
+
+    /**
+     * Creates or updates VNF data in the Config table for a specified Service
+     * Instance. If it is a new Service Instance or a new VNF, creates all
+     * necessary parent data containers, then performs the updates.
+     * <p>
+     * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/
+     * @param serviceInstanceId the Service Instance ID to perform the delete on
+     * @param vnfId the VNF ID of the VNF to delete
+     * @param genericResourceApiServicedataServicedataVnfsVnfBodyParam the playload
+     * @return HttpStatus.CREATED (201) on successful create
+     *         <p>
+     *         HttpStatus.NO_CONTENT (204) on successful update
+     *         <p>
+     *         HttpStatus.BAD_REQUEST (400) if {@code vnfId} does not match
+     *         what is specified in the
+     *         {@code genericResourceApiServicedataServicedataVnfsVnfBodyParam}
+     *         , or if updating the database fails.
+     * @throws RestException
+     */
+    @Override
+    public ResponseEntity<Void> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdPut(String serviceInstanceId, String vnfId, GenericResourceApiServicedataServicedataVnfsVnf genericResourceApiServicedataServicedataVnfsVnfBodyParam) throws RestException {
+        log.info("PUT | VNF Data for ({})", vnfId);
+        if(!vnfId.equals(genericResourceApiServicedataServicedataVnfsVnfBodyParam.getVnfId())) {
+            throw new RestProtocolException("bad-attribute", "vnf-id mismatch", HttpStatus.BAD_REQUEST.value());
+        }
+        if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) {
+            log.info("Something with header");
+        } else {
+            log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated");
+        }
+
+        List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId);
+        ConfigServices data;
+        if((services == null) || (services.isEmpty())) {
+            log.info("Could not find data for ({}). Creating new Service Object.", serviceInstanceId);
+            data = new ConfigServices();
+            data.setSvcInstanceId(serviceInstanceId);
+        } else {
+            data = services.get(0);
+        }
+
+        GenericResourceApiServicedataServiceData svcData = null;
+        try {
+            svcData = objectMapper.readValue(data.getSvcData(), GenericResourceApiServicedataServiceData.class);
+        } catch(JsonProcessingException e) {
+            log.error("Could not map service data for ({})", serviceInstanceId);
+        }
+        if(svcData == null) {
+            log.info("Could not find Service Data for ({}). Creating new Service Data Container", serviceInstanceId);
+            svcData = new GenericResourceApiServicedataServiceData();
+        }
+        if(svcData.getVnfs() == null) {
+            log.info("VNF List not found for ({}). Creating new VNF List Container.", serviceInstanceId);
+            svcData.setVnfs(new GenericResourceApiServicedataServicedataVnfs());
+            svcData.getVnfs().setVnf(new ArrayList<>());
+        }
+
+        GenericResourceApiServicedataServicedataVnfs vnflist = new GenericResourceApiServicedataServicedataVnfs();
+        HttpStatus responseStatus = HttpStatus.NO_CONTENT;
+        if(svcData.getVnfs().getVnf().isEmpty()) {
+            log.info("Creating VNF data for ({})", vnfId);
+            vnflist.addVnfItem(genericResourceApiServicedataServicedataVnfsVnfBodyParam);
+            responseStatus = HttpStatus.CREATED;
+        } else {
+            log.info("Updating VNF data for ({})", vnfId);
+            // Filter out all of the other vnf objects into a new VNF List
+            // Replace if a delete method exists
+            svcData.getVnfs()
+                    .getVnf()
+                    .stream()
+                    .filter(targetVnf -> !targetVnf.getVnfId().equals(vnfId))
+                    .forEach(vnflist::addVnfItem);
+            vnflist.addVnfItem(genericResourceApiServicedataServicedataVnfsVnfBodyParam);
+        }
+        svcData.setVnfs(vnflist);
+        // Map and save the new data
+        try {
+            data.setSvcData(objectMapper.writeValueAsString(svcData));
+            configServicesRepository.save(data);
+            return new ResponseEntity<>(responseStatus);
+        } catch(JsonProcessingException e) {
+            log.error("Error mapping object to JSON", e);
+            // Should probably be a 500 INTERNAL_SERVICE_ERROR
+            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+        }
+    }
+
+    /**
+     * Extracts VNF Topology data from the Config table specified Service
+     * Instance and VNF ID.
+     * <p>
+     * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/vnf-data/vnf-topology/
+     * @param serviceInstanceId the Service Instance ID to lookup data for
+     * @param vnfId the VNF ID of the VNF to extract topology data from.
+     * @return HttpStatus.OK (200) if the data is found.
+     * @throws RestException if the data does not exist.
+     */
+    @Override
+    public ResponseEntity<GenericResourceApiVnftopologyVnfTopology> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyGet(String serviceInstanceId, String vnfId) throws RestException {
+        log.info("GET | VNF Topology for ({})", vnfId);
+        if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) {
+            if (getAcceptHeader().get().contains("application/json")) {
+
+            }
+        } else {
+            log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated");
+        }
+        List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId);
+        if((services == null) || (services.isEmpty())) {
+            throw new RestProtocolException("data-missing", "No service entry found", HttpStatus.NOT_FOUND.value());
+        }
+
+        Optional<GenericResourceApiServicedataServicedataVnfsVnf> vnf = getVnfObject(services.get(0), vnfId);
+        // Drill down to find the data
+        if(vnf.isPresent()
+                   && vnf.get().getVnfData() != null
+                   && vnf.get().getVnfData().getVnfTopology() != null) {
+            return new ResponseEntity<>(vnf.get().getVnfData().getVnfTopology(), HttpStatus.OK);
+        } else {
+            log.info("No information found for {}", vnfId);
+            throw new RestApplicationException("data-missing", "Request could not be completed because the relevant data model content does not exist", HttpStatus.NOT_FOUND.value());
+        }
+    }
+
+    /**
+     * Creates or updates VNF Level Operation Status data in the Config table
+     * for a specified Service Instance. If it is a new Service Instance or a
+     * new VNF, creates all necessary parent data containers, then performs the
+     * updates.
+     * <p>
+     * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/vnf-data/vnf-level-oper-status/
+     * @param serviceInstanceId the Service Instance ID to perform the delete on
+     * @param vnfId the VNF ID of the VNF to delete
+     * @param genericResourceApiOperStatusDataBodyParam the payload
+     * @return HttpStatus.CREATED (201) on successful create.
+     *         <p>
+     *         HttpStatus.NO_CONTENT (204) on successful update.
+     *         <p>
+     *         HttpStatus.BAD_REQUEST (400) if updating the database fails.
+     * @throws RestException
+     */
+    @Override
+    public ResponseEntity<Void> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfLevelOperStatusPut(String serviceInstanceId, String vnfId, GenericResourceApiOperStatusData genericResourceApiOperStatusDataBodyParam) throws RestException {
+        log.info("PUT | VNF Level Oper Status ({})", vnfId);
+        if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) {
+        } else {
+            log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated");
+        }
+
+        List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId);
+        ConfigServices data;
+        if((services == null) || (services.isEmpty())) {
+            log.info("Could not find data for ({}). Creating new Service Object.", serviceInstanceId);
+            data = new ConfigServices();
+            data.setSvcInstanceId(serviceInstanceId);
+        } else {
+            data = services.get(0);
+        }
+
+        GenericResourceApiServicedataServiceData svcData = null;
+        try {
+            svcData = objectMapper.readValue(data.getSvcData(), GenericResourceApiServicedataServiceData.class);
+        } catch(JsonProcessingException e) {
+            log.error("Could not map service data for ({})", serviceInstanceId);
+        }
+        if(svcData == null) {
+            log.info("Could not find Service Data for ({}). Creating new Service Data Container", serviceInstanceId);
+            svcData = new GenericResourceApiServicedataServiceData();
+        }
+        if(svcData.getVnfs() == null) {
+            log.info("VNF List not found for ({}). Creating new VNF List Container.", serviceInstanceId);
+            svcData.setVnfs(new GenericResourceApiServicedataServicedataVnfs());
+            svcData.getVnfs().setVnf(new ArrayList<>());
+        }
+
+        GenericResourceApiServicedataServicedataVnfs vnflist = new GenericResourceApiServicedataServicedataVnfs();
+        HttpStatus responseStatus = HttpStatus.NO_CONTENT;
+        if(svcData.getVnfs().getVnf().isEmpty()) {
+            log.info("Creating VNF data for ({})", vnfId);
+            GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf();
+            vnf.setVnfId(vnfId);
+            vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData());
+            vnf.getVnfData().setVnfLevelOperStatus(genericResourceApiOperStatusDataBodyParam);
+            vnflist.addVnfItem(vnf);
+            responseStatus = HttpStatus.CREATED;
+        } else {
+            log.info("Updating VNF data for ({})", vnfId);
+            // Filter out all of the other vnf objects into a new VNF List
+            // Replace if a delete method exists
+            svcData.getVnfs()
+                    .getVnf()
+                    .stream()
+                    .filter(targetVnf -> !targetVnf.getVnfId().equals(vnfId))
+                    .forEach(vnflist::addVnfItem);
+            GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf();
+            // If the vnf exists, set it up with new data
+            Optional<GenericResourceApiServicedataServicedataVnfsVnf> vnfOptional = getVnfObject(data, vnfId);
+            if(vnfOptional.isPresent()) {
+                vnf = vnfOptional.get();
+            }
+            if(vnf.getVnfData() == null) {
+                vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData());
+                responseStatus = HttpStatus.CREATED;
+            }
+
+            vnf.getVnfData().setVnfLevelOperStatus(genericResourceApiOperStatusDataBodyParam);
+            vnflist.addVnfItem(vnf);
+        }
+
+        svcData.setVnfs(vnflist);
+        // Map and save the new data
+        try {
+            data.setSvcData(objectMapper.writeValueAsString(svcData));
+            configServicesRepository.save(data);
+            return new ResponseEntity<>(responseStatus);
+        } catch(JsonProcessingException e) {
+            log.error("Error mapping object to JSON", e);
+            // Should probably be a 500 INTERNAL_SERVICE_ERROR
+            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+        }
+    }
+
+    /**
+     * Creates or updates VNF Onap Model Information data in the Config table
+     * for a specified Service Instance. If it is a new Service Instance or a
+     * new VNF, creates all necessary parent data containers, then performs the
+     * updates.
+     * <p>
+     * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/vnf-data/vnf-topology/onap-model-information/
+     * @param serviceInstanceId the Service Instance ID to perform the delete on
+     * @param vnfId the VNF ID of the VNF to delete
+     * @param genericResourceApiOnapmodelinformationOnapModelInformationBodyParam the payload
+     * @return HttpStatus.CREATED (201) on successful create.
+     *         <p>
+     *         HttpStatus.NO_CONTENT (204) on successful update.
+     *         <p>
+     *         HttpStatus.BAD_REQUEST (400) if updating the database fails.
+     * @throws RestException
+     */
+    @Override
+    public ResponseEntity<Void> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyOnapModelInformationPut(String serviceInstanceId, String vnfId, GenericResourceApiOnapmodelinformationOnapModelInformation genericResourceApiOnapmodelinformationOnapModelInformationBodyParam) throws RestException {
+        log.info("PUT | VNF Topology Onap Model Information ({})", vnfId);
+        if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) {
+        } else {
+            log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated");
+        }
+
+        List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId);
+        ConfigServices data;
+        if((services == null) || (services.isEmpty())) {
+            log.info("Could not find data for ({}). Creating new Service Object.", serviceInstanceId);
+            data = new ConfigServices();
+            data.setSvcInstanceId(serviceInstanceId);
+        } else {
+            data = services.get(0);
+        }
+
+        GenericResourceApiServicedataServiceData svcData = null;
+        try {
+            svcData = objectMapper.readValue(data.getSvcData(), GenericResourceApiServicedataServiceData.class);
+        } catch(JsonProcessingException e) {
+            log.error("Could not map service data for ({})", serviceInstanceId);
+        }
+        if(svcData == null) {
+            log.info("Could not find Service Data for ({}). Creating new Service Data Container", serviceInstanceId);
+            svcData = new GenericResourceApiServicedataServiceData();
+        }
+        if(svcData.getVnfs() == null) {
+            log.info("VNF List not found for ({}). Creating new VNF List Container.", serviceInstanceId);
+            svcData.setVnfs(new GenericResourceApiServicedataServicedataVnfs());
+            svcData.getVnfs().setVnf(new ArrayList<>());
+        }
+
+        GenericResourceApiServicedataServicedataVnfs vnflist = new GenericResourceApiServicedataServicedataVnfs();
+        HttpStatus responseStatus = HttpStatus.NO_CONTENT;
+        if(svcData.getVnfs().getVnf().isEmpty()) {
+            log.info("Creating VNF data for ({})", vnfId);
+            GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf();
+            vnf.setVnfId(vnfId);
+            vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData());
+            vnf.getVnfData().setVnfTopology(new GenericResourceApiVnftopologyVnfTopology());
+            vnf.getVnfData().getVnfTopology().setOnapModelInformation(genericResourceApiOnapmodelinformationOnapModelInformationBodyParam);
+            vnflist.addVnfItem(vnf);
+            responseStatus = HttpStatus.CREATED;
+        } else {
+            log.info("Updating VNF data for ({})", vnfId);
+            // Filter out all of the other vnf objects into a new VNF List
+            // Replace if a delete method exists
+            svcData.getVnfs()
+                    .getVnf()
+                    .stream()
+                    .filter(targetVnf -> !targetVnf.getVnfId().equals(vnfId))
+                    .forEach(vnflist::addVnfItem);
+            GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf();
+            // If the vnf exists, set it up with new data
+            Optional<GenericResourceApiServicedataServicedataVnfsVnf> vnfOptional = getVnfObject(data, vnfId);
+            if(vnfOptional.isPresent()) {
+                vnf = vnfOptional.get();
+            }
+            if(vnf.getVnfData() == null) {
+                vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData());
+            }
+            if(vnf.getVnfData().getVnfTopology() == null) {
+                vnf.getVnfData().setVnfTopology(new GenericResourceApiVnftopologyVnfTopology());
+                responseStatus = HttpStatus.CREATED;
+            }
+
+            vnf.getVnfData().getVnfTopology().setOnapModelInformation(genericResourceApiOnapmodelinformationOnapModelInformationBodyParam);
+            vnflist.addVnfItem(vnf);
+        }
+
+        svcData.setVnfs(vnflist);
+        // Map and save the new data
+        try {
+            data.setSvcData(objectMapper.writeValueAsString(svcData));
+            configServicesRepository.save(data);
+            return new ResponseEntity<>(responseStatus);
+        } catch(JsonProcessingException e) {
+            log.error("Error mapping object to JSON", e);
+            // Should probably be a 500 INTERNAL_SERVICE_ERROR
+            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+        }
+    }
+
+    /**
+     * Creates or updates VNF Network data in the Config table for a specified
+     * Service Instance. If it is a new Service Instance or a new VNF, creates
+     * all necessary parent data containers, then performs the updates.
+     * <p>
+     * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/vnf-data/vnf-topology/vnf-resource-assignments/vnf-networks/
+     * @param serviceInstanceId the Service Instance ID to perform the delete on
+     * @param vnfId the VNF ID of the VNF to delete
+     * @param genericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworksBodyParam the payload
+     * @return HttpStatus.CREATED (201) on successful create.
+     *         <p>
+     *         HttpStatus.NO_CONTENT (204) on successful update.
+     *         <p>
+     *         HttpStatus.BAD_REQUEST (400) if updating the database fails.
+     * @throws RestException
+     */
+    @Override
+    public ResponseEntity<Void> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyVnfResourceAssignmentsVnfNetworksPut(String serviceInstanceId, String vnfId, GenericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworks genericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworksBodyParam) throws RestException {
+        log.info("PUT | VNF Topology VNF Resource Assignments VNF Networks ({})", vnfId);
+        if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) {
+        } else {
+            log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated");
+        }
+
+        List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId);
+        ConfigServices data;
+        if((services == null) || (services.isEmpty())) {
+            log.info("Could not find data for ({}). Creating new Service Object.", serviceInstanceId);
+            data = new ConfigServices();
+            data.setSvcInstanceId(serviceInstanceId);
+        } else {
+            data = services.get(0);
+        }
+
+        GenericResourceApiServicedataServiceData svcData = null;
+        try {
+            svcData = objectMapper.readValue(data.getSvcData(), GenericResourceApiServicedataServiceData.class);
+        } catch(JsonProcessingException e) {
+            log.error("Could not map service data for ({})", serviceInstanceId);
+        }
+        if(svcData == null) {
+            log.info("Could not find Service Data for ({}). Creating new Service Data Container", serviceInstanceId);
+            svcData = new GenericResourceApiServicedataServiceData();
+        }
+        if(svcData.getVnfs() == null) {
+            log.info("VNF List not found for ({}). Creating new VNF List Container.", serviceInstanceId);
+            svcData.setVnfs(new GenericResourceApiServicedataServicedataVnfs());
+            svcData.getVnfs().setVnf(new ArrayList<>());
+        }
+
+        GenericResourceApiServicedataServicedataVnfs vnflist = new GenericResourceApiServicedataServicedataVnfs();
+        HttpStatus responseStatus = HttpStatus.NO_CONTENT;
+        if(svcData.getVnfs().getVnf().isEmpty()) {
+            log.info("Creating VNF data for ({})", vnfId);
+            GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf();
+            vnf.setVnfId(vnfId);
+            vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData());
+            vnf.getVnfData().setVnfTopology(new GenericResourceApiVnftopologyVnfTopology());
+            vnf.getVnfData().getVnfTopology().setVnfResourceAssignments(new GenericResourceApiVnfresourceassignmentsVnfResourceAssignments());
+            vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().setVnfNetworks(genericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworksBodyParam);
+            vnflist.addVnfItem(vnf);
+            responseStatus = HttpStatus.CREATED;
+        } else {
+            log.info("Updating VNF data for ({})", vnfId);
+            // Filter out all of the other vnf objects into a new VNF List
+            // Replace if a delete method exists
+            svcData.getVnfs()
+                    .getVnf()
+                    .stream()
+                    .filter(targetVnf -> !targetVnf.getVnfId().equals(vnfId))
+                    .forEach(vnflist::addVnfItem);
+            GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf();
+            // If the vnf exists, set it up with new data
+            Optional<GenericResourceApiServicedataServicedataVnfsVnf> vnfOptional = getVnfObject(data, vnfId);
+            if(vnfOptional.isPresent()) {
+                vnf = vnfOptional.get();
+            }
+            if(vnf.getVnfData() == null) {
+                vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData());
+            }
+            if(vnf.getVnfData().getVnfTopology() == null) {
+                vnf.getVnfData().setVnfTopology(new GenericResourceApiVnftopologyVnfTopology());
+            }
+            if(vnf.getVnfData().getVnfTopology().getVnfResourceAssignments() == null) {
+                vnf.getVnfData().getVnfTopology().setVnfResourceAssignments(new GenericResourceApiVnfresourceassignmentsVnfResourceAssignments());
+                responseStatus = HttpStatus.CREATED;
+            }
+
+            vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().setVnfNetworks(genericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworksBodyParam);
+            vnflist.addVnfItem(vnf);
+        }
+
+        svcData.setVnfs(vnflist);
+        // Map and save the new data
+        try {
+            data.setSvcData(objectMapper.writeValueAsString(svcData));
+            configServicesRepository.save(data);
+            return new ResponseEntity<>(responseStatus);
+        } catch(JsonProcessingException e) {
+            log.error("Error mapping object to JSON", e);
+            // Should probably be a 500 INTERNAL_SERVICE_ERROR
+            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+        }
+    }
+
+    /**
+     * Creates or updates VNF Network Role data in the Config table for a
+     * specified Service Instance. If it is a new Service Instance or a new
+     * VNF, creates all necessary parent data containers, then performs the
+     * updates.
+     * <p>
+     * Maps to /config/GENERIC-RESOURCE-API:services/service/{service-instance-id}/service-data/vnfs/vnf/{vnf-id}/vnf-data/vnf-topology/vnf-resource-assignments/vnf-networks/vnf-network/{network-role}/
+     * @param serviceInstanceId the Service Instance ID to perform the delete on
+     * @param vnfId the VNF ID of the VNF to delete
+     * @param genericResourceApiVnfNetworkDataBodyParam the payload
+     * @return HttpStatus.CREATED (201) on successful create.
+     *         <p>
+     *         HttpStatus.NO_CONTENT (204) on successful update.
+     *         <p>
+     *         HttpStatus.BAD_REQUEST (400) if updating the database fails.
+     * @throws RestException
+     */
+    @Override
+    public ResponseEntity<Void> configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyVnfResourceAssignmentsVnfNetworksVnfNetworkNetworkRolePut(String serviceInstanceId, String vnfId, String networkRole, GenericResourceApiVnfNetworkData genericResourceApiVnfNetworkDataBodyParam) throws RestException {
+        log.info("PUT | VNF Network Network Role ({})", vnfId);
+        if(!networkRole.equals(genericResourceApiVnfNetworkDataBodyParam.getNetworkRole())) {
+            throw new RestProtocolException("bad-attribute", "network-role mismatch", HttpStatus.BAD_REQUEST.value());
+        }
+        if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) {
+        } else {
+            log.warn("ObjectMapper or HttpServletRequest not configured in default ConfigApi interface so no example is generated");
+        }
+
+        List<ConfigServices> services = configServicesRepository.findBySvcInstanceId(serviceInstanceId);
+        ConfigServices data;
+        if((services == null) || (services.isEmpty())) {
+            log.info("Could not find data for ({}). Creating new Service Object.", serviceInstanceId);
+            data = new ConfigServices();
+            data.setSvcInstanceId(serviceInstanceId);
+        } else {
+            data = services.get(0);
+        }
+
+        GenericResourceApiServicedataServiceData svcData = null;
+        try {
+            svcData = objectMapper.readValue(data.getSvcData(), GenericResourceApiServicedataServiceData.class);
+        } catch(JsonProcessingException e) {
+            log.error("Could not map service data for ({})", serviceInstanceId);
+        }
+        if(svcData == null) {
+            log.info("Could not find Service Data for ({}). Creating new Service Data Container", serviceInstanceId);
+            svcData = new GenericResourceApiServicedataServiceData();
+        }
+        if(svcData.getVnfs() == null) {
+            log.info("VNF List not found for ({}). Creating new VNF List Container.", serviceInstanceId);
+            svcData.setVnfs(new GenericResourceApiServicedataServicedataVnfs());
+            svcData.getVnfs().setVnf(new ArrayList<>());
+        }
+
+        GenericResourceApiServicedataServicedataVnfs vnflist = new GenericResourceApiServicedataServicedataVnfs();
+        HttpStatus responseStatus = HttpStatus.NO_CONTENT;
+        if(svcData.getVnfs().getVnf().isEmpty()) {
+            log.info("Creating VNF data for ({})", vnfId);
+            GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf();
+            vnf.setVnfId(vnfId);
+            vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData());
+            vnf.getVnfData().setVnfTopology(new GenericResourceApiVnftopologyVnfTopology());
+            vnf.getVnfData().getVnfTopology().setVnfResourceAssignments(new GenericResourceApiVnfresourceassignmentsVnfResourceAssignments());
+            vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().setVnfNetworks(new GenericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworks());
+            vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks().setVnfNetwork(new ArrayList<>());
+            vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks().addVnfNetworkItem(genericResourceApiVnfNetworkDataBodyParam);
+            vnflist.addVnfItem(vnf);
+            responseStatus = HttpStatus.CREATED;
+        } else {
+            log.info("Updating VNF data for ({})", vnfId);
+            // Filter out all of the other vnf objects into a new VNF List
+            // Replace if a delete method exists
+            svcData.getVnfs()
+                    .getVnf()
+                    .stream()
+                    .filter(targetVnf -> !targetVnf.getVnfId().equals(vnfId))
+                    .forEach(vnflist::addVnfItem);
+            GenericResourceApiServicedataServicedataVnfsVnf vnf = new GenericResourceApiServicedataServicedataVnfsVnf();
+            // If the vnf exists, set it up with new data
+            Optional<GenericResourceApiServicedataServicedataVnfsVnf> vnfOptional = getVnfObject(data, vnfId);
+            if(vnfOptional.isPresent()) {
+                vnf = vnfOptional.get();
+            }
+            if(vnf.getVnfData() == null) {
+                vnf.setVnfData(new GenericResourceApiServicedataServicedataVnfsVnfVnfData());
+            }
+            if(vnf.getVnfData().getVnfTopology() == null) {
+                vnf.getVnfData().setVnfTopology(new GenericResourceApiVnftopologyVnfTopology());
+            }
+            if(vnf.getVnfData().getVnfTopology().getVnfResourceAssignments() == null) {
+                vnf.getVnfData().getVnfTopology().setVnfResourceAssignments(new GenericResourceApiVnfresourceassignmentsVnfResourceAssignments());
+            }
+            if(vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks() == null) {
+                log.info("Creating new VnfNetworks");
+                vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().setVnfNetworks(new GenericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworks());
+            }
+
+            GenericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworks networkList = new GenericResourceApiVnfresourceassignmentsVnfresourceassignmentsVnfNetworks();
+            if(vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks().getVnfNetwork().isEmpty()) {
+                log.info("First entry into network info.");
+                vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks().addVnfNetworkItem(genericResourceApiVnfNetworkDataBodyParam);
+                responseStatus = HttpStatus.CREATED;
+            } else {
+                log.info("Found networks. Filtering.");
+                vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks().getVnfNetwork().stream()
+                        .filter(targetNetwork -> !targetNetwork.getNetworkRole().equals(networkRole))
+                        .forEach(networkList::addVnfNetworkItem);
+                networkList.addVnfNetworkItem(genericResourceApiVnfNetworkDataBodyParam);
+
+                if(networkList.getVnfNetwork().size() != vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().getVnfNetworks().getVnfNetwork().size()) {
+                    log.info("Added a new Item");
+                    responseStatus = HttpStatus.CREATED;
+                }
+                vnf.getVnfData().getVnfTopology().getVnfResourceAssignments().setVnfNetworks(networkList);
+            }
+
+            vnflist.addVnfItem(vnf);
+        }
+
+        svcData.setVnfs(vnflist);
+        // Map and save the new data
+        try {
+            data.setSvcData(objectMapper.writeValueAsString(svcData));
+            configServicesRepository.save(data);
+            return new ResponseEntity<>(responseStatus);
+        } catch(JsonProcessingException e) {
+            log.error("Error mapping object to JSON", e);
+            // Should probably be a 500 INTERNAL_SERVICE_ERROR
+            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+        }
+    }
+
+    /**
+     * Extracts a VNF object from the database,
+     * @param configServices A Config Services option created from a Service
+     *                       Instance ID
+     * @param vnfId the target VNF ID
+     * @return An empty Optional if the Service Data does not exist, an empty
+     *         Optional if the VNF is not found, or an optional containing the
+     *         found VNF.
+     */
+    private Optional<GenericResourceApiServicedataServicedataVnfsVnf> getVnfObject(ConfigServices configServices, String vnfId) {
+        // Map the Marshall the JSON String into a Java Object
+        log.info("Getting VNF Data for ({})", vnfId);
+        GenericResourceApiServicedataServiceData svcData;
+        try {
+            svcData = objectMapper.readValue(configServices.getSvcData(), GenericResourceApiServicedataServiceData.class);
+        } catch(JsonProcessingException e) {
+            log.error("Error", e);
+            return Optional.empty();
+        }
+
+        /*Get a stream of the VNF Objects and return the target if it's found,
+         * assuming that each VNF ID is unique within a Service Instance Object
+         */
+        return svcData.getVnfs().getVnf()
+                       .stream()
+                       .filter(targetVnf -> targetVnf.getVnfId().equals(vnfId))
+                       .findFirst();
+    }
 }
index 609e780..7bcfefe 100644 (file)
@@ -2,10 +2,12 @@ package org.onap.sdnc.apps.ms.gra.controllers;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
 
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Paths;
+import java.util.ArrayList;
 import java.util.List;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -461,6 +463,192 @@ public class ConfigApiServicesControllerTest {
         configServicesRepository.deleteAll();
     }
 
+    @Test
+    public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdDelete() throws Exception {
+        // Clean up data
+        configServicesRepository.deleteAll();
+
+        // Test with no data
+        MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.delete("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content(""))
+                                      .andReturn();
+        assertEquals(404, mvcResult.getResponse().getStatus());
+        assertEquals(0, configServicesRepository.count());
+
+        // Load data
+        loadVnfData("src/test/resources/vnf-data.json");
+        assertEquals(1, configServicesRepository.count());
+
+        // Test with data
+        mvcResult = mvc.perform(MockMvcRequestBuilders.delete("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content(""))
+                            .andReturn();
+        assertEquals(204, mvcResult.getResponse().getStatus());
+        assertEquals(1, configServicesRepository.count());
+
+        configServicesRepository.deleteAll();
+        loadVnfData("src/test/resources/vnf-data.json");
+        assertEquals(1, configServicesRepository.count());
+        mvcResult = mvc.perform(MockMvcRequestBuilders.delete("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c/").contentType(MediaType.APPLICATION_JSON).content(""))
+                            .andReturn();
+        assertEquals(404, mvcResult.getResponse().getStatus());
+
+        configServicesRepository.deleteAll();
+        createBadVnfData(true, true);
+        assertEquals(1, configServicesRepository.count());
+        mvcResult = mvc.perform(MockMvcRequestBuilders.delete("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content(""))
+                            .andReturn();
+        assertEquals(404, mvcResult.getResponse().getStatus());
+
+        configServicesRepository.deleteAll();
+        createBadVnfData(false, false);
+        assertEquals(1, configServicesRepository.count());
+        mvcResult = mvc.perform(MockMvcRequestBuilders.delete("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content(""))
+                            .andReturn();
+        assertEquals(404, mvcResult.getResponse().getStatus());
+
+        configServicesRepository.deleteAll();
+        createBadVnfData(false, true);
+        assertEquals(1, configServicesRepository.count());
+        mvcResult = mvc.perform(MockMvcRequestBuilders.delete("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content(""))
+                            .andReturn();
+        assertEquals(404, mvcResult.getResponse().getStatus());
+    }
+
+    @Test
+    public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdGet() throws Exception {
+        // Clean up data
+        configServicesRepository.deleteAll();
+
+        // Test with no data
+        MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content(""))
+                                      .andReturn();
+        assertEquals(404, mvcResult.getResponse().getStatus());
+        assertEquals(0, configServicesRepository.count());
+
+        // Load data
+        loadVnfData("src/test/resources/vnf-data.json");
+        assertEquals(1, configServicesRepository.count());
+
+        // Test with data
+        mvcResult = mvc.perform(MockMvcRequestBuilders.get("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content(""))
+                            .andReturn();
+        assertEquals(200, mvcResult.getResponse().getStatus());
+
+        configServicesRepository.deleteAll();
+        createBadVnfData(false, false);
+        assertEquals(1, configServicesRepository.count());
+        mvcResult = mvc.perform(MockMvcRequestBuilders.get("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content(""))
+                            .andReturn();
+        assertEquals(404, mvcResult.getResponse().getStatus());
+    }
+
+    @Test
+    public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdPut() throws Exception {
+        // Clean up data
+        configServicesRepository.deleteAll();
+        assertEquals(0, configServicesRepository.count());
+        MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-data.json")))
+                                      .andReturn();
+        assertEquals(201, mvcResult.getResponse().getStatus());
+        assertEquals(1, configServicesRepository.count());
+
+        mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-data.json")))
+                            .andReturn();
+        assertEquals(204, mvcResult.getResponse().getStatus());
+        assertEquals(1, configServicesRepository.count());
+    }
+
+    @Test
+    public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyGet() throws Exception {
+        // Clean up data
+        configServicesRepository.deleteAll();
+
+        // Test with no data
+        MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.get("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/").contentType(MediaType.APPLICATION_JSON).content(""))
+                                      .andReturn();
+        assertEquals(404, mvcResult.getResponse().getStatus());
+        assertEquals(0, configServicesRepository.count());
+
+        // Load data
+        loadVnfData("src/test/resources/vnf-data.json");
+        assertEquals(1, configServicesRepository.count());
+
+        // Test with data
+        mvcResult = mvc.perform(MockMvcRequestBuilders.get("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/").contentType(MediaType.APPLICATION_JSON).content(""))
+                            .andReturn();
+        assertEquals(200, mvcResult.getResponse().getStatus());
+
+        configServicesRepository.deleteAll();
+        createBadVnfData(false, false);
+        assertEquals(1, configServicesRepository.count());
+        mvcResult = mvc.perform(MockMvcRequestBuilders.get("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/").contentType(MediaType.APPLICATION_JSON).content(""))
+                            .andReturn();
+        assertEquals(404, mvcResult.getResponse().getStatus());
+    }
+
+    @Test
+    public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfLevelOperStatusPut() throws Exception {
+        // Clean up data
+        configServicesRepository.deleteAll();
+        assertEquals(0, configServicesRepository.count());
+        MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-level-oper-status/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-level-oper-status.json")))
+                                      .andReturn();
+        assertEquals(201, mvcResult.getResponse().getStatus());
+        assertEquals(1, configServicesRepository.count());
+
+        mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-level-oper-status/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-level-oper-status.json")))
+                            .andReturn();
+        assertEquals(204, mvcResult.getResponse().getStatus());
+        assertEquals(1, configServicesRepository.count());
+    }
+
+    @Test
+    public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyOnapModelInformationPut() throws Exception {
+        // Clean up data
+        configServicesRepository.deleteAll();
+        assertEquals(0, configServicesRepository.count());
+        MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/onap-model-information/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-onap-model-info.json")))
+                                      .andReturn();
+        assertEquals(201, mvcResult.getResponse().getStatus());
+        assertEquals(1, configServicesRepository.count());
+
+        mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/onap-model-information/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-onap-model-info.json")))
+                            .andReturn();
+        assertEquals(204, mvcResult.getResponse().getStatus());
+        assertEquals(1, configServicesRepository.count());
+    }
+
+    @Test
+    public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyVnfResourceAssignmentsVnfNetworksPut() throws Exception {
+        // Clean up data
+        configServicesRepository.deleteAll();
+        assertEquals(0, configServicesRepository.count());
+        MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/vnf-resource-assignments/vnf-networks/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-vnf-networks.json")))
+                                      .andReturn();
+        assertEquals(201, mvcResult.getResponse().getStatus());
+        assertEquals(1, configServicesRepository.count());
+
+        mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/vnf-resource-assignments/vnf-networks/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-vnf-networks.json")))
+                            .andReturn();
+        assertEquals(204, mvcResult.getResponse().getStatus());
+        assertEquals(1, configServicesRepository.count());
+    }
+
+    @Test
+    public void configGENERICRESOURCEAPIservicesServiceServiceInstanceIdServiceDataVnfsVnfVnfIdVnfDataVnfTopologyVnfResourceAssignmentsVnfNetworksVnfNetworkNetworkRolePut() throws Exception {
+        // Clean up data
+        configServicesRepository.deleteAll();
+        assertEquals(0, configServicesRepository.count());
+        MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/vnf-resource-assignments/vnf-networks/vnf-network/test-network-role/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-vnf-networks-network-role.json")))
+                                      .andReturn();
+        assertEquals(201, mvcResult.getResponse().getStatus());
+        assertEquals(1, configServicesRepository.count());
+
+        mvcResult = mvc.perform(MockMvcRequestBuilders.put("/config/GENERIC-RESOURCE-API:services/service/test-siid/service-data/vnfs/vnf/2a3bfc93-cd4c-4845-8919-434b2d999ada/vnf-data/vnf-topology/vnf-resource-assignments/vnf-networks/vnf-network/test-network-role/").contentType(MediaType.APPLICATION_JSON).content(readFileContent("src/test/resources/vnf-vnf-networks-network-role.json")))
+                            .andReturn();
+        assertEquals(204, mvcResult.getResponse().getStatus());
+        assertEquals(1, configServicesRepository.count());
+    }
+
     private String readFileContent(String path) throws IOException {
         String content = new String(Files.readAllBytes(Paths.get(path)));
         return content;
@@ -485,4 +673,36 @@ public class ConfigApiServicesControllerTest {
         }
     }
 
+    private void loadVnfData(String path) throws IOException {
+        ObjectMapper objectMapper = new ObjectMapper();
+        String content = readFileContent(path);
+        GenericResourceApiServicedataServiceData svcData = new GenericResourceApiServicedataServiceData();
+        GenericResourceApiServicedataServicedataVnfsVnf vnfData = objectMapper.readValue(content, GenericResourceApiServicedataServicedataVnfsVnf.class);
+        svcData.setVnfs(new GenericResourceApiServicedataServicedataVnfs());
+        svcData.getVnfs().setVnf(new ArrayList<>());
+        svcData.getVnfs().addVnfItem(vnfData);
+        ConfigServices newService = new ConfigServices();
+        newService.setSvcData(objectMapper.writeValueAsString(svcData));
+        newService.setSvcInstanceId("test-siid");
+        configServicesRepository.save(newService);
+    }
+
+    private void createBadVnfData(boolean useNullSvc, boolean useNullVnfs) throws IOException {
+        ObjectMapper objectMapper = new ObjectMapper();
+        ConfigServices newService = new ConfigServices();
+        GenericResourceApiServicedataServiceData svcData = useNullSvc ? null : new GenericResourceApiServicedataServiceData();
+        GenericResourceApiServicedataServicedataVnfs vnfs = useNullVnfs ? null : new GenericResourceApiServicedataServicedataVnfs();
+
+        // Overrides useNullSvc
+        if(!useNullVnfs) {
+            svcData = new GenericResourceApiServicedataServiceData();
+            vnfs.setVnf(new ArrayList<>());
+            svcData.setVnfs(vnfs);
+        }
+
+        newService.setSvcInstanceId("test-siid");
+        newService.setSvcData(objectMapper.writeValueAsString(svcData));
+        configServicesRepository.save(newService);
+    }
+
 }
\ No newline at end of file
diff --git a/ms/generic-resource-api/src/test/resources/vnf-data.json b/ms/generic-resource-api/src/test/resources/vnf-data.json
new file mode 100644 (file)
index 0000000..22fc4aa
--- /dev/null
@@ -0,0 +1,603 @@
+{
+  "vnf-data": {
+    "request-information": {
+      "notification-url": "https://dev.null",
+      "order-number": "Order-123",
+      "order-version": "Order-v22",
+      "request-action": "CreateNetworkInstance",
+      "request-id": "a44e8401-2c62-47df-98be-9a09f6cbd996",
+      "source": "unit-test"
+    },
+    "sdnc-request-header": {
+      "svc-action": "assign",
+      "svc-notification-url": "https://dev.null",
+      "svc-request-id": "9c06a7c6-be3a-4530-bdd8-c65b58f123a5"
+    },
+    "service-information": {
+      "global-customer-id": "226fbb03-baf2-42bb-8311-03643a801238",
+      "onap-model-information": {
+        "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f",
+        "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e",
+        "model-name": "SMSF-NC2-578",
+        "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9",
+        "model-version": "3.0"
+      },
+      "service-id": "98f189dd-2971-46f5-b4f1-1a9a323f39a4",
+      "service-instance-id": "98f189dd-2971-46f5-b4f1-1a9a323f39a4",
+      "subscriber-name": "unit-test",
+      "subscription-service-type": "unit-test"
+    },
+    "vf-modules": {
+      "vf-module": [
+        {
+          "vf-module-data": {
+            "request-information": {
+              "notification-url": "https://dev.null",
+              "order-number": "Order-123",
+              "order-version": "Order-v22",
+              "request-action": "CreateNetworkInstance",
+              "request-id": "a44e8401-2c62-47df-98be-9a09f6cbd996",
+              "source": "unit-test"
+            },
+            "sdnc-request-header": {
+              "svc-action": "assign",
+              "svc-notification-url": "https://dev.null",
+              "svc-request-id": "9c06a7c6-be3a-4530-bdd8-c65b58f123a5"
+            },
+            "service-information": {
+              "global-customer-id": "226fbb03-baf2-42bb-8311-03643a801238",
+              "onap-model-information": {
+                "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f",
+                "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e",
+                "model-name": "SMSF-NC2-578",
+                "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9",
+                "model-version": "3.0"
+              },
+              "service-id": "98f189dd-2971-46f5-b4f1-1a9a323f39a4",
+              "service-instance-id": "98f189dd-2971-46f5-b4f1-1a9a323f39a4",
+              "subscriber-name": "unit-test",
+              "subscription-service-type": "unit-test"
+            },
+            "vf-module-information": {
+              "from-preload": true,
+              "onap-model-information": {
+                "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f",
+                "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e",
+                "model-name": "SMSF-NC2-578",
+                "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9",
+                "model-version": "3.0"
+              },
+              "vf-module-id": "9270c447-3caf-4e12-85aa-3578b0fa61d5",
+              "vf-module-type": "some-vf-module-type"
+            },
+            "vf-module-level-oper-status": {
+              "create-timestamp": "string",
+              "last-action": "CreateNetworkInstance",
+              "last-order-status": "Active",
+              "last-rpc-action": "assign",
+              "last-svc-request-id": "9c06a7c6-be3a-4530-bdd8-c65b58f123a5",
+              "modify-timestamp": "string",
+              "order-status": "Active"
+            },
+            "vf-module-request-input": {
+              "aic-clli": "string",
+              "aic-cloud-region": "test-region",
+              "cloud-owner": "unit-test",
+              "request-version": "string",
+              "tenant": "string",
+              "vf-module-input-parameters": {
+                "param": [
+                  {
+                    "name": "string",
+                    "resource-resolution-data": {
+                      "capability-name": "string",
+                      "payload": "string",
+                      "resource-key": [
+                        {
+                          "name": "string",
+                          "value": "string"
+                        }
+                      ],
+                      "status": "string"
+                    },
+                    "value": "string"
+                  }
+                ]
+              },
+              "vf-module-name": "string"
+            },
+            "vf-module-topology": {
+              "aic-clli": "string",
+              "aic-cloud-region": "test-region",
+              "cloud-owner": "unit-test",
+              "onap-model-information": {
+                "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f",
+                "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e",
+                "model-name": "SMSF-NC2-578",
+                "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9",
+                "model-version": "3.0"
+              },
+              "sdnc-generated-cloud-resources": true,
+              "tenant": "string",
+              "vf-module-assignments": {
+                "dhcp-subnet-assignments": {
+                  "dhcp-subnet-assignment": [
+                    {
+                      "ip-version": "string",
+                      "network-role": "test-network-role",
+                      "neutron-subnet-id": "string"
+                    }
+                  ]
+                },
+                "vf-module-status": "string",
+                "vlan-vnfc-instance-groups": {
+                  "vlan-vnfc-instance-group": [
+                    {
+                      "instance-group-function": "string",
+                      "instance-group-id": "string",
+                      "vnf-id": "2a3bfc93-cd4c-4845-8919-434b2d999ada",
+                      "vnfcs": {
+                        "vnfc": [
+                          {
+                            "vnfc-name": "string",
+                            "vnic-groups": {
+                              "vnic-group": [
+                                {
+                                  "network-instance-group-function": "string",
+                                  "vlan-assignment-policy-name": "string",
+                                  "vlan-common-ip-addresses": {
+                                    "ip-addresses": {
+                                      "ipv4-address": "string",
+                                      "ipv6-address": "string",
+                                      "vipv4-address": "string",
+                                      "vipv6-address": "string"
+                                    }
+                                  },
+                                  "vlan-tag-index-next": 0,
+                                  "vlan-vnics": {
+                                    "vlan-vnic": [
+                                      {
+                                        "vnic-port-id": "string",
+                                        "vnic-sub-interfaces": {
+                                          "sub-interface-network-data": [
+                                            {
+                                              "floating-ips": {
+                                                "floating-ip-v4": [
+                                                  "string"
+                                                ],
+                                                "floating-ip-v6": [
+                                                  "string"
+                                                ]
+                                              },
+                                              "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf",
+                                              "network-information-items": {
+                                                "network-information-item": [
+                                                  {
+                                                    "ip-count": 0,
+                                                    "ip-version": "string",
+                                                    "network-ips": {
+                                                      "network-ip": [
+                                                        "string"
+                                                      ]
+                                                    },
+                                                    "use-dhcp": "Y"
+                                                  }
+                                                ]
+                                              },
+                                              "network-name": 0,
+                                              "network-role": "test-network-role",
+                                              "network-role-tag": "string",
+                                              "neutron-network-id": "string",
+                                              "vlan-tag-id": 0
+                                            }
+                                          ]
+                                        }
+                                      }
+                                    ]
+                                  },
+                                  "vnic-interface-role": "string"
+                                }
+                              ]
+                            }
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                "vms": {
+                  "vm": [
+                    {
+                      "nfc-naming-code": "string",
+                      "onap-model-information": {
+                        "model-customization-uuid": "string",
+                        "model-invariant-uuid": "string",
+                        "model-name": "string",
+                        "model-uuid": "string",
+                        "model-version": "string"
+                      },
+                      "vm-count": 0,
+                      "vm-names": {
+                        "vm-name": [
+                          "string"
+                        ],
+                        "vnfc-names": [
+                          {
+                            "vnfc-name": "string",
+                            "vnfc-networks": {
+                              "vnfc-network-data": [
+                                {
+                                  "connection-point": {
+                                    "connection-point-id": "string",
+                                    "port-id": "string",
+                                    "vlan-data": [
+                                      {
+                                        "vlan-role": "string",
+                                        "vlan-tag-description": "string",
+                                        "vlan-tag-id": "string",
+                                        "vlan-uuid": "string"
+                                      }
+                                    ]
+                                  },
+                                  "vnfc-network-role": "string",
+                                  "vnfc-ports": {
+                                    "vnfc-port": [
+                                      {
+                                        "common-sub-interface-role": "string",
+                                        "vnfc-port-id": "string",
+                                        "vnic-sub-interfaces": {
+                                          "sub-interface-network-data": [
+                                            {
+                                              "floating-ips": {
+                                                "floating-ip-v4": [
+                                                  "string"
+                                                ],
+                                                "floating-ip-v6": [
+                                                  "string"
+                                                ]
+                                              },
+                                              "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf",
+                                              "network-information-items": {
+                                                "network-information-item": [
+                                                  {
+                                                    "ip-count": 0,
+                                                    "ip-version": "string",
+                                                    "network-ips": {
+                                                      "network-ip": [
+                                                        "string"
+                                                      ]
+                                                    },
+                                                    "use-dhcp": "Y"
+                                                  }
+                                                ]
+                                              },
+                                              "network-name": 0,
+                                              "network-role": "test-network-role",
+                                              "network-role-tag": "string",
+                                              "neutron-network-id": "string",
+                                              "vlan-tag-id": 0
+                                            }
+                                          ]
+                                        }
+                                      }
+                                    ]
+                                  },
+                                  "vnfc-subnet": [
+                                    {
+                                      "vnfc-ip-assignments": [
+                                        {
+                                          "vnfc-address-family": "ipv4",
+                                          "vnfc-subnet-dhcp": "Y",
+                                          "vnfc-subnet-ip": [
+                                            {
+                                              "ip-type": "FIXED",
+                                              "vnfc-client-key": "string",
+                                              "vnfc-ip-address": "string"
+                                            }
+                                          ],
+                                          "vnfc-subnet-ip-count": 0
+                                        }
+                                      ],
+                                      "vnfc-subnet-role": "string"
+                                    }
+                                  ],
+                                  "vnfc-type": "string"
+                                }
+                              ]
+                            }
+                          }
+                        ]
+                      },
+                      "vm-networks": {
+                        "vm-network": [
+                          {
+                            "floating-ips": {
+                              "floating-ip-v4": [
+                                "string"
+                              ],
+                              "floating-ip-v6": [
+                                "string"
+                              ]
+                            },
+                            "interface-route-prefixes": {
+                              "interface-route-prefix": [
+                                "string"
+                              ]
+                            },
+                            "is-trunked": true,
+                            "mac-addresses": {
+                              "mac-address": [
+                                "string"
+                              ]
+                            },
+                            "network-information-items": {
+                              "network-information-item": [
+                                {
+                                  "ip-count": 0,
+                                  "ip-version": "string",
+                                  "network-ips": {
+                                    "network-ip": [
+                                      "string"
+                                    ]
+                                  },
+                                  "use-dhcp": "Y"
+                                }
+                              ]
+                            },
+                            "network-role": "test-network-role",
+                            "network-role-tag": "string",
+                            "related-networks": {
+                              "related-network": [
+                                {
+                                  "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf",
+                                  "network-role": "test-network-role",
+                                  "vlan-tags": {
+                                    "is-private": true,
+                                    "lower-tag-id": 0,
+                                    "upper-tag-id": 0,
+                                    "vlan-interface": "string"
+                                  }
+                                }
+                              ]
+                            },
+                            "segmentation-id": "string",
+                            "sriov-parameters": {
+                              "application-tags": {
+                                "c-tags": {
+                                  "c-tag": [
+                                    "string"
+                                  ],
+                                  "ctag": [
+                                    "string"
+                                  ]
+                                },
+                                "ctags": {
+                                  "c-tag": [
+                                    "string"
+                                  ],
+                                  "ctag": [
+                                    "string"
+                                  ]
+                                },
+                                "s-tags": {
+                                  "s-tag": [
+                                    "string"
+                                  ],
+                                  "stag": [
+                                    "string"
+                                  ]
+                                },
+                                "stags": {
+                                  "s-tag": [
+                                    "string"
+                                  ],
+                                  "stag": [
+                                    "string"
+                                  ]
+                                }
+                              },
+                              "heat-vlan-filters": {
+                                "heat-vlan-filter": [
+                                  "string"
+                                ]
+                              }
+                            }
+                          }
+                        ]
+                      },
+                      "vm-type": "string",
+                      "vm-type-tag": "string"
+                    }
+                  ]
+                }
+              },
+              "vf-module-parameters": {
+                "param": [
+                  {
+                    "name": "string",
+                    "resource-resolution-data": {
+                      "capability-name": "string",
+                      "payload": "string",
+                      "resource-key": [
+                        {
+                          "name": "string",
+                          "value": "string"
+                        }
+                      ],
+                      "status": "string"
+                    },
+                    "value": "string"
+                  }
+                ]
+              },
+              "vf-module-topology-identifier": {
+                "vf-module-id": "9270c447-3caf-4e12-85aa-3578b0fa61d5",
+                "vf-module-name": "some-vf-module-name",
+                "vf-module-type": "some-vf-module-type"
+              }
+            },
+            "vnf-information": {
+              "onap-model-information": {
+                "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f",
+                "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e",
+                "model-name": "SMSF-NC2-578",
+                "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9",
+                "model-version": "3.0"
+              },
+              "vnf-id": "2a3bfc93-cd4c-4845-8919-434b2d999ada",
+              "vnf-name": "mytestvnf",
+              "vnf-type" : "SMSF-NC2-578-SVC/SMSF-NC2-578"
+            }
+          },
+          "vf-module-id": "9270c447-3caf-4e12-85aa-3578b0fa61d5"
+        }
+      ]
+    },
+    "vnf-information": {
+      "onap-model-information": {
+        "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f",
+        "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e",
+        "model-name": "SMSF-NC2-578",
+        "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9",
+        "model-version": "3.0"
+      },
+      "vnf-id": "2a3bfc93-cd4c-4845-8919-434b2d999ada",
+      "vnf-name": "mytestvnf",
+      "vnf-type" : "SMSF-NC2-578-SVC/SMSF-NC2-578"
+    },
+    "vnf-level-oper-status": {
+      "create-timestamp": "string",
+      "last-action": "CreateNetworkInstance",
+      "last-order-status": "Active",
+      "last-rpc-action": "assign",
+      "last-svc-request-id": "9c06a7c6-be3a-4530-bdd8-c65b58f123a5",
+      "modify-timestamp": "string",
+      "order-status": "Active"
+    },
+    "vnf-request-input": {
+      "aic-clli": "string",
+      "aic-cloud-region": "test-region",
+      "cloud-owner": "unit-test",
+      "request-version": "string",
+      "tenant": "string",
+      "vnf-name": "mytestvnf",
+      "vnf-networks": {
+        "vnf-network": [
+          {
+            "contrail-network-fqdn": "string",
+            "is-trunked": true,
+            "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf",
+            "network-name": "test-network-name",
+            "network-role": "test-network-role",
+            "neutron-id": "812562dd-9d91-4ba6-9c3e-e52bf1cd4cc6",
+            "related-networks": {
+              "related-network": [
+                {
+                  "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf",
+                  "network-role": "test-network-role",
+                  "vlan-tags": {
+                    "is-private": true,
+                    "lower-tag-id": 0,
+                    "upper-tag-id": 0,
+                    "vlan-interface": "string"
+                  }
+                }
+              ]
+            },
+            "segmentation-id": "string",
+            "subnets-data": {
+              "subnet-data": [
+                {
+                  "cidr-mask": "string",
+                  "dhcp-enabled": "Y",
+                  "gateway-address": "string",
+                  "ip-version": "string",
+                  "network-start-address": "string",
+                  "sdnc-subnet-id": "string",
+                  "subnet-id": "string",
+                  "subnet-name": "string",
+                  "subnet-role": "string"
+                }
+              ]
+            }
+          }
+        ]
+      }
+    },
+    "vnf-topology": {
+      "aic-clli": "string",
+      "aic-cloud-region": "test-region",
+      "cloud-owner": "unit-test",
+      "onap-model-information": {
+        "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f",
+        "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e",
+        "model-name": "SMSF-NC2-578",
+        "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9",
+        "model-version": "3.0"
+      },
+      "sdnc-generated-cloud-resources": true,
+      "tenant": "string",
+      "vnf-resource-assignments": {
+        "availability-zones": {
+          "availability-zone": [
+            "string"
+          ],
+          "max-count": 0
+        },
+        "vnf-networks": {
+          "vnf-network": [
+            {
+              "contrail-network-fqdn": "string",
+              "is-trunked": true,
+              "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf",
+              "network-name": "test-network-name",
+              "network-role": "test-network-role",
+              "neutron-id": "812562dd-9d91-4ba6-9c3e-e52bf1cd4cc6",
+              "related-networks": {
+                "related-network": [
+                  {
+                    "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf",
+                    "network-role": "test-network-role",
+                    "vlan-tags": {
+                      "is-private": true,
+                      "lower-tag-id": 0,
+                      "upper-tag-id": 0,
+                      "vlan-interface": "string"
+                    }
+                  }
+                ]
+              },
+              "segmentation-id": "string",
+              "subnets-data": {
+                "subnet-data": [
+                  {
+                    "cidr-mask": "string",
+                    "dhcp-enabled": "Y",
+                    "gateway-address": "string",
+                    "ip-version": "string",
+                    "network-start-address": "string",
+                    "sdnc-subnet-id": "string",
+                    "subnet-id": "string",
+                    "subnet-name": "string",
+                    "subnet-role": "string"
+                  }
+                ]
+              }
+            }
+          ]
+        },
+        "vnf-status": "string"
+      },
+      "vnf-topology-identifier-structure": {
+        "nf-code": "string",
+        "nf-function": "string",
+        "nf-role": "string",
+        "nf-type": "string",
+        "vnf-id": "2a3bfc93-cd4c-4845-8919-434b2d999ada",
+        "vnf-name": "mytestvnf",
+        "vnf-type" : "SMSF-NC2-578-SVC/SMSF-NC2-578"
+      }
+    }
+  },
+  "vnf-id": "2a3bfc93-cd4c-4845-8919-434b2d999ada"
+}
\ No newline at end of file
diff --git a/ms/generic-resource-api/src/test/resources/vnf-level-oper-status.json b/ms/generic-resource-api/src/test/resources/vnf-level-oper-status.json
new file mode 100644 (file)
index 0000000..1778cab
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "vnf-level-oper-status": {
+    "create-timestamp": "string",
+    "last-action": "CreateNetworkInstance",
+    "last-order-status": "Active",
+    "last-rpc-action": "assign",
+    "last-svc-request-id": "9c06a7c6-be3a-4530-bdd8-c65b58f123a5",
+    "modify-timestamp": "string",
+    "order-status": "Active"
+  }
+}
\ No newline at end of file
diff --git a/ms/generic-resource-api/src/test/resources/vnf-onap-model-info.json b/ms/generic-resource-api/src/test/resources/vnf-onap-model-info.json
new file mode 100644 (file)
index 0000000..d44dc49
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "onap-model-information": {
+    "model-customization-uuid": "602c6bcc-6cfa-41cb-a8a7-968b38d5935f",
+    "model-invariant-uuid": "bdb4f943-c9be-4742-b976-a34607f3687e",
+    "model-name": "SMSF-NC2-578",
+    "model-uuid": "86c76b5d-fa8d-4034-b79a-1cc4326021a9",
+    "model-version": "3.0"
+  }
+}
\ No newline at end of file
diff --git a/ms/generic-resource-api/src/test/resources/vnf-vnf-networks-network-role.json b/ms/generic-resource-api/src/test/resources/vnf-vnf-networks-network-role.json
new file mode 100644 (file)
index 0000000..d435c4a
--- /dev/null
@@ -0,0 +1,34 @@
+{
+    "contrail-network-fqdn": "string",
+    "is-trunked": true,
+    "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf",
+    "network-name": "test-network-name",
+    "network-role": "test-network-role",
+    "neutron-id": "812562dd-9d91-4ba6-9c3e-e52bf1cd4cc6",
+    "related-networks": {
+        "related-network": [{
+            "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf",
+            "network-role": "test-network-role",
+            "vlan-tags": {
+                "is-private": true,
+                "lower-tag-id": 0,
+                "upper-tag-id": 0,
+                "vlan-interface": "string"
+            }
+        }]
+    },
+    "segmentation-id": "string",
+    "subnets-data": {
+        "subnet-data": [{
+            "cidr-mask": "string",
+            "dhcp-enabled": "Y",
+            "gateway-address": "string",
+            "ip-version": "string",
+            "network-start-address": "string",
+            "sdnc-subnet-id": "string",
+            "subnet-id": "string",
+            "subnet-name": "string",
+            "subnet-role": "string"
+        }]
+    }
+}
\ No newline at end of file
diff --git a/ms/generic-resource-api/src/test/resources/vnf-vnf-networks.json b/ms/generic-resource-api/src/test/resources/vnf-vnf-networks.json
new file mode 100644 (file)
index 0000000..3f73cba
--- /dev/null
@@ -0,0 +1,38 @@
+{
+    "vnf-networks": {
+        "vnf-network": [{
+            "contrail-network-fqdn": "string",
+            "is-trunked": true,
+            "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf",
+            "network-name": "test-network-name",
+            "network-role": "test-network-role",
+            "neutron-id": "812562dd-9d91-4ba6-9c3e-e52bf1cd4cc6",
+            "related-networks": {
+                "related-network": [{
+                    "network-id": "69f09279-8af1-4475-83cf-7e357c579dbf",
+                    "network-role": "test-network-role",
+                    "vlan-tags": {
+                        "is-private": true,
+                        "lower-tag-id": 0,
+                        "upper-tag-id": 0,
+                        "vlan-interface": "string"
+                    }
+                }]
+            },
+            "segmentation-id": "string",
+            "subnets-data": {
+                "subnet-data": [{
+                    "cidr-mask": "string",
+                    "dhcp-enabled": "Y",
+                    "gateway-address": "string",
+                    "ip-version": "string",
+                    "network-start-address": "string",
+                    "sdnc-subnet-id": "string",
+                    "subnet-id": "string",
+                    "subnet-name": "string",
+                    "subnet-role": "string"
+                }]
+            }
+        }]
+    }
+}
\ No newline at end of file