From ff5433e350678f5f45e8b2aa14cdb00f9cecfceb Mon Sep 17 00:00:00 2001 From: Vodafone Date: Mon, 25 Mar 2019 17:38:23 +0530 Subject: CCVPN (East-west Interface) Change-Id: I11dbe477db3310ef054b2e894e8005b0f8e4be96 Issue-ID: EXTAPI-204 Co-authored-by: madhuri.verma@vodafone.com Signed-off-by: Vodafone --- docs/configuration/configuration.rst | 2 + .../java/org/onap/nbi/OnapComponentsUrlPaths.java | 10 ++ .../org/onap/nbi/apis/hub/ExtApiClientForHub.java | 90 --------------- .../java/org/onap/nbi/apis/hub/HubResource.java | 59 +++++++--- .../org/onap/nbi/apis/hub/ListenerResource.java | 53 --------- .../org/onap/nbi/apis/hub/model/Subscriber.java | 22 ++++ .../org/onap/nbi/apis/hub/model/Subscription.java | 23 ++++ .../nbi/apis/hub/service/NotificationAspect.java | 9 -- .../nbi/apis/listener/ListenerResourceTarget.java | 71 ++++++++++++ .../ServiceSpecificationResource.java | 3 +- .../serviceinventory/ServiceInventoryResource.java | 3 +- .../onap/nbi/apis/serviceorder/ExtApiClient.java | 107 ----------------- .../apis/serviceorder/ServiceOrderResource.java | 49 ++++---- .../org/onap/nbi/commons/EWInterfaceUtils.java | 128 +++++++++++++++++++++ src/main/resources/application.properties | 5 +- src/test/resources/karatetest/data/Event.json | 13 --- src/test/resources/karatetest/data/subscriber.json | 4 - .../karatetest/features/02--ServiceOrder.feature | 27 +++-- .../karatetest/features/03--Subscriber.feature | 36 ------ .../05--ListenerResourceTestTarget.feature | 74 ++++++++++++ 20 files changed, 419 insertions(+), 369 deletions(-) delete mode 100644 src/main/java/org/onap/nbi/apis/hub/ExtApiClientForHub.java delete mode 100644 src/main/java/org/onap/nbi/apis/hub/ListenerResource.java create mode 100644 src/main/java/org/onap/nbi/apis/listener/ListenerResourceTarget.java delete mode 100644 src/main/java/org/onap/nbi/apis/serviceorder/ExtApiClient.java create mode 100644 src/main/java/org/onap/nbi/commons/EWInterfaceUtils.java delete mode 100644 src/test/resources/karatetest/data/Event.json create mode 100644 src/test/resources/karatetest/features/05--ListenerResourceTestTarget.feature diff --git a/docs/configuration/configuration.rst b/docs/configuration/configuration.rst index 6290691..a498e4d 100644 --- a/docs/configuration/configuration.rst +++ b/docs/configuration/configuration.rst @@ -25,6 +25,7 @@ Default values # SERVER server.servlet.context-path = /nbi/api/${nbi.version} server.port = 8080 + server.public.ip = localhost # LOGGING logging.level. = WARN @@ -41,6 +42,7 @@ Default values # NBI nbi.url = http://localhost:${server.port}${server.servlet.context-path} nbi.callForVNF = false + nbi.public.url = http://${server.public.ip}:${server.port}${server.servlet.context-path} # SCHEDULER scheduler.pollingDurationInMins = 360 diff --git a/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java b/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java index 0796c2f..8828321 100644 --- a/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java +++ b/src/main/java/org/onap/nbi/OnapComponentsUrlPaths.java @@ -23,6 +23,15 @@ public final class OnapComponentsUrlPaths { private OnapComponentsUrlPaths() {} + // NBI + public static final String SERVICE_ORDER_PATH= "/serviceOrder"; + public static final String SERVICE_INVENTORY_PATH= "/service"; + public static final String SERVICE_SPECIFICATION_PATH= "/serviceSpecification"; + public static final String HUB_PATH= "/hub"; + public static final String LISTENER_PATH= "/listener"; + + + // SDC public static final String SDC_ROOT_URL = "/sdc/v1/catalog/services"; public static final String SDC_GET_PATH = "/metadata"; @@ -60,4 +69,5 @@ public final class OnapComponentsUrlPaths { // DMaaP Message Router REST Client public static final String DMAAP_CONSUME_EVENTS = "/events/$topic/$consumergroup/$consumerid?timeout=$timeout"; + } \ No newline at end of file diff --git a/src/main/java/org/onap/nbi/apis/hub/ExtApiClientForHub.java b/src/main/java/org/onap/nbi/apis/hub/ExtApiClientForHub.java deleted file mode 100644 index 10d6f7c..0000000 --- a/src/main/java/org/onap/nbi/apis/hub/ExtApiClientForHub.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Copyright (c) 2019 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. - */ -package org.onap.nbi.apis.hub; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.onap.nbi.apis.hub.model.Subscription; -import org.onap.nbi.exceptions.BackendFunctionalException; -import org.onap.nbi.exceptions.TechnicalException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.*; -import org.springframework.stereotype.Service; -import org.springframework.web.client.ResourceAccessException; -import org.springframework.web.client.RestTemplate; - -@Service -public class ExtApiClientForHub { - - @Autowired - RestTemplate restTemplate; - - @Value("${external.nbi.url}") - private String externalNbiUrl; - - @Value("${nbi.url}") - private String nbiUrl; - - private static final Logger LOGGER = LoggerFactory.getLogger(ExtApiClientForHub.class); - - private static final ObjectMapper mapper = new ObjectMapper(); - - public ResponseEntity postEventSubscription(Subscription subscription, String targetURL) { - try { - - - String url = externalNbiUrl.replace("{targetUrl}", targetURL) + "/hub"; - LOGGER.debug("Sending create event notification request to " + url); - String nbiListenerUrl = nbiUrl + "/listener"; - subscription.setCallback(nbiListenerUrl); - String subscriptionAsBody = mapper.writeValueAsString(subscription); - ResponseEntity response = postRequest(url, subscriptionAsBody, buildRequestHeaders()); - LOGGER.info("Received response from " + targetURL + "with status : " + response.getStatusCode()); - LOGGER.debug("Response Body: " + response.getBody()); - return response; - }catch(JsonProcessingException ex) { - LOGGER.error("error occurred while parsing service order to Json: " + ex); - throw new TechnicalException("error occurred while parsing service order to Json:"+ HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - private HttpHeaders buildRequestHeaders() { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.add("Accept", "application/json"); - httpHeaders.add("Content-Type", "application/json"); - return httpHeaders; - } - - - private ResponseEntity postRequest(String url, String body, HttpHeaders httpHeaders) { - try { - ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, httpHeaders), Object.class); - return response; - }catch(BackendFunctionalException ex) { - LOGGER.error("error on calling " + url + " ," + ex); - return new ResponseEntity<>("problem calling onap services", ex.getHttpStatus()); - }catch (ResourceAccessException ex) { - LOGGER.error("error on calling " + url + " ," + ex); - return new ResponseEntity<>("unable to reach onap services", HttpStatus.INTERNAL_SERVER_ERROR); - - } - - } -} - diff --git a/src/main/java/org/onap/nbi/apis/hub/HubResource.java b/src/main/java/org/onap/nbi/apis/hub/HubResource.java index 28e1313..3f14b8a 100755 --- a/src/main/java/org/onap/nbi/apis/hub/HubResource.java +++ b/src/main/java/org/onap/nbi/apis/hub/HubResource.java @@ -13,19 +13,23 @@ */ package org.onap.nbi.apis.hub; +import java.util.LinkedHashMap; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; +import org.onap.nbi.OnapComponentsUrlPaths; import org.onap.nbi.apis.hub.model.Subscriber; import org.onap.nbi.apis.hub.model.Subscription; import org.onap.nbi.apis.hub.service.dmaap.CheckDMaaPEventsManager; import org.onap.nbi.apis.hub.service.SubscriptionService; +import org.onap.nbi.commons.EWInterfaceUtils; import org.onap.nbi.commons.JsonRepresentation; import org.onap.nbi.commons.MultiCriteriaRequestBuilder; import org.onap.nbi.commons.ResourceManagement; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Query; import org.springframework.http.HttpHeaders; @@ -39,14 +43,14 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.bind.annotation.RequestHeader; @RestController -@RequestMapping("/hub") +@RequestMapping(OnapComponentsUrlPaths.HUB_PATH) @EnableScheduling public class HubResource extends ResourceManagement { @@ -65,27 +69,40 @@ public class HubResource extends ResourceManagement { CheckDMaaPEventsManager checkDMaaPEventMAnager; @Autowired - ExtApiClientForHub extApiClientForHub; + EWInterfaceUtils ewInterfaceUtils; + + @Value("${nbi.public.url}") + private String nbiPublicUrl; @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity createEventSubscription(@RequestBody Subscription subscription, - @RequestParam MultiValueMap params, @RequestHeader(required = false) String targetURL) { + @RequestParam MultiValueMap params, @RequestHeader(value="Target",required = false)String targetUrl) { logger.debug("POST request for subscription : {}", subscription); - if(targetURL != null) { - Subscriber subscriber = subscriptionService.createSubscription(subscription); - return extApiClientForHub.postEventSubscription(subscription,targetURL); - }else { - Subscriber subscriber = subscriptionService.createSubscription(subscription); - JsonRepresentation filter = new JsonRepresentation(params); - return this.createResponse(Subscription.createFromSubscriber(subscriber), filter); + if (targetUrl != null) { + targetUrl = targetUrl + OnapComponentsUrlPaths.HUB_PATH; + String originalCallback = subscription.getCallback(); + subscription.setCallback(nbiPublicUrl + OnapComponentsUrlPaths.LISTENER_PATH); + ResponseEntity ewResponse = ewInterfaceUtils.callPostRequestTarget(subscription, targetUrl); + if (ewResponse.getStatusCode() == HttpStatus.CREATED) { + subscription.setCallback(originalCallback); + subscription.setEwHost(targetUrl); + subscription.setEwId(((LinkedHashMap)ewResponse.getBody()).get( "id" ).toString()); + } else { + return ewResponse; + } } + Subscriber subscriber = subscriptionService.createSubscription(subscription); + JsonRepresentation filter = new JsonRepresentation(params); + return this.createResponse(Subscription.createFromSubscriber(subscriber), filter); + } @GetMapping(value = "/{subscriptionId}", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity getSubscription(@PathVariable String subscriptionId) { - Optional optionalSubscriber = subscriptionService.findSubscriptionById(subscriptionId); + Optional optionalSubscriber = + subscriptionService.findSubscriptionById(subscriptionId); if (!optionalSubscriber.isPresent()) { return ResponseEntity.notFound().build(); } @@ -93,7 +110,8 @@ public class HubResource extends ResourceManagement { } @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity findSubscribers(@RequestParam MultiValueMap params) { + public ResponseEntity findSubscribers( + @RequestParam MultiValueMap params) { Query query = multiCriteriaRequestBuilder.buildRequest(params); List subscribers = mongoTemplate.find(query, Subscriber.class); @@ -102,7 +120,8 @@ public class HubResource extends ResourceManagement { HttpHeaders headers = new HttpHeaders(); headers.add("X-Total-Count", String.valueOf(totalCount)); headers.add("X-Result-Count", String.valueOf(subscribers.size())); - List subscriptions = subscribers.stream().map(Subscription::createFromSubscriber).collect(Collectors.toList()); + List subscriptions = + subscribers.stream().map(Subscription::createFromSubscriber).collect(Collectors.toList()); return this.findResponse(subscriptions, filter, headers); @@ -121,7 +140,19 @@ public class HubResource extends ResourceManagement { @ResponseStatus(HttpStatus.NO_CONTENT) public void deleteSubscription(@PathVariable String subscriptionId) { logger.debug("DELETE request for subscription id #{}", subscriptionId); + Optional optionalSubscriber= subscriptionService.findSubscriptionById(subscriptionId); subscriptionService.deleteSubscription(subscriptionId); + String ewHost=optionalSubscriber.get().getEwHost(); + String ewId=optionalSubscriber.get().getEwId(); + logger.info("POST delete for ewHost : {}", ewHost); + logger.info("POST delete for ewId : {}", ewId); + if ( ewHost !=null && ewId !=null ) + { + logger.info("POST deleteIF for ewHost : {}", ewHost); + String targetUrl = ewHost+ "/" + ewId; + ewInterfaceUtils.callDeleteRequestTarget(targetUrl); + logger.info("POST deleteIF for ewHost is : {}", targetUrl); + } } } diff --git a/src/main/java/org/onap/nbi/apis/hub/ListenerResource.java b/src/main/java/org/onap/nbi/apis/hub/ListenerResource.java deleted file mode 100644 index aa236d1..0000000 --- a/src/main/java/org/onap/nbi/apis/hub/ListenerResource.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2019 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. - */ -package org.onap.nbi.apis.hub; - -import org.onap.nbi.apis.hub.service.NotificationAspect; -import org.onap.nbi.commons.ResourceManagement; -import org.onap.nbi.exceptions.BackendFunctionalException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.MediaType; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.onap.nbi.apis.hub.model.Event; - - - -@RestController -@RequestMapping("/listener") -public class ListenerResource extends ResourceManagement { - - @Autowired - NotificationAspect notificationAspect; - - private static final Logger LOGGER = LoggerFactory.getLogger(ListenerResource.class); - - @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) - public void receiveNotification(@RequestBody Event event) { - try { - LOGGER.debug("Received notification from external NBI || Sending it to original listener"); - notificationAspect.forwardNotificationToOriginalListener(event); - }catch(BackendFunctionalException ex) { - LOGGER.error("Unable to send the recieved notification to original Listener"); - - } - } -} diff --git a/src/main/java/org/onap/nbi/apis/hub/model/Subscriber.java b/src/main/java/org/onap/nbi/apis/hub/model/Subscriber.java index ab2b05f..582b14b 100755 --- a/src/main/java/org/onap/nbi/apis/hub/model/Subscriber.java +++ b/src/main/java/org/onap/nbi/apis/hub/model/Subscriber.java @@ -34,6 +34,26 @@ public class Subscriber implements Resource { private String id; private String callback; + public String getEwId() { + return ewId; + } + + public void setEwId(String ewId) { + this.ewId = ewId; + } + + private String ewId; + + public String getEwHost() { + return ewHost; + } + + public void setEwHost(String ewHost) { + this.ewHost = ewHost; + } + + private String ewHost; + private Map query = new HashMap<>(); public String getId() { @@ -59,6 +79,8 @@ public class Subscriber implements Resource { public static Subscriber createFromSubscription(Subscription request) { Subscriber sub = new Subscriber(); sub.setCallback(request.getCallback()); + sub.setEwId( request.getEwId()); + sub.setEwHost( request.getEwHost()); Stream.of(request.getQuery().split("&")) .map(q -> q.split("=")) diff --git a/src/main/java/org/onap/nbi/apis/hub/model/Subscription.java b/src/main/java/org/onap/nbi/apis/hub/model/Subscription.java index 34e23e1..646d39b 100755 --- a/src/main/java/org/onap/nbi/apis/hub/model/Subscription.java +++ b/src/main/java/org/onap/nbi/apis/hub/model/Subscription.java @@ -26,6 +26,26 @@ public class Subscription implements Resource{ private String callback; private String query; + private String ewId; + private String ewHost; + + public void setEwHost(String ewHost) { + this.ewHost = ewHost; + } + + public String getEwId() { + return ewId; + } + + public void setEwId(String ewId) { + this.ewId = ewId; + } + + + + public String getEwHost() { + return ewHost; + } public Subscription(){ @@ -65,6 +85,9 @@ public class Subscription implements Resource{ Subscription sub = new Subscription(); sub.setId(subscriber.getId()); sub.setCallback(subscriber.getCallback()); + sub.setEwId( subscriber.getEwId()); + sub.setEwHost( subscriber.getEwHost()); + String query = subscriber.getQuery().entrySet() .stream() diff --git a/src/main/java/org/onap/nbi/apis/hub/service/NotificationAspect.java b/src/main/java/org/onap/nbi/apis/hub/service/NotificationAspect.java index 3033404..cd242e8 100755 --- a/src/main/java/org/onap/nbi/apis/hub/service/NotificationAspect.java +++ b/src/main/java/org/onap/nbi/apis/hub/service/NotificationAspect.java @@ -27,7 +27,6 @@ import org.onap.nbi.apis.serviceorder.model.StateType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.stereotype.Component; -import org.onap.nbi.exceptions.TechnicalException; @Aspect @Component @@ -72,14 +71,6 @@ public class NotificationAspect { } } - public void forwardNotificationToOriginalListener(Event event) { - if(event != null) { - processEvent(event); - }else{ - throw new TechnicalException("Received null event from external NBI"); - } - } - /** * Retreive subscribers that match an event and fire notification * asynchronously diff --git a/src/main/java/org/onap/nbi/apis/listener/ListenerResourceTarget.java b/src/main/java/org/onap/nbi/apis/listener/ListenerResourceTarget.java new file mode 100644 index 0000000..8b8e50f --- /dev/null +++ b/src/main/java/org/onap/nbi/apis/listener/ListenerResourceTarget.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2019 Vodafone Group + * + * 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.nbi.apis.listener; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MappingJsonFactory; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.onap.nbi.apis.hub.repository.SubscriberRepository; +import org.onap.nbi.apis.hub.service.NotifierService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.onap.nbi.apis.hub.model.Event; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ListenerResourceTarget { + private static final ObjectMapper mapper = new ObjectMapper(new MappingJsonFactory()); + + @Autowired + private SubscriberRepository subscriberRepository; + @Autowired + private NotifierService notifier; + + Logger logger = LoggerFactory.getLogger(ListenerResourceTarget.class); + + static Map events = new ConcurrentHashMap<>(); + + /* + listener resource test for hub resource + */ + @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity postListenerResource(@RequestBody JsonNode event) { + if (logger.isDebugEnabled()) { + logger.debug("POST event from nbi : {}", event.toString()); + + } + try { + Event eventListener = mapper.treeToValue(event, Event.class); + subscriberRepository + .findSubscribersUsingEvent(eventListener) + .forEach(sub -> notifier.run(sub, eventListener)); + } + catch(Exception e){ + logger.error("listener not called " + " ," + e.getMessage()); + return ResponseEntity.badRequest().build(); + } + + return ResponseEntity.ok().build(); + } +} + diff --git a/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationResource.java b/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationResource.java index 6484672..49b9f08 100644 --- a/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationResource.java +++ b/src/main/java/org/onap/nbi/apis/servicecatalog/ServiceSpecificationResource.java @@ -18,6 +18,7 @@ package org.onap.nbi.apis.servicecatalog; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import org.onap.nbi.OnapComponentsUrlPaths; import org.onap.nbi.commons.JsonRepresentation; import org.onap.nbi.commons.ResourceManagement; import org.springframework.beans.factory.annotation.Autowired; @@ -31,7 +32,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping("/serviceSpecification") +@RequestMapping(OnapComponentsUrlPaths.SERVICE_SPECIFICATION_PATH) public class ServiceSpecificationResource extends ResourceManagement { diff --git a/src/main/java/org/onap/nbi/apis/serviceinventory/ServiceInventoryResource.java b/src/main/java/org/onap/nbi/apis/serviceinventory/ServiceInventoryResource.java index cd46d74..eda6f96 100644 --- a/src/main/java/org/onap/nbi/apis/serviceinventory/ServiceInventoryResource.java +++ b/src/main/java/org/onap/nbi/apis/serviceinventory/ServiceInventoryResource.java @@ -18,6 +18,7 @@ package org.onap.nbi.apis.serviceinventory; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import org.onap.nbi.OnapComponentsUrlPaths; import org.onap.nbi.commons.JsonRepresentation; import org.onap.nbi.commons.ResourceManagement; import org.springframework.beans.factory.annotation.Autowired; @@ -31,7 +32,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController -@RequestMapping("/service") +@RequestMapping(OnapComponentsUrlPaths.SERVICE_INVENTORY_PATH) public class ServiceInventoryResource extends ResourceManagement { @Autowired diff --git a/src/main/java/org/onap/nbi/apis/serviceorder/ExtApiClient.java b/src/main/java/org/onap/nbi/apis/serviceorder/ExtApiClient.java deleted file mode 100644 index 7fd06e6..0000000 --- a/src/main/java/org/onap/nbi/apis/serviceorder/ExtApiClient.java +++ /dev/null @@ -1,107 +0,0 @@ -/** - * Copyright (c) 2019 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. - */ -package org.onap.nbi.apis.serviceorder; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.onap.nbi.apis.serviceorder.model.ServiceOrder; -import org.onap.nbi.exceptions.BackendFunctionalException; -import org.onap.nbi.exceptions.TechnicalException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.*; -import org.springframework.stereotype.Service; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.ResourceAccessException; -import org.springframework.web.client.RestTemplate; - -@Service -public class ExtApiClient { - - @Autowired - RestTemplate restTemplate; - - @Value("${external.nbi.url}") - private String externalNbiUrl; - - private static final Logger LOGGER = LoggerFactory.getLogger(ExtApiClient.class); - - private static final ObjectMapper mapper = new ObjectMapper(); - - public ResponseEntity postServiceOrder(ServiceOrder serviceOrder, String targetURL) { - try { - - - String url = externalNbiUrl.replace("{targetUrl}", targetURL) + "/serviceOrder"; - LOGGER.debug("Sending create service order request to " + url); - String serviceOrderAsBody = mapper.writeValueAsString(serviceOrder); - ResponseEntity response = postRequest(url, serviceOrderAsBody, buildRequestHeaders()); - LOGGER.info("Received response from " + targetURL + "with status : " + response.getStatusCode()); - LOGGER.debug("Response Body: " + response.getBody()); - return response; - }catch(JsonProcessingException ex) { - LOGGER.error("error occurred while parsing subscription data to Json: " + ex); - throw new TechnicalException("error occurred while parsing subscription data to Json:"+ HttpStatus.INTERNAL_SERVER_ERROR); - } - } - - private HttpHeaders buildRequestHeaders() { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.add("Accept", "application/json"); - httpHeaders.add("Content-Type", "application/json"); - return httpHeaders; - } - - public ResponseEntity getServiceOrder(String serviceOrderId, String targetURL) { - - String url = externalNbiUrl.replace("{targetUrl}", targetURL) + "/serviceOrder/" + serviceOrderId; - LOGGER.debug("Sending get service order request to " + url); - ResponseEntity response = getRequest(url, buildRequestHeaders()); - LOGGER.info("Received response from " + targetURL + "with status : " + response.getStatusCode()); - LOGGER.debug("Response Body: " + response.getBody()); - return response; - } - - - private ResponseEntity getRequest(String url, HttpHeaders httpHeaders) { - try { - ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(httpHeaders), Object.class); - return response; - }catch(BackendFunctionalException ex) { - LOGGER.error("Error occurred while sending post request to " + url); - return new ResponseEntity<>("Found Error: " + ex.getBodyResponse(), ex.getHttpStatus()); - }catch (ResourceAccessException ex) { - LOGGER.error("Error occurred while sending post request to " + url); - return new ResponseEntity<>("Unable to access the resource at " + url, HttpStatus.INTERNAL_SERVER_ERROR); - } -} - - private ResponseEntity postRequest(String url, String body, HttpHeaders httpHeaders) { - try { - ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, httpHeaders), Object.class); - return response; - }catch(BackendFunctionalException ex) { - LOGGER.error("Error occurred while sending post request to " + url); - return new ResponseEntity<>("Found Error: " + ex.getBodyResponse(), ex.getHttpStatus()); - }catch (ResourceAccessException ex) { - LOGGER.error("Error occurred while sending post request to " + url); - return new ResponseEntity<>("Unable to access the resource at " + url, HttpStatus.INTERNAL_SERVER_ERROR); - } - - } -} diff --git a/src/main/java/org/onap/nbi/apis/serviceorder/ServiceOrderResource.java b/src/main/java/org/onap/nbi/apis/serviceorder/ServiceOrderResource.java index f8085b9..90d84a4 100644 --- a/src/main/java/org/onap/nbi/apis/serviceorder/ServiceOrderResource.java +++ b/src/main/java/org/onap/nbi/apis/serviceorder/ServiceOrderResource.java @@ -15,6 +15,8 @@ package org.onap.nbi.apis.serviceorder; import java.util.List; import java.util.Optional; import javax.validation.Valid; +import org.onap.nbi.OnapComponentsUrlPaths; +import org.onap.nbi.commons.EWInterfaceUtils; import org.onap.nbi.apis.serviceorder.model.ServiceOrder; import org.onap.nbi.apis.serviceorder.model.StateType; import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfo; @@ -41,13 +43,13 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.bind.annotation.RequestHeader; @RestController -@RequestMapping("/serviceOrder") +@RequestMapping(OnapComponentsUrlPaths.SERVICE_ORDER_PATH) public class ServiceOrderResource extends ResourceManagement { @Autowired @@ -72,25 +74,24 @@ public class ServiceOrderResource extends ResourceManagement { MultiCriteriaRequestBuilder multiCriteriaRequestBuilder; @Autowired - ExtApiClient extApiClient; + EWInterfaceUtils eWInterfaceUtils; @GetMapping(value = "/{serviceOrderId}", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity getServiceOrder(@PathVariable String serviceOrderId, - @RequestParam MultiValueMap params, @RequestHeader(required = false) String targetURL) { - - if(targetURL != null) { - return extApiClient.getServiceOrder(serviceOrderId, targetURL); - }else { + @RequestParam MultiValueMap params,@RequestHeader(value="Target",required = false)String targetUrl) { + if (targetUrl != null) { + targetUrl = targetUrl + OnapComponentsUrlPaths.SERVICE_ORDER_PATH + "/" + serviceOrderId; + return eWInterfaceUtils.callGetRequestTarget(targetUrl); + } else { Optional optionalServiceOrder = serviceOrderService.findServiceOrderById(serviceOrderId); if (!optionalServiceOrder.isPresent()) { return ResponseEntity.notFound().build(); + } else { + JsonRepresentation filter = new JsonRepresentation(params); + return this.getResponse(optionalServiceOrder.get(), filter); } - - JsonRepresentation filter = new JsonRepresentation(params); - return this.getResponse(optionalServiceOrder.get(), filter); } - } @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE) @@ -119,26 +120,26 @@ public class ServiceOrderResource extends ResourceManagement { @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity createServiceOrder(@Valid @RequestBody ServiceOrder serviceOrder, Errors errors, - @RequestParam MultiValueMap params, @RequestHeader(required = false) String targetURL) { - - if (errors != null && errors.hasErrors()) { - throw new ValidationException(errors.getAllErrors()); + @RequestParam MultiValueMap params, @RequestHeader(value="Target",required = false)String targetUrl) { + if (targetUrl != null) { + targetUrl = targetUrl + OnapComponentsUrlPaths.SERVICE_ORDER_PATH; + return eWInterfaceUtils.callPostRequestTarget(serviceOrder, targetUrl); + } else { + if (errors != null && errors.hasErrors()) { + throw new ValidationException(errors.getAllErrors()); + } } - if(targetURL != null) { - return extApiClient.postServiceOrder(serviceOrder, targetURL); - }else { - ServiceOrder serviceOrderSaved = serviceOrderService.createServiceOrder(serviceOrder); - JsonRepresentation filter = new JsonRepresentation(params); - return this.createResponse(serviceOrderSaved, filter); - } + ServiceOrder serviceOrderSaved = serviceOrderService.createServiceOrder(serviceOrder); + JsonRepresentation filter = new JsonRepresentation(params); + return this.createResponse(serviceOrderSaved, filter); } @PutMapping(value = "/test/{serviceOrderId}", consumes = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity checkServiceOrderRessource(@PathVariable String serviceOrderId, - @RequestParam MultiValueMap params) { + @RequestParam MultiValueMap params) { Optional optionalServiceOrder = serviceOrderService.findServiceOrderById(serviceOrderId); if (!optionalServiceOrder.isPresent()) { return ResponseEntity.notFound().build(); diff --git a/src/main/java/org/onap/nbi/commons/EWInterfaceUtils.java b/src/main/java/org/onap/nbi/commons/EWInterfaceUtils.java new file mode 100644 index 0000000..24bf1fc --- /dev/null +++ b/src/main/java/org/onap/nbi/commons/EWInterfaceUtils.java @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2019 Vodafone Group + * + * 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.nbi.commons; +import org.onap.nbi.exceptions.BackendFunctionalException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.*; +import org.springframework.stereotype.Service; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.RestTemplate; + + +@Service +public class EWInterfaceUtils { + + public static final String RESPONSE_STATUS = "response status : "; + public static final String RETURNS = " returns "; + public static final String ERROR_ON_CALLING = "error on calling "; + private static final Logger LOGGER = LoggerFactory.getLogger( EWInterfaceUtils.class); + @Autowired + private RestTemplate restTemplate; + @Value("${so.host}") + private String soHostname; + + @Value("${so.api.id}") + private String soApiId; + + @Value("${so.header.authorization}") + private String soHeaderAuthorization; + + private static final String HEADER_AUTHORIZATION = "Authorization"; + private static final String X_FROM_APP_ID = "X-FromAppId"; + + + public ResponseEntity callPostRequestTarget(Object obj, String targetUrl) { + + try { + ResponseEntity response = restTemplate.exchange(targetUrl, HttpMethod.POST, + new HttpEntity<>(obj, buildRequestHeader()), Object.class); + + logResponseGet(targetUrl, response); + if (null == response) { + return null; + } else { + return response; + } + + } catch (BackendFunctionalException | ResourceAccessException e) { + LOGGER.error(ERROR_ON_CALLING + " ," + e.getMessage()); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } + + + public ResponseEntity callGetRequestTarget(String targetUrl) { + try { + ResponseEntity response = restTemplate.exchange(targetUrl, HttpMethod.GET, + new HttpEntity<>(buildRequestHeader()), Object.class); + LOGGER.info("response status : {}", targetUrl); + logResponseGet(targetUrl, response); + if (null == response) { + return null; + } else { + return response; + } + + } catch (BackendFunctionalException | ResourceAccessException e) { + LOGGER.error(ERROR_ON_CALLING + targetUrl + " ," + e); + return null; + } + } + + public ResponseEntity callDeleteRequestTarget(String targetUrl) { + try { + ResponseEntity response = restTemplate.exchange(targetUrl, HttpMethod.DELETE, + new HttpEntity<>(buildRequestHeader()), Object.class); + LOGGER.info("response status ewhost : {}", targetUrl); + + if (null == response) { + return null; + } else { + return response; + } + + } catch (BackendFunctionalException | ResourceAccessException e) { + LOGGER.error(ERROR_ON_CALLING + targetUrl + " ," + e); + return null; + } + } + private void logResponseGet(String url, ResponseEntity response) { + if (response != null) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("response body : {}", response.getBody().toString()); + } + if (LOGGER.isWarnEnabled() && !response.getStatusCode().equals( HttpStatus.OK)) { + LOGGER.warn("HTTP call EWInterface on {} returns {} , {}", url, response.getStatusCodeValue(), + response.getBody().toString()); + } + } else { + LOGGER.info("no response calling url {}", url); + } + } + + private HttpHeaders buildRequestHeader() { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add(HEADER_AUTHORIZATION, soHeaderAuthorization); + httpHeaders.add(X_FROM_APP_ID, soApiId); + httpHeaders.add("Accept", "application/json"); + httpHeaders.add("Content-Type", "application/json"); + return httpHeaders; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 5b908b3..f290102 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -25,6 +25,7 @@ nbi.version = v4 # SERVER server.servlet.context-path = /nbi/api/${nbi.version} server.port = 8080 +server.public.ip = localhost # LOGGING logging.level. = WARN @@ -40,11 +41,9 @@ onap.cloudOwner = CloudOwner # NBI nbi.url = http://localhost:${server.port}${server.servlet.context-path} +nbi.public.url = http://${server.public.ip}:${server.port}${server.servlet.context-path} nbi.callForVNF = false -# External NBI -external.nbi.url = http://{targetUrl}:${server.port}${server.servlet.context-path} - # SCHEDULER scheduler.pollingDurationInMins = 360 serviceOrder.schedule = 5000 diff --git a/src/test/resources/karatetest/data/Event.json b/src/test/resources/karatetest/data/Event.json deleted file mode 100644 index 5887deb..0000000 --- a/src/test/resources/karatetest/data/Event.json +++ /dev/null @@ -1,13 +0,0 @@ -[{ - "eventType": "ServiceOrderStateChangeNotification", - "eventDate": "2019-03-27T14:58:32.740Z", - "eventId": "12345", - "event": { - "id": "testEventId", - "href": "www.testHref.com", - "externalId": "testExternalId", - "state": "acknowledged", - "orderDate": "2019-03-27T04:58:32.740Z" - - } -}] \ No newline at end of file diff --git a/src/test/resources/karatetest/data/subscriber.json b/src/test/resources/karatetest/data/subscriber.json index 14dfdb8..5fceb9f 100644 --- a/src/test/resources/karatetest/data/subscriber.json +++ b/src/test/resources/karatetest/data/subscriber.json @@ -11,9 +11,5 @@ { "callback": "http://localhost/test", "query": "eventType=ServiceOrderItemStateChangeNotification" - }, - { - "callback": "http://localhost:8080/nbi/api/v4/test/listener", - "query": "eventType=ServiceOrderStateChangeNotification" } ] \ No newline at end of file diff --git a/src/test/resources/karatetest/features/02--ServiceOrder.feature b/src/test/resources/karatetest/features/02--ServiceOrder.feature index 756a00e..4b4891d 100644 --- a/src/test/resources/karatetest/features/02--ServiceOrder.feature +++ b/src/test/resources/karatetest/features/02--ServiceOrder.feature @@ -359,6 +359,19 @@ Given path 'serviceOrder',serviceOrderId16 When method delete Then status 204 +Scenario: testCheckServiceOrderWithTargetHeader +Given path 'serviceOrder' +And header Target = 'http://localhost:8080/nbi/api/v4' +And request data[0] +When method post +Then status 201 +And match $.id contains '#notnull' +And match $.state == 'acknowledged' +And def serviceOrderId = $.id +Given path 'serviceOrder',serviceOrderId +And header Target = 'http://localhost:8080/nbi/api/v4' +When method get +Then status 200 Scenario: testCheckServiceOrderWithCustomerAAINotResponding * call Context.removeWireMockMapping("/aai/v14/business/customers/customer/new"); @@ -436,17 +449,3 @@ Given path 'serviceOrder',serviceOrderId When method get Then status 200 * call Context.startServers(); - -Scenario: testCheckServiceOrderWithTargetURLPresent -Given path 'serviceOrder' -And header targetURL = '127.0.0.1' -And request data[0] -When method post -Then status 201 -And match $.id contains '#notnull' -And match $.state == 'acknowledged' -And def serviceOrderId = $.id -Given path 'serviceOrder', serviceOrderId -And header targetURL = '127.0.0.1' -When method get -Then status 200 \ No newline at end of file diff --git a/src/test/resources/karatetest/features/03--Subscriber.feature b/src/test/resources/karatetest/features/03--Subscriber.feature index ea8c24a..1d9bfdf 100644 --- a/src/test/resources/karatetest/features/03--Subscriber.feature +++ b/src/test/resources/karatetest/features/03--Subscriber.feature @@ -9,7 +9,6 @@ Background: * call Context.startServers(); * def data = read('../data/subscriber.json') * def serviceOrderData = read('../data/serviceOrder.json') -* def eventData = read('../data/Event.json') * configure retry = { count: 10, interval: 500 } * def checkDateFormat = """ @@ -250,38 +249,3 @@ Then status 204 Given path 'test/listener',eventId When method delete Then status 204 - - -Scenario: testHubAndListenerResourceWhenTargetURLIsPresent -Given path 'hub' -And header targetURL = '127.0.0.1' -And request data[3] -When method post -Then status 201 -And def location = responseHeaders['Location'][0] -Given path "listener" -And request eventData[0] -When method post -Then status 200 -Given path "test/listener/12345" -When method get -Then status 200 -And match $ contains -""" -{ - "eventType": "ServiceOrderStateChangeNotification", - "eventDate": "2019-03-27T14:58:32.740Z", - "eventId": "12345", - "event": { - "id": "testEventId", - "href": "www.testHref.com", - "externalId": "testExternalId", - "state": "acknowledged", - "orderDate": "2019-03-27T04:58:32.740Z" - - } -} -""" -Given url location -When method delete -Then status 204 diff --git a/src/test/resources/karatetest/features/05--ListenerResourceTestTarget.feature b/src/test/resources/karatetest/features/05--ListenerResourceTestTarget.feature new file mode 100644 index 0000000..a42f9b7 --- /dev/null +++ b/src/test/resources/karatetest/features/05--ListenerResourceTestTarget.feature @@ -0,0 +1,74 @@ +# new feature +# Tags: optional + +Feature: Listener + +Background: +* url nbiBaseUrl +* def Context = Java.type('org.onap.nbi.test.Context'); +* call Context.startServers(); +* def data = read('../data/subscriber.json') +* def serviceOrderData = read('../data/serviceOrder.json') +* configure retry = { count: 10, interval: 500 } +* def checkDateFormat = +""" +function(s) { + var SimpleDateFormat = Java.type("java.text.SimpleDateFormat"); + var sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + return sdf.parse(s); +} +""" + +Scenario: testcreateEventSubscription +Given path 'hub' +And header Target = 'http://localhost:8080/nbi/api/v4' +And request data[0] +When method post +Then status 201 +And def hubId = $.id +And header Target = 'http://localhost:8080/nbi/api/v4' +Given path 'hub',hubId +When method get +Then status 200 +And match hubId == $.id +Given path 'hub',hubId +And header Target = 'http://localhost:8080/nbi/api/v4' +When method delete +Then status 204 + +Scenario: testPostListenerResource +* def listenerUrl = nbiBaseUrl + "/test/listener" +Given path 'test/listener' +When method delete +Then status 204 +Given path 'hub' +And header Target = 'http://localhost:8080/nbi/api/v4' +And request { callback : '#(listenerUrl)' , query : 'eventType = ServiceOrderCreationNotification' } +When method post +Then status 201 +And def hubId = $.id +Given path 'serviceOrder' +And request serviceOrderData[17] +And header Target = 'http://localhost:8080/nbi/api/v4' +When method post +Then status 201 +And def serviceOrderId = $.id +Given path 'test/listener' +And params {serviceOrderId : '#(serviceOrderId)'} +And retry until responseStatus == 200 +When method get +And assert response.length == 1 +And match $[0] contains { eventId : '#notnull' , eventType : 'ServiceOrderCreationNotification' , eventDate : '#notnull' , event :'#notnull'} +And def eventId = $[0].eventId +And def eventDate = $[0].eventDate +And call checkDateFormat(eventDate) +Given path 'serviceOrder',serviceOrderId +When method delete +Then status 204 +Given path 'hub',hubId +And header Target = 'http://localhost:8080/nbi/api/v4' +When method delete +Then status 204 +Given path 'test/listener',eventId +When method delete +Then status 204 \ No newline at end of file -- cgit 1.2.3-korg