2  * ============LICENSE_START=======================================================
 
   3  *  Copyright (C) 2020 Nordix Foundation.
 
   4  * ================================================================================
 
   5  * Licensed under the Apache License, Version 2.0 (the "License");
 
   6  * you may not use this file except in compliance with the License.
 
   7  * You may obtain a copy of the License at
 
   9  *      http://www.apache.org/licenses/LICENSE-2.0
 
  11  * Unless required by applicable law or agreed to in writing, software
 
  12  * distributed under the License is distributed on an "AS IS" BASIS,
 
  13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  14  * See the License for the specific language governing permissions and
 
  15  * limitations under the License.
 
  17  * SPDX-License-Identifier: Apache-2.0
 
  18  * ============LICENSE_END=========================================================
 
  21 package org.onap.so.adapters.etsisol003adapter.pkgm.rest;
 
  23 import static org.hamcrest.Matchers.is;
 
  24 import static org.junit.Assert.assertEquals;
 
  25 import static org.junit.Assert.assertNotEquals;
 
  26 import static org.junit.Assert.assertNotNull;
 
  27 import static org.junit.Assert.assertNull;
 
  28 import static org.junit.Assert.assertThat;
 
  29 import static org.junit.Assert.assertTrue;
 
  30 import static org.onap.so.adapters.etsi.sol003.adapter.common.CommonConstants.ETSI_SUBSCRIPTION_NOTIFICATION_BASE_URL;
 
  31 import static org.onap.so.adapters.etsi.sol003.adapter.common.CommonConstants.PACKAGE_MANAGEMENT_BASE_URL;
 
  32 import static org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.EtsiCatalogServiceProviderConfiguration.ETSI_CATALOG_REST_TEMPLATE_BEAN;
 
  33 import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
 
  34 import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
 
  35 import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
 
  36 import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
 
  39 import java.net.URISyntaxException;
 
  40 import java.nio.file.Files;
 
  41 import java.nio.file.Paths;
 
  42 import java.security.GeneralSecurityException;
 
  43 import java.util.ArrayList;
 
  44 import java.util.List;
 
  45 import java.util.Objects;
 
  46 import java.util.UUID;
 
  47 import org.junit.After;
 
  48 import org.junit.Before;
 
  49 import org.junit.Test;
 
  50 import org.junit.runner.RunWith;
 
  51 import org.onap.so.adapters.etsisol003adapter.pkgm.PackageManagementConstants;
 
  52 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.BasicAuth;
 
  53 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.LinkSelf;
 
  54 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.NsdmSubscription;
 
  55 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.PkgmNotificationsFilter;
 
  56 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.PkgmSubscription;
 
  57 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.ProblemDetails;
 
  58 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.SubscriptionAuthentication;
 
  59 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.Version;
 
  60 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.VnfProducts;
 
  61 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.VnfProductsProviders;
 
  62 import org.onap.so.adapters.etsisol003adapter.pkgm.model.InlineResponse2002;
 
  63 import org.onap.so.adapters.etsisol003adapter.pkgm.model.InlineResponse201;
 
  64 import org.onap.so.adapters.etsisol003adapter.pkgm.model.PkgmSubscriptionRequest;
 
  65 import org.onap.so.adapters.etsisol003adapter.pkgm.model.SubscriptionsAuthentication;
 
  66 import org.onap.so.adapters.etsisol003adapter.pkgm.model.SubscriptionsFilter1;
 
  67 import org.onap.so.adapters.etsisol003adapter.pkgm.model.SubscriptionsFilterVnfProductsFromProviders;
 
  68 import org.onap.so.adapters.etsisol003adapter.pkgm.model.SubscriptionsLinks;
 
  69 import org.onap.so.adapters.etsisol003adapter.pkgm.model.VnfPackagesLinksSelf;
 
  70 import org.springframework.beans.factory.annotation.Autowired;
 
  71 import org.springframework.beans.factory.annotation.Qualifier;
 
  72 import org.springframework.boot.test.context.SpringBootTest;
 
  73 import org.springframework.boot.test.web.client.TestRestTemplate;
 
  74 import org.springframework.boot.web.server.LocalServerPort;
 
  75 import org.springframework.cache.Cache;
 
  76 import org.springframework.cache.CacheManager;
 
  77 import org.springframework.http.HttpHeaders;
 
  78 import org.springframework.http.HttpMethod;
 
  79 import org.springframework.http.HttpStatus;
 
  80 import org.springframework.http.MediaType;
 
  81 import org.springframework.http.ResponseEntity;
 
  82 import org.springframework.test.context.ActiveProfiles;
 
  83 import org.springframework.test.context.junit4.SpringRunner;
 
  84 import org.springframework.test.web.client.MockRestServiceServer;
 
  85 import org.springframework.test.web.client.match.MockRestRequestMatchers;
 
  86 import org.springframework.web.client.RestTemplate;
 
  87 import com.google.gson.Gson;
 
  90  * @author Ronan Kenny (ronan.kenny@est.tech)
 
  91  * @author Gareth Roper (gareth.roper@est.tech)
 
  93 @RunWith(SpringRunner.class)
 
  94 @SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
 
  95 @ActiveProfiles("test")
 
  96 public class Sol003PackageManagementSubscriptionControllerTest {
 
  98     private final Gson gson = new Gson();
 
  99     private final URI msbEndpoint = URI.create("http://msb-iag.onap:80/api/vnfpkgm/v1/subscriptions");
 
 100     private static final String _NOTIFICATION_CALLBACK_URI =
 
 101             "https://so-vnfm-adapter.onap:30406" + ETSI_SUBSCRIPTION_NOTIFICATION_BASE_URL;
 
 102     private static final String LOCALHOST_URL = "http://localhost:";
 
 105     @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN)
 
 106     private RestTemplate restTemplate;
 
 107     private MockRestServiceServer mockRestServiceServer;
 
 109     private CacheManager cacheServiceProvider;
 
 111     private Sol003PackageManagementSubscriptionController sol003PackageManagementSubscriptionController;
 
 114     private TestRestTemplate testRestTemplate;
 
 119     private static final String ID = UUID.randomUUID().toString();
 
 122     public void setUp() {
 
 123         mockRestServiceServer = MockRestServiceServer.bindTo(restTemplate).build();
 
 125                 cacheServiceProvider.getCache(PackageManagementConstants.PACKAGE_MANAGEMENT_SUBSCRIPTION_CACHE);
 
 130     public void after() {
 
 131         mockRestServiceServer.reset();
 
 135     public void testSuccessPostSubscription() throws GeneralSecurityException, URISyntaxException {
 
 136         final PkgmSubscriptionRequest pkgmSubscriptionRequest = postSubscriptionForTest();
 
 137         final ResponseEntity<InlineResponse201> response =
 
 138                 (ResponseEntity<InlineResponse201>) sol003PackageManagementSubscriptionController
 
 139                         .postSubscriptionRequest(pkgmSubscriptionRequest);
 
 141         final HttpHeaders headers = buildHttpHeaders(Objects.requireNonNull(response.getBody()).getCallbackUri());
 
 143         final SubscriptionsLinks subscriptionsLinks = new SubscriptionsLinks();
 
 144         final VnfPackagesLinksSelf vnfPackagesLinksSelf = new VnfPackagesLinksSelf();
 
 145         vnfPackagesLinksSelf.setHref("https://so-vnfm-adapter.onap:30406" + PACKAGE_MANAGEMENT_BASE_URL
 
 146                 + "/subscriptions/" + response.getBody().getId());
 
 147         subscriptionsLinks.setSelf(vnfPackagesLinksSelf);
 
 149         assertEquals(pkgmSubscriptionRequest.getFilter(), response.getBody().getFilter());
 
 150         assertEquals(subscriptionsLinks, response.getBody().getLinks());
 
 151         assertEquals(response.getBody().getFilter(), pkgmSubscriptionRequest.getFilter());
 
 152         assert (response.getHeaders().equals(headers));
 
 153         assertThat(response.getStatusCode(), is(HttpStatus.CREATED));
 
 154         assertNotNull(response.getBody().getCallbackUri());
 
 158     public void testFailPostSubscriptionAlreadyExists() throws GeneralSecurityException {
 
 159         final PkgmSubscriptionRequest pkgmSubscriptionRequest = postSubscriptionForTest();
 
 161         final ResponseEntity<InlineResponse2002> response =
 
 162                 (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
 
 163                         .postSubscriptionRequest(pkgmSubscriptionRequest);
 
 165         // Create duplicate entry
 
 166         final PkgmSubscriptionRequest pkgmSubscriptionRequest2 = buildPkgmSubscriptionRequest();
 
 168         final ResponseEntity<InlineResponse2002> response2002 =
 
 169                 (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
 
 170                         .postSubscriptionRequest(pkgmSubscriptionRequest2);
 
 172         assertEquals(HttpStatus.SEE_OTHER, response2002.getStatusCode());
 
 176     public void testSuccessGetSubscriptionWithSubscriptionId() throws GeneralSecurityException, URISyntaxException {
 
 178         final PkgmSubscriptionRequest pkgmSubscriptionRequest = postSubscriptionForTest();
 
 180         mockRestServiceServer.expect(requestTo(msbEndpoint + "/" + ID)).andExpect(method(HttpMethod.GET))
 
 181                 .andRespond(withSuccess(gson.toJson(new NsdmSubscription().id(ID)), MediaType.APPLICATION_JSON));
 
 183         final ResponseEntity<InlineResponse201> response =
 
 184                 (ResponseEntity<InlineResponse201>) sol003PackageManagementSubscriptionController
 
 185                         .postSubscriptionRequest(pkgmSubscriptionRequest);
 
 186         final String subscriptionId = response.getBody().getId();
 
 190         final ResponseEntity<InlineResponse201> responseEntity =
 
 191                 (ResponseEntity<InlineResponse201>) sol003PackageManagementSubscriptionController
 
 192                         .getSubscription(subscriptionId);
 
 194         final HttpHeaders headers = buildHttpHeaders(response.getBody().getCallbackUri());
 
 196         assertEquals(response.getBody().getFilter(), pkgmSubscriptionRequest.getFilter());
 
 197         assertEquals(response.getHeaders(), headers);
 
 198         assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
 
 199         assertEquals(pkgmSubscriptionRequest.getFilter(), response.getBody().getFilter());
 
 200         // Ensure CallBackUri is set to new URI
 
 201         assertNotEquals(pkgmSubscriptionRequest.getCallbackUri(), response.getBody().getCallbackUri());
 
 205     public void testFailGetSubscriptionWithInvalidSubscriptionId() {
 
 206         final String invalidId = "invalidSubscriptionId";
 
 207         mockRestServiceServer.expect(requestTo(msbEndpoint + "/" + invalidId)).andExpect(method(HttpMethod.GET))
 
 208                 .andRespond(withStatus(HttpStatus.NOT_FOUND));
 
 209         final ResponseEntity<?> response = sol003PackageManagementSubscriptionController.getSubscription(invalidId);
 
 210         assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
 
 211         assertTrue(response.getBody() instanceof ProblemDetails);
 
 215     public void testSuccessGetSubscriptions() throws GeneralSecurityException {
 
 216         final PkgmSubscription pkgmSubscription = buildPkgmSubscription();
 
 217         final PkgmSubscriptionRequest pkgmSubscriptionRequest = buildPkgmSubscriptionRequest();
 
 219         mockRestServiceServer.expect(requestTo(msbEndpoint)).andExpect(method(HttpMethod.POST))
 
 220                 .andRespond(withSuccess(gson.toJson(pkgmSubscription), MediaType.APPLICATION_JSON));
 
 221         mockRestServiceServer.expect(requestTo(msbEndpoint + "/" + ID)).andExpect(method(HttpMethod.GET))
 
 222                 .andRespond(withSuccess(gson.toJson(new NsdmSubscription().id(ID)), MediaType.APPLICATION_JSON));
 
 224         sol003PackageManagementSubscriptionController.postSubscriptionRequest(pkgmSubscriptionRequest);
 
 225         final ResponseEntity<List<InlineResponse201>> response =
 
 226                 sol003PackageManagementSubscriptionController.getSubscriptions();
 
 228         final List<InlineResponse201> subscriptionsList = response.getBody();
 
 230         assertEquals(Objects.requireNonNull(response.getBody()).get(0).getFilter(),
 
 231                 pkgmSubscriptionRequest.getFilter());
 
 232         assertNotNull(subscriptionsList != null);
 
 233         assertNotEquals('0', subscriptionsList.size());
 
 234         assertEquals(HttpStatus.OK, response.getStatusCode());
 
 238     public void testSuccessDeleteSubscriptionWithSubscriptionId() throws GeneralSecurityException {
 
 239         final PkgmSubscriptionRequest pkgmSubscriptionRequest = buildPkgmSubscriptionRequest();
 
 240         final PkgmSubscription pkgmSubscription = buildPkgmSubscription();
 
 241         final String subscriptionId = pkgmSubscription.getId();
 
 243         mockRestServiceServer.expect(requestTo(msbEndpoint)).andExpect(method(HttpMethod.POST))
 
 244                 .andRespond(withSuccess(gson.toJson(pkgmSubscription), MediaType.APPLICATION_JSON));
 
 246         mockRestServiceServer.expect(requestTo(msbEndpoint + "/" + subscriptionId)).andExpect(method(HttpMethod.DELETE))
 
 247                 .andRespond(withStatus(HttpStatus.NO_CONTENT));
 
 248         mockRestServiceServer.expect(requestTo(msbEndpoint + "/" + subscriptionId)).andExpect(method(HttpMethod.GET))
 
 249                 .andRespond(withSuccess(gson.toJson(new NsdmSubscription().id(subscriptionId)),
 
 250                         MediaType.APPLICATION_JSON));
 
 252         final ResponseEntity<InlineResponse2002> responsePost =
 
 253                 (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
 
 254                         .postSubscriptionRequest(pkgmSubscriptionRequest);
 
 256         final ResponseEntity responseDelete =
 
 257                 sol003PackageManagementSubscriptionController.deleteSubscription(subscriptionId);
 
 259         // Attempt to retrieve the subscription after delete
 
 260         final ResponseEntity<InlineResponse2002> responseGetSubscription =
 
 261                 (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
 
 262                         .getSubscription(subscriptionId);
 
 264         assertEquals(HttpStatus.NOT_FOUND, responseGetSubscription.getStatusCode());
 
 265         assertEquals(HttpStatus.NO_CONTENT, responseDelete.getStatusCode());
 
 269     public void testDeleteSubscription_SubscripitonNotFoundInEtsiCatalogManager_SubscriptionDeletedFromLocalCache()
 
 270             throws GeneralSecurityException {
 
 271         final PkgmSubscriptionRequest pkgmSubscriptionRequest = buildPkgmSubscriptionRequest();
 
 272         final PkgmSubscription pkgmSubscription = buildPkgmSubscription();
 
 274         mockRestServiceServer.expect(requestTo(msbEndpoint)).andExpect(method(HttpMethod.POST))
 
 275                 .andRespond(withSuccess(gson.toJson(pkgmSubscription), MediaType.APPLICATION_JSON));
 
 277         mockRestServiceServer.expect(requestTo(msbEndpoint + "/" + ID)).andExpect(method(HttpMethod.DELETE))
 
 278                 .andRespond(withStatus(HttpStatus.NOT_FOUND));
 
 280         final ResponseEntity<InlineResponse2002> responsePost =
 
 281                 (ResponseEntity<InlineResponse2002>) sol003PackageManagementSubscriptionController
 
 282                         .postSubscriptionRequest(pkgmSubscriptionRequest);
 
 285                 cacheServiceProvider.getCache(PackageManagementConstants.PACKAGE_MANAGEMENT_SUBSCRIPTION_CACHE);
 
 286         assertNotNull(cache.get(ID));
 
 288         final ResponseEntity responseDelete = sol003PackageManagementSubscriptionController.deleteSubscription(ID);
 
 290         assertEquals(HttpStatus.NO_CONTENT, responseDelete.getStatusCode());
 
 291         assertNull(cache.get(ID));
 
 296     public void testFailDeleteSubscriptionWithInvalidSubscriptionId() throws URISyntaxException, InterruptedException {
 
 297         final ResponseEntity<Void> responseDelete = (ResponseEntity<Void>) sol003PackageManagementSubscriptionController
 
 298                 .deleteSubscription("invalidSubscriptionId");
 
 299         assertEquals(HttpStatus.NOT_FOUND, responseDelete.getStatusCode());
 
 304     public void testSuccessPostSubscriptionWithValidNotificationTypes() throws Exception {
 
 306         final String file = getAbsolutePath("src/test/resources/requests/SubscriptionRequest.json");
 
 307         final String json = new String(Files.readAllBytes(Paths.get(file)));
 
 308         final PkgmSubscriptionRequest request = gson.fromJson(json, PkgmSubscriptionRequest.class);
 
 310         mockRestServiceServer.expect(requestTo(msbEndpoint)).andExpect(method(HttpMethod.POST))
 
 311                 .andExpect(MockRestRequestMatchers.content().json(gson.toJson(getEtsiCatalogPkgmSubscriptionRequest())))
 
 312                 .andRespond(withSuccess(gson.toJson(buildPkgmSubscription()), MediaType.APPLICATION_JSON));
 
 315         final ResponseEntity<InlineResponse201> responseEntity =
 
 316                 testRestTemplate.postForEntity(LOCALHOST_URL + port + PACKAGE_MANAGEMENT_BASE_URL + "/subscriptions",
 
 317                         request, InlineResponse201.class);
 
 319         assertEquals(HttpStatus.CREATED, responseEntity.getStatusCode());
 
 320         assertTrue(responseEntity.hasBody());
 
 321         final InlineResponse201 actual = responseEntity.getBody();
 
 322         assertEquals(ID, actual.getId());
 
 327     private org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.PkgmSubscriptionRequest getEtsiCatalogPkgmSubscriptionRequest() {
 
 328         return new org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.PkgmSubscriptionRequest()
 
 329                 .filter(new PkgmNotificationsFilter()
 
 330                         .addNotificationTypesItem(
 
 331                                 PkgmNotificationsFilter.NotificationTypesEnum.VNFPACKAGEONBOARDINGNOTIFICATION)
 
 332                         .addVnfdIdItem("VNFDID").addVnfPkgIdItem("VNFPKGID")
 
 333                         .addOperationalStateItem(PkgmNotificationsFilter.OperationalStateEnum.ENABLED)
 
 334                         .addVnfProductsFromProvidersItem(new VnfProductsProviders().vnfProvider("EST")
 
 335                                 .addVnfProductsItem(new VnfProducts().vnfProductName("VnfProducts")
 
 336                                         .addVersionsItem(new Version().vnfSoftwareVersion("vnfSoftwareVersion")
 
 337                                                 .addVnfdVersionsItem("version1")))))
 
 338                 .callbackUri(_NOTIFICATION_CALLBACK_URI).authentication(
 
 339                         new SubscriptionAuthentication().addAuthTypeItem(SubscriptionAuthentication.AuthTypeEnum.BASIC)
 
 340                                 .paramsBasic(new BasicAuth().userName("vnfm").password("password1$")));
 
 343     private PkgmSubscriptionRequest buildPkgmSubscriptionRequest() {
 
 344         final PkgmSubscriptionRequest pkgmSubscriptionRequest = new PkgmSubscriptionRequest();
 
 345         final SubscriptionsFilter1 sub = buildSubscriptionsFilter();
 
 346         final SubscriptionsAuthentication auth = new SubscriptionsAuthentication();
 
 347         pkgmSubscriptionRequest.setFilter(sub);
 
 348         pkgmSubscriptionRequest.setCallbackUri(msbEndpoint.toString());
 
 349         pkgmSubscriptionRequest.setAuthentication(auth);
 
 350         return pkgmSubscriptionRequest;
 
 353     private SubscriptionsFilter1 buildSubscriptionsFilter() {
 
 354         final SubscriptionsFilter1 sub = new SubscriptionsFilter1();
 
 355         final List<String> vnfdIdList = new ArrayList<>();
 
 356         final List<String> vnfPkgIdList = new ArrayList<>();
 
 357         final List<SubscriptionsFilter1.NotificationTypesEnum> notificationTypes = new ArrayList<>();
 
 358         final SubscriptionsFilterVnfProductsFromProviders subscriptionsFilterVnfProductsFromProviders =
 
 359                 new SubscriptionsFilterVnfProductsFromProviders();
 
 360         final List<SubscriptionsFilterVnfProductsFromProviders> vnfProductsFromProviders = new ArrayList<>();
 
 362         vnfProductsFromProviders.add(subscriptionsFilterVnfProductsFromProviders);
 
 363         sub.setVnfdId(vnfdIdList);
 
 364         sub.setNotificationTypes(notificationTypes);
 
 365         sub.setVnfPkgId(vnfPkgIdList);
 
 366         sub.setVnfProductsFromProviders(vnfProductsFromProviders);
 
 370     private PkgmSubscription buildPkgmSubscription() {
 
 371         final PkgmSubscription pkgmSubscription = new PkgmSubscription();
 
 372         final PkgmNotificationsFilter pkgmNotificationsFilter = new PkgmNotificationsFilter();
 
 373         final LinkSelf linkSelf = new LinkSelf();
 
 375         pkgmSubscription.setId(ID);
 
 376         pkgmSubscription.setCallbackUri(msbEndpoint + "/" + pkgmSubscription.getId().toString());
 
 377         pkgmSubscription.setFilter(pkgmNotificationsFilter);
 
 378         pkgmSubscription.setLinks(linkSelf);
 
 379         return pkgmSubscription;
 
 382     private PkgmSubscriptionRequest postSubscriptionForTest() {
 
 383         final PkgmSubscriptionRequest pkgmSubscriptionRequest = buildPkgmSubscriptionRequest();
 
 384         final PkgmSubscription pkgmSubscription = buildPkgmSubscription();
 
 386         mockRestServiceServer.expect(requestTo(msbEndpoint)).andExpect(method(HttpMethod.POST))
 
 387                 .andRespond(withSuccess(gson.toJson(pkgmSubscription), MediaType.APPLICATION_JSON));
 
 388         return pkgmSubscriptionRequest;
 
 391     private HttpHeaders buildHttpHeaders(final String uri) throws URISyntaxException {
 
 392         final HttpHeaders headers = new HttpHeaders();
 
 393         final URI myUri = new URI(uri);
 
 394         headers.setLocation(myUri);
 
 398     private String getAbsolutePath(final String path) {
 
 399         final File file = new File(path);
 
 400         return file.getAbsolutePath();