From 0b15d4c2f54bb0ac622a393f041f1eb8582c2268 Mon Sep 17 00:00:00 2001 From: "waqas.ikram" Date: Fri, 26 Jul 2019 16:38:09 +0000 Subject: [PATCH] Adding service instances endpoint supports Change-Id: I778d750fe68a88b10eacb9b447a2a96e670b181c Issue-ID: SO-1953 Signed-off-by: waqas.ikram --- .../so-simulators/aai-simulator/pom.xml | 10 + .../so/aai/simulator/AaiSimulatorApplication.java | 1 - .../configration/WebSecurityConfigImpl.java | 71 ++++++ .../controller/AaiSimulatorController.java | 1 + .../simulator/controller/BusinessController.java | 119 +++++++++-- ...viceProvider.java => CacheServiceProvider.java} | 13 +- .../providers/CacheServiceProviderImpl.java | 193 +++++++++++++++++ .../providers/CustomerServiceProviderImpl.java | 94 -------- .../org/onap/so/aai/simulator/utils/Constant.java | 2 +- .../src/main/resources/application.yaml | 14 +- .../controller/BusinessControllerTest.java | 237 +++++++++++++++++++-- .../test/resources/test-data/service-instance.json | 9 + 12 files changed, 634 insertions(+), 130 deletions(-) create mode 100644 plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/configration/WebSecurityConfigImpl.java rename plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/{CustomerServiceProvider.java => CacheServiceProvider.java} (69%) create mode 100644 plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CacheServiceProviderImpl.java delete mode 100644 plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CustomerServiceProviderImpl.java create mode 100644 plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/test/resources/test-data/service-instance.json diff --git a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/pom.xml b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/pom.xml index c7371ea6..97d4d7d7 100644 --- a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/pom.xml +++ b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/pom.xml @@ -22,6 +22,16 @@ com.fasterxml.jackson.module jackson-module-jaxb-annotations + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-tomcat + + + diff --git a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/AaiSimulatorApplication.java b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/AaiSimulatorApplication.java index 240ec8e5..26f52e32 100644 --- a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/AaiSimulatorApplication.java +++ b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/AaiSimulatorApplication.java @@ -35,5 +35,4 @@ public class AaiSimulatorApplication extends SpringBootServletInitializer { public static void main(final String[] args) { SpringApplication.run(AaiSimulatorApplication.class, args); } - } diff --git a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/configration/WebSecurityConfigImpl.java b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/configration/WebSecurityConfigImpl.java new file mode 100644 index 00000000..2e96b9fd --- /dev/null +++ b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/configration/WebSecurityConfigImpl.java @@ -0,0 +1,71 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.aai.simulator.configration; + +import org.onap.so.aai.simulator.utils.Constant; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +/** + * @author waqas.ikram@ericsson.com + * + */ +@Configuration +@EnableWebSecurity +public class WebSecurityConfigImpl extends WebSecurityConfigurerAdapter { + + private final String username; + private final String password; + private final String role; + + public WebSecurityConfigImpl(@Value("${spring.security.username}") final String username, + @Value("${spring.security.password}") final String password, + @Value("${spring.security.role}") final String role) { + this.username = username; + this.password = password; + this.role = role; + } + + + @Override + protected void configure(final HttpSecurity http) throws Exception { + http.csrf().disable().authorizeRequests().antMatchers(Constant.BUSINESS_URL + "/**/**").authenticated().and() + .httpBasic(); + } + + @Bean + public BCryptPasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Autowired + public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().passwordEncoder(passwordEncoder()).withUser(username).password(password) + .roles(role); + } + +} diff --git a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/controller/AaiSimulatorController.java b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/controller/AaiSimulatorController.java index e0184823..67cc34ff 100644 --- a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/controller/AaiSimulatorController.java +++ b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/controller/AaiSimulatorController.java @@ -20,6 +20,7 @@ package org.onap.so.aai.simulator.controller; import static org.onap.so.aai.simulator.utils.Constant.HEALTHY; +import javax.ws.rs.PathParam; import javax.ws.rs.core.MediaType; import org.onap.so.aai.simulator.utils.Constant; import org.slf4j.Logger; diff --git a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/controller/BusinessController.java b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/controller/BusinessController.java index 3b3c10e1..8f55d644 100644 --- a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/controller/BusinessController.java +++ b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/controller/BusinessController.java @@ -26,8 +26,10 @@ import java.util.Optional; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.MediaType; import org.onap.aai.domain.yang.Customer; +import org.onap.aai.domain.yang.ServiceInstance; +import org.onap.aai.domain.yang.ServiceInstances; import org.onap.aai.domain.yang.ServiceSubscription; -import org.onap.so.aai.simulator.service.providers.CustomerServiceProvider; +import org.onap.so.aai.simulator.service.providers.CacheServiceProvider; import org.onap.so.aai.simulator.utils.RequestErrorBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,6 +42,7 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; /** * @author waqas.ikram@ericsson.com @@ -50,11 +53,11 @@ import org.springframework.web.bind.annotation.RequestMapping; public class BusinessController { private static final Logger LOGGER = LoggerFactory.getLogger(BusinessController.class); - private final CustomerServiceProvider customerServiceProvider; + private final CacheServiceProvider cacheServiceProvider; @Autowired - public BusinessController(final CustomerServiceProvider customerServiceProvider) { - this.customerServiceProvider = customerServiceProvider; + public BusinessController(final CacheServiceProvider cacheServiceProvider) { + this.cacheServiceProvider = cacheServiceProvider; } @GetMapping(value = "/customers/customer/{global-customer-id}", @@ -63,7 +66,7 @@ public class BusinessController { final HttpServletRequest request) { LOGGER.info("Will retrieve customer for 'global customer id': {} ...", globalCustomerId); - final Optional optional = customerServiceProvider.getCustomer(globalCustomerId); + final Optional optional = cacheServiceProvider.getCustomer(globalCustomerId); if (optional.isPresent()) { final Customer customer = optional.get(); LOGGER.info("found customer {} in cache", customer); @@ -71,8 +74,7 @@ public class BusinessController { } LOGGER.error("Couldn't find {} in cache", globalCustomerId); - return new ResponseEntity<>(new RequestErrorBuilder().messageId(ERROR_MESSAGE_ID).text(ERROR_MESSAGE) - .variables(request.getMethod(), request.getRequestURI()).build(), HttpStatus.NOT_FOUND); + return getRequestErrorResponseEntity(request); } @PutMapping(value = "/customers/customer/{global-customer-id}", @@ -83,10 +85,10 @@ public class BusinessController { LOGGER.info("Will put customer for 'global customer id': {} ...", globalCustomerId); if (customer.getResourceVersion() == null || customer.getResourceVersion().isEmpty()) { - customer.setResourceVersion(System.currentTimeMillis() + ""); + customer.setResourceVersion(getResourceVersion()); } - customerServiceProvider.putCustomer(globalCustomerId, customer); + cacheServiceProvider.putCustomer(globalCustomerId, customer); return ResponseEntity.accepted().build(); } @@ -100,17 +102,108 @@ public class BusinessController { globalCustomerId, serviceType); final Optional optional = - customerServiceProvider.getServiceSubscription(globalCustomerId, serviceType); + cacheServiceProvider.getServiceSubscription(globalCustomerId, serviceType); if (optional.isPresent()) { final ServiceSubscription serviceSubscription = optional.get(); LOGGER.info("found service subscription {} in cache", serviceSubscription); return ResponseEntity.ok(serviceSubscription); } - LOGGER.error("Couldn't find {} in cache", globalCustomerId); - return new ResponseEntity<>(new RequestErrorBuilder().messageId(ERROR_MESSAGE_ID).text(ERROR_MESSAGE) - .variables(request.getMethod(), request.getRequestURI()).build(), HttpStatus.NOT_FOUND); + LOGGER.error("Couldn't find 'global customer id': {} and 'service type': {} in cache", globalCustomerId, + serviceType); + return getRequestErrorResponseEntity(request); + } + + @GetMapping( + value = "/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances", + produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public ResponseEntity getSericeInstances(@PathVariable("global-customer-id") final String globalCustomerId, + @PathVariable("service-type") final String serviceType, + @RequestParam(name = "service-instance-name") final String serviceInstanceName, + @RequestParam(name = "depth", required = false) final Integer depth, final HttpServletRequest request) { + + LOGGER.info( + "Will retrieve service instances for 'global customer id': {}, 'service type': {} and 'service instance name: '{} with depth: {}...", + globalCustomerId, serviceType, serviceInstanceName, depth); + + final Optional optional = + cacheServiceProvider.getServiceInstances(globalCustomerId, serviceType, serviceInstanceName); + if (optional.isPresent()) { + final ServiceInstances serviceInstances = optional.get(); + LOGGER.info("found service instance {} in cache", serviceInstances); + return ResponseEntity.ok(serviceInstances); + } + LOGGER.error( + "Couldn't find 'global customer id': {}, 'service type': {} and 'service instance name': {} with depth: {} in cache", + globalCustomerId, serviceType, serviceInstanceName, depth); + return getRequestErrorResponseEntity(request); + } + + @GetMapping( + value = "/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}", + produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public ResponseEntity getSericeInstance(@PathVariable("global-customer-id") final String globalCustomerId, + @PathVariable("service-type") final String serviceType, + @PathVariable(name = "service-instance-id") final String serviceInstanceId, + @RequestParam(name = "depth", required = false) final Integer depth, + @RequestParam(name = "resultIndex", required = false) final Integer resultIndex, + @RequestParam(name = "resultSize", required = false) final Integer resultSize, + @RequestParam(name = "format", required = false) final String format, final HttpServletRequest request) { + + LOGGER.info( + "Will retrieve service instances for 'global customer id': {}, 'service type': {} and 'service instance id: '{} with depth: {}, resultIndex:{}, resultSize: {} and format: {}...", + globalCustomerId, serviceType, serviceInstanceId, depth, resultIndex, resultSize, format); + + final Optional optional = + cacheServiceProvider.getServiceInstance(globalCustomerId, serviceType, serviceInstanceId); + if (optional.isPresent()) { + final ServiceInstance serviceInstance = optional.get(); + LOGGER.info("found service instance {} in cache", serviceInstance); + return ResponseEntity.ok(serviceInstance); + } + LOGGER.error( + "Couldn't find 'global customer id': {}, 'service type': {} and 'service instance id': {} with depth: {}, resultIndex:{}, resultSize: {} and format: {} in cache", + globalCustomerId, serviceType, serviceInstanceId, depth, resultIndex, resultSize, format); + return getRequestErrorResponseEntity(request); } + @PutMapping( + value = "/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}", + produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public ResponseEntity putSericeInstance(@PathVariable("global-customer-id") final String globalCustomerId, + @PathVariable("service-type") final String serviceType, + @PathVariable(name = "service-instance-id") final String serviceInstanceId, + @RequestBody final ServiceInstance serviceInstance, final HttpServletRequest request) { + + LOGGER.info( + "Will add service instance for 'global customer id': {}, 'service type': {} and 'service instance id: '{} ...", + globalCustomerId, serviceType, serviceInstanceId); + + if (serviceInstance.getResourceVersion() == null || serviceInstance.getResourceVersion().isEmpty()) { + serviceInstance.setResourceVersion(getResourceVersion()); + } + + if (cacheServiceProvider.putServiceInstance(globalCustomerId, serviceType, serviceInstanceId, + serviceInstance)) { + ResponseEntity.accepted().build(); + } + + LOGGER.error( + "Couldn't add 'global customer id': {}, 'service type': {} and 'service instance id': {} with depth: {}, resultIndex:{}, resultSize: {} and format: {} to cache", + globalCustomerId, serviceType, serviceInstanceId); + return getRequestErrorResponseEntity(request); + } + + private String getResourceVersion() { + return System.currentTimeMillis() + ""; + } + + private ResponseEntity getRequestErrorResponseEntity(final HttpServletRequest request) { + return new ResponseEntity<>(new RequestErrorBuilder().messageId(ERROR_MESSAGE_ID).text(ERROR_MESSAGE) + .variables(request.getMethod(), request.getRequestURI(), + "Node Not Found:No Node of type service-instance found at: " + request.getRequestURI(), + "ERR.5.4.6114") + .build(), HttpStatus.NOT_FOUND); + } } diff --git a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CustomerServiceProvider.java b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CacheServiceProvider.java similarity index 69% rename from plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CustomerServiceProvider.java rename to plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CacheServiceProvider.java index 7f549f0b..ca0340c6 100644 --- a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CustomerServiceProvider.java +++ b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CacheServiceProvider.java @@ -21,13 +21,15 @@ package org.onap.so.aai.simulator.service.providers; import java.util.Optional; import org.onap.aai.domain.yang.Customer; +import org.onap.aai.domain.yang.ServiceInstance; +import org.onap.aai.domain.yang.ServiceInstances; import org.onap.aai.domain.yang.ServiceSubscription; /** * @author waqas.ikram@ericsson.com * */ -public interface CustomerServiceProvider { +public interface CacheServiceProvider { Optional getCustomer(final String globalCustomerId); @@ -35,6 +37,15 @@ public interface CustomerServiceProvider { Optional getServiceSubscription(final String globalCustomerId, final String serviceType); + Optional getServiceInstances(final String globalCustomerId, final String serviceType, + final String serviceInstanceName); + + Optional getServiceInstance(final String globalCustomerId, final String serviceType, + final String serviceInstanceId); + + boolean putServiceInstance(final String globalCustomerId, final String serviceType, final String serviceInstanceId, + final ServiceInstance serviceInstance); + void clearAll(); } diff --git a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CacheServiceProviderImpl.java b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CacheServiceProviderImpl.java new file mode 100644 index 00000000..5c55824d --- /dev/null +++ b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CacheServiceProviderImpl.java @@ -0,0 +1,193 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.so.aai.simulator.service.providers; + +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import org.onap.aai.domain.yang.Customer; +import org.onap.aai.domain.yang.ServiceInstance; +import org.onap.aai.domain.yang.ServiceInstances; +import org.onap.aai.domain.yang.ServiceSubscription; +import org.onap.so.aai.simulator.utils.Constant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.stereotype.Service; + +/** + * @author waqas.ikram@ericsson.com + * + */ +@Service +public class CacheServiceProviderImpl implements CacheServiceProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(CacheServiceProviderImpl.class); + + public final CacheManager cacheManager; + + @Autowired + public CacheServiceProviderImpl(final CacheManager cacheManager) { + this.cacheManager = cacheManager; + } + + @Override + public Optional getCustomer(final String globalCustomerId) { + LOGGER.info("getting customer from cache using key: {}", globalCustomerId); + final Cache cache = cacheManager.getCache(Constant.CUSTOMER_CACHE); + final Customer value = cache.get(globalCustomerId, Customer.class); + if (value != null) { + return Optional.of(value); + } + return Optional.empty(); + } + + @Override + public void putCustomer(final String globalCustomerId, final Customer customer) { + LOGGER.info("Adding customer: {} with key: {} in cache ...", customer, globalCustomerId); + final Cache cache = cacheManager.getCache(Constant.CUSTOMER_CACHE); + + cache.put(globalCustomerId, customer); + } + + @Override + public Optional getServiceSubscription(final String globalCustomerId, + final String serviceType) { + LOGGER.info("getting service subscription from cache for globalCustomerId: {} and serviceType: {}", + globalCustomerId, serviceType); + + final Cache cache = cacheManager.getCache(Constant.CUSTOMER_CACHE); + + final Customer value = cache.get(globalCustomerId, Customer.class); + + if (value != null) { + return Optional.ofNullable(value.getServiceSubscriptions().getServiceSubscription().stream() + .filter(s -> serviceType.equals(s.getServiceType())).findFirst().orElse(null)); + } + return Optional.empty(); + + } + + @Override + public Optional getServiceInstances(final String globalCustomerId, final String serviceType, + final String serviceInstanceName) { + + final Cache cache = cacheManager.getCache(Constant.CUSTOMER_CACHE); + final Customer value = cache.get(globalCustomerId, Customer.class); + + if (value != null) { + final Optional serviceSubscription = value.getServiceSubscriptions() + .getServiceSubscription().stream().filter(s -> serviceType.equals(s.getServiceType())).findFirst(); + + if (serviceSubscription.isPresent()) { + LOGGER.info("Found service subscription ..."); + final List serviceInstancesList = serviceSubscription.get().getServiceInstances() + .getServiceInstance().stream() + .filter(serviceInstance -> serviceInstanceName.equals(serviceInstance.getServiceInstanceName())) + .collect(Collectors.toList()); + if (serviceInstancesList != null && !serviceInstancesList.isEmpty()) { + LOGGER.info("Found {} service instances ", serviceInstancesList.size()); + final ServiceInstances serviceInstances = new ServiceInstances(); + serviceInstances.getServiceInstance().addAll(serviceInstancesList); + return Optional.of(serviceInstances); + + } + } + } + return Optional.empty(); + } + + @Override + public Optional getServiceInstance(final String globalCustomerId, final String serviceType, + final String serviceInstanceId) { + final Cache cache = cacheManager.getCache(Constant.CUSTOMER_CACHE); + final Customer value = cache.get(globalCustomerId, Customer.class); + + if (value != null) { + final Optional serviceSubscription = value.getServiceSubscriptions() + .getServiceSubscription().stream().filter(s -> serviceType.equals(s.getServiceType())).findFirst(); + + if (serviceSubscription.isPresent()) { + LOGGER.info("Found service subscription ..."); + final ServiceInstances serviceInstances = serviceSubscription.get().getServiceInstances(); + if (serviceInstances != null) { + return Optional.ofNullable(serviceInstances.getServiceInstance().stream() + .filter(serviceInstance -> serviceInstanceId.equals(serviceInstance.getServiceInstanceId())) + .findFirst().orElse(null)); + } + + } + } + return Optional.empty(); + } + + @Override + public boolean putServiceInstance(final String globalCustomerId, final String serviceType, + final String serviceInstanceId, final ServiceInstance serviceInstance) { + LOGGER.info("Adding serviceInstance: {} in cache ...", serviceInstance, globalCustomerId); + + final Cache cache = cacheManager.getCache(Constant.CUSTOMER_CACHE); + final Customer value = cache.get(globalCustomerId, Customer.class); + + if (value != null) { + final Optional serviceSubscription = value.getServiceSubscriptions() + .getServiceSubscription().stream().filter(s -> serviceType.equals(s.getServiceType())).findFirst(); + + if (serviceSubscription.isPresent()) { + final ServiceInstances serviceInstances = getServiceInstances(serviceSubscription); + + + if (!serviceInstances.getServiceInstance().stream() + .filter(existing -> serviceInstanceId.equals(existing.getServiceInstanceId())).findFirst() + .isPresent()) { + return serviceInstances.getServiceInstance().add(serviceInstance); + } + LOGGER.error("Service {} already exists ....", serviceInstanceId); + return false; + } + LOGGER.error("Couldn't find service subscription with serviceType: {} in cache ", serviceType); + return false; + } + LOGGER.error("Couldn't find Customer with key: {} in cache ", globalCustomerId); + return false; + } + + private ServiceInstances getServiceInstances(final Optional optional) { + final ServiceSubscription serviceSubscription = optional.get(); + final ServiceInstances serviceInstances = serviceSubscription.getServiceInstances(); + if (serviceInstances == null) { + final ServiceInstances instances = new ServiceInstances(); + serviceSubscription.setServiceInstances(instances); + return instances; + } + return serviceInstances; + } + + @Override + public void clearAll() { + final Cache cache = cacheManager.getCache(Constant.CUSTOMER_CACHE); + final ConcurrentHashMap nativeCache = (ConcurrentHashMap) cache.getNativeCache(); + LOGGER.info("Clear all entries from cahce: {}", cache.getName()); + nativeCache.clear(); + } + +} diff --git a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CustomerServiceProviderImpl.java b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CustomerServiceProviderImpl.java deleted file mode 100644 index 42a09e44..00000000 --- a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/service/providers/CustomerServiceProviderImpl.java +++ /dev/null @@ -1,94 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2019 Nordix Foundation. - * ================================================================================ - * 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. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ -package org.onap.so.aai.simulator.service.providers; - -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import org.onap.aai.domain.yang.Customer; -import org.onap.aai.domain.yang.ServiceSubscription; -import org.onap.so.aai.simulator.utils.Constant; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.Cache; -import org.springframework.cache.CacheManager; -import org.springframework.stereotype.Service; - -/** - * @author waqas.ikram@ericsson.com - * - */ -@Service -public class CustomerServiceProviderImpl implements CustomerServiceProvider { - private static final Logger LOGGER = LoggerFactory.getLogger(CustomerServiceProviderImpl.class); - - public final CacheManager cacheManager; - - @Autowired - public CustomerServiceProviderImpl(final CacheManager cacheManager) { - this.cacheManager = cacheManager; - } - - @Override - public Optional getCustomer(final String globalCustomerId) { - LOGGER.info("getting customer from cache using key: {}", globalCustomerId); - final Cache cache = cacheManager.getCache(Constant.CUSTOMER_CACHE); - final Customer value = cache.get(globalCustomerId, Customer.class); - if (value != null) { - return Optional.of(value); - } - return Optional.empty(); - } - - @Override - public void putCustomer(final String globalCustomerId, final Customer customer) { - LOGGER.info("Adding customer: {} with key: {} in cache ...", customer, globalCustomerId); - final Cache cache = cacheManager.getCache(Constant.CUSTOMER_CACHE); - - cache.put(globalCustomerId, customer); - } - - @Override - public Optional getServiceSubscription(final String globalCustomerId, - final String serviceType) { - LOGGER.info("getting service subscription from cache for globalCustomerId: {} and serviceType: {}", - globalCustomerId, serviceType); - - final Cache cache = cacheManager.getCache(Constant.CUSTOMER_CACHE); - - final Customer value = cache.get(globalCustomerId, Customer.class); - - if (value != null) { - return Optional.ofNullable(value.getServiceSubscriptions().getServiceSubscription().stream() - .filter(s -> serviceType.equals(s.getServiceType())).findFirst().orElse(null)); - } - return Optional.empty(); - - } - - @Override - public void clearAll() { - final Cache cache = cacheManager.getCache(Constant.CUSTOMER_CACHE); - final ConcurrentHashMap nativeCache = (ConcurrentHashMap) cache.getNativeCache(); - LOGGER.info("Clear all entries from cahce: {}", cache.getName()); - nativeCache.clear(); - } - -} diff --git a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/utils/Constant.java b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/utils/Constant.java index 71a89597..5a85be16 100644 --- a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/utils/Constant.java +++ b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/java/org/onap/so/aai/simulator/utils/Constant.java @@ -25,7 +25,7 @@ package org.onap.so.aai.simulator.utils; */ public class Constant { - public static final String BASE_URL = "/simulator/aai"; + public static final String BASE_URL = "/simulator/aai/v15/"; public static final String BUSINESS_URL = BASE_URL + "/business/"; diff --git a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/resources/application.yaml b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/resources/application.yaml index 69f46eab..f0d7ba76 100644 --- a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/resources/application.yaml +++ b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/main/resources/application.yaml @@ -1,5 +1,13 @@ server: - port: 9993 - tomcat: - max-threads: 4 + port: 9993 + tomcat: + max-threads: 4 ssl-enable: false + +spring: + security: + username: aai + #password: aai.onap.org:demo123456! + password: $2a$04$crRntT01fAF4kb48mxlvgu68/silcLg.czC1LxQsKTdWuDBPpO3YO + role: VID + \ No newline at end of file diff --git a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/test/java/org/onap/so/aai/simulator/controller/BusinessControllerTest.java b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/test/java/org/onap/so/aai/simulator/controller/BusinessControllerTest.java index 3d856844..d317e6b6 100644 --- a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/test/java/org/onap/so/aai/simulator/controller/BusinessControllerTest.java +++ b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/test/java/org/onap/so/aai/simulator/controller/BusinessControllerTest.java @@ -25,16 +25,22 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; +import java.util.Base64; +import java.util.Optional; +import java.util.UUID; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.onap.aai.domain.yang.Customer; +import org.onap.aai.domain.yang.ServiceInstance; +import org.onap.aai.domain.yang.ServiceInstances; import org.onap.aai.domain.yang.ServiceSubscription; -import org.onap.so.aai.simulator.service.providers.CustomerServiceProvider; +import org.onap.so.aai.simulator.service.providers.CacheServiceProvider; import org.onap.so.aai.simulator.utils.Constant; import org.onap.so.aai.simulator.utils.RequestError; import org.onap.so.aai.simulator.utils.ServiceException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -42,6 +48,7 @@ import org.springframework.boot.web.server.LocalServerPort; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -60,42 +67,61 @@ import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; @Configuration public class BusinessControllerTest { + private static final String SERVICE_INSTANCES_URL = "/service-instances"; + + private static final String SERVICE_NAME = "ServiceTest"; + + private static final String SERVICE_INSTANCE_ID = "ccece8fe-13da-456a-baf6-41b3a4a2bc2b"; + + private static final String SERVICE_INSTANCE_URL = + SERVICE_INSTANCES_URL + "/service-instance/" + SERVICE_INSTANCE_ID; + private static final String SERVICE_TYPE = "vCPE"; + private static final String SERVICE_SUBSCRIPTIONS_URL = + "/service-subscriptions/service-subscription/" + SERVICE_TYPE; + private static final String GLOBAL_CUSTOMER_ID = "DemoCustomer"; + private static final String CUSTOMERS_URL = Constant.BUSINESS_URL + "customers/customer/" + GLOBAL_CUSTOMER_ID; + + private static final String PASSWORD = "aai.onap.org:demo123456!"; + @LocalServerPort private int port; @Autowired private TestRestTemplate restTemplate; + @Value("${spring.security.username}") + private String username; + @Autowired - private CustomerServiceProvider customerServiceProvider; + private CacheServiceProvider cacheServiceProvider; @After public void after() { - customerServiceProvider.clearAll(); + cacheServiceProvider.clearAll(); } @Test public void test_putCustomer_successfullyAddedToCache() throws Exception { final Customer customer = getCustomer(getFile("test-data/business-customer.json")); - final String url = getBaseUrl() + "/customers/customer/" + GLOBAL_CUSTOMER_ID; - final ResponseEntity actual = invokeHttpPut(url, customer); + final ResponseEntity actual = invokeHttpPut(getCustomerEndPointUrl(), customer); assertEquals(HttpStatus.ACCEPTED, actual.getStatusCode()); - assertTrue(customerServiceProvider.getCustomer(GLOBAL_CUSTOMER_ID).isPresent()); + assertTrue(cacheServiceProvider.getCustomer(GLOBAL_CUSTOMER_ID).isPresent()); } @Test public void test_getCustomer_ableToRetrieveCustomer() throws Exception { final Customer customer = getCustomer(getFile("test-data/business-customer.json")); - final String url = getBaseUrl() + "/customers/customer/" + GLOBAL_CUSTOMER_ID; + final String url = getCustomerEndPointUrl(); invokeHttpPut(url, customer); - final ResponseEntity actual = restTemplate.getForEntity(url, Customer.class); + final ResponseEntity actual = + restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(getHttpHeaders()), Customer.class); assertEquals(HttpStatus.OK, actual.getStatusCode()); assertTrue(actual.hasBody()); @@ -108,9 +134,10 @@ public class BusinessControllerTest { @Test public void test_getCustomer_returnRequestError_ifCustomerNotInCache() throws Exception { - final String url = getBaseUrl() + "/customers/customer/" + GLOBAL_CUSTOMER_ID; + final String url = getCustomerEndPointUrl(); - final ResponseEntity actual = restTemplate.getForEntity(url, RequestError.class); + final ResponseEntity actual = + restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(getHttpHeaders()), RequestError.class); assertEquals(HttpStatus.NOT_FOUND, actual.getStatusCode()); @@ -127,12 +154,12 @@ public class BusinessControllerTest { @Test public void test_getServiceSubscription_ableToRetrieveServiceSubscriptionFromCache() throws Exception { final Customer customer = getCustomer(getFile("test-data/business-customer.json")); - final String customerUrl = getBaseUrl() + "/customers/customer/" + GLOBAL_CUSTOMER_ID; - final String url = customerUrl + "/service-subscriptions/service-subscription/" + SERVICE_TYPE; + final String url = getCustomerEndPointUrl() + SERVICE_SUBSCRIPTIONS_URL; - invokeHttpPut(customerUrl, customer); + invokeHttpPut(getCustomerEndPointUrl(), customer); - final ResponseEntity actual = restTemplate.getForEntity(url, ServiceSubscription.class); + final ResponseEntity actual = restTemplate.exchange(url, HttpMethod.GET, + new HttpEntity<>(getHttpHeaders()), ServiceSubscription.class); assertEquals(HttpStatus.OK, actual.getStatusCode()); assertTrue(actual.hasBody()); @@ -143,8 +170,176 @@ public class BusinessControllerTest { assertFalse(actualServiceSubscription.getRelationshipList().getRelationship().isEmpty()); } + @Test + public void test_putSericeInstance_ableToRetrieveServiceInstanceFromCache() throws Exception { + final Customer customer = getCustomer(getFile("test-data/business-customer.json")); + + final String url = getCustomerEndPointUrl() + SERVICE_SUBSCRIPTIONS_URL + SERVICE_INSTANCE_URL; + + final ResponseEntity response = invokeHttpPut(getCustomerEndPointUrl(), customer); + + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + + final ServiceInstance serviceInstance = + getObjectFromFile(getFile("test-data/service-instance.json"), ServiceInstance.class); + + invokeHttpPut(url, serviceInstance); + + final Optional actual = + cacheServiceProvider.getServiceInstance(GLOBAL_CUSTOMER_ID, SERVICE_TYPE, SERVICE_INSTANCE_ID); + + assertTrue(actual.isPresent()); + final ServiceInstance actualServiceInstance = actual.get(); + + assertEquals(SERVICE_INSTANCE_ID, actualServiceInstance.getServiceInstanceId()); + assertEquals(SERVICE_NAME, actualServiceInstance.getServiceInstanceName()); + + } + + @Test + public void test_getSericeInstance_usingServiceInstanceName_ableToRetrieveServiceInstanceFromCache() + throws Exception { + final Customer customer = getCustomer(getFile("test-data/business-customer.json")); + + final String url = getCustomerEndPointUrl() + SERVICE_SUBSCRIPTIONS_URL + SERVICE_INSTANCE_URL; + + final ResponseEntity response = invokeHttpPut(getCustomerEndPointUrl(), customer); + + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + + final ServiceInstance serviceInstance = + getObjectFromFile(getFile("test-data/service-instance.json"), ServiceInstance.class); + + invokeHttpPut(url, serviceInstance); + + final String serviceInstanceUrl = getCustomerEndPointUrl() + SERVICE_SUBSCRIPTIONS_URL + SERVICE_INSTANCES_URL + + "?service-instance-name=" + SERVICE_NAME; + + final ResponseEntity actual = restTemplate.exchange(serviceInstanceUrl, HttpMethod.GET, + new HttpEntity<>(getHttpHeaders()), ServiceInstances.class); + + assertEquals(HttpStatus.OK, actual.getStatusCode()); + assertTrue(actual.hasBody()); + + final ServiceInstances actualServiceInstances = actual.getBody(); + assertFalse(actualServiceInstances.getServiceInstance().isEmpty()); + + assertEquals(SERVICE_NAME, actualServiceInstances.getServiceInstance().get(0).getServiceInstanceName()); + + } + + @Test + public void test_getSericeInstance_usingServiceInstanceId_ableToRetrieveServiceInstanceFromCache() + throws Exception { + final Customer customer = getCustomer(getFile("test-data/business-customer.json")); + + final String url = getCustomerEndPointUrl() + SERVICE_SUBSCRIPTIONS_URL + SERVICE_INSTANCE_URL; + + final ResponseEntity response = invokeHttpPut(getCustomerEndPointUrl(), customer); + + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + + final ServiceInstance serviceInstance = + getObjectFromFile(getFile("test-data/service-instance.json"), ServiceInstance.class); + + invokeHttpPut(url, serviceInstance); + + final ResponseEntity actual = + restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(getHttpHeaders()), ServiceInstance.class); + + assertEquals(HttpStatus.OK, actual.getStatusCode()); + assertTrue(actual.hasBody()); + + final ServiceInstance actualServiceInstance = actual.getBody(); + + assertEquals(SERVICE_NAME, actualServiceInstance.getServiceInstanceName()); + assertEquals(SERVICE_INSTANCE_ID, actualServiceInstance.getServiceInstanceId()); + + } + + @Test + public void test_getSericeInstance_usinginvalidServiceInstanceId_shouldReturnError() throws Exception { + final Customer customer = getCustomer(getFile("test-data/business-customer.json")); + + final String url = getCustomerEndPointUrl() + SERVICE_SUBSCRIPTIONS_URL + SERVICE_INSTANCE_URL; + + final ResponseEntity response = invokeHttpPut(getCustomerEndPointUrl(), customer); + + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + + final ServiceInstance serviceInstance = + getObjectFromFile(getFile("test-data/service-instance.json"), ServiceInstance.class); + + invokeHttpPut(url, serviceInstance); + + String invalidServiceInstanceUrl = getCustomerEndPointUrl() + SERVICE_SUBSCRIPTIONS_URL + SERVICE_INSTANCES_URL + + "/service-instance/" + UUID.randomUUID(); + + final ResponseEntity actual = restTemplate.exchange(invalidServiceInstanceUrl, HttpMethod.GET, + new HttpEntity<>(getHttpHeaders()), RequestError.class); + + assertEquals(HttpStatus.NOT_FOUND, actual.getStatusCode()); + + final RequestError actualError = actual.getBody(); + final ServiceException serviceException = actualError.getServiceException(); + + assertNotNull(serviceException); + assertEquals(Constant.ERROR_MESSAGE_ID, serviceException.getMessageId()); + assertEquals(Constant.ERROR_MESSAGE, serviceException.getText()); + assertTrue(serviceException.getVariables().contains(HttpMethod.GET.toString())); + + } + + @Test + public void test_getSericeInstance_usinginvalidServiceInstanceName_shouldReturnError() throws Exception { + final Customer customer = getCustomer(getFile("test-data/business-customer.json")); + + final String url = getCustomerEndPointUrl() + SERVICE_SUBSCRIPTIONS_URL + SERVICE_INSTANCE_URL; + + final ResponseEntity response = invokeHttpPut(getCustomerEndPointUrl(), customer); + + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + + final ServiceInstance serviceInstance = + getObjectFromFile(getFile("test-data/service-instance.json"), ServiceInstance.class); + + invokeHttpPut(url, serviceInstance); + + final String serviceInstanceUrl = getCustomerEndPointUrl() + SERVICE_SUBSCRIPTIONS_URL + SERVICE_INSTANCES_URL + + "?service-instance-name=Dummy&depth=2"; + + final ResponseEntity actual = restTemplate.exchange(serviceInstanceUrl, HttpMethod.GET, + new HttpEntity<>(getHttpHeaders()), RequestError.class); + + assertEquals(HttpStatus.NOT_FOUND, actual.getStatusCode()); + + final RequestError actualError = actual.getBody(); + final ServiceException serviceException = actualError.getServiceException(); + + assertNotNull(serviceException); + assertEquals(Constant.ERROR_MESSAGE_ID, serviceException.getMessageId()); + assertEquals(Constant.ERROR_MESSAGE, serviceException.getText()); + assertTrue(serviceException.getVariables().contains(HttpMethod.GET.toString())); + + } + + private String getCustomerEndPointUrl() { + return getBaseUrl() + CUSTOMERS_URL; + } + private ResponseEntity invokeHttpPut(final String url, final Object obj) { - return restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(obj), Void.class); + final HttpEntity httpEntity = getHttpEntity(obj); + return restTemplate.exchange(url, HttpMethod.PUT, httpEntity, Void.class); + } + + private HttpEntity getHttpEntity(final Object obj) { + return new HttpEntity<>(obj, getHttpHeaders()); + } + + private HttpHeaders getHttpHeaders() { + final HttpHeaders requestHeaders = new HttpHeaders(); + requestHeaders.add("Authorization", getBasicAuth()); + return requestHeaders; } private File getFile(final String file) throws IOException { @@ -152,14 +347,22 @@ public class BusinessControllerTest { } private Customer getCustomer(final File file) throws Exception { + return getObjectFromFile(file, Customer.class); + } + + private T getObjectFromFile(final File file, final Class clazz) throws Exception { final ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new JaxbAnnotationModule()); - return mapper.readValue(file, Customer.class); + return mapper.readValue(file, clazz); + } + + private String getBasicAuth() { + return "Basic " + new String(Base64.getEncoder().encodeToString((username + ":" + PASSWORD).getBytes())); } private String getBaseUrl() { - return "http://localhost:" + port + Constant.BUSINESS_URL; + return "http://localhost:" + port; } } diff --git a/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/test/resources/test-data/service-instance.json b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/test/resources/test-data/service-instance.json new file mode 100644 index 00000000..18ae8cb6 --- /dev/null +++ b/plans/so/integration-etsi-testing/so-simulators/aai-simulator/src/test/resources/test-data/service-instance.json @@ -0,0 +1,9 @@ +{ + "service-instance-id": "ccece8fe-13da-456a-baf6-41b3a4a2bc2b", + "service-instance-name": "ServiceTest", + "environment-context": "General_Revenue-Bearing", + "workload-context": "Production", + "model-invariant-id": "e9acd081-9c89-4b4d-bcb3-e0e2b9715b2a", + "model-version-id": "c112a499-6148-488b-ba82-3f5938cf26d2", + "orchestration-status": "Inventoried" +} -- 2.16.6