2 * ============LICENSE_START=======================================================
3 * PNF-REGISTRATION-HANDLER
4 * ================================================================================
5 * Copyright (C) 2019-2021 NOKIA Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.dcaegen2.services.prh.tasks;
23 import static io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;
24 import static io.netty.handler.codec.http.HttpResponseStatus.OK;
25 import static org.assertj.core.api.Assertions.assertThat;
26 import static org.assertj.core.api.Assertions.assertThatThrownBy;
27 import static org.junit.jupiter.api.Assertions.assertEquals;
28 import static org.mockito.ArgumentMatchers.any;
29 import static org.mockito.BDDMockito.given;
30 import static org.mockito.Mockito.mock;
31 import static org.mockito.Mockito.times;
32 import static org.mockito.Mockito.verify;
33 import static org.mockito.Mockito.verifyZeroInteractions;
34 import static org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpMethod.DELETE;
35 import static org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpMethod.GET;
36 import static org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpMethod.PUT;
38 import com.google.gson.JsonObject;
39 import io.netty.handler.codec.http.HttpResponseStatus;
40 import java.nio.charset.StandardCharsets;
41 import java.util.List;
42 import java.util.Scanner;
43 import org.junit.jupiter.api.Test;
44 import org.mockito.ArgumentCaptor;
45 import org.mockito.ArgumentMatchers;
46 import org.onap.dcaegen2.services.prh.TestAppConfiguration;
47 import org.onap.dcaegen2.services.prh.adapter.aai.api.ConsumerDmaapModel;
48 import org.onap.dcaegen2.services.prh.adapter.aai.api.ImmutableConsumerDmaapModel;
49 import org.onap.dcaegen2.services.prh.adapter.aai.main.AaiClientConfiguration;
50 import org.onap.dcaegen2.services.prh.configuration.CbsConfiguration;
51 import org.onap.dcaegen2.services.prh.exceptions.AaiFailureException;
52 import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpRequest;
53 import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpResponse;
54 import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.ImmutableHttpResponse;
55 import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.RxHttpClient;
56 import reactor.core.publisher.Mono;
58 class BbsActionsTaskTest {
60 private static final String AAI_URL = "https://aai.onap.svc.cluster.local:8443/aai/v23/network";
61 private static final String PNF_URL = "/pnfs/pnf";
62 private static final String LOGICAL_LINK_URL = "/logical-links/logical-link";
63 private static final String ATTACHMENT_POINT = "attachment-point";
65 private static final String PNF_WITHOUT_LINK_JSON = "BbsActionsTaskTestFiles/pnfWithoutLinks.json";
66 private static final String PNF_WITH_LINK_JSON = "BbsActionsTaskTestFiles/pnfWithLogicalLink.json";
67 private static final String LOGICAL_LINK_JSON = "BbsActionsTaskTestFiles/oldLogicalLink.json";
68 private static final String LOGICAL_LINK_BODY = "BbsActionsTaskTestFiles/logicalLinkBody.json";
69 private static final String LOGICAL_LINK_BODY_WITH_SPACE = "BbsActionsTaskTestFiles/logicalLinkBodyWithSpace.json";
72 private CbsConfiguration cbsConfiguration = mock(CbsConfiguration.class);
73 private AaiClientConfiguration aaiClientConfiguration = TestAppConfiguration.createDefaultAaiClientConfiguration();
74 private RxHttpClient httpClient = mock(RxHttpClient.class);
76 private ClassLoader loader = getClass().getClassLoader();
79 void whenPassedObjectDoesntHaveAdditionalFields_ReturnPayloadTransparently() {
81 given(cbsConfiguration.getAaiClientConfiguration()).willReturn(aaiClientConfiguration);
82 ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(null);
85 ConsumerDmaapModel result = new BbsActionsTaskImpl(cbsConfiguration, httpClient).execute(consumerDmaapModel).block();
88 verifyZeroInteractions(httpClient);
89 assertThat(result).isEqualTo(consumerDmaapModel);
93 void whenPassedObjectHasEmptyLogicalLink_ReturnPayloadTransparently() {
95 given(cbsConfiguration.getAaiClientConfiguration()).willReturn(aaiClientConfiguration);
97 JsonObject additionalFields = new JsonObject();
98 additionalFields.addProperty(ATTACHMENT_POINT, "");
99 ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(additionalFields);
102 ConsumerDmaapModel result = new BbsActionsTaskImpl(cbsConfiguration, httpClient).execute(consumerDmaapModel).block();
105 verifyZeroInteractions(httpClient);
106 assertThat(result).isEqualTo(consumerDmaapModel);
110 void whenPassedObjectHasLogicalLink_and_pnfHasNoLogicalLink_createLogicalLink_and_associateWithPnf_and_ReturnPayloadTransparently() {
112 given(cbsConfiguration.getAaiClientConfiguration()).willReturn(aaiClientConfiguration);
114 JsonObject additionalFields = new JsonObject();
115 String linkName = "some link";
116 String encodedLinkName = "some%20link";
117 additionalFields.addProperty(ATTACHMENT_POINT, linkName);
118 ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(additionalFields);
120 given(httpClient.call(any()))
121 .willReturn(Mono.just(buildAaiResponse(OK, getBodyJson(PNF_WITHOUT_LINK_JSON))),
122 Mono.just(buildAaiResponse(OK, "")));
125 Mono<ConsumerDmaapModel> response = new BbsActionsTaskImpl(cbsConfiguration, httpClient).execute(consumerDmaapModel);
128 assertEquals(consumerDmaapModel, response.block());
130 ArgumentCaptor<HttpRequest> captor = ArgumentCaptor.forClass(HttpRequest.class);
131 verify(httpClient, times(2)).call(captor.capture());
133 List<HttpRequest> args = captor.getAllValues();
134 assertEquals(2, args.size());
136 HttpRequest pnfGet = args.get(0);
137 HttpRequest linkPut = args.get(1);
139 assertEquals(AAI_URL + PNF_URL + "/Nokia123", pnfGet.url());
140 assertEquals(GET, pnfGet.method());
141 assertEquals(AAI_URL + LOGICAL_LINK_URL + "/" + encodedLinkName, linkPut.url());
142 assertEquals(PUT, linkPut.method());
143 assertEquals(getBodyJson(LOGICAL_LINK_BODY_WITH_SPACE), extractBodyFromRequest(linkPut));
147 void whenPassedObjectHasLogicalLink_and_pnfHasLogicalLink_deleteOldLogicalLink_and_createLogicalLink_and_associateWithPnf_and_ReturnPayloadTransparently() {
149 given(cbsConfiguration.getAaiClientConfiguration()).willReturn(aaiClientConfiguration);
151 JsonObject additionalFields = new JsonObject();
152 String linkName = "some-link";
153 additionalFields.addProperty(ATTACHMENT_POINT, linkName);
154 ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(additionalFields);
156 given(httpClient.call(any()))
157 .willReturn(Mono.just(buildAaiResponse(OK, getBodyJson(PNF_WITH_LINK_JSON))),
158 Mono.just(buildAaiResponse(OK, "")),
159 Mono.just(buildAaiResponse(OK, getBodyJson(LOGICAL_LINK_JSON))),
160 Mono.just(buildAaiResponse(OK, "")));
163 Mono<ConsumerDmaapModel> response = new BbsActionsTaskImpl(cbsConfiguration, httpClient).execute(consumerDmaapModel);
166 assertEquals(consumerDmaapModel, response.block());
168 ArgumentCaptor<HttpRequest> captor = ArgumentCaptor.forClass(HttpRequest.class);
169 verify(httpClient, times(4)).call(captor.capture());
171 List<HttpRequest> args = captor.getAllValues();
172 assertEquals(4, args.size());
174 HttpRequest pnfGet = args.get(0);
175 HttpRequest linkPut = args.get(1);
176 HttpRequest linkGet = args.get(2);
177 HttpRequest linkDelete = args.get(3);
179 assertEquals(AAI_URL + PNF_URL + "/Nokia123", pnfGet.url());
180 assertEquals(GET, pnfGet.method());
181 assertEquals(AAI_URL + LOGICAL_LINK_URL + "/" + linkName, linkPut.url());
182 assertEquals(PUT, linkPut.method());
183 assertEquals(AAI_URL + LOGICAL_LINK_URL + "/" + linkName, linkGet.url());
184 assertEquals(GET, linkGet.method());
185 assertEquals(AAI_URL + LOGICAL_LINK_URL + "/" + linkName + "?resource-version=1560171816043", linkDelete.url());
186 assertEquals(DELETE, linkDelete.method());
187 assertEquals(getBodyJson(LOGICAL_LINK_BODY), extractBodyFromRequest(linkPut));
191 void whenPassedObjectHasLogicalLink_butAaiQueryFails_returnError() {
193 given(cbsConfiguration.getAaiClientConfiguration()).willReturn(aaiClientConfiguration);
195 JsonObject additionalFields = new JsonObject();
196 String linkName = "some-link";
197 additionalFields.addProperty(ATTACHMENT_POINT, linkName);
198 ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(additionalFields);
200 given(httpClient.call(
201 ArgumentMatchers.argThat(argument -> argument.url().equals(AAI_URL + PNF_URL + "/Nokia123")
202 || argument.url().equals(AAI_URL + LOGICAL_LINK_URL + "/" + linkName))))
203 .willReturn(Mono.just(buildAaiResponse(INTERNAL_SERVER_ERROR, "")));
206 Mono<ConsumerDmaapModel> response = new BbsActionsTaskImpl(cbsConfiguration, httpClient)
207 .execute(consumerDmaapModel);
210 assertThatThrownBy(response::block).hasCauseInstanceOf(AaiFailureException.class).hasMessage(
211 "org.onap.dcaegen2.services.prh.exceptions.AaiFailureException: "
212 + "Incorrect response when performing BBS-related actions: 500. Occurred in GET PNF request. Pnf name: Nokia123");
215 private ConsumerDmaapModel buildConsumerDmaapModel(JsonObject additionalFields) {
216 return ImmutableConsumerDmaapModel.builder()
217 .ipv4("10.16.123.234")
218 .ipv6("0:0:0:0:0:FFFF:0A10:7BEA")
219 .correlationId("Nokia123")
220 .serialNumber("QTFCOC540002E")
221 .equipVendor("nokia")
225 .swVersion("v4.5.0.1")
226 .additionalFields(additionalFields)
230 private HttpResponse buildAaiResponse(HttpResponseStatus status, String body) {
231 return ImmutableHttpResponse
233 .statusCode(status.code())
235 .rawBody(body.getBytes())
239 private String extractBodyFromRequest(HttpRequest request) {
240 return Mono.from(request.body().contents()).block().toString(StandardCharsets.UTF_8);
243 private String getBodyJson(String filename) {
244 return new Scanner(loader.getResourceAsStream(filename)).useDelimiter("\\A").next();