rApp instance creation payload values compared with the rApp package for validation
Issue-ID: NONRTRIC-1080
Change-Id: Ic4cde14eddf4b3ad0294e1adb2a944b204027f89
Signed-off-by: aravind.est <aravindhan.a@est.tech>
import org.oransc.rappmanager.models.rappinstance.DeployOrder;
import org.oransc.rappmanager.models.rappinstance.RappInstance;
import org.oransc.rappmanager.models.rappinstance.RappInstanceDeployOrder;
+import org.oransc.rappmanager.models.rappinstance.validator.RappInstanceValidationHandler;
import org.oransc.rappmanager.models.statemachine.RappInstanceStateMachine;
import org.oransc.rappmanager.service.RappService;
import org.springframework.http.HttpStatus;
private final RappCacheService rappCacheService;
private final RappInstanceStateMachine rappInstanceStateMachine;
+ private final RappInstanceValidationHandler rappInstanceValidationHandler;
private final RappService rappService;
private static final String RAPP_INSTANCE_NOT_FOUND = "rApp instance %s not found.";
public ResponseEntity<RappInstance> createRappInstance(@PathVariable("rapp_id") String rappId,
@Valid @RequestBody RappInstance rappInstance) {
return rappCacheService.getRapp(rappId).map(rapp -> {
+ rappInstanceValidationHandler.validateRappInstance(rapp, rappInstance);
rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
rapp.getRappInstances().put(rappInstance.getRappInstanceId(), rappInstance);
return ResponseEntity.ok(rappInstance);
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.oransc.rappmanager.dme.service.DmeDeployer;
import org.oransc.rappmanager.models.cache.RappCacheService;
import org.oransc.rappmanager.models.rapp.Rapp;
+import org.oransc.rappmanager.models.rapp.RappResources;
import org.oransc.rappmanager.models.rapp.RappState;
import org.oransc.rappmanager.models.rappinstance.DeployOrder;
import org.oransc.rappmanager.models.rappinstance.RappACMInstance;
rappACMInstance.setInstance("test-instance");
rappInstance.setAcm(rappACMInstance);
rappInstance.setState(RappInstanceState.UNDEPLOYED);
+ RappResources rappResources = new RappResources();
+ rappResources.setAcm(RappResources.ACMResources.builder().compositionInstances(Set.of("test-instance")).build());
Rapp rapp = Rapp.builder().rappId(rappId).name(String.valueOf(rappId)).packageName(validRappFile)
- .packageLocation(validCsarFileLocation).state(RappState.PRIMED).build();
+ .packageLocation(validCsarFileLocation).rappResources(rappResources).state(RappState.PRIMED).build();
rappCacheService.putRapp(rapp);
mockMvc.perform(
MockMvcRequestBuilders.post("/rapps/{rapp_id}/instance", rappId).contentType(MediaType.APPLICATION_JSON)
--- /dev/null
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. 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.oransc.rappmanager.models.rappinstance.validator;
+
+import org.jetbrains.annotations.NotNull;
+import org.oransc.rappmanager.models.rapp.Rapp;
+import org.oransc.rappmanager.models.rappinstance.RappInstance;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AcmPayloadValidator implements RappInstanceValidator {
+
+ private static final int VALIDATION_ORDER = 5;
+
+ @Override
+ public int getOrder() {
+ return VALIDATION_ORDER;
+ }
+
+ @Override
+ public void validate(@NotNull Rapp rApp, @NotNull RappInstance rAppInstance) {
+ if (rAppInstance.getAcm() != null) {
+ comparePayloadValue(rAppInstance.getAcm().getInstance(),
+ rApp.getRappResources().getAcm().getCompositionInstances(),
+ "Invalid ACM instance in the rApp instance payload.");
+ }
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. 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.oransc.rappmanager.models.rappinstance.validator;
+
+import org.jetbrains.annotations.NotNull;
+import org.oransc.rappmanager.models.exception.RappValidationException;
+import org.oransc.rappmanager.models.rapp.Rapp;
+import org.oransc.rappmanager.models.rappinstance.RappInstance;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DmePayloadValidator implements RappInstanceValidator {
+
+ private static final int VALIDATION_ORDER = 15;
+
+ @Override
+ public int getOrder() {
+ return VALIDATION_ORDER;
+ }
+
+ @Override
+ public void validate(@NotNull Rapp rApp, @NotNull RappInstance rAppInstance) {
+ if (rAppInstance.isDMEEnabled()) {
+ if (rAppInstance.getDme().getInfoTypesProducer() != null && !rApp.getRappResources().getDme()
+ .getProducerInfoTypes().containsAll(
+ rAppInstance.getDme().getInfoTypesProducer())) {
+ throw new RappValidationException("Invalid DME info types producer in the rApp instance payload.");
+ }
+
+ comparePayloadValue(rAppInstance.getDme().getInfoProducer(),
+ rApp.getRappResources().getDme().getInfoProducers(),
+ "Invalid DME info producer in the rApp instance payload.");
+
+ comparePayloadValue(rAppInstance.getDme().getInfoTypeConsumer(),
+ rApp.getRappResources().getDme().getConsumerInfoTypes(),
+ "Invalid DME info type consumer in the rApp instance payload.");
+
+ comparePayloadValue(rAppInstance.getDme().getInfoConsumer(),
+ rApp.getRappResources().getDme().getInfoConsumers(),
+ "Invalid DME info consumer in the rApp instance payload.");
+ }
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. 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.oransc.rappmanager.models.rappinstance.validator;
+
+import java.util.Comparator;
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.oransc.rappmanager.models.rapp.Rapp;
+import org.oransc.rappmanager.models.rappinstance.RappInstance;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class RappInstanceValidationHandler {
+
+ private final List<RappInstanceValidator> rappInstanceValidators;
+
+ public void validateRappInstance(Rapp rApp, RappInstance rAppInstance) {
+ List<RappInstanceValidator> validatorList =
+ rappInstanceValidators.stream().sorted(Comparator.comparing(RappInstanceValidator::getOrder)).toList();
+ validatorList.forEach(rAppValidator -> rAppValidator.validate(rApp, rAppInstance));
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. 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.oransc.rappmanager.models.rappinstance.validator;
+
+import java.util.Set;
+import org.oransc.rappmanager.models.exception.RappValidationException;
+import org.oransc.rappmanager.models.rapp.Rapp;
+import org.oransc.rappmanager.models.rappinstance.RappInstance;
+
+public interface RappInstanceValidator {
+
+ int getOrder();
+
+ void validate(Rapp rApp, RappInstance rAppInstance);
+
+ default void comparePayloadValue(String rAppInstancePayloadValue, Set<String> allowedValues, String errorMessage) {
+ if (rAppInstancePayloadValue != null && !allowedValues.contains(rAppInstancePayloadValue)) {
+ throw new RappValidationException(errorMessage);
+ }
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. 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.oransc.rappmanager.models.rappinstance.validator;
+
+import org.jetbrains.annotations.NotNull;
+import org.oransc.rappmanager.models.exception.RappValidationException;
+import org.oransc.rappmanager.models.rapp.Rapp;
+import org.oransc.rappmanager.models.rapp.RappState;
+import org.oransc.rappmanager.models.rappinstance.RappInstance;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RappStatusValidator implements RappInstanceValidator {
+
+ private static final int VALIDATION_ORDER = 1;
+
+ @Override
+ public int getOrder() {
+ return VALIDATION_ORDER;
+ }
+
+ @Override
+ public void validate(@NotNull Rapp rApp, @NotNull RappInstance rAppInstance) {
+ if (!rApp.getState().equals(RappState.PRIMED)) {
+ throw new RappValidationException("Unable to create rApp instance as rApp is not in PRIMED state");
+ }
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. 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.oransc.rappmanager.models.rappinstance.validator;
+
+import org.jetbrains.annotations.NotNull;
+import org.oransc.rappmanager.models.rapp.Rapp;
+import org.oransc.rappmanager.models.rappinstance.RappInstance;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SmePayloadValidator implements RappInstanceValidator {
+
+ private static final int VALIDATION_ORDER = 10;
+
+ @Override
+ public int getOrder() {
+ return VALIDATION_ORDER;
+ }
+
+ @Override
+ public void validate(@NotNull Rapp rApp, @NotNull RappInstance rAppInstance) {
+ if (rAppInstance.isSMEEnabled()) {
+ comparePayloadValue(rAppInstance.getSme().getProviderFunction(),
+ rApp.getRappResources().getSme().getProviderFunctions(),
+ "Invalid SME provider function in the rApp instance payload.");
+
+ comparePayloadValue(rAppInstance.getSme().getServiceApis(),
+ rApp.getRappResources().getSme().getServiceApis(),
+ "Invalid SME service APIs in the rApp instance payload.");
+
+ comparePayloadValue(rAppInstance.getSme().getInvokers(), rApp.getRappResources().getSme().getInvokers(),
+ "Invalid SME invokers in the rApp instance payload.");
+ }
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. 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.oransc.rappmanager.models.rappinstance.validator;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.Set;
+import org.junit.jupiter.api.Test;
+import org.oransc.rappmanager.models.exception.RappValidationException;
+import org.oransc.rappmanager.models.rapp.Rapp;
+import org.oransc.rappmanager.models.rapp.RappResources;
+import org.oransc.rappmanager.models.rappinstance.RappACMInstance;
+import org.oransc.rappmanager.models.rappinstance.RappInstance;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ContextConfiguration;
+
+@SpringBootTest
+@ContextConfiguration(classes = {AcmPayloadValidator.class})
+class AcmPayloadValidatorTest {
+
+ public static final String K8S_INSTANCE = "k8s-instance";
+ @Autowired
+ AcmPayloadValidator acmPayloadValidator;
+
+ @Test
+ void testAcmPayloadValidationSuccess() {
+ RappResources rappResources = new RappResources();
+ RappResources.ACMResources rappACMResources =
+ RappResources.ACMResources.builder().compositionInstances(Set.of(K8S_INSTANCE)).build();
+ rappResources.setAcm(rappACMResources);
+ Rapp rapp = Rapp.builder().rappResources(rappResources).build();
+ RappInstance rappInstance = new RappInstance();
+ RappACMInstance rappACMInstance = new RappACMInstance();
+ rappACMInstance.setInstance(K8S_INSTANCE);
+ rappInstance.setAcm(rappACMInstance);
+ assertDoesNotThrow(() -> acmPayloadValidator.validate(rapp, rappInstance));
+ }
+
+ @Test
+ void testAcmPayloadValidationWithNull() {
+ RappResources rappResources = new RappResources();
+ RappResources.ACMResources rappACMResources =
+ RappResources.ACMResources.builder().compositionInstances(Set.of(K8S_INSTANCE)).build();
+ rappResources.setAcm(rappACMResources);
+ Rapp rapp = Rapp.builder().rappResources(rappResources).build();
+ RappInstance rappInstance = new RappInstance();
+ rappInstance.setAcm(null);
+ assertDoesNotThrow(() -> acmPayloadValidator.validate(rapp, rappInstance));
+ }
+
+ @Test
+ void testAcmPayloadValidationSuccessNoAcm() {
+ Rapp rapp = Rapp.builder().build();
+ RappInstance rappInstance = new RappInstance();
+ assertDoesNotThrow(() -> acmPayloadValidator.validate(rapp, rappInstance));
+ }
+
+ @Test
+ void testAcmPayloadValidationFailure() {
+ RappResources rappResources = new RappResources();
+ RappResources.ACMResources rappACMResources =
+ RappResources.ACMResources.builder().compositionInstances(Set.of(K8S_INSTANCE)).build();
+ rappResources.setAcm(rappACMResources);
+ Rapp rapp = Rapp.builder().rappResources(rappResources).build();
+ RappInstance rappInstance = new RappInstance();
+ RappACMInstance rappACMInstance = new RappACMInstance();
+ rappACMInstance.setInstance("invalid-instance");
+ rappInstance.setAcm(rappACMInstance);
+ RappValidationException rappValidationException =
+ assertThrows(RappValidationException.class, () -> acmPayloadValidator.validate(rapp, rappInstance));
+ assertEquals("Invalid ACM instance in the rApp instance payload.", rappValidationException.getMessage());
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. 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.oransc.rappmanager.models.rappinstance.validator;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.Set;
+import org.junit.jupiter.api.Test;
+import org.oransc.rappmanager.models.exception.RappValidationException;
+import org.oransc.rappmanager.models.rapp.Rapp;
+import org.oransc.rappmanager.models.rapp.RappResources;
+import org.oransc.rappmanager.models.rappinstance.RappDMEInstance;
+import org.oransc.rappmanager.models.rappinstance.RappInstance;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ContextConfiguration;
+
+@SpringBootTest
+@ContextConfiguration(classes = {DmePayloadValidator.class})
+class DmePayloadValidatorTest {
+
+ private static final String PRODUCER_INFOTYPE_1 = "producer-infotype-1";
+ private static final String PRODUCER_INFOTYPE_2 = "producer-infotype-2";
+ private static final String CONSUMER_INFOTYPE_1 = "consumer-infotype-1";
+ private static final String CONSUMER_INFOTYPE_2 = "consumer-infotype-2";
+ private static final String INFO_CONSUMER_1 = "info-consumer-1";
+ private static final String INFO_CONSUMER_2 = "info-consumer-2";
+ private static final String INFO_PRODUCER_1 = "info-producer-1";
+ private static final String INFO_PRODUCER_2 = "info-producer-2";
+
+ @Autowired
+ private DmePayloadValidator dmePayloadValidator;
+
+ @Test
+ void testDmePayloadValidatorSuccess() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoTypesProducer(Set.of(PRODUCER_INFOTYPE_1));
+ rappDMEInstance.setInfoTypeConsumer(CONSUMER_INFOTYPE_1);
+ rappDMEInstance.setInfoConsumer(INFO_CONSUMER_1);
+ rappDMEInstance.setInfoProducer(INFO_PRODUCER_1);
+ rappInstance.setDme(rappDMEInstance);
+ assertDoesNotThrow(() -> dmePayloadValidator.validate(rapp, rappInstance));
+ }
+
+ @Test
+ void testDmePayloadValidatorSuccessWithNull() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoTypesProducer(null);
+ rappDMEInstance.setInfoTypeConsumer(null);
+ rappDMEInstance.setInfoConsumer(null);
+ rappDMEInstance.setInfoProducer(INFO_PRODUCER_1);
+ rappInstance.setDme(rappDMEInstance);
+ assertDoesNotThrow(() -> dmePayloadValidator.validate(rapp, rappInstance));
+ }
+
+ @Test
+ void testDmePayloadValidatorFailureInvalidProducerInfoType() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoTypesProducer(Set.of("invalid-infotype"));
+ rappDMEInstance.setInfoTypeConsumer(CONSUMER_INFOTYPE_1);
+ rappDMEInstance.setInfoConsumer(INFO_CONSUMER_1);
+ rappDMEInstance.setInfoProducer(INFO_PRODUCER_1);
+ rappInstance.setDme(rappDMEInstance);
+
+ RappValidationException rappValidationException =
+ assertThrows(RappValidationException.class, () -> dmePayloadValidator.validate(rapp, rappInstance));
+ assertEquals("Invalid DME info types producer in the rApp instance payload.",
+ rappValidationException.getMessage());
+ }
+
+ @Test
+ void testDmePayloadValidatorFailureInvalidConsumerInfoType() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoTypesProducer(Set.of(PRODUCER_INFOTYPE_1));
+ rappDMEInstance.setInfoTypeConsumer("invalid-infotype");
+ rappDMEInstance.setInfoConsumer(INFO_CONSUMER_1);
+ rappDMEInstance.setInfoProducer(INFO_PRODUCER_1);
+ rappInstance.setDme(rappDMEInstance);
+
+ RappValidationException rappValidationException =
+ assertThrows(RappValidationException.class, () -> dmePayloadValidator.validate(rapp, rappInstance));
+ assertEquals("Invalid DME info type consumer in the rApp instance payload.",
+ rappValidationException.getMessage());
+ }
+
+ @Test
+ void testDmePayloadValidatorFailureInvalidInfoConsumer() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoTypesProducer(Set.of(PRODUCER_INFOTYPE_1));
+ rappDMEInstance.setInfoTypeConsumer(CONSUMER_INFOTYPE_1);
+ rappDMEInstance.setInfoConsumer("invalid-consumer");
+ rappDMEInstance.setInfoProducer(INFO_PRODUCER_1);
+ rappInstance.setDme(rappDMEInstance);
+
+ RappValidationException rappValidationException =
+ assertThrows(RappValidationException.class, () -> dmePayloadValidator.validate(rapp, rappInstance));
+ assertEquals("Invalid DME info consumer in the rApp instance payload.", rappValidationException.getMessage());
+ }
+
+ @Test
+ void testDmePayloadValidatorFailureInvalidInfoProducer() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoTypesProducer(Set.of(PRODUCER_INFOTYPE_1));
+ rappDMEInstance.setInfoTypeConsumer(CONSUMER_INFOTYPE_1);
+ rappDMEInstance.setInfoConsumer(INFO_CONSUMER_1);
+ rappDMEInstance.setInfoProducer("invalid-producer");
+ rappInstance.setDme(rappDMEInstance);
+
+ RappValidationException rappValidationException =
+ assertThrows(RappValidationException.class, () -> dmePayloadValidator.validate(rapp, rappInstance));
+ assertEquals("Invalid DME info producer in the rApp instance payload.", rappValidationException.getMessage());
+ }
+
+
+ private Rapp getRapp() {
+ RappResources rappResources = new RappResources();
+ RappResources.DMEResources rappDMEResources =
+ RappResources.DMEResources.builder().producerInfoTypes(Set.of(PRODUCER_INFOTYPE_1, PRODUCER_INFOTYPE_2))
+ .consumerInfoTypes(Set.of(CONSUMER_INFOTYPE_1, CONSUMER_INFOTYPE_2))
+ .infoConsumers(Set.of(INFO_CONSUMER_1, INFO_CONSUMER_2))
+ .infoProducers(Set.of(INFO_PRODUCER_1, INFO_PRODUCER_2)).build();
+
+ rappResources.setDme(rappDMEResources);
+ return Rapp.builder().rappResources(rappResources).build();
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. 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.oransc.rappmanager.models.rappinstance.validator;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.Set;
+import org.junit.jupiter.api.Test;
+import org.oransc.rappmanager.models.exception.RappValidationException;
+import org.oransc.rappmanager.models.rapp.Rapp;
+import org.oransc.rappmanager.models.rapp.RappResources;
+import org.oransc.rappmanager.models.rapp.RappState;
+import org.oransc.rappmanager.models.rappinstance.RappACMInstance;
+import org.oransc.rappmanager.models.rappinstance.RappDMEInstance;
+import org.oransc.rappmanager.models.rappinstance.RappInstance;
+import org.oransc.rappmanager.models.rappinstance.RappSMEInstance;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ContextConfiguration;
+
+@SpringBootTest
+@ContextConfiguration(
+ classes = {RappInstanceValidationHandler.class, RappStatusValidator.class, AcmPayloadValidator.class,
+ SmePayloadValidator.class, DmePayloadValidator.class})
+class RappInstanceValidationHandlerTest {
+
+ public static final String K8S_INSTANCE = "k8s-instance";
+ public static final String A1PMS_INSTANCE = "a1pms-instance";
+ public static final String PROVIDER_1 = "provider-1";
+ public static final String PROVIDER_2 = "provider-2";
+ public static final String INV_1 = "inv-1";
+ public static final String INV_2 = "inv-2";
+ public static final String SVC_API_1 = "svc-api-1";
+ public static final String SVC_API_2 = "svc-api-2";
+ public static final String PROD_INFO_1 = "prod-info-1";
+ public static final String PROD_INFO_2 = "prod-info-2";
+ public static final String CONS_INFO_1 = "cons-info-1";
+ public static final String CONS_INFO_2 = "cons-info-2";
+ public static final String INFO_CONSUMER_1 = "info-consumer-1";
+ public static final String INFO_CONSUMER_2 = "info-consumer-2";
+ public static final String INFO_PRODUCER_1 = "info-producer-1";
+ public static final String INFO_PRODUCER_2 = "info-producer-2";
+ @Autowired
+ RappInstanceValidationHandler rappValidationHandler;
+
+ @Test
+ void testrAppInstanceValidationSuccessAcmInstance() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappACMInstance rappACMInstance = new RappACMInstance();
+ rappACMInstance.setInstance(K8S_INSTANCE);
+ rappInstance.setAcm(rappACMInstance);
+ assertDoesNotThrow(() -> rappValidationHandler.validateRappInstance(rapp, rappInstance));
+ }
+
+ @Test
+ void testrAppInstanceValidationSuccessSmeInstance() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappSMEInstance rappSMEInstance = new RappSMEInstance();
+ rappSMEInstance.setProviderFunction(PROVIDER_1);
+ rappSMEInstance.setServiceApis(SVC_API_1);
+ rappSMEInstance.setInvokers(INV_1);
+ rappInstance.setSme(rappSMEInstance);
+ assertDoesNotThrow(() -> rappValidationHandler.validateRappInstance(rapp, rappInstance));
+ }
+
+ @Test
+ void testrAppInstanceValidationSuccessDmeInstance() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoTypesProducer(Set.of(PROD_INFO_1));
+ rappDMEInstance.setInfoTypeConsumer(CONS_INFO_1);
+ rappDMEInstance.setInfoConsumer(INFO_CONSUMER_1);
+ rappDMEInstance.setInfoProducer(INFO_PRODUCER_1);
+ rappInstance.setDme(rappDMEInstance);
+ assertDoesNotThrow(() -> rappValidationHandler.validateRappInstance(rapp, rappInstance));
+ }
+
+ @Test
+ void testAppInstanceValidationSuccessAllInstances() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+
+ RappACMInstance rappACMInstance = new RappACMInstance();
+ rappACMInstance.setInstance(K8S_INSTANCE);
+ rappInstance.setAcm(rappACMInstance);
+
+ RappSMEInstance rappSMEInstance = new RappSMEInstance();
+ rappSMEInstance.setProviderFunction(PROVIDER_1);
+ rappSMEInstance.setServiceApis(SVC_API_1);
+ rappSMEInstance.setInvokers(INV_1);
+ rappInstance.setSme(rappSMEInstance);
+
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoTypesProducer(Set.of(PROD_INFO_1));
+ rappDMEInstance.setInfoTypeConsumer(CONS_INFO_1);
+ rappDMEInstance.setInfoConsumer(INFO_CONSUMER_1);
+ rappDMEInstance.setInfoProducer(INFO_PRODUCER_1);
+ rappInstance.setDme(rappDMEInstance);
+
+ assertDoesNotThrow(() -> rappValidationHandler.validateRappInstance(rapp, rappInstance));
+ }
+
+ @Test
+ void testrAppInstanceValidationFailureOnRappState() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappACMInstance rappACMInstance = new RappACMInstance();
+ rappACMInstance.setInstance(K8S_INSTANCE);
+ rappInstance.setAcm(rappACMInstance);
+ rapp.setState(RappState.COMMISSIONED);
+
+ RappValidationException rappValidationException = assertThrows(RappValidationException.class,
+ () -> rappValidationHandler.validateRappInstance(rapp, rappInstance));
+ assertEquals("Unable to create rApp instance as rApp is not in PRIMED state",
+ rappValidationException.getMessage());
+ }
+
+ @Test
+ void testrAppInstanceValidationFailureOnAcmPayload() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappACMInstance rappACMInstance = new RappACMInstance();
+ rappACMInstance.setInstance("invalid-instance");
+ rappInstance.setAcm(rappACMInstance);
+
+ RappValidationException rappValidationException = assertThrows(RappValidationException.class,
+ () -> rappValidationHandler.validateRappInstance(rapp, rappInstance));
+ assertEquals("Invalid ACM instance in the rApp instance payload.", rappValidationException.getMessage());
+ }
+
+ @Test
+ void testrAppInstanceValidationFailureOnSmePayload() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappSMEInstance rappSMEInstance = new RappSMEInstance();
+ rappSMEInstance.setProviderFunction("invalid-provider");
+ rappSMEInstance.setServiceApis(SVC_API_1);
+ rappSMEInstance.setInvokers(INV_1);
+ rappInstance.setSme(rappSMEInstance);
+
+ RappValidationException rappValidationException = assertThrows(RappValidationException.class,
+ () -> rappValidationHandler.validateRappInstance(rapp, rappInstance));
+ assertEquals("Invalid SME provider function in the rApp instance payload.",
+ rappValidationException.getMessage());
+ }
+
+ @Test
+ void testrAppInstanceValidationFailureOnDmePayload() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoTypesProducer(Set.of("invalid-prod-info"));
+ rappDMEInstance.setInfoTypeConsumer(CONS_INFO_1);
+ rappDMEInstance.setInfoConsumer(INFO_CONSUMER_1);
+ rappDMEInstance.setInfoProducer(INFO_PRODUCER_1);
+ rappInstance.setDme(rappDMEInstance);
+
+ RappValidationException rappValidationException = assertThrows(RappValidationException.class,
+ () -> rappValidationHandler.validateRappInstance(rapp, rappInstance));
+ assertEquals("Invalid DME info types producer in the rApp instance payload.",
+ rappValidationException.getMessage());
+ }
+
+ Rapp getRapp() {
+ RappResources rappResources = new RappResources();
+ RappResources.ACMResources acmResources =
+ RappResources.ACMResources.builder().compositionInstances(Set.of(K8S_INSTANCE, A1PMS_INSTANCE)).build();
+ rappResources.setAcm(acmResources);
+ RappResources.SMEResources smeResources =
+ RappResources.SMEResources.builder().providerFunctions(Set.of(PROVIDER_1, PROVIDER_2))
+ .serviceApis(Set.of(SVC_API_1, SVC_API_2)).invokers(Set.of(INV_1, INV_2)).build();
+ rappResources.setSme(smeResources);
+ RappResources.DMEResources dmeResources =
+ RappResources.DMEResources.builder().producerInfoTypes(Set.of(PROD_INFO_1, PROD_INFO_2))
+ .consumerInfoTypes(Set.of(CONS_INFO_1, CONS_INFO_2))
+ .infoConsumers(Set.of(INFO_CONSUMER_1, INFO_CONSUMER_2))
+ .infoProducers(Set.of(INFO_PRODUCER_1, INFO_PRODUCER_2)).build();
+ rappResources.setDme(dmeResources);
+
+ return Rapp.builder().name("").state(RappState.PRIMED).rappResources(rappResources).build();
+ }
+}
--- /dev/null
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. 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.oransc.rappmanager.models.rappinstance.validator;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+import org.oransc.rappmanager.models.exception.RappValidationException;
+import org.oransc.rappmanager.models.rapp.Rapp;
+import org.oransc.rappmanager.models.rapp.RappState;
+import org.oransc.rappmanager.models.rappinstance.RappInstance;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ContextConfiguration;
+
+@SpringBootTest
+@ContextConfiguration(classes = {RappStatusValidator.class})
+class RappStatusValidatorTest {
+
+ @Autowired
+ private RappStatusValidator rappStatusValidator;
+
+ @Test
+ void testRappStatusValidatorSuccess() {
+ Rapp rapp = Rapp.builder().state(RappState.PRIMED).build();
+ RappInstance rAppInstance = new RappInstance();
+ assertDoesNotThrow(() -> rappStatusValidator.validate(rapp, rAppInstance));
+ }
+
+ @Test
+ void testRappStatusValidatorFailure() {
+ Rapp rapp = Rapp.builder().state(RappState.COMMISSIONED).build();
+ RappInstance rAppInstance = new RappInstance();
+ RappValidationException rappValidationException =
+ assertThrows(RappValidationException.class, () -> rappStatusValidator.validate(rapp, rAppInstance));
+ assertEquals("Unable to create rApp instance as rApp is not in PRIMED state",
+ rappValidationException.getMessage());
+ }
+
+}
--- /dev/null
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. 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.oransc.rappmanager.models.rappinstance.validator;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.Set;
+import org.junit.jupiter.api.Test;
+import org.oransc.rappmanager.models.exception.RappValidationException;
+import org.oransc.rappmanager.models.rapp.Rapp;
+import org.oransc.rappmanager.models.rapp.RappResources;
+import org.oransc.rappmanager.models.rappinstance.RappInstance;
+import org.oransc.rappmanager.models.rappinstance.RappSMEInstance;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ContextConfiguration;
+
+@SpringBootTest
+@ContextConfiguration(classes = {SmePayloadValidator.class})
+class SmePayloadValidatorTest {
+
+ public static final String PROVIDER_FUNCTION_1 = "provider-function-1";
+ public static final String SERVICE_API_1 = "service-api-1";
+ public static final String INVOKER_1 = "invoker-1";
+ @Autowired
+ private SmePayloadValidator smePayloadValidator;
+
+ @Test
+ void testSmePayloadValidatorSuccess() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappSMEInstance rappSMEInstance = new RappSMEInstance();
+ rappSMEInstance.setProviderFunction(PROVIDER_FUNCTION_1);
+ rappSMEInstance.setServiceApis(SERVICE_API_1);
+ rappSMEInstance.setInvokers(INVOKER_1);
+ rappInstance.setSme(rappSMEInstance);
+ assertDoesNotThrow(() -> smePayloadValidator.validate(rapp, rappInstance));
+ }
+
+ @Test
+ void testSmePayloadValidatorSuccessWithNull() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappSMEInstance rappSMEInstance = new RappSMEInstance();
+ rappSMEInstance.setProviderFunction(null);
+ rappSMEInstance.setServiceApis(null);
+ rappSMEInstance.setInvokers(INVOKER_1);
+ rappInstance.setSme(rappSMEInstance);
+ assertDoesNotThrow(() -> smePayloadValidator.validate(rapp, rappInstance));
+ }
+
+ @Test
+ void testSmePayloadValidatorFailureInvalidProviderFunction() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappSMEInstance rappSMEInstance = new RappSMEInstance();
+ rappSMEInstance.setProviderFunction("invalid-provider-function");
+ rappSMEInstance.setServiceApis(SERVICE_API_1);
+ rappSMEInstance.setInvokers(INVOKER_1);
+ rappInstance.setSme(rappSMEInstance);
+
+ RappValidationException rappValidationException =
+ assertThrows(RappValidationException.class, () -> smePayloadValidator.validate(rapp, rappInstance));
+ assertEquals("Invalid SME provider function in the rApp instance payload.",
+ rappValidationException.getMessage());
+ }
+
+ @Test
+ void testSmePayloadValidatorFailureInvalidServiceApis() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappSMEInstance rappSMEInstance = new RappSMEInstance();
+ rappSMEInstance.setProviderFunction(PROVIDER_FUNCTION_1);
+ rappSMEInstance.setServiceApis("invalid-service-api");
+ rappSMEInstance.setInvokers(INVOKER_1);
+ rappInstance.setSme(rappSMEInstance);
+
+ RappValidationException rappValidationException =
+ assertThrows(RappValidationException.class, () -> smePayloadValidator.validate(rapp, rappInstance));
+ assertEquals("Invalid SME service APIs in the rApp instance payload.", rappValidationException.getMessage());
+ }
+
+ @Test
+ void testSmePayloadValidatorFailureInvalidInvokers() {
+ Rapp rapp = getRapp();
+ RappInstance rappInstance = new RappInstance();
+ RappSMEInstance rappSMEInstance = new RappSMEInstance();
+ rappSMEInstance.setProviderFunction(PROVIDER_FUNCTION_1);
+ rappSMEInstance.setServiceApis(SERVICE_API_1);
+ rappSMEInstance.setInvokers("invalid-invoker");
+ rappInstance.setSme(rappSMEInstance);
+
+ RappValidationException rappValidationException =
+ assertThrows(RappValidationException.class, () -> smePayloadValidator.validate(rapp, rappInstance));
+ assertEquals("Invalid SME invokers in the rApp instance payload.", rappValidationException.getMessage());
+ }
+
+
+ private Rapp getRapp() {
+ RappResources rappResources = new RappResources();
+ RappResources.SMEResources rappSMEResources = RappResources.SMEResources.builder().providerFunctions(
+ Set.of(PROVIDER_FUNCTION_1, "provider-function-2")).serviceApis(Set.of(SERVICE_API_1, "service-api-2"))
+ .invokers(Set.of(INVOKER_1, "invoker-2")).build();
+
+ rappResources.setSme(rappSMEResources);
+ return Rapp.builder().rappResources(rappResources).build();
+ }
+}