/*-
* ============LICENSE_START======================================================================
* Copyright (C) 2023 Nordix Foundation. All rights reserved.
- * Copyright (C) 2023-2024 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2023-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.
automationComposition.getCompositionId(), automationComposition.getInstanceId(),
UUID.randomUUID());
rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMUNDEPLOYED);
+ rappInstance.getAcm().setAcmInstanceId(null);
return true;
}
}
}
public void syncRappInstanceStatus(UUID compositionId, RappInstance rappInstance) {
- if (rappInstance.getAcm().getAcmInstanceId() != null) {
+ if (rappInstance.getAcm() != null && rappInstance.getAcm().getAcmInstanceId() != null) {
try {
AutomationComposition compositionInstance =
automationCompositionInstanceApiClient.getCompositionInstance(compositionId,
boolean rappUndeployStateActual = acmDeployer.undeployRappInstance(rapp, rappInstance);
mockServer.verify();
assertTrue(rappUndeployStateActual);
+ assertNull(rappInstance.getAcm().getAcmInstanceId());
}
@Test
verify(rappInstanceStateMachine, never()).sendRappInstanceEvent(any(), any());
}
+ @Test
+ void testSyncRappStatusFailureAcmNull() {
+ UUID compositionId = UUID.randomUUID();
+ RappInstance rappInstance = rappResourceBuilder.getRappInstance();
+ rappInstance.setAcm(null);
+ rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
+ acmDeployer.syncRappInstanceStatus(compositionId, rappInstance);
+ verify(rappInstanceStateMachine, never()).sendRappInstanceEvent(any(), any());
+ }
+
+ @Test
+ void testSyncRappStatusFailureAcmInstanceIdNull() {
+ UUID compositionId = UUID.randomUUID();
+ RappInstance rappInstance = rappResourceBuilder.getRappInstance();
+ rappInstance.getAcm().setAcmInstanceId(null);
+ rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
+ acmDeployer.syncRappInstanceStatus(compositionId, rappInstance);
+ verify(rappInstanceStateMachine, never()).sendRappInstanceEvent(any(), any());
+ }
+
@Test
void testPrimeRapp() throws JsonProcessingException {
UUID compositionId = UUID.randomUUID();
import org.oransc.rappmanager.models.rapp.RappPrimeOrder;
import org.oransc.rappmanager.models.rapp.RappState;
import org.oransc.rappmanager.service.RappService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
@RequiredArgsConstructor
public class RappController {
- Logger logger = LoggerFactory.getLogger(RappController.class);
private final RappCsarConfigurationHandler rappCsarConfigurationHandler;
private final RappValidationHandler rappValidationHandler;
private final RappManagerConfiguration rappManagerConfiguration;
@GetMapping
public ResponseEntity<Collection<Rapp>> getRapps() {
- return ResponseEntity.ok(rappCacheService.getAllRapp());
+ return ResponseEntity.ok(rappService.syncRappStates(rappCacheService.getAllRapp()));
}
@GetMapping("{rapp_id}")
public ResponseEntity<Rapp> getRapp(@PathVariable("rapp_id") String rappId) {
- return rappCacheService.getRapp(rappId).map(ResponseEntity::ok).orElseThrow(
+ return rappCacheService.getRapp(rappId).map(rappService::syncRappState).map(ResponseEntity::ok).orElseThrow(
() -> new RappHandlerException(HttpStatus.NOT_FOUND, String.format(RAPP_NOT_FOUND, rappId)));
}
@GetMapping
public ResponseEntity<Map<UUID, RappInstance>> getAllRappInstances(@PathVariable("rapp_id") String rappId) {
- return rappCacheService.getRapp(rappId).map(Rapp::getRappInstances).map(ResponseEntity::ok).orElseThrow(
- () -> new RappHandlerException(HttpStatus.NOT_FOUND, "No instance found for rApp '" + rappId + "'."));
+ return rappCacheService.getRapp(rappId).map(rappService::syncRappState).map(Rapp::getRappInstances)
+ .map(ResponseEntity::ok).orElseThrow(() -> new RappHandlerException(HttpStatus.NOT_FOUND,
+ "No instance found for rApp '" + rappId + "'."));
}
@PostMapping
/*-
* ============LICENSE_START======================================================================
* Copyright (C) 2023 Nordix Foundation. All rights reserved.
- * Copyright (C) 2023-2024 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2023-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.
package org.oransc.rappmanager.service;
+import java.util.Collection;
import java.util.List;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
if (rApp.getRappInstances().get(rappInstanceId).getState().equals(RappInstanceState.UNDEPLOYED)) {
rappInstanceStateMachine.deleteRappInstance(rApp.getRappInstances().get(rappInstanceId));
rApp.getRappInstances().remove(rappInstanceId);
+ rappCacheService.putRapp(rApp);
return ResponseEntity.noContent().build();
}
throw new RappHandlerException(HttpStatus.BAD_REQUEST,
public void updateRappInstanceState(Rapp rapp, RappInstance rappInstance) {
acmDeployer.syncRappInstanceStatus(rapp.getCompositionId(), rappInstance);
}
+
+ public Collection<Rapp> syncRappStates(Collection<Rapp> rapps) {
+ rapps.forEach(this::syncRappState);
+ return rapps;
+ }
+
+ public Rapp syncRappState(Rapp rapp) {
+ rapp.getRappInstances().forEach((instanceId, instance) -> {
+ updateRappInstanceState(rapp, instance);
+ instance.setState(rappInstanceStateMachine.getRappInstanceState(instanceId));
+ });
+ return rapp;
+ }
}
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.oransc.rappmanager.models.rapp.Rapp;
import org.oransc.rappmanager.models.rapp.RappPrimeOrder;
import org.oransc.rappmanager.models.rapp.RappState;
+import org.oransc.rappmanager.models.rappinstance.RappInstance;
+import org.oransc.rappmanager.models.rappinstance.RappInstanceState;
+import org.oransc.rappmanager.models.statemachine.RappInstanceStateMachine;
import org.oransc.rappmanager.sme.service.SmeLifecycleManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
@Autowired
private RappCacheService rappCacheService;
+ @Autowired
+ RappInstanceStateMachine rappInstanceStateMachine;
+
@MockitoBean
AcmDeployer acmDeployer;
mockMvc.perform(MockMvcRequestBuilders.get("/rapps")).andExpect(status().isOk())
.andExpect(jsonPath("$", hasSize(0)));
UUID rappId = UUID.randomUUID();
+ UUID instanceId = UUID.randomUUID();
+ RappInstance instance = new RappInstance();
+ instance.setRappInstanceId(instanceId);
+ instance.setState(RappInstanceState.UNDEPLOYED);
+ Map<UUID, RappInstance> instances = Map.of(instanceId, instance);
Rapp rapp = Rapp.builder().rappId(rappId).name(String.valueOf(rappId)).packageName(validRappFile)
- .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build();
+ .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).rappInstances(instances).build();
AsdMetadata asdMetadata = new AsdMetadata();
asdMetadata.setDescriptorId(UUID.randomUUID().toString());
asdMetadata.setDescriptorInvariantId(UUID.randomUUID().toString());
asdMetadata.setDeploymentItems(List.of());
rapp.setAsdMetadata(asdMetadata);
rappCacheService.putRapp(rapp);
+ rappInstanceStateMachine.onboardRappInstance(instanceId);
mockMvc.perform(MockMvcRequestBuilders.get("/rapps")).andExpect(status().isOk())
- .andExpect(jsonPath("$", hasSize(1)));
+ .andExpect(jsonPath("$", hasSize(1)))
+ .andExpect(jsonPath("$[0].rappInstances." + instanceId + ".rappInstanceId").value(instanceId.toString()))
+ .andExpect(jsonPath("$[0].rappInstances." + instanceId + ".state").value(instance.getState().name()));
}
@Test
void testGetRapp() throws Exception {
UUID rappId = UUID.randomUUID();
+ UUID instanceId = UUID.randomUUID();
+ RappInstance instance = new RappInstance();
+ instance.setRappInstanceId(instanceId);
+ instance.setState(RappInstanceState.UNDEPLOYED);
+ Map<UUID, RappInstance> instances = Map.of(instanceId, instance);
Rapp rapp = Rapp.builder().rappId(rappId).name(String.valueOf(rappId)).packageName(validRappFile)
- .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build();
+ .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).rappInstances(instances).build();
AsdMetadata asdMetadata = new AsdMetadata();
asdMetadata.setDescriptorId(UUID.randomUUID().toString());
asdMetadata.setDescriptorInvariantId(UUID.randomUUID().toString());
asdMetadata.setDeploymentItems(List.of());
rapp.setAsdMetadata(asdMetadata);
rappCacheService.putRapp(rapp);
+ rappInstanceStateMachine.onboardRappInstance(instanceId);
mockMvc.perform(MockMvcRequestBuilders.get("/rapps/{rapp_id}", rappId)).andExpect(status().isOk())
.andExpect(jsonPath("$.rappId").value(rappId.toString()))
- .andExpect(jsonPath("$.state").value(RappState.COMMISSIONED.name()));
+ .andExpect(jsonPath("$.state").value(RappState.COMMISSIONED.name()))
+ .andExpect(jsonPath("$.rappInstances." + instanceId + ".rappInstanceId").value(instanceId.toString()))
+ .andExpect(jsonPath("$.rappInstances." + instanceId + ".state").value(instance.getState().name()));
}
@Test
UUID rappInstanceId = UUID.randomUUID();
Rapp rapp = getRapp(rappId, rappInstanceId);
rappCacheService.putRapp(rapp);
+ rappInstanceStateMachine.onboardRappInstance(rappInstanceId);
mockMvc.perform(MockMvcRequestBuilders.get("/rapps/{rapp_id}/instance", rappId)).andExpect(status().isOk())
.andExpect(
jsonPath("$." + rappInstanceId.toString() + ".rappInstanceId").value(rappInstanceId.toString()))
},
"namespace": "nonrtric",
"releaseName": "ics-consumer",
- "podName": "ics-consumer",
+ "podName": "kafka-consumer",
"repository": {
"repoName": "local",
"address": "UPDATE_THIS_CHART_MUSEUM_GET_CHARTS_URI"
},
"namespace": "nonrtric",
"releaseName": "ics-producer",
- "podName": "ics-producer",
+ "podName": "kafka-producer",
"repository": {
"repoName": "local",
"address": "UPDATE_THIS_CHART_MUSEUM_GET_CHARTS_URI"