diff options
21 files changed, 174 insertions, 79 deletions
diff --git a/cps-application/src/main/java/org/onap/cps/config/MicroMeterConfig.java b/cps-application/src/main/java/org/onap/cps/config/MicroMeterConfig.java index b85f391b8e..6782669db2 100644 --- a/cps-application/src/main/java/org/onap/cps/config/MicroMeterConfig.java +++ b/cps-application/src/main/java/org/onap/cps/config/MicroMeterConfig.java @@ -37,7 +37,7 @@ import org.springframework.context.annotation.Configuration; public class MicroMeterConfig { private static final String STATE_TAG = "state"; - private static final String CM_HANDLE_STATE_GAUGE = "cmHandlesByState"; + private static final String CM_HANDLE_STATE_GAUGE = "cps_ncmp_inventory_cm_handles_by_state"; final IMap<String, Integer> cmHandlesByState; @Bean diff --git a/cps-application/src/test/groovy/org/onap/cps/config/MicroMeterConfigSpec.groovy b/cps-application/src/test/groovy/org/onap/cps/config/MicroMeterConfigSpec.groovy index b9302ccd72..faef32b04b 100644 --- a/cps-application/src/test/groovy/org/onap/cps/config/MicroMeterConfigSpec.groovy +++ b/cps-application/src/test/groovy/org/onap/cps/config/MicroMeterConfigSpec.groovy @@ -53,7 +53,7 @@ class MicroMeterConfigSpec extends Specification { objectUnderTest.deletedCmHandles(simpleMeterRegistry) then: 'each state has the correct value when queried' ['ADVISED', 'READY', 'LOCKED', 'DELETING', 'DELETED'].each { state -> - def gaugeValue = simpleMeterRegistry.get('cmHandlesByState').tag('state',state).gauge().value() + def gaugeValue = simpleMeterRegistry.get(objectUnderTest.CM_HANDLE_STATE_GAUGE).tag('state',state).gauge().value() assert gaugeValue == 1 } } diff --git a/cps-ncmp-events/pom.xml b/cps-ncmp-events/pom.xml index 2667d0924b..36c034ed5b 100644 --- a/cps-ncmp-events/pom.xml +++ b/cps-ncmp-events/pom.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- ============LICENSE_START======================================================= - Copyright (c) 2022-2023 Nordix Foundation. + Copyright (c) 2022-2025 Nordix Foundation. ================================================================================ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -39,6 +39,10 @@ <groupId>jakarta.validation</groupId> <artifactId>jakarta.validation-api</artifactId> </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + </dependency> </dependencies> <build> diff --git a/cps-ncmp-events/src/main/java/org/onap/cps/ncmp/events/NcmpEventDataSchema.java b/cps-ncmp-events/src/main/java/org/onap/cps/ncmp/events/NcmpEventDataSchema.java new file mode 100644 index 0000000000..9cdb6d76ee --- /dev/null +++ b/cps-ncmp-events/src/main/java/org/onap/cps/ncmp/events/NcmpEventDataSchema.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2025 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.events; + +import lombok.Getter; + +@Getter +public enum NcmpEventDataSchema { + + BATCH_RESPONSE_V1("urn:cps:org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent:1.0.0"), + SUBSCRIPTIONS_V1("urn:cps:org.onap.ncmp.events.subscription:1.0.0"), + MOI_CHANGES_V1("urn:cps:org.onap.cps.ncmp.events.moi-changes:1.0.0"), + INVENTORY_EVENTS_V1("urn:cps:org.onap.cps.ncmp.events:inventory-event:1.0.0"), + CM_HANDLE_TRUST_LEVEL_V1("urn:cps:org.onap.cps.ncmp.dmi.events:cm-handle-trust-level:1.0.0"); + + private final String dataSchema; + + NcmpEventDataSchema(final String dataSchema) { + this.dataSchema = dataSchema; + } + + +} diff --git a/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/avc-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/avc-event-schema-1.0.0.json index d24ec2c737..5094e1808f 100644 --- a/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/avc-event-schema-1.0.0.json +++ b/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/avc-event-schema-1.0.0.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "urn:cps:org.onap.cps.ncmp.events:avc-event-schema:1.0.0", + "$id": "urn:cps:org.onap.cps.ncmp.events.inventory-event-schema:1.0.0", "$ref": "#/definitions/AvcEvent", "definitions": { "AvcEvent": { diff --git a/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/dmi-in-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/dmi-in-event-schema-1.0.0.json index 93ec216e3d..fb86c5ddb4 100644 --- a/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/dmi-in-event-schema-1.0.0.json +++ b/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/dmi-in-event-schema-1.0.0.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "urn:cps:org.onap.cps.ncmp.events:cm-notification-subscription-dmi-in-event-schema:1.0.0", + "$id": "urn:cps:org.onap.ncmp.events.subscription:1.0.0", "$ref": "#/definitions/DmiInEvent", "definitions": { "DmiInEvent": { diff --git a/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/dmi-out-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/dmi-out-event-schema-1.0.0.json index 0910de1529..b47a70cd90 100644 --- a/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/dmi-out-event-schema-1.0.0.json +++ b/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/dmi-out-event-schema-1.0.0.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "urn:cps:org.onap.cps.ncmp.events:cm-notification-subscription-dmi-out-event-schema:1.0.0", + "$id": "urn:cps:org.onap.ncmp.events.subscription:1.0.0", "$ref": "#/definitions/DmiOutEvent", "definitions": { "DmiOutEvent": { diff --git a/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/ncmp-in-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/ncmp-in-event-schema-1.0.0.json index f8b6c2e680..d4e8519956 100644 --- a/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/ncmp-in-event-schema-1.0.0.json +++ b/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/ncmp-in-event-schema-1.0.0.json @@ -1,5 +1,5 @@ { - "$id": "urn:cps:org.onap.cps.ncmp.events:cm-notification-subscription-ncmp-in-event:1.0.0", + "$id": "urn:cps:org.onap.ncmp.events.subscription:1.0.0", "$ref": "#/definitions/NcmpInEvent", "$schema": "https://json-schema.org/draft/2019-09/schema", "definitions": { diff --git a/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/ncmp-out-event-schema-1.0.0.json b/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/ncmp-out-event-schema-1.0.0.json index 11dc4e1114..466ce04a0f 100644 --- a/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/ncmp-out-event-schema-1.0.0.json +++ b/cps-ncmp-events/src/main/resources/schemas/ncmp/avc/ncmp-out-event-schema-1.0.0.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "urn:cps:org.onap.cps.ncmp.events:cm-notification-subscription-ncmp-out-event-schema:1.0.0", + "$id": "urn:cps:org.onap.ncmp.events.subscription:1.0.0", "$ref": "#/definitions/NcmpOutEvent", "definitions": { "NcmpOutEvent": { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducer.java index c62916f05c..232803a941 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducer.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation + * Copyright (C) 2024-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,14 +20,14 @@ package org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi; +import static org.onap.cps.ncmp.events.NcmpEventDataSchema.SUBSCRIPTIONS_V1; + import io.cloudevents.CloudEvent; -import io.cloudevents.core.builder.CloudEventBuilder; -import java.net.URI; -import java.util.UUID; +import java.util.Map; import lombok.RequiredArgsConstructor; import org.onap.cps.events.EventsPublisher; import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.DmiInEvent; -import org.onap.cps.utils.JsonObjectMapper; +import org.onap.cps.ncmp.utils.events.NcmpEvent; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; @@ -38,7 +38,6 @@ import org.springframework.stereotype.Component; public class DmiInEventProducer { private final EventsPublisher<CloudEvent> eventsPublisher; - private final JsonObjectMapper jsonObjectMapper; @Value("${app.ncmp.avc.cm-subscription-dmi-in}") private String dmiInEventTopic; @@ -58,13 +57,15 @@ public class DmiInEventProducer { } - private CloudEvent buildAndGetDmiInEventAsCloudEvent(final String subscriptionId, - final String dmiPluginName, final String eventType, final DmiInEvent dmiInEvent) { - return CloudEventBuilder.v1().withId(UUID.randomUUID().toString()).withType(eventType) - .withSource(URI.create("NCMP")) - .withDataSchema(URI.create("org.onap.ncmp.dmi.cm.subscription:1.0.0")) - .withExtension("correlationid", subscriptionId.concat("#").concat(dmiPluginName)) - .withData(jsonObjectMapper.asJsonBytes(dmiInEvent)).build(); + private CloudEvent buildAndGetDmiInEventAsCloudEvent(final String subscriptionId, final String dmiPluginName, + final String eventType, final DmiInEvent dmiInEvent) { + return NcmpEvent.builder() + .type(eventType) + .dataSchema(SUBSCRIPTIONS_V1.getDataSchema()) + .extensions(Map.of("correlationid", String.join("#", subscriptionId, dmiPluginName))) + .data(dmiInEvent) + .build() + .asCloudEvent(); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java index 3371d59f7a..8cfb3ad563 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducer.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation + * Copyright (C) 2024-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +20,10 @@ package org.onap.cps.ncmp.impl.cmnotificationsubscription.ncmp; +import static org.onap.cps.ncmp.events.NcmpEventDataSchema.SUBSCRIPTIONS_V1; + import io.cloudevents.CloudEvent; -import io.cloudevents.core.builder.CloudEventBuilder; -import java.net.URI; import java.util.Map; -import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -35,7 +34,7 @@ import lombok.extern.slf4j.Slf4j; import org.onap.cps.events.EventsPublisher; import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler; import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent; -import org.onap.cps.utils.JsonObjectMapper; +import org.onap.cps.ncmp.utils.events.NcmpEvent; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; @@ -53,7 +52,6 @@ public class NcmpOutEventProducer { private Integer dmiOutEventTimeoutInMs; private final EventsPublisher<CloudEvent> eventsPublisher; - private final JsonObjectMapper jsonObjectMapper; private final NcmpOutEventMapper ncmpOutEventMapper; private final DmiCacheHandler dmiCacheHandler; private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); @@ -91,49 +89,48 @@ public class NcmpOutEventProducer { } } + /** + * Get an NCMP out event as cloud event. + * + * @param subscriptionId subscription id + * @param eventType event type + * @param ncmpOutEvent cm notification subscription NCMP out event + * @return cm notification subscription NCMP out event as cloud event + */ + public static CloudEvent buildAndGetNcmpOutEventAsCloudEvent( + final String subscriptionId, final String eventType, final NcmpOutEvent ncmpOutEvent) { + + return NcmpEvent.builder() + .type(eventType) + .dataSchema(SUBSCRIPTIONS_V1.getDataSchema()) + .extensions(Map.of("correlationid", subscriptionId)) + .data(ncmpOutEvent) + .build() + .asCloudEvent(); + } + private ScheduledFuture<?> scheduleAndPublishNcmpOutEvent(final String subscriptionId, final String eventType) { final NcmpOutEventPublishingTask ncmpOutEventPublishingTask = new NcmpOutEventPublishingTask(ncmpOutEventTopic, subscriptionId, eventType, eventsPublisher, - jsonObjectMapper, ncmpOutEventMapper, dmiCacheHandler); + ncmpOutEventMapper, dmiCacheHandler); return scheduledExecutorService.schedule(ncmpOutEventPublishingTask, dmiOutEventTimeoutInMs, TimeUnit.MILLISECONDS); } private void cancelScheduledTask(final String taskKey) { - final ScheduledFuture<?> scheduledFuture = scheduledTasksPerSubscriptionIdAndEventType.get(taskKey); if (scheduledFuture != null) { scheduledFuture.cancel(true); scheduledTasksPerSubscriptionIdAndEventType.remove(taskKey); } - } - private void publishNcmpOutEventNow(final String subscriptionId, final String eventType, final NcmpOutEvent ncmpOutEvent) { final CloudEvent ncmpOutEventAsCloudEvent = - buildAndGetNcmpOutEventAsCloudEvent(jsonObjectMapper, subscriptionId, eventType, ncmpOutEvent); + buildAndGetNcmpOutEventAsCloudEvent(subscriptionId, eventType, ncmpOutEvent); eventsPublisher.publishCloudEvent(ncmpOutEventTopic, subscriptionId, ncmpOutEventAsCloudEvent); dmiCacheHandler.removeAcceptedAndRejectedDmiSubscriptionEntries(subscriptionId); } - /** - * Get an NCMP out event as cloud event. - * - * @param jsonObjectMapper JSON object mapper - * @param subscriptionId subscription id - * @param eventType event type - * @param ncmpOutEvent cm notification subscription NCMP out event - * @return cm notification subscription NCMP out event as cloud event - */ - public static CloudEvent buildAndGetNcmpOutEventAsCloudEvent(final JsonObjectMapper jsonObjectMapper, - final String subscriptionId, final String eventType, final NcmpOutEvent ncmpOutEvent) { - - return CloudEventBuilder.v1().withId(UUID.randomUUID().toString()).withType(eventType) - .withSource(URI.create("NCMP")).withDataSchema(URI.create("org.onap.ncmp.cm.subscription:1.0.0")) - .withExtension("correlationid", subscriptionId) - .withData(jsonObjectMapper.asJsonBytes(ncmpOutEvent)).build(); - } - } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java index f8f253d275..e9d6d78429 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventPublishingTask.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2024 Nordix Foundation + * Copyright (C) 2024-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,6 @@ import org.onap.cps.events.EventsPublisher; import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler; import org.onap.cps.ncmp.impl.cmnotificationsubscription.models.DmiCmSubscriptionDetails; import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent; -import org.onap.cps.utils.JsonObjectMapper; @Slf4j @RequiredArgsConstructor @@ -40,7 +39,6 @@ public class NcmpOutEventPublishingTask implements Runnable { private final String subscriptionId; private final String eventType; private final EventsPublisher<CloudEvent> eventsPublisher; - private final JsonObjectMapper jsonObjectMapper; private final NcmpOutEventMapper ncmpOutEventMapper; private final DmiCacheHandler dmiCacheHandler; @@ -55,8 +53,7 @@ public class NcmpOutEventPublishingTask implements Runnable { final NcmpOutEvent ncmpOutEvent = ncmpOutEventMapper.toNcmpOutEvent(subscriptionId, dmiSubscriptionsPerDmi); eventsPublisher.publishCloudEvent(topicName, subscriptionId, - buildAndGetNcmpOutEventAsCloudEvent(jsonObjectMapper, subscriptionId, eventType, - ncmpOutEvent)); + buildAndGetNcmpOutEventAsCloudEvent(subscriptionId, eventType, ncmpOutEvent)); dmiCacheHandler.removeAcceptedAndRejectedDmiSubscriptionEntries(subscriptionId); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java index d74abb9935..14e2eda2d2 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/utils/DataOperationEventCreator.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation + * Copyright (C) 2023-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,8 @@ package org.onap.cps.ncmp.impl.data.utils; +import static org.onap.cps.ncmp.events.NcmpEventDataSchema.BATCH_RESPONSE_V1; + import io.cloudevents.CloudEvent; import java.util.ArrayList; import java.util.HashMap; @@ -27,7 +29,6 @@ import java.util.List; import java.util.Map; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.NcmpResponseStatus; import org.onap.cps.ncmp.events.async1_0_0.Data; import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent; @@ -36,7 +37,6 @@ import org.onap.cps.ncmp.impl.data.models.DmiDataOperation; import org.onap.cps.ncmp.utils.events.NcmpEvent; import org.springframework.util.MultiValueMap; -@Slf4j @NoArgsConstructor(access = AccessLevel.PRIVATE) public class DataOperationEventCreator { @@ -57,8 +57,13 @@ public class DataOperationEventCreator { final Data data = createPayloadFromDataOperationResponses(cmHandleIdsPerResponseCodesPerOperation); dataOperationEvent.setData(data); final Map<String, String> extensions = createDataOperationExtensions(requestId, clientTopic); - return NcmpEvent.builder().type(DataOperationEvent.class.getName()) - .data(dataOperationEvent).extensions(extensions).build().asCloudEvent(); + return NcmpEvent.builder() + .type(DataOperationEvent.class.getName()) + .data(dataOperationEvent) + .dataSchema(BATCH_RESPONSE_V1.getDataSchema()) + .extensions(extensions) + .build() + .asCloudEvent(); } private static Data createPayloadFromDataOperationResponses(final MultiValueMap<DmiDataOperation, diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java index bdc7899724..2bb35864d3 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/CmAvcEventPublisher.java @@ -20,6 +20,8 @@ package org.onap.cps.ncmp.utils.events; +import static org.onap.cps.ncmp.events.NcmpEventDataSchema.INVENTORY_EVENTS_V1; + import io.cloudevents.CloudEvent; import java.util.Collections; import java.util.HashMap; @@ -51,9 +53,13 @@ public class CmAvcEventPublisher { final AvcEvent avcEvent = buildAvcEvent(attributeName, oldAttributeValue, newAttributeValue); final Map<String, String> extensions = createAvcEventExtensions(eventKey); - final CloudEvent avcCloudEvent = - NcmpEvent.builder().type(AvcEvent.class.getTypeName()) - .data(avcEvent).extensions(extensions).build().asCloudEvent(); + final CloudEvent avcCloudEvent = NcmpEvent.builder() + .type(AvcEvent.class.getTypeName()) + .dataSchema(INVENTORY_EVENTS_V1.getDataSchema()) + .data(avcEvent) + .extensions(extensions) + .build() + .asCloudEvent(); eventsPublisher.publishCloudEvent(ncmpInventoryEventsTopicName, eventKey, avcCloudEvent); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java index 8d3190eb00..6db962c068 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpEvent.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation + * Copyright (C) 2023-2025 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,12 +34,11 @@ import org.onap.cps.utils.JsonObjectMapper; @Builder public class NcmpEvent { + private String dataSchema; private Object data; private Map<String, String> extensions; private String type; @Builder.Default - private static final String CLOUD_EVENT_SPEC_VERSION_V1 = "1.0.0"; - @Builder.Default private static final String CLOUD_EVENT_SOURCE = "NCMP"; /** @@ -53,7 +52,7 @@ public class NcmpEvent { .withId(UUID.randomUUID().toString()) .withSource(URI.create(CLOUD_EVENT_SOURCE)) .withType(type) - .withDataSchema(URI.create("urn:cps:" + type + ":" + CLOUD_EVENT_SPEC_VERSION_V1)) + .withDataSchema(URI.create(dataSchema)) .withTime(EventDateTimeFormatter.toIsoOffsetDateTime( EventDateTimeFormatter.getCurrentIsoFormattedDateTime())) .withData(jsonObjectMapper.asJsonBytes(data)); diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducerSpec.groovy index 34fa4549f5..3bf4c2c160 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/dmi/DmiInEventProducerSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (c) 2024 Nordix Foundation. + * Copyright (c) 2024-2025 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,19 +23,23 @@ package org.onap.cps.ncmp.impl.cmnotificationsubscription.dmi import com.fasterxml.jackson.databind.ObjectMapper import io.cloudevents.CloudEvent import org.onap.cps.events.EventsPublisher +import org.onap.cps.ncmp.config.CpsApplicationContext import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.CmHandle import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.Data import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_dmi.DmiInEvent import org.onap.cps.ncmp.utils.events.CloudEventMapper import org.onap.cps.utils.JsonObjectMapper +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ContextConfiguration import spock.lang.Specification +@SpringBootTest(classes = [ObjectMapper, JsonObjectMapper]) +@ContextConfiguration(classes = [CpsApplicationContext]) class DmiInEventProducerSpec extends Specification { def mockEventsPublisher = Mock(EventsPublisher) - def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper()) - def objectUnderTest = new DmiInEventProducer(mockEventsPublisher, jsonObjectMapper) + def objectUnderTest = new DmiInEventProducer(mockEventsPublisher) def 'Create and Publish Cm Notification Subscription DMI In Event'() { given: 'a cm subscription for a dmi plugin' diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy index afa2e9874e..fde7e182d0 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cmnotificationsubscription/ncmp/NcmpOutEventProducerSpec.groovy @@ -1,23 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2025 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.impl.cmnotificationsubscription.ncmp import com.fasterxml.jackson.databind.ObjectMapper import io.cloudevents.CloudEvent import org.onap.cps.events.EventsPublisher +import org.onap.cps.ncmp.config.CpsApplicationContext import org.onap.cps.ncmp.impl.cmnotificationsubscription.cache.DmiCacheHandler import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.Data import org.onap.cps.ncmp.impl.cmnotificationsubscription_1_0_0.ncmp_to_client.NcmpOutEvent import org.onap.cps.ncmp.utils.events.CloudEventMapper import org.onap.cps.utils.JsonObjectMapper +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ContextConfiguration import spock.lang.Specification +@SpringBootTest(classes = [ObjectMapper, JsonObjectMapper]) +@ContextConfiguration(classes = [CpsApplicationContext]) class NcmpOutEventProducerSpec extends Specification { def mockEventsPublisher = Mock(EventsPublisher) - def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper()) def mockNcmpOutEventMapper = Mock(NcmpOutEventMapper) def mockDmiCacheHandler = Mock(DmiCacheHandler) - def objectUnderTest = new NcmpOutEventProducer(mockEventsPublisher, jsonObjectMapper, mockNcmpOutEventMapper, mockDmiCacheHandler) + def objectUnderTest = new NcmpOutEventProducer(mockEventsPublisher, mockNcmpOutEventMapper, mockDmiCacheHandler) def 'Create and #scenario Cm Notification Subscription NCMP out event'() { given: 'a cm subscription response for the client' @@ -102,5 +126,4 @@ class NcmpOutEventProducerSpec extends Specification { 0 * mockEventsPublisher.publishCloudEvent(*_) } - } diff --git a/cps-service/src/main/java/org/onap/cps/init/AbstractModelLoader.java b/cps-service/src/main/java/org/onap/cps/init/AbstractModelLoader.java index a80239039a..df068c68a6 100644 --- a/cps-service/src/main/java/org/onap/cps/init/AbstractModelLoader.java +++ b/cps-service/src/main/java/org/onap/cps/init/AbstractModelLoader.java @@ -34,6 +34,7 @@ import org.onap.cps.api.CpsDataService; import org.onap.cps.api.CpsDataspaceService; import org.onap.cps.api.CpsModuleService; import org.onap.cps.api.exceptions.AlreadyDefinedException; +import org.onap.cps.api.exceptions.DuplicatedYangResourceException; import org.onap.cps.api.exceptions.ModelOnboardingException; import org.onap.cps.api.parameters.CascadeDeleteAllowed; import org.onap.cps.utils.JsonObjectMapper; @@ -57,10 +58,10 @@ public abstract class AbstractModelLoader implements ModelLoader { public void onApplicationEvent(final ApplicationStartedEvent applicationStartedEvent) { try { onboardOrUpgradeModel(); - } catch (final Exception modelOnboardUpException) { + } catch (final Exception exception) { log.error("Exiting application due to failure in onboarding model: {} ", - modelOnboardUpException.getMessage()); - SpringApplication.exit(applicationStartedEvent.getApplicationContext(), () -> EXIT_CODE_ON_ERROR); + exception.getMessage()); + exitApplication(applicationStartedEvent); } } @@ -76,6 +77,8 @@ public abstract class AbstractModelLoader implements ModelLoader { cpsModuleService.createSchemaSet(dataspaceName, schemaSetName, yangResourcesContentByResourceName); } catch (final AlreadyDefinedException alreadyDefinedException) { log.warn("Creating new schema set failed as schema set already exists"); + } catch (final DuplicatedYangResourceException duplicatedYangResourceException) { + log.warn("Ignoring yang resource duplication exception. Assuming model was created by another instance"); } catch (final Exception exception) { log.error("Creating schema set {} failed: {} ", schemaSetName, exception.getMessage()); throw new ModelOnboardingException("Creating schema set failed", exception.getMessage()); @@ -180,4 +183,8 @@ public abstract class AbstractModelLoader implements ModelLoader { throw new ModelOnboardingException(message, exception.getMessage()); } } + + private void exitApplication(final ApplicationStartedEvent applicationStartedEvent) { + SpringApplication.exit(applicationStartedEvent.getApplicationContext(), () -> EXIT_CODE_ON_ERROR); + } } diff --git a/cps-service/src/test/groovy/org/onap/cps/init/AbstractModelLoaderSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/init/AbstractModelLoaderSpec.groovy index 0618cad951..c3cb4f205b 100644 --- a/cps-service/src/test/groovy/org/onap/cps/init/AbstractModelLoaderSpec.groovy +++ b/cps-service/src/test/groovy/org/onap/cps/init/AbstractModelLoaderSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023-2024 Nordix Foundation + * Copyright (C) 2023-2025 Nordix Foundation * Modification Copyright (C) 2024 TechMahindra Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,6 +28,7 @@ import org.onap.cps.api.CpsAnchorService import org.onap.cps.api.CpsDataService import org.onap.cps.api.CpsDataspaceService import org.onap.cps.api.CpsModuleService +import org.onap.cps.api.exceptions.DuplicatedYangResourceException import org.onap.cps.api.exceptions.ModelOnboardingException import org.onap.cps.api.parameters.CascadeDeleteAllowed import org.onap.cps.api.exceptions.AlreadyDefinedException @@ -117,6 +118,16 @@ class AbstractModelLoaderSpec extends Specification { 1 * mockCpsModuleService.createSchemaSet('some dataspace','new name',_) } + def 'Creating a schema set handles duplicated yang resource exception'() { + given: 'module service throws duplicated yang resource exception' + mockCpsModuleService.createSchemaSet(*_) >> { throw new DuplicatedYangResourceException('my-yang-resource', 'my-yang-resource-checksum', null) } + when: 'attempt to create a schema set' + objectUnderTest.createSchemaSet('some dataspace','some schema set','cps-notification-subscriptions@2024-07-03.yang') + then: 'exception is ignored, and correct exception message is logged' + noExceptionThrown() + assertLogContains('Ignoring yang resource duplication exception. Assuming model was created by another instance') + } + def 'Creating a schema set handles already defined exception.'() { given: 'the module service throws an already defined exception' mockCpsModuleService.createSchemaSet(*_) >> { throw AlreadyDefinedException.forSchemaSet('name','context',null) } diff --git a/docker-compose/config/grafana/inventory-dashboard.json b/docker-compose/config/grafana/inventory-dashboard.json index 959995fa69..d4046b8b08 100644 --- a/docker-compose/config/grafana/inventory-dashboard.json +++ b/docker-compose/config/grafana/inventory-dashboard.json @@ -105,7 +105,7 @@ { "disableTextWrap": false, "editorMode": "builder", - "expr": "cmHandlesByState{instance=\"$Instance\", job=\"$Job\"}", + "expr": "cps_ncmp_inventory_cm_handles_by_state{instance=\"$Instance\", job=\"$Job\"}", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "__auto", diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml index 3c85200042..3b7cc6063a 100644 --- a/docker-compose/docker-compose.yml +++ b/docker-compose/docker-compose.yml @@ -79,7 +79,7 @@ services: JAVA_TOOL_OPTIONS: "-XX:InitialRAMPercentage=70.0 -XX:MaxRAMPercentage=70.0" ### DEBUG: Uncomment next line to enable java debugging # JAVA_TOOL_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 - restart: no + restart: on-failure:3 depends_on: - dbpostgresql deploy: |