diff options
6 files changed, 305 insertions, 2 deletions
@@ -1,6 +1,6 @@ <!-- ============LICENSE_START======================================================= - Copyright (c) 2021-2022 Nordix Foundation. + Copyright (c) 2021-2023 Nordix Foundation. Modifications Copyright (C) 2021 Bell Canada. ================================================================================ Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,7 +40,7 @@ <properties> <app>org.onap.cps.ncmp.dmi.Application</app> <base.image>${docker.pull.registry}/onap/integration-java11:8.0.0</base.image> - <cps.version>3.1.4</cps.version> + <cps.version>3.2.1</cps.version> <image.tag>${project.version}-${maven.build.timestamp}</image.tag> <jacoco.minimum.coverage>0.98</jacoco.minimum.coverage> <maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format> diff --git a/src/main/java/org/onap/cps/ncmp/dmi/notifications/avc/DmiDataAvcEventCreator.java b/src/main/java/org/onap/cps/ncmp/dmi/notifications/avc/DmiDataAvcEventCreator.java new file mode 100644 index 00000000..6902b2eb --- /dev/null +++ b/src/main/java/org/onap/cps/ncmp/dmi/notifications/avc/DmiDataAvcEventCreator.java @@ -0,0 +1,63 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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.cps.ncmp.dmi.notifications.avc; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.UUID; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.event.model.AvcEvent; +import org.onap.cps.ncmp.event.model.Event; + +/** + * Helper to create AvcEvents. + */ +@Slf4j +public class DmiDataAvcEventCreator { + + private static final DateTimeFormatter dateTimeFormatter + = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + + /** + * Create an AVC event. + * + * @param eventCorrelationId the event correlation id + * @return DmiAsyncRequestResponseEvent + */ + public AvcEvent createEvent(final String eventCorrelationId) { + final AvcEvent avcEvent = new AvcEvent(); + avcEvent.setEventId(UUID.randomUUID().toString()); + avcEvent.setEventCorrelationId(eventCorrelationId); + avcEvent.setEventType(AvcEvent.class.getName()); + avcEvent.setEventSchema("urn:cps:" + AvcEvent.class.getName()); + avcEvent.setEventSchemaVersion("v1"); + avcEvent.setEventTarget("NCMP"); + avcEvent.setEventTime(ZonedDateTime.now().format(dateTimeFormatter)); + + final Event event = new Event(); + event.setAdditionalProperty("payload", "Hello world!"); + avcEvent.setEvent(event); + + log.debug("Avc Event Created ID: {}", avcEvent.getEventId()); + return avcEvent; + } + +}
\ No newline at end of file diff --git a/src/main/java/org/onap/cps/ncmp/dmi/notifications/avc/DmiDataAvcEventProducer.java b/src/main/java/org/onap/cps/ncmp/dmi/notifications/avc/DmiDataAvcEventProducer.java new file mode 100644 index 00000000..4fd46b66 --- /dev/null +++ b/src/main/java/org/onap/cps/ncmp/dmi/notifications/avc/DmiDataAvcEventProducer.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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.cps.ncmp.dmi.notifications.avc; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.event.model.AvcEvent; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +@RequiredArgsConstructor +public class DmiDataAvcEventProducer { + + private final KafkaTemplate<String, AvcEvent> kafkaTemplate; + + /** + * Sends message to the configured topic with a message key. + * + * @param requestId the request id + * @param avcEvent the event to publish + */ + public void sendMessage(final String requestId, final AvcEvent avcEvent) { + kafkaTemplate.send("dmi-cm-events", requestId, avcEvent); + log.debug("AVC event sent"); + } +} diff --git a/src/main/java/org/onap/cps/ncmp/dmi/notifications/avc/DmiDataAvcEventSimulationController.java b/src/main/java/org/onap/cps/ncmp/dmi/notifications/avc/DmiDataAvcEventSimulationController.java new file mode 100644 index 00000000..f7f4bf96 --- /dev/null +++ b/src/main/java/org/onap/cps/ncmp/dmi/notifications/avc/DmiDataAvcEventSimulationController.java @@ -0,0 +1,61 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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.cps.ncmp.dmi.notifications.avc; + +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.event.model.AvcEvent; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + + +@RequestMapping("${rest.api.dmi-base-path}") +@RestController +@Slf4j +@RequiredArgsConstructor +public class DmiDataAvcEventSimulationController { + + private final DmiDataAvcEventProducer dmiDataAvcEventProducer; + + /** + * Simulate Event for AVC. + * @param numberOfSimulatedEvents number of events to be generated + * @return ResponseEntity + */ + @GetMapping(path = "/v1/simulateDmiDataEvent") + public ResponseEntity<Void> simulateEvents(@RequestParam("numberOfSimulatedEvents") + final Integer numberOfSimulatedEvents) { + final DmiDataAvcEventCreator dmiDataAvcEventCreator = new DmiDataAvcEventCreator(); + + for (int i = 0; i < numberOfSimulatedEvents; i++) { + final String eventCorrelationId = UUID.randomUUID().toString(); + final AvcEvent avcEvent = dmiDataAvcEventCreator.createEvent(eventCorrelationId); + dmiDataAvcEventProducer.sendMessage(eventCorrelationId, avcEvent); + } + + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/api/kafka/MessagingBaseSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/api/kafka/MessagingBaseSpec.groovy new file mode 100644 index 00000000..59e45c20 --- /dev/null +++ b/src/test/groovy/org/onap/cps/ncmp/dmi/api/kafka/MessagingBaseSpec.groovy @@ -0,0 +1,71 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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.cps.ncmp.dmi.api.kafka + +import org.apache.kafka.common.serialization.StringDeserializer +import org.apache.kafka.common.serialization.StringSerializer +import org.springframework.kafka.core.DefaultKafkaProducerFactory +import org.springframework.kafka.core.KafkaTemplate +import org.springframework.kafka.support.serializer.JsonSerializer +import org.springframework.test.context.DynamicPropertyRegistry +import org.springframework.test.context.DynamicPropertySource +import org.testcontainers.containers.KafkaContainer +import org.testcontainers.utility.DockerImageName +import spock.lang.Specification + +class MessagingBaseSpec extends Specification { + + def setupSpec() { + kafkaTestContainer.start() + } + + def cleanupSpec() { + kafkaTestContainer.stop() + } + + static kafkaTestContainer = new KafkaContainer(DockerImageName.parse('registry.nordix.org/onaptest/confluentinc/cp-kafka:6.2.1').asCompatibleSubstituteFor('confluentinc/cp-kafka')) + + def producerConfigProperties() { + return [('bootstrap.servers'): kafkaTestContainer.getBootstrapServers().split(',')[0], + ('retries') : 0, + ('batch-size') : 16384, + ('linger.ms') : 1, + ('buffer.memory') : 33554432, + ('key.serializer') : StringSerializer, + ('value.serializer') : JsonSerializer] + } + + def consumerConfigProperties(consumerGroupId) { + return [('bootstrap.servers') : kafkaTestContainer.getBootstrapServers().split(',')[0], + ('key.deserializer') : StringDeserializer, + ('value.deserializer'): StringDeserializer, + ('auto.offset.reset') : 'earliest', + ('group.id') : consumerGroupId + ] + } + + def kafkaTemplate = new KafkaTemplate<>(new DefaultKafkaProducerFactory<Integer, String>(producerConfigProperties())) + + @DynamicPropertySource + static void registerKafkaProperties(DynamicPropertyRegistry dynamicPropertyRegistry) { + dynamicPropertyRegistry.add('spring.kafka.bootstrap-servers', kafkaTestContainer::getBootstrapServers) + } +} diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/notifications/avc/AvcEventExecutorIntegrationSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/notifications/avc/AvcEventExecutorIntegrationSpec.groovy new file mode 100644 index 00000000..5f7ed878 --- /dev/null +++ b/src/test/groovy/org/onap/cps/ncmp/dmi/notifications/avc/AvcEventExecutorIntegrationSpec.groovy @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 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.cps.ncmp.dmi.notifications.avc + +import com.fasterxml.jackson.databind.ObjectMapper +import org.apache.kafka.clients.consumer.KafkaConsumer +import org.onap.cps.ncmp.dmi.api.kafka.MessagingBaseSpec +import org.onap.cps.ncmp.dmi.notifications.async.AsyncTaskExecutor +import org.onap.cps.ncmp.dmi.service.DmiService +import org.onap.cps.ncmp.dmi.notifications.avc.DmiDataAvcEventSimulationController +import org.onap.cps.ncmp.event.model.AvcEvent +import org.spockframework.spring.SpringBean +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.annotation.DirtiesContext +import org.testcontainers.spock.Testcontainers + +import java.time.Duration + +@SpringBootTest(classes = [DmiDataAvcEventProducer]) +@Testcontainers +@DirtiesContext +class AvcEventExecutorIntegrationSpec extends MessagingBaseSpec { + + @SpringBean + DmiDataAvcEventProducer dmiDataAvcEventProducer = new DmiDataAvcEventProducer(kafkaTemplate) + + def dmiService = new DmiDataAvcEventSimulationController(dmiDataAvcEventProducer) + + def objectMapper = new ObjectMapper() + + def 'Publish Avc Event'() { + given: 'a simulated event' + dmiService.simulateEvents(1) + and: 'a consumer subscribed to dmi-cm-events topic' + def consumer = new KafkaConsumer<>(consumerConfigProperties('test')) + consumer.subscribe(['dmi-cm-events']) + when: 'the next event record is consumed' + def record = consumer.poll(Duration.ofMillis(1500)).iterator().next() + then: 'record has correct topic' + assert record.topic == 'dmi-cm-events' + and: 'the record value can be mapped to an avcEvent' + objectMapper.readValue(record.value(), AvcEvent) + } +}
\ No newline at end of file |