summaryrefslogtreecommitdiffstats
path: root/prh-app-server/src
diff options
context:
space:
mode:
Diffstat (limited to 'prh-app-server/src')
-rw-r--r--prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/exceptions/AaiFailureException.java28
-rw-r--r--prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTask.java145
-rw-r--r--prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasks.java19
-rw-r--r--prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTaskTest.java181
-rw-r--r--prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/ScheduleControllerSpy.java9
-rw-r--r--prh-app-server/src/test/resources/bbs_action/correct_logical_link.json11
6 files changed, 388 insertions, 5 deletions
diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/exceptions/AaiFailureException.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/exceptions/AaiFailureException.java
new file mode 100644
index 00000000..6741bb2d
--- /dev/null
+++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/exceptions/AaiFailureException.java
@@ -0,0 +1,28 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.prh.exceptions;
+
+public class AaiFailureException extends PrhTaskException {
+
+ public AaiFailureException(String message) {
+ super(message);
+ }
+}
diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTask.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTask.java
new file mode 100644
index 00000000..755d1282
--- /dev/null
+++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTask.java
@@ -0,0 +1,145 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.prh.tasks;
+
+import static org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpMethod.PUT;
+
+import com.google.gson.JsonObject;
+import io.netty.buffer.ByteBuf;
+import io.vavr.collection.HashMap;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+import org.onap.dcaegen2.services.prh.configuration.Config;
+import org.onap.dcaegen2.services.prh.exceptions.AaiFailureException;
+import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel;
+import org.onap.dcaegen2.services.prh.model.bbs.ImmutableLogicalLink;
+import org.onap.dcaegen2.services.prh.model.bbs.ImmutableRelationship;
+import org.onap.dcaegen2.services.prh.model.bbs.ImmutableRelationshipWrapper;
+import org.onap.dcaegen2.services.prh.model.bbs.RelationshipWrapper;
+import org.onap.dcaegen2.services.prh.model.utils.GsonSerializer;
+import org.onap.dcaegen2.services.prh.model.utils.HttpUtils;
+import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpResponse;
+import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.ImmutableHttpRequest;
+import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.RequestBody;
+import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.RxHttpClient;
+import org.onap.dcaegen2.services.sdk.rest.services.uri.URI.URIBuilder;
+import org.reactivestreams.Publisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+@Component
+public class BbsActionsTask {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(BbsActionsTask.class);
+ private static final String ATTACHMENT_POINT = "attachmentPoint";
+ private static final String LOGICAL_LINK_URI = "/network/logical-links/logical-link/";
+ private static final String PNF_URI = "/network/pnfs/pnf/";
+
+ private final AaiClientConfiguration aaiConfig;
+ private final RxHttpClient httpClient;
+
+ @Autowired
+ BbsActionsTask(Config config) {
+ this(config, RxHttpClient.create());
+ }
+
+ BbsActionsTask(Config config, RxHttpClient httpClient) {
+ this.aaiConfig = config.getAaiClientConfiguration();
+ this.httpClient = httpClient;
+ }
+
+ public Mono<ConsumerDmaapModel> execute(ConsumerDmaapModel consumerDmaapModel) {
+ JsonObject additionalFields = consumerDmaapModel.getAdditionalFields();
+ if (additionalFields == null || !additionalFields.has(ATTACHMENT_POINT)) {
+ return Mono.just(consumerDmaapModel);
+ }
+ String linkName = additionalFields.get(ATTACHMENT_POINT).getAsString();
+ if (linkName.isEmpty()) {
+ LOGGER.warn("Attachment point is empty! Ignore related actions.");
+ return Mono.just(consumerDmaapModel);
+ }
+ String pnfName = consumerDmaapModel.getCorrelationId();
+ return createLogicalLinkInAai(linkName, pnfName).flatMap(handleResponse(consumerDmaapModel));
+ }
+
+ private Function<HttpResponse, Mono<ConsumerDmaapModel>> handleResponse(ConsumerDmaapModel consumerDmaapModel) {
+ return response -> HttpUtils.isSuccessfulResponseCode(response.statusCode())
+ ? Mono.just(consumerDmaapModel)
+ : Mono.error(new AaiFailureException(
+ "Incorrect response when performing BBS-related actions: " + response.statusCode()));
+ }
+
+ private Mono<HttpResponse> createLogicalLinkInAai(String linkName, String pnfName) {
+ ImmutableHttpRequest request = buildLogicalLinkRequest(linkName, pnfName);
+
+ return httpClient.call(request);
+ }
+
+ private ImmutableHttpRequest buildLogicalLinkRequest(String linkName, String pnfName) {
+ String uri = buildLogicalLinkUri(linkName);
+ ImmutableLogicalLink logicalLink = buildModel(linkName, pnfName);
+ Publisher<ByteBuf> jsonPayload = RequestBody.fromString(GsonSerializer.createJsonBody(logicalLink));
+
+ return ImmutableHttpRequest
+ .builder()
+ .method(PUT)
+ .url(uri)
+ .body(jsonPayload)
+ .customHeaders(HashMap.ofAll(aaiConfig.aaiHeaders()))
+ .build();
+ }
+
+ private ImmutableLogicalLink buildModel(String linkName, String pnfName) {
+ List<RelationshipWrapper> relationships = buildRelationLink(pnfName);
+
+ return ImmutableLogicalLink
+ .builder()
+ .linkName(linkName)
+ .linkType(ATTACHMENT_POINT)
+ .relationshipList(relationships)
+ .build();
+ }
+
+ private List<RelationshipWrapper> buildRelationLink(String pnfName) {
+ return Arrays.asList(ImmutableRelationshipWrapper
+ .builder()
+ .relationship(ImmutableRelationship
+ .builder()
+ .relatedLink(PNF_URI + pnfName)
+ .build())
+ .build());
+ }
+
+ private String buildLogicalLinkUri(String linkName) {
+ return new URIBuilder()
+ .scheme(aaiConfig.aaiProtocol())
+ .host(aaiConfig.aaiHost())
+ .port(aaiConfig.aaiPort())
+ .path(aaiConfig.aaiBasePath() + LOGICAL_LINK_URI + linkName)
+ .build()
+ .toString();
+ }
+} \ No newline at end of file
diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasks.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasks.java
index 6ae8a3c7..16a6f8c5 100644
--- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasks.java
+++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/ScheduledTasks.java
@@ -54,6 +54,7 @@ public class ScheduledTasks {
private final DmaapConsumerTask dmaapConsumerTask;
private final DmaapPublisherTask dmaapProducerTask;
private final AaiProducerTask aaiProducerTask;
+ private final BbsActionsTask bbsActionsTask;
private Map<String, String> mdcContextMap;
/**
@@ -64,11 +65,16 @@ public class ScheduledTasks {
* @param aaiPublisherTask - second task
*/
@Autowired
- public ScheduledTasks(DmaapConsumerTask dmaapConsumerTask, DmaapPublisherTask dmaapPublisherTask,
- AaiProducerTask aaiPublisherTask, Map<String, String> mdcContextMap) {
+ public ScheduledTasks(
+ DmaapConsumerTask dmaapConsumerTask,
+ DmaapPublisherTask dmaapPublisherTask,
+ AaiProducerTask aaiPublisherTask,
+ BbsActionsTask bbsActionsTask,
+ Map<String, String> mdcContextMap) {
this.dmaapConsumerTask = dmaapConsumerTask;
this.dmaapProducerTask = dmaapPublisherTask;
this.aaiProducerTask = aaiPublisherTask;
+ this.bbsActionsTask = bbsActionsTask;
this.mdcContextMap = mdcContextMap;
}
@@ -88,6 +94,9 @@ public class ScheduledTasks {
.doOnError(exception ->
logger.warn("AAIProducerTask exception has been registered: ", exception))
.onErrorResume(resumePrhPredicate(), exception -> Mono.empty())
+ .flatMap(this::processAdditionalFields)
+ .doOnError(exception ->
+ logger.warn("BBSActionsTask exception has been registered: ", exception))
.flatMap(this::publishToDmaapConfiguration)
.doOnError(exception ->
logger.warn("DMaaPProducerTask exception has been registered: ", exception))
@@ -102,7 +111,6 @@ public class ScheduledTasks {
}
}
-
private void onComplete() {
logger.info("PRH tasks have been completed");
}
@@ -121,7 +129,6 @@ public class ScheduledTasks {
}
}
-
private Flux<ConsumerDmaapModel> consumeFromDMaaPMessage() {
return Flux.defer(() -> {
MdcVariables.setMdcContextMap(mdcContextMap);
@@ -148,6 +155,10 @@ public class ScheduledTasks {
}
}
+ private Mono<ConsumerDmaapModel> processAdditionalFields(ConsumerDmaapModel consumerDmaapModel) {
+ return bbsActionsTask.execute(consumerDmaapModel);
+ }
+
private Mono<HttpClientResponse> publishToDmaapConfiguration(ConsumerDmaapModel monoAaiModel) {
try {
return dmaapProducerTask.execute(monoAaiModel);
diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTaskTest.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTaskTest.java
new file mode 100644
index 00000000..197d9a8c
--- /dev/null
+++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/BbsActionsTaskTest.java
@@ -0,0 +1,181 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.prh.tasks;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import io.netty.buffer.ByteBuf;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import java.io.InputStreamReader;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.onap.dcaegen2.services.prh.TestAppConfiguration;
+import org.onap.dcaegen2.services.prh.configuration.AppConfig;
+import org.onap.dcaegen2.services.prh.exceptions.AaiFailureException;
+import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel;
+import org.onap.dcaegen2.services.prh.model.ImmutableConsumerDmaapModel;
+import org.onap.dcaegen2.services.sdk.rest.services.aai.client.config.AaiClientConfiguration;
+import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpRequest;
+import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.HttpResponse;
+import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.ImmutableHttpResponse;
+import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.RxHttpClient;
+import org.reactivestreams.Publisher;
+import reactor.core.publisher.Mono;
+
+class BbsActionsTaskTest {
+
+ private static final String CORRECT_LOGICAL_LINK_JSON = "bbs_action/correct_logical_link.json";
+ public static final String AAI_URL = "https://aai.onap.svc.cluster.local:8443/aai/v12/network/logical-links/logical-link/some-link";
+
+ private AaiClientConfiguration aaiClientConfiguration = TestAppConfiguration.createDefaultAaiClientConfiguration();
+ private AppConfig appConfig = mock(AppConfig.class);
+ private RxHttpClient httpClient = mock(RxHttpClient.class);
+
+ @Test
+ void whenPassedObjectDoesntHaveAdditionalFields_ReturnPayloadTransparently() {
+ // given
+ given(appConfig.getAaiClientConfiguration()).willReturn(aaiClientConfiguration);
+ ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(null);
+
+ // when
+ ConsumerDmaapModel result = new BbsActionsTask(appConfig, httpClient).execute(consumerDmaapModel).block();
+
+ // then
+ verifyZeroInteractions(httpClient);
+ assertThat(result).isEqualTo(consumerDmaapModel);
+ }
+
+ @Test
+ void whenPassedObjectHasEmptyLogicalLink_ReturnPayloadTransparently() {
+ // given
+ given(appConfig.getAaiClientConfiguration()).willReturn(aaiClientConfiguration);
+
+ JsonObject additionalFields = new JsonObject();
+ additionalFields.addProperty("attachmentPoint", "");
+ ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(additionalFields);
+
+ // when
+ ConsumerDmaapModel result = new BbsActionsTask(appConfig, httpClient).execute(consumerDmaapModel).block();
+
+ // then
+ verifyZeroInteractions(httpClient);
+ assertThat(result).isEqualTo(consumerDmaapModel);
+ }
+
+ @Test
+ void whenPassedObjectHasLogicalLink_createLogicalLink_and_associateWithPnf_and_ReturnPayloadTransparently() {
+ // given
+ given(appConfig.getAaiClientConfiguration()).willReturn(aaiClientConfiguration);
+
+ JsonObject additionalFields = new JsonObject();
+ additionalFields.addProperty("attachmentPoint", "some-link");
+ ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(additionalFields);
+
+ given(httpClient.call(any())).willReturn(Mono.just(buildAaiResponse(HttpResponseStatus.OK)));
+
+ // when
+ Mono<ConsumerDmaapModel> response = new BbsActionsTask(appConfig, httpClient).execute(consumerDmaapModel);
+
+ // then
+ ArgumentCaptor<HttpRequest> captor = ArgumentCaptor.forClass(HttpRequest.class);
+ verify(httpClient).call(captor.capture());
+ verifyNoMoreInteractions(httpClient);
+
+ HttpRequest request = captor.getValue();
+ assertThat(request.url()).isEqualTo(
+ "https://aai.onap.svc.cluster.local:8443/aai/v12/network/logical-links/logical-link/some-link");
+ assertJsonEquals(request.body(), CORRECT_LOGICAL_LINK_JSON);
+ assertThat(request.headers().toJavaMap()).containsOnlyKeys("X-InvocationID", "X-RequestID");
+ assertEquals(consumerDmaapModel, response.block());
+ }
+
+ @Test
+ void whenPassedObjectHasLogicalLink_butAaiQueryFails_returnError() {
+ // given
+ given(appConfig.getAaiClientConfiguration()).willReturn(aaiClientConfiguration);
+
+ JsonObject additionalFields = new JsonObject();
+ additionalFields.addProperty("attachmentPoint", "some-link");
+ ConsumerDmaapModel consumerDmaapModel = buildConsumerDmaapModel(additionalFields);
+
+ given(httpClient.call(any())).willReturn(Mono.just(buildAaiResponse(HttpResponseStatus.INTERNAL_SERVER_ERROR)));
+
+ // when
+ Mono<ConsumerDmaapModel> response = new BbsActionsTask(appConfig, httpClient).execute(consumerDmaapModel);
+
+ // then
+ ArgumentCaptor<HttpRequest> captor = ArgumentCaptor.forClass(HttpRequest.class);
+ verify(httpClient).call(captor.capture());
+ verifyNoMoreInteractions(httpClient);
+
+ HttpRequest request = captor.getValue();
+ assertThat(request.url()).isEqualTo(AAI_URL);
+ assertJsonEquals(request.body(), CORRECT_LOGICAL_LINK_JSON);
+ assertThat(request.headers().toJavaMap()).containsOnlyKeys("X-InvocationID", "X-RequestID");
+
+ assertThatThrownBy(response::block).hasCauseInstanceOf(AaiFailureException.class);
+ }
+
+ private ConsumerDmaapModel buildConsumerDmaapModel(JsonObject additionalFields) {
+ return ImmutableConsumerDmaapModel.builder()
+ .ipv4("10.16.123.234")
+ .ipv6("0:0:0:0:0:FFFF:0A10:7BEA")
+ .correlationId("NOKQTFCOC540002E")
+ .serialNumber("QTFCOC540002E")
+ .equipVendor("nokia")
+ .equipModel("3310")
+ .equipType("type")
+ .nfRole("role")
+ .swVersion("v4.5.0.1")
+ .additionalFields(additionalFields)
+ .build();
+ }
+
+ private HttpResponse buildAaiResponse(HttpResponseStatus status) {
+ return ImmutableHttpResponse
+ .builder()
+ .statusCode(status.code())
+ .url("")
+ .rawBody("".getBytes())
+ .build();
+ }
+
+ private void assertJsonEquals(Publisher<ByteBuf> requestBody, String path) {
+ JsonParser parser = new JsonParser();
+ JsonElement result = parser.parse(Mono.from(requestBody).block().toString(UTF_8));
+ JsonElement expected = parser
+ .parse(new InputStreamReader(getClass().getClassLoader().getResourceAsStream(path)));
+
+ assertThat(result).isEqualTo(expected);
+ }
+} \ No newline at end of file
diff --git a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/ScheduleControllerSpy.java b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/ScheduleControllerSpy.java
index 2f7ff61c..b12b3d39 100644
--- a/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/ScheduleControllerSpy.java
+++ b/prh-app-server/src/test/java/org/onap/dcaegen2/services/prh/tasks/ScheduleControllerSpy.java
@@ -45,12 +45,19 @@ public class ScheduleControllerSpy {
private AaiProducerTask aaiPublisherTaskImplSpy;
@Autowired
+ private BbsActionsTask bbsActionsTaskImplSpy;
+
+ @Autowired
private Map<String, String> mdcContextMap;
@Bean
@Primary
public ScheduledTasks registerSimpleScheduledTask() {
- return spy(new ScheduledTasks(dmaapConsumerTaskImplSpy, dmaapPublisherTaskImplSpy, aaiPublisherTaskImplSpy,
+ return spy(new ScheduledTasks(
+ dmaapConsumerTaskImplSpy,
+ dmaapPublisherTaskImplSpy,
+ aaiPublisherTaskImplSpy,
+ bbsActionsTaskImplSpy,
mdcContextMap));
}
}
diff --git a/prh-app-server/src/test/resources/bbs_action/correct_logical_link.json b/prh-app-server/src/test/resources/bbs_action/correct_logical_link.json
new file mode 100644
index 00000000..e49a45ba
--- /dev/null
+++ b/prh-app-server/src/test/resources/bbs_action/correct_logical_link.json
@@ -0,0 +1,11 @@
+{
+ "link-name": "some-link",
+ "link-type": "attachmentPoint",
+ "relationship-list": [
+ {
+ "relationship": {
+ "related-link": "/network/pnfs/pnf/NOKQTFCOC540002E"
+ }
+ }
+ ]
+} \ No newline at end of file