From: aravind.est Date: Wed, 26 Jul 2023 11:24:30 +0000 (+0100) Subject: Add Rapp Instances X-Git-Tag: 0.0.1~61 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F25%2F11525%2F2;p=nonrtric%2Fplt%2Frappmanager.git Add Rapp Instances Add rapp instances. Move deployment lifecycle to rapp instance. Issue-ID: NONRTRIC-897 Signed-off-by: aravind.est Change-Id: I36cb3c204b5a2aa4fdfd2d3361c4abc7cf38f236 --- diff --git a/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/configuration/ACMConfiguration.java b/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/configuration/ACMConfiguration.java index 6582775..956f928 100755 --- a/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/configuration/ACMConfiguration.java +++ b/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/configuration/ACMConfiguration.java @@ -30,7 +30,6 @@ public class ACMConfiguration { String baseUrl; String username; String password; - String compositionDefinitionLocation; int maxRetries; int retryInterval; } diff --git a/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/service/AcmDeployer.java b/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/service/AcmDeployer.java index def268b..287761a 100755 --- a/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/service/AcmDeployer.java +++ b/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/service/AcmDeployer.java @@ -21,24 +21,20 @@ package com.oransc.rappmanager.acm.service; import com.oransc.rappmanager.acm.configuration.ACMConfiguration; import com.oransc.rappmanager.acm.rest.AutomationCompositionDefinitionApiClient; import com.oransc.rappmanager.acm.rest.AutomationCompositionInstanceApiClient; -import com.oransc.rappmanager.acm.rest.ParticipantMonitoringApiClient; -import com.oransc.rappmanager.models.Rapp; -import com.oransc.rappmanager.models.RappCsarConfigurationHandler; import com.oransc.rappmanager.models.RappDeployer; -import com.oransc.rappmanager.models.RappEvent; -import com.oransc.rappmanager.models.RappState; -import com.oransc.rappmanager.models.cache.RappCacheService; -import com.oransc.rappmanager.models.statemachine.RappStateMachine; -import java.util.List; +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.rapp.RappEvent; +import com.oransc.rappmanager.models.rapp.RappState; +import com.oransc.rappmanager.models.rappinstance.RappACMInstance; +import com.oransc.rappmanager.models.rappinstance.RappInstance; +import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine; import java.util.UUID; import java.util.concurrent.TimeUnit; -import lombok.Getter; import lombok.RequiredArgsConstructor; -import org.onap.policy.clamp.models.acm.concepts.AcTypeState; import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; import org.onap.policy.clamp.models.acm.concepts.DeployState; import org.onap.policy.clamp.models.acm.concepts.LockState; -import org.onap.policy.clamp.models.acm.concepts.ParticipantInformation; import org.onap.policy.clamp.models.acm.messages.rest.commissioning.AcTypeStateUpdate; import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse; import org.onap.policy.clamp.models.acm.messages.rest.commissioning.PrimeOrder; @@ -56,26 +52,17 @@ public class AcmDeployer implements RappDeployer { Logger logger = LoggerFactory.getLogger(AcmDeployer.class); - private final ParticipantMonitoringApiClient participantMonitoringApiClient; private final AutomationCompositionDefinitionApiClient automationCompositionDefinitionApiClient; private final AutomationCompositionInstanceApiClient automationCompositionInstanceApiClient; private final RappCsarConfigurationHandler rappCsarConfigurationHandler; - private final RappCacheService rappCacheService; - private final RappStateMachine rappStateMachine; + private final RappInstanceStateMachine rappInstanceStateMachine; private final ACMConfiguration acmConfiguration; - @Getter - private UUID compositionId; - public List getAllParticipants() { - return participantMonitoringApiClient.queryParticipants(null, null, UUID.randomUUID()); - } - - - void updateACMInstanceState(Rapp rapp, DeployOrder deployOrder) { + void updateACMInstanceState(UUID compositionId, RappACMInstance rappACMInstance, DeployOrder deployOrder) { AcInstanceStateUpdate acInstanceStateUpdate = new AcInstanceStateUpdate(); acInstanceStateUpdate.setDeployOrder(deployOrder); - automationCompositionInstanceApiClient.compositionInstanceState(rapp.getCompositionId(), - rapp.getCompositionInstanceId(), acInstanceStateUpdate, UUID.randomUUID()); + automationCompositionInstanceApiClient.compositionInstanceState(compositionId, + rappACMInstance.getAcmInstanceId(), acInstanceStateUpdate, UUID.randomUUID()); } public void primeACMComposition(UUID compositionId, PrimeOrder primeOrder) { @@ -91,7 +78,6 @@ public class AcmDeployer implements RappDeployer { commissioningResponse = automationCompositionDefinitionApiClient.createCompositionDefinitions(compositionPayload, UUID.randomUUID()); - compositionId = commissioningResponse.getCompositionId(); } catch (Exception e) { logger.warn("Error in creating composition", e); } @@ -99,13 +85,13 @@ public class AcmDeployer implements RappDeployer { } public CommissioningResponse deleteComposition(UUID compositionId) { - return automationCompositionDefinitionApiClient.deleteCompositionDefinition(compositionId, UUID.randomUUID()); - } - - public boolean isCompositionStateEquals(UUID compositionId, AcTypeState acTypeState) { - //automationCompositionDefinitionApiClient.getCompositionDefinition(compositionId, UUID.randomUUID()).getState().equals(acTypeState); - //TODO httpmessage converter doesn't map AutomationCompositionDefinition properly, Fix that and check the response - return true; + try { + return automationCompositionDefinitionApiClient.deleteCompositionDefinition(compositionId, + UUID.randomUUID()); + } catch (Exception e) { + logger.warn("Error in deleting composition {}", compositionId, e); + } + return null; } boolean isCompositionInstanceStateEquals(UUID compositionId, UUID compositionIntanceId, DeployState deployState) { @@ -113,15 +99,17 @@ public class AcmDeployer implements RappDeployer { UUID.randomUUID()).getDeployState().equals(deployState); } - boolean waitForCompositionInstanceTargetState(Rapp rapp, DeployState deployState) { + boolean waitForCompositionInstanceTargetState(UUID compositionId, RappInstance rappInstance, + DeployState deployState) { boolean targetInstanceStateTransition = false; try { for (int i = 0; i < acmConfiguration.getMaxRetries(); i++) { logger.debug("Composition instance state check {}", i + 1); - if (isCompositionInstanceStateEquals(rapp.getCompositionId(), rapp.getCompositionInstanceId(), + if (isCompositionInstanceStateEquals(compositionId, rappInstance.getAcm().getAcmInstanceId(), deployState)) { - sendRappStateEvent(rapp, deployState); - logger.info("Composition instance {} state is {}", rapp.getCompositionInstanceId(), deployState); + sendRappInstanceStateEvent(rappInstance, deployState); + logger.info("Composition instance {} state is {}", rappInstance.getAcm().getAcmInstanceId(), + deployState); targetInstanceStateTransition = true; break; } else { @@ -129,23 +117,23 @@ public class AcmDeployer implements RappDeployer { } } } catch (Exception e) { - logger.warn("Unable to get composition instance state for composition {}", rapp.getCompositionId()); + logger.warn("Unable to get composition instance state for composition {}", compositionId, e); } return targetInstanceStateTransition; } @Override - public boolean deployRapp(Rapp rapp) { + public boolean deployRappInstance(Rapp rapp, RappInstance rappInstance) { try { - rapp.setCompositionId(getCompositionId()); String instantiationPayload = - rappCsarConfigurationHandler.getInstantiationPayload(rapp, getCompositionId()); + rappCsarConfigurationHandler.getInstantiationPayload(rapp, rappInstance.getAcm(), + rapp.getCompositionId()); InstantiationResponse instantiationResponse = - automationCompositionInstanceApiClient.createCompositionInstance(getCompositionId(), + automationCompositionInstanceApiClient.createCompositionInstance(rapp.getCompositionId(), instantiationPayload, UUID.randomUUID()); if (instantiationResponse.getInstanceId() != null) { - rapp.setCompositionInstanceId(instantiationResponse.getInstanceId()); - updateACMInstanceState(rapp, DeployOrder.DEPLOY); + rappInstance.getAcm().setAcmInstanceId(instantiationResponse.getInstanceId()); + updateACMInstanceState(rapp.getCompositionId(), rappInstance.getAcm(), DeployOrder.DEPLOY); return true; } } catch (Exception e) { @@ -155,47 +143,82 @@ public class AcmDeployer implements RappDeployer { } @Override - public boolean undeployRapp(Rapp rapp) { + public boolean undeployRappInstance(Rapp rapp, RappInstance rappInstance) { AutomationComposition automationComposition = automationCompositionInstanceApiClient.getCompositionInstance(rapp.getCompositionId(), - rapp.getCompositionInstanceId(), UUID.randomUUID()); + rappInstance.getAcm().getAcmInstanceId(), UUID.randomUUID()); if (automationComposition.getDeployState().equals(DeployState.DEPLOYED) && automationComposition.getLockState() .equals(LockState.LOCKED)) { - updateACMInstanceState(rapp, DeployOrder.UNDEPLOY); - if (waitForCompositionInstanceTargetState(rapp, DeployState.UNDEPLOYED)) { + updateACMInstanceState(rapp.getCompositionId(), rappInstance.getAcm(), DeployOrder.UNDEPLOY); + if (waitForCompositionInstanceTargetState(rapp.getCompositionId(), rappInstance, DeployState.UNDEPLOYED)) { automationCompositionInstanceApiClient.deleteCompositionInstance( automationComposition.getCompositionId(), automationComposition.getInstanceId(), UUID.randomUUID()); - rappStateMachine.sendRappEvent(rapp, RappEvent.ACMUNDEPLOYED); + rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMUNDEPLOYED); + return true; + } + } + return false; + } + + @Override + public boolean primeRapp(Rapp rapp) { + logger.info("Priming rapp {}", rapp.getName()); + try { + String compositionPayload = rappCsarConfigurationHandler.getAcmCompositionPayload(rapp); + CommissioningResponse commissioningResponse = createComposition(compositionPayload); + if (commissioningResponse != null && commissioningResponse.getCompositionId() != null) { + rapp.setCompositionId(commissioningResponse.getCompositionId()); + logger.info("Priming automation Composition"); + primeACMComposition(commissioningResponse.getCompositionId(), PrimeOrder.PRIME); + rapp.setState(RappState.PRIMED); return true; + } else { + logger.error("Failed to create automation composition"); } + } catch (Exception e) { + logger.error("Failed to create automation composition", e); + } + return false; + } + + @Override + public boolean deprimeRapp(Rapp rapp) { + try { + primeACMComposition(rapp.getCompositionId(), PrimeOrder.DEPRIME); + CommissioningResponse commissioningResponse = deleteComposition(rapp.getCompositionId()); + if (commissioningResponse != null) { + rapp.setState(RappState.COMMISSIONED); + return true; + } + } catch (Exception e) { + logger.error("Failed deprime automation composition", e); } return false; } - public void syncRappStatus(Rapp rapp) { - if (rapp.getCompositionId() != null && rapp.getCompositionInstanceId() != null) { + public void syncRappInstanceStatus(UUID compositionId, RappInstance rappInstance) { + if (rappInstance.getAcm().getAcmInstanceId() != null) { try { AutomationComposition compositionInstance = - automationCompositionInstanceApiClient.getCompositionInstance(rapp.getCompositionId(), - rapp.getCompositionInstanceId(), UUID.randomUUID()); - logger.info("ACM details are " + compositionInstance.toString()); - sendRappStateEvent(rapp, compositionInstance.getDeployState()); + automationCompositionInstanceApiClient.getCompositionInstance(compositionId, + rappInstance.getAcm().getAcmInstanceId(), UUID.randomUUID()); + sendRappInstanceStateEvent(rappInstance, compositionInstance.getDeployState()); } catch (RestClientException exception) { - logger.warn("Unable to get the ACM details for rapp {}", rapp.getName()); + logger.warn("Unable to get the ACM details for rapp instance {}", rappInstance.getRappInstanceId()); } } } - void sendRappStateEvent(Rapp rapp, DeployState deployState) { + void sendRappInstanceStateEvent(RappInstance rappInstance, DeployState deployState) { if (deployState.equals(DeployState.DEPLOYED)) { - rappStateMachine.sendRappEvent(rapp, RappEvent.ACMDEPLOYED); + rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMDEPLOYED); } else if (deployState.equals(DeployState.UNDEPLOYED)) { - rappStateMachine.sendRappEvent(rapp, RappEvent.ACMUNDEPLOYED); + rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.ACMUNDEPLOYED); } else if (deployState.equals(DeployState.DEPLOYING)) { - rappStateMachine.sendRappEvent(rapp, RappEvent.DEPLOYING); + rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DEPLOYING); } else if (deployState.equals(DeployState.UNDEPLOYING)) { - rappStateMachine.sendRappEvent(rapp, RappEvent.UNDEPLOYING); + rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.UNDEPLOYING); } } } diff --git a/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/service/AutomationCompositionLifeCycleManager.java b/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/service/AutomationCompositionLifeCycleManager.java deleted file mode 100755 index 8498bdf..0000000 --- a/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/service/AutomationCompositionLifeCycleManager.java +++ /dev/null @@ -1,104 +0,0 @@ -/*- - * ============LICENSE_START====================================================================== - * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.acm.service; - - -import com.oransc.rappmanager.acm.configuration.ACMConfiguration; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.concurrent.TimeUnit; -import lombok.RequiredArgsConstructor; -import org.onap.policy.clamp.models.acm.concepts.AcTypeState; -import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse; -import org.onap.policy.clamp.models.acm.messages.rest.commissioning.PrimeOrder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.SmartLifecycle; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class AutomationCompositionLifeCycleManager implements SmartLifecycle { - - Logger logger = LoggerFactory.getLogger(AutomationCompositionLifeCycleManager.class); - private final ACMConfiguration acmConfiguration; - private final AcmDeployer acmDeployer; - private boolean running; - - @Override - public void start() { - logger.info("Initializing automation Composition"); - try { - String compositionPayload = Files.readString(Path.of(acmConfiguration.getCompositionDefinitionLocation())); - CommissioningResponse commissioningResponse = - acmDeployer.createComposition(compositionPayload); - if (commissioningResponse != null && commissioningResponse.getCompositionId() != null) { - logger.info("Priming automation Composition"); - acmDeployer.primeACMComposition(commissioningResponse.getCompositionId(), - PrimeOrder.PRIME); - for (int i = 0; i < acmConfiguration.getMaxRetries(); i++) { - logger.debug("Composition priming check {}", i + 1); - if (acmDeployer.isCompositionStateEquals(commissioningResponse.getCompositionId(), - AcTypeState.PRIMED)) { - logger.info("Composition {} is primed", commissioningResponse.getCompositionId()); - running = true; - break; - } else { - TimeUnit.SECONDS.sleep(acmConfiguration.getRetryInterval()); - } - } - } else { - logger.error("Failed to create automation composition"); - } - } catch (Exception e) { - logger.error("Failed to create automation composition", e); - } - } - - @Override - public void stop() { - logger.info("Depriming automation Composition"); - if (running) { - try { - acmDeployer.primeACMComposition(acmDeployer.getCompositionId(), - PrimeOrder.DEPRIME); - for (int i = 0; i < acmConfiguration.getMaxRetries(); i++) { - logger.debug("Composition depriming check {}", i + 1); - if (acmDeployer.isCompositionStateEquals( - acmDeployer.getCompositionId(), AcTypeState.COMMISSIONED)) { - logger.info("Composition {} is deprimed", acmDeployer.getCompositionId()); - logger.info("Deleting automation Composition"); - acmDeployer.deleteComposition(acmDeployer.getCompositionId()); - running = false; - break; - } else { - TimeUnit.SECONDS.sleep(acmConfiguration.getRetryInterval()); - } - } - } catch (Exception e) { - logger.error("Failed to cleanup automation composition"); - } - } - } - - @Override - public boolean isRunning() { - return running; - } -} diff --git a/rapp-manager-acm/src/test/java/com/oransc/rappmanager/acm/service/AcmDeployerTest.java b/rapp-manager-acm/src/test/java/com/oransc/rappmanager/acm/service/AcmDeployerTest.java new file mode 100755 index 0000000..928f4bc --- /dev/null +++ b/rapp-manager-acm/src/test/java/com/oransc/rappmanager/acm/service/AcmDeployerTest.java @@ -0,0 +1,394 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.acm.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.oransc.rappmanager.acm.configuration.ACMConfiguration; +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.rapp.RappEvent; +import com.oransc.rappmanager.models.rappinstance.RappInstance; +import com.oransc.rappmanager.models.rapp.RappResourceBuilder; +import com.oransc.rappmanager.models.rapp.RappResources; +import com.oransc.rappmanager.models.rapp.RappState; +import com.oransc.rappmanager.models.cache.RappCacheService; +import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine; +import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachineConfig; +import java.io.IOException; +import java.util.UUID; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.DeployState; +import org.onap.policy.clamp.models.acm.concepts.LockState; +import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse; +import org.onap.policy.clamp.models.acm.messages.rest.commissioning.PrimeOrder; +import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.test.web.client.ExpectedCount; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.web.client.RestTemplate; + +@SpringBootTest(classes = {BeanTestConfiguration.class, ACMConfiguration.class, AcmDeployer.class, + RappCsarConfigurationHandler.class, RappCacheService.class, RappInstanceStateMachineConfig.class, + RappInstanceStateMachine.class}) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@AutoConfigureMockMvc +public class AcmDeployerTest { + + MockRestServiceServer mockServer; + @SpyBean + AcmDeployer acmDeployer; + @Autowired + RestTemplate restTemplate; + @Autowired + ACMConfiguration acmConfiguration; + @SpyBean + RappInstanceStateMachine rappInstanceStateMachine; + @Autowired + RappCsarConfigurationHandler rappCsarConfigurationHandler; + + RappResourceBuilder rappResourceBuilder = new RappResourceBuilder(); + private final String validRappFile = "valid-rapp-package.csar"; + String validCsarFileLocation = "src/test/resources/"; + ObjectMapper objectMapper = new ObjectMapper(); + String URI_ACM_COMPOSITIONS, URI_ACM_COMPOSITION, URI_ACM_INSTANCES, URI_ACM_INSTANCE; + + @BeforeAll + void initACMURI() { + URI_ACM_COMPOSITIONS = acmConfiguration.getBaseUrl() + "compositions"; + URI_ACM_COMPOSITION = acmConfiguration.getBaseUrl() + "compositions/%s"; + URI_ACM_INSTANCES = acmConfiguration.getBaseUrl() + "compositions/%s/instances"; + URI_ACM_INSTANCE = acmConfiguration.getBaseUrl() + "compositions/%s/instances/%s"; + } + + @BeforeEach + public void init() { + mockServer = MockRestServiceServer.createServer(restTemplate); + } + + @Test + void testCreateComposition() throws IOException { + RappResources rappResources = rappResourceBuilder.getResources(); + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED) + .rappResources(rappResources).build(); + + String compositionPayload = rappCsarConfigurationHandler.getAcmCompositionPayload(rapp); + + CommissioningResponse commissioningResponseExpected = new CommissioningResponse(); + commissioningResponseExpected.setCompositionId(UUID.randomUUID()); + mockServer.expect(ExpectedCount.once(), requestTo(URI_ACM_COMPOSITIONS)).andExpect(method(HttpMethod.POST)) + .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) + .body(objectMapper.writeValueAsString(commissioningResponseExpected))); + CommissioningResponse commissioningResponseActual = acmDeployer.createComposition(compositionPayload); + mockServer.verify(); + assertEquals(commissioningResponseActual.getCompositionId(), commissioningResponseExpected.getCompositionId()); + } + + @Test + void testCreateCompositionFailure() { + RappResources rappResources = rappResourceBuilder.getResources(); + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED) + .rappResources(rappResources).build(); + String compositionPayload = rappCsarConfigurationHandler.getAcmCompositionPayload(rapp); + mockServer.expect(ExpectedCount.once(), requestTo(URI_ACM_COMPOSITIONS)).andExpect(method(HttpMethod.POST)) + .andRespond(withStatus(HttpStatus.BAD_GATEWAY)); + CommissioningResponse commissioningResponseActual = acmDeployer.createComposition(compositionPayload); + mockServer.verify(); + assertNull(commissioningResponseActual); + } + + @Test + void testCompositionPriming() { + UUID compositionId = UUID.randomUUID(); + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId))) + .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED)); + + acmDeployer.primeACMComposition(compositionId, PrimeOrder.PRIME); + mockServer.verify(); + } + + @Test + void testDeployRappInstance() throws Exception { + + UUID compositionId = UUID.randomUUID(); + UUID rappId = UUID.randomUUID(); + UUID instanceId = UUID.randomUUID(); + Rapp rapp = Rapp.builder().name(rappId.toString()).packageName(validRappFile).compositionId(compositionId) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + InstantiationResponse instantiationResponse = new InstantiationResponse(); + instantiationResponse.setInstanceId(instanceId); + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCES, compositionId))) + .andExpect(method(HttpMethod.POST)).andRespond( + withStatus(HttpStatus.ACCEPTED).contentType(MediaType.APPLICATION_JSON) + .body(objectMapper.writeValueAsString(instantiationResponse))); + mockServer.expect(ExpectedCount.once(), + requestTo(acmConfiguration.getBaseUrl() + "compositions/" + compositionId + "/instances/" + instanceId)) + .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED)); + boolean rappDeployStateActual = acmDeployer.deployRappInstance(rapp, rappResourceBuilder.getRappInstance()); + assertTrue(rappDeployStateActual); + mockServer.verify(); + } + + @Test + void testDeployRappInstanceFailure() throws Exception { + UUID compositionId = UUID.randomUUID(); + UUID rappId = UUID.randomUUID(); + UUID instanceId = UUID.randomUUID(); + Rapp rapp = Rapp.builder().name(rappId.toString()).packageName(validRappFile).compositionId(compositionId) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + InstantiationResponse instantiationResponse = new InstantiationResponse(); + instantiationResponse.setInstanceId(instanceId); + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCES, compositionId))) + .andExpect(method(HttpMethod.POST)).andRespond(withStatus(HttpStatus.BAD_GATEWAY)); + + boolean rappDeployStateActual = acmDeployer.deployRappInstance(rapp, rappResourceBuilder.getRappInstance()); + mockServer.verify(); + assertFalse(rappDeployStateActual); + } + + @Test + void testUndeployRappInstance() throws JsonProcessingException { + UUID compositionId = UUID.randomUUID(); + UUID rappId = UUID.randomUUID(); + UUID instanceId = UUID.randomUUID(); + Rapp rapp = Rapp.builder().rappId(rappId).name("").packageName(validRappFile).compositionId(compositionId) + .state(RappState.PRIMED).build(); + + expectAcmGetInstanceToReturnState(compositionId, instanceId, DeployState.DEPLOYED, LockState.LOCKED, + ExpectedCount.once()); + + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId))) + .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED)); + + expectAcmGetInstanceToReturnState(compositionId, instanceId, DeployState.UNDEPLOYED, LockState.UNLOCKED, + ExpectedCount.once()); + + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId))) + .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.NO_CONTENT)); + + RappInstance rappInstance = rappResourceBuilder.getRappInstance(); + rappInstance.getAcm().setAcmInstanceId(instanceId); + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + boolean rappUndeployStateActual = acmDeployer.undeployRappInstance(rapp, rappInstance); + mockServer.verify(); + assertTrue(rappUndeployStateActual); + } + + @Test + void testUndeployRappInstanceFailure() throws JsonProcessingException { + UUID compositionId = UUID.randomUUID(); + UUID rappId = UUID.randomUUID(); + UUID instanceId = UUID.randomUUID(); + Rapp rapp = Rapp.builder().name(rappId.toString()).packageName(validRappFile).compositionId(compositionId) + .state(RappState.PRIMED).build(); + + expectAcmGetInstanceToReturnState(compositionId, instanceId, DeployState.DEPLOYED, LockState.LOCKED, + ExpectedCount.once()); + + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId))) + .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED)); + + expectAcmGetInstanceToReturnState(compositionId, instanceId, DeployState.UNDEPLOYING, LockState.UNLOCKING, + ExpectedCount.manyTimes()); + + RappInstance rappInstance = rappResourceBuilder.getRappInstance(); + rappInstance.getAcm().setAcmInstanceId(instanceId); + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + boolean rappUndeployStateActual = acmDeployer.undeployRappInstance(rapp, rappInstance); + mockServer.verify(); + assertFalse(rappUndeployStateActual); + } + + @Test + void testSyncRappInstanceStatus() throws JsonProcessingException { + UUID compositionId = UUID.randomUUID(); + UUID instanceId = UUID.randomUUID(); + expectAcmGetInstanceToReturnState(compositionId, instanceId, DeployState.UNDEPLOYING, LockState.UNLOCKING, + ExpectedCount.once()); + RappInstance rappInstance = rappResourceBuilder.getRappInstance(); + rappInstance.getAcm().setAcmInstanceId(instanceId); + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + acmDeployer.syncRappInstanceStatus(compositionId, rappInstance); + mockServer.verify(); + verify(rappInstanceStateMachine, times(1)).sendRappInstanceEvent(rappInstance, RappEvent.UNDEPLOYING); + } + + @Test + void testSyncRappStatusFailure() { + UUID compositionId = UUID.randomUUID(); + UUID instanceId = UUID.randomUUID(); + + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId))) + .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.BAD_GATEWAY)); + + RappInstance rappInstance = rappResourceBuilder.getRappInstance(); + rappInstance.getAcm().setAcmInstanceId(instanceId); + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + acmDeployer.syncRappInstanceStatus(compositionId, rappInstance); + mockServer.verify(); + verify(rappInstanceStateMachine, never()).sendRappInstanceEvent(any(), any()); + } + + @Test + void testPrimeRapp() throws JsonProcessingException { + UUID compositionId = UUID.randomUUID(); + RappResources rappResources = rappResourceBuilder.getResources(); + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED) + .compositionId(compositionId).rappResources(rappResources).build(); + + CommissioningResponse commissioningResponseExpected = new CommissioningResponse(); + commissioningResponseExpected.setCompositionId(compositionId); + mockServer.expect(ExpectedCount.once(), requestTo(URI_ACM_COMPOSITIONS)).andExpect(method(HttpMethod.POST)) + .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) + .body(objectMapper.writeValueAsString(commissioningResponseExpected))); + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId))) + .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED)); + boolean primeRapp = acmDeployer.primeRapp(rapp); + mockServer.verify(); + assertTrue(primeRapp); + assertEquals(RappState.PRIMED, rapp.getState()); + + } + + @Test + void testPrimeRappFailure() throws JsonProcessingException { + UUID compositionId = UUID.randomUUID(); + RappResources rappResources = rappResourceBuilder.getResources(); + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED) + .compositionId(compositionId).rappResources(rappResources).build(); + + CommissioningResponse commissioningResponseExpected = new CommissioningResponse(); + commissioningResponseExpected.setCompositionId(compositionId); + mockServer.expect(ExpectedCount.once(), requestTo(URI_ACM_COMPOSITIONS)).andExpect(method(HttpMethod.POST)) + .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) + .body(objectMapper.writeValueAsString(commissioningResponseExpected))); + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId))) + .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR)); + boolean primeRapp = acmDeployer.primeRapp(rapp); + mockServer.verify(); + assertFalse(primeRapp); + assertEquals(RappState.COMMISSIONED, rapp.getState()); + } + + @Test + void testDeprimeRapp() throws JsonProcessingException { + UUID compositionId = UUID.randomUUID(); + RappResources rappResources = rappResourceBuilder.getResources(); + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED) + .compositionId(compositionId).rappResources(rappResources).build(); + + CommissioningResponse commissioningResponseExpected = new CommissioningResponse(); + commissioningResponseExpected.setCompositionId(compositionId); + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId))) + .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.OK)); + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId))) + .andExpect(method(HttpMethod.DELETE)).andRespond( + withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) + .body(objectMapper.writeValueAsString(commissioningResponseExpected))); + + boolean deprimeRapp = acmDeployer.deprimeRapp(rapp); + mockServer.verify(); + assertTrue(deprimeRapp); + } + + @Test + void testDeprimeFailureRapp() { + UUID compositionId = UUID.randomUUID(); + RappResources rappResources = rappResourceBuilder.getResources(); + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED) + .compositionId(compositionId).rappResources(rappResources).build(); + + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId))) + .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.OK)); + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId))) + .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR)); + + boolean deprimeRapp = acmDeployer.deprimeRapp(rapp); + mockServer.verify(); + assertFalse(deprimeRapp); + } + + @Test + void testDeleteComposition() throws JsonProcessingException { + UUID compositionId = UUID.randomUUID(); + CommissioningResponse commissioningResponseExpected = new CommissioningResponse(); + commissioningResponseExpected.setCompositionId(compositionId); + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId))) + .andExpect(method(HttpMethod.DELETE)).andRespond( + withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) + .body(objectMapper.writeValueAsString(commissioningResponseExpected))); + CommissioningResponse commissioningResponse = acmDeployer.deleteComposition(compositionId); + mockServer.verify(); + assertEquals(commissioningResponse.getCompositionId(), compositionId); + } + + @Test + void testDeleteCompositionFailure() { + UUID compositionId = UUID.randomUUID(); + CommissioningResponse commissioningResponseExpected = new CommissioningResponse(); + commissioningResponseExpected.setCompositionId(compositionId); + mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId))) + .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR)); + CommissioningResponse commissioningResponse = acmDeployer.deleteComposition(compositionId); + mockServer.verify(); + assertNull(commissioningResponse); + } + + void expectAcmGetInstanceToReturnState(UUID compositionId, UUID instanceId, DeployState deployState, + LockState lockState, ExpectedCount expectedCount) throws JsonProcessingException { + AutomationComposition automationCompositionDeployed = new AutomationComposition(); + automationCompositionDeployed.setCompositionId(compositionId); + automationCompositionDeployed.setInstanceId(instanceId); + automationCompositionDeployed.setDeployState(deployState); + automationCompositionDeployed.setLockState(lockState); + + mockServer.expect(expectedCount, requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId))) + .andExpect(method(HttpMethod.GET)).andRespond( + withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) + .body(objectMapper.writeValueAsString(automationCompositionDeployed))); + } +} diff --git a/rapp-manager-acm/src/test/java/com/oransc/rappmanager/acm/service/BeanTestConfiguration.java b/rapp-manager-acm/src/test/java/com/oransc/rappmanager/acm/service/BeanTestConfiguration.java new file mode 100755 index 0000000..f59f8fb --- /dev/null +++ b/rapp-manager-acm/src/test/java/com/oransc/rappmanager/acm/service/BeanTestConfiguration.java @@ -0,0 +1,74 @@ +package com.oransc.rappmanager.acm.service; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.oransc.rappmanager.acm.ApiClient; +import com.oransc.rappmanager.acm.configuration.ACMConfiguration; +import com.oransc.rappmanager.acm.rest.AutomationCompositionDefinitionApiClient; +import com.oransc.rappmanager.acm.rest.AutomationCompositionInstanceApiClient; +import com.oransc.rappmanager.acm.rest.ParticipantMonitoringApiClient; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.cache.CacheManager; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; + +@TestConfiguration +@RequiredArgsConstructor +public class BeanTestConfiguration { + + private final ACMConfiguration acmConfiguration; + + @Bean + public ObjectMapper objectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return objectMapper; + } + + @Bean + public RestTemplateBuilder restTemplateBuilder() { + return new RestTemplateBuilder(); + } + + @Bean + public CacheManager cacheManager() { + return new ConcurrentMapCacheManager(); // or any other CacheManager implementation you want to use in the test + } + + @Bean + public RestTemplate restTemplate(RestTemplateBuilder builder) { + return builder.build(); + } + + @Bean("acmApiClient") + public ApiClient acmApiClient(RestTemplate restTemplate) { + ApiClient apiClient = new ApiClient(restTemplate); + apiClient.setUsername(acmConfiguration.getUsername()); + apiClient.setPassword(acmConfiguration.getPassword()); + return apiClient.setBasePath(acmConfiguration.getBaseUrl()); + } + + @Bean + public ParticipantMonitoringApiClient participantMonitoringApiClient( + @Qualifier("acmApiClient") ApiClient apiClient) { + return new ParticipantMonitoringApiClient(apiClient); + } + + @Bean + public AutomationCompositionDefinitionApiClient automationCompositionDefinitionApiClient( + @Qualifier("acmApiClient") ApiClient apiClient) { + return new AutomationCompositionDefinitionApiClient(apiClient); + } + + @Bean + public AutomationCompositionInstanceApiClient automationCompositionInstanceApiClient( + @Qualifier("acmApiClient") ApiClient apiClient) { + return new AutomationCompositionInstanceApiClient(apiClient); + } + + +} diff --git a/rapp-manager-acm/src/test/java/com/oransc/rappmanager/models/rapp/RappResourceBuilder.java b/rapp-manager-acm/src/test/java/com/oransc/rappmanager/models/rapp/RappResourceBuilder.java new file mode 100755 index 0000000..f939ccc --- /dev/null +++ b/rapp-manager-acm/src/test/java/com/oransc/rappmanager/models/rapp/RappResourceBuilder.java @@ -0,0 +1,24 @@ +package com.oransc.rappmanager.models.rapp; + +import com.oransc.rappmanager.models.rappinstance.RappACMInstance; +import com.oransc.rappmanager.models.rappinstance.RappInstance; +import java.util.List; + +public class RappResourceBuilder { + + public RappResources getResources() { + RappResources rappResources = new RappResources(); + RappResources.ACMResources acmResources = new RappResources.ACMResources("compositions", List.of()); + acmResources.setCompositionInstances(List.of("kserve-instance")); + rappResources.setAcm(acmResources); + return rappResources; + } + + public RappInstance getRappInstance() { + RappInstance rappInstance = new RappInstance(); + RappACMInstance rappACMInstance = new RappACMInstance(); + rappACMInstance.setInstance("kserve-instance"); + rappInstance.setAcm(rappACMInstance); + return rappInstance; + } +} diff --git a/rapp-manager-acm/src/test/resources/application.yaml b/rapp-manager-acm/src/test/resources/application.yaml new file mode 100755 index 0000000..2fdadf4 --- /dev/null +++ b/rapp-manager-acm/src/test/resources/application.yaml @@ -0,0 +1,7 @@ +rappmanager: + acm: + baseurl: http://10.101.3.22:30442/onap/policy/clamp/acm/v2/ + username: runtimeUser + password: zb!XztG34 + maxRetries: 3 + retryInterval: 2 #seconds \ No newline at end of file diff --git a/rapp-manager-acm/src/test/resources/valid-rapp-package.csar b/rapp-manager-acm/src/test/resources/valid-rapp-package.csar new file mode 100755 index 0000000..b8b36e3 Binary files /dev/null and b/rapp-manager-acm/src/test/resources/valid-rapp-package.csar differ diff --git a/rapp-manager-application/src/main/java/com/oransc/rappmanager/RappManagerApplication.java b/rapp-manager-application/src/main/java/com/oransc/rappmanager/RappManagerApplication.java index 94f865a..31fbd28 100755 --- a/rapp-manager-application/src/main/java/com/oransc/rappmanager/RappManagerApplication.java +++ b/rapp-manager-application/src/main/java/com/oransc/rappmanager/RappManagerApplication.java @@ -22,12 +22,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cache.annotation.EnableCaching; -import org.springframework.retry.annotation.EnableRetry; @SpringBootApplication @EnableConfigurationProperties @EnableCaching -@EnableRetry public class RappManagerApplication { public static void main(String[] args) { diff --git a/rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/OnboardingController.java b/rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/RappController.java similarity index 55% rename from rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/OnboardingController.java rename to rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/RappController.java index 6742686..7bef1f1 100755 --- a/rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/OnboardingController.java +++ b/rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/RappController.java @@ -18,15 +18,14 @@ package com.oransc.rappmanager.rest; -import com.oransc.rappmanager.acm.service.AcmDeployer; import com.oransc.rappmanager.configuration.RappManagerConfiguration; -import com.oransc.rappmanager.models.Rapp; -import com.oransc.rappmanager.models.RappCsarConfigurationHandler; -import com.oransc.rappmanager.models.RappEvent; -import com.oransc.rappmanager.models.RappState; import com.oransc.rappmanager.models.cache.RappCacheService; -import com.oransc.rappmanager.models.statemachine.RappStateMachine; -import com.oransc.rappmanager.sme.service.SmeDeployer; +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.rapp.PrimeOrder; +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.rapp.RappPrimeOrder; +import com.oransc.rappmanager.models.rapp.RappState; +import com.oransc.rappmanager.service.RappService; import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -37,9 +36,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cache.Cache; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; @@ -48,16 +50,13 @@ import org.springframework.web.multipart.MultipartFile; @RestController @RequestMapping(path = "rapps") @RequiredArgsConstructor -public class OnboardingController { +public class RappController { - Logger logger = LoggerFactory.getLogger(OnboardingController.class); + Logger logger = LoggerFactory.getLogger(RappController.class); private final RappCsarConfigurationHandler rappCsarConfigurationHandler; - private final AcmDeployer acmDeployer; - private final SmeDeployer smeDeployer; private final RappManagerConfiguration rappManagerConfiguration; - private final RappStateMachine rappStateMachine; private final RappCacheService rappCacheService; - + private final RappService rappService; @GetMapping public ResponseEntity getRapps() { @@ -65,17 +64,12 @@ public class OnboardingController { } @GetMapping("{rapp_id}") - public ResponseEntity getRapps(@PathVariable("rapp_id") String rappId) { - Optional rappOptional = rappCacheService.getRapp(rappId); - if (rappOptional.isPresent()) { - acmDeployer.syncRappStatus(rappOptional.get()); - return ResponseEntity.ok(rappCacheService.getRapp(rappId).get()); - } - return ResponseEntity.badRequest().build(); + public ResponseEntity getRapp(@PathVariable("rapp_id") String rappId) { + return rappCacheService.getRapp(rappId).map(ResponseEntity::ok).orElse(ResponseEntity.badRequest().build()); } - @PostMapping("{rapp_id}/onboard") - public ResponseEntity uploadRappCsarFile(@PathVariable("rapp_id") String rappId, + @PostMapping("{rapp_id}") + public ResponseEntity createRapp(@PathVariable("rapp_id") String rappId, @RequestPart("file") MultipartFile csarFilePart) throws IOException { if (rappCsarConfigurationHandler.isValidRappPackage(csarFilePart)) { File csarFile = new File( @@ -85,9 +79,9 @@ public class OnboardingController { Files.copy(csarFilePart.getInputStream(), csarFile.getAbsoluteFile().toPath(), StandardCopyOption.REPLACE_EXISTING); Rapp rapp = Rapp.builder().name(rappId).packageLocation(rappManagerConfiguration.getCsarLocation()) - .packageName(csarFile.getName()).state(RappState.ONBOARDED).build(); + .packageName(csarFile.getName()).state(RappState.COMMISSIONED).build(); + rapp.setRappResources(rappCsarConfigurationHandler.getRappResource(rapp)); rappCacheService.putRapp(rapp); - rappStateMachine.onboardRapp(rapp.getRappId()); return ResponseEntity.accepted().build(); } else { logger.info("Invalid Rapp package for {}", rappId); @@ -95,37 +89,29 @@ public class OnboardingController { } } - @PostMapping("{rapp_id}/deploy") - public ResponseEntity deployRapp(@PathVariable("rapp_id") String rappId) { - Optional rappOptional = rappCacheService.getRapp(rappId); - rappOptional.ifPresent(rapp -> { - rappStateMachine.sendRappEvent(rapp, RappEvent.DEPLOYING); - }); - if (rappOptional.isPresent() && acmDeployer.deployRapp(rappOptional.get()) && smeDeployer.deployRapp( - rappOptional.get())) { - return ResponseEntity.accepted().build(); - } - return ResponseEntity.internalServerError().build(); + @PutMapping("{rapp_id}") + public ResponseEntity primeRapp(@PathVariable("rapp_id") String rappId, + @RequestBody RappPrimeOrder rappPrimeOrder) { + // @formatter:off + return rappCacheService.getRapp(rappId) + .map(rapp -> Optional.ofNullable(rappPrimeOrder.getPrimeOrder()) + .filter(primeOrder -> primeOrder.equals(PrimeOrder.PRIME)) + .map(primeOrder -> rappService.primeRapp(rapp)) + .orElseGet(() -> rappService.deprimeRapp(rapp))) + .orElse(ResponseEntity.notFound().build()); + // @formatter:on } - @PostMapping("{rapp_id}/undeploy") - public ResponseEntity undeployRapp(@PathVariable("rapp_id") String rappId) { - Optional rappOptional = rappCacheService.getRapp(rappId); - rappOptional.ifPresent(rapp -> { - rappStateMachine.sendRappEvent(rapp, RappEvent.UNDEPLOYING); - }); - if (rappOptional.isPresent() && acmDeployer.undeployRapp(rappOptional.get()) && smeDeployer.undeployRapp( - rappOptional.get())) { - rappCacheService.deleteRapp(rappOptional.get()); - rappStateMachine.deleteRapp(rappOptional.get()); - return ResponseEntity.accepted().build(); - } - return ResponseEntity.internalServerError().build(); - } - - @GetMapping("info") - public ResponseEntity getInfo() { - return ResponseEntity.ok(acmDeployer.getAllParticipants()); + @DeleteMapping("{rapp_id}") + public ResponseEntity deleteRapp(@PathVariable("rapp_id") String rappId) { + // @formatter:off + return rappCacheService.getRapp(rappId) + .filter(rapp -> rapp.getRappInstances().isEmpty() && rapp.getState().equals(RappState.COMMISSIONED)) + .map(rapp -> { + rappCacheService.deleteRapp(rapp); + return ResponseEntity.ok().build(); + }) + .orElse(ResponseEntity.notFound().build()); + // @formatter:on } - } diff --git a/rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/RappInstanceController.java b/rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/RappInstanceController.java new file mode 100755 index 0000000..20fbdb0 --- /dev/null +++ b/rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/RappInstanceController.java @@ -0,0 +1,114 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.rest; + +import com.oransc.rappmanager.models.rappinstance.DeployOrder; +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.rappinstance.RappInstance; +import com.oransc.rappmanager.models.rappinstance.RappInstanceDeployOrder; +import com.oransc.rappmanager.models.rappinstance.RappInstanceState; +import com.oransc.rappmanager.models.cache.RappCacheService; +import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine; +import com.oransc.rappmanager.service.RappService; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.tuple.Pair; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(path = "rapps/{rapp_id}/instance") +@RequiredArgsConstructor +public class RappInstanceController { + + private final RappCacheService rappCacheService; + private final RappInstanceStateMachine rappInstanceStateMachine; + private final RappService rappService; + + @GetMapping + public ResponseEntity> getAllRappInstances(@PathVariable("rapp_id") String rappId) { + return rappCacheService.getRapp(rappId).map(Rapp::getRappInstances).map(ResponseEntity::ok) + .orElse(ResponseEntity.notFound().build()); + } + + @PostMapping + public ResponseEntity createRappInstance(@PathVariable("rapp_id") String rappId, + @RequestBody RappInstance rappInstance) { + return rappCacheService.getRapp(rappId).map(rapp -> { + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + rapp.getRappInstances().put(rappInstance.getRappInstanceId(), rappInstance); + return ResponseEntity.ok(rappInstance); + }).orElse(ResponseEntity.notFound().build()); + } + + @GetMapping("{rapp_instance_id}") + public ResponseEntity getRappInstance(@PathVariable("rapp_id") String rappId, + @PathVariable("rapp_instance_id") UUID rappInstanceId) { + return rappCacheService.getRapp(rappId).map(rapp -> Pair.of(rapp, rapp.getRappInstances().get(rappInstanceId))) + .filter(rappPair -> rappPair.getLeft().getRappInstances().containsKey(rappInstanceId)) + .map(rappPair -> { + rappService.updateRappInstanceState(rappPair.getLeft(), rappPair.getRight()); + RappInstance rappInstance = rappPair.getLeft().getRappInstances().get(rappInstanceId); + rappInstance.setState(rappInstanceStateMachine.getRappInstanceState(rappInstanceId)); + return rappInstance; + }).map(ResponseEntity::ok).orElse(ResponseEntity.notFound().build()); + } + + @PutMapping("{rapp_instance_id}") + public ResponseEntity deployRappInstance(@PathVariable("rapp_id") String rappId, + @PathVariable("rapp_instance_id") UUID rappInstanceId, + @RequestBody RappInstanceDeployOrder rappInstanceDeployOrder) { + //@formatter:off + return rappCacheService.getRapp(rappId) + .filter(rapp -> rapp.getRappInstances().containsKey(rappInstanceId)) + .map(rapp -> Pair.of(rapp, rapp.getRappInstances().get(rappInstanceId))) + .map(rappPair -> Optional.ofNullable(rappInstanceDeployOrder.getDeployOrder()) + .filter(deployOrder -> deployOrder.equals(DeployOrder.DEPLOY)) + .map(primeOrder -> rappService.deployRappInstance(rappPair.getLeft(), rappPair.getRight())) + .orElseGet(() -> rappService.undeployRappInstance(rappPair.getLeft(), rappPair.getRight()))) + .orElse(ResponseEntity.notFound().build()); + //@formatter:on + } + + @DeleteMapping("{rapp_instance_id}") + public ResponseEntity deleteRappInstance(@PathVariable("rapp_id") String rappId, + @PathVariable("rapp_instance_id") UUID rappInstanceId) { + return rappCacheService.getRapp(rappId).map(rapp -> Pair.of(rapp, rapp.getRappInstances())) + .filter(rappPair -> rappPair.getRight().containsKey(rappInstanceId) && rappPair.getRight() + .get(rappInstanceId) + .getState() + .equals(RappInstanceState.UNDEPLOYED)) + .map(rappPair -> { + rappInstanceStateMachine.deleteRappInstance( + rappPair.getLeft().getRappInstances().get(rappInstanceId)); + rappPair.getLeft().getRappInstances().remove(rappInstanceId); + return ResponseEntity.noContent().build(); + }).orElse(ResponseEntity.notFound().build()); + } + +} diff --git a/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/RappService.java b/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/RappService.java new file mode 100755 index 0000000..82054f5 --- /dev/null +++ b/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/RappService.java @@ -0,0 +1,107 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.service; + +import com.oransc.rappmanager.acm.service.AcmDeployer; +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.rapp.RappEvent; +import com.oransc.rappmanager.models.rappinstance.RappInstance; +import com.oransc.rappmanager.models.rappinstance.RappInstanceState; +import com.oransc.rappmanager.models.rapp.RappState; +import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine; +import com.oransc.rappmanager.sme.service.SmeDeployer; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class RappService { + + private final AcmDeployer acmDeployer; + private final SmeDeployer smeDeployer; + private final RappInstanceStateMachine rappInstanceStateMachine; + + public ResponseEntity primeRapp(Rapp rapp) { + if (rapp.getState().equals(RappState.COMMISSIONED)) { + rapp.setState(RappState.PRIMING); + if (!acmDeployer.primeRapp(rapp)) { + rapp.setState(RappState.COMMISSIONED); + } + return ResponseEntity.ok().build(); + } else { + return ResponseEntity.badRequest() + .body("State transition from " + RappState.PRIMED.name() + " to " + rapp.getState().name() + + " is not permitted."); + } + } + + public ResponseEntity deprimeRapp(Rapp rapp) { + if (rapp.getState().equals(RappState.PRIMED) && rapp.getRappInstances().isEmpty()) { + rapp.setState(RappState.DEPRIMING); + if (!acmDeployer.deprimeRapp(rapp)) { + rapp.setState(RappState.PRIMED); + } + return ResponseEntity.ok().build(); + } else { + if (!rapp.getRappInstances().isEmpty()) { + return ResponseEntity.badRequest().body("Unable to deprime as there are active rapp instances,"); + } else { + return ResponseEntity.badRequest() + .body("State transition from " + RappState.COMMISSIONED.name() + " to " + rapp.getState() + .name() + + " is not permitted."); + } + } + } + + public ResponseEntity deployRappInstance(Rapp rapp, RappInstance rappInstance) { + if (rappInstance.getState().equals(RappInstanceState.UNDEPLOYED)) { + rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DEPLOYING); + if (acmDeployer.deployRappInstance(rapp, rappInstance) && smeDeployer.deployRappInstance(rapp, + rappInstance)) { + return ResponseEntity.accepted().build(); + } + return ResponseEntity.status(HttpStatus.BAD_GATEWAY).build(); + } else { + return ResponseEntity.badRequest().body("State transition from " + rappInstance.getState().name() + " to " + + RappInstanceState.DEPLOYED.name() + " is not permitted."); + } + } + + public ResponseEntity undeployRappInstance(Rapp rapp, RappInstance rappInstance) { + if (rappInstance.getState().equals(RappInstanceState.DEPLOYED)) { + rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.UNDEPLOYING); + if (acmDeployer.undeployRappInstance(rapp, rappInstance) && smeDeployer.undeployRappInstance(rapp, + rappInstance)) { + return ResponseEntity.accepted().build(); + } + return ResponseEntity.status(HttpStatus.BAD_GATEWAY).build(); + } else { + return ResponseEntity.badRequest().body("State transition from " + rappInstance.getState().name() + " to " + + RappInstanceState.UNDEPLOYED.name() + + " is not permitted."); + } + } + + public void updateRappInstanceState(Rapp rapp, RappInstance rappInstance) { + acmDeployer.syncRappInstanceStatus(rapp.getCompositionId(), rappInstance); + } +} diff --git a/rapp-manager-application/src/main/resources/application.yaml b/rapp-manager-application/src/main/resources/application.yaml index 445297a..987214f 100755 --- a/rapp-manager-application/src/main/resources/application.yaml +++ b/rapp-manager-application/src/main/resources/application.yaml @@ -1,14 +1,13 @@ rappmanager: csarlocation: src/main/resources/csar acm: - baseurl: http://10.101.2.254:30442/onap/policy/clamp/acm/v2/ + baseurl: http://10.101.3.22:30442/onap/policy/clamp/acm/v2/ username: runtimeUser password: zb!XztG34 - compositionDefinitionLocation: src/main/resources/compositiondefinition.json maxRetries: 3 retryInterval: 2 #seconds sme: - baseurl: http://10.101.2.254:30232 + baseurl: http://localhost:60821 #http://10.101.3.22:61761 providerBasePath: /api-provider-management/v1/ invokerBasePath: /api-invoker-management/v1/ publishApiBasePath: /published-apis/v1/ @@ -27,4 +26,4 @@ management: endpoints: web: exposure: - include: "*" \ No newline at end of file + include: "*" diff --git a/rapp-manager-application/src/main/resources/compositiondefinition.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/definition/compositions.json similarity index 100% rename from rapp-manager-application/src/main/resources/compositiondefinition.json rename to rapp-manager-application/src/main/resources/resource-csar/Files/Acm/definition/compositions.json diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/a1pms-instance.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/a1pms-instance.json new file mode 100755 index 0000000..fa5d207 --- /dev/null +++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/a1pms-instance.json @@ -0,0 +1,28 @@ +{ + "name": "A1PMSInstance0", + "version": "1.0.1", + "compositionId": "COMPOSITIONID", + "description": "Demo automation composition instance 0", + "elements": { + "709c62b3-8918-41b9-a747-d21eb79c6c12": { + "id": "709c62b3-8918-41b9-a747-d21eb79c6c12", + "definition": { + "name": "onap.policy.clamp.ac.element.A1PMSAutomationCompositionElement", + "version": "1.2.3" + }, + "description": "Starter Automation Composition Element for the Demo", + "properties": { + "policyServiceEntities": [ + { + "a1PolicyServiceEntityId": { + "name": "entity1", + "version": "1.0.1" + }, + "clientId": "firstService", + "callbackUrl": "http:\\localhost" + } + ] + } + } + } +} \ No newline at end of file diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/k8s-instance.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/k8s-instance.json new file mode 100755 index 0000000..286a943 --- /dev/null +++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/k8s-instance.json @@ -0,0 +1,31 @@ +{ + "name": "DemoInstance0", + "version": "1.0.1", + "compositionId": "COMPOSITIONID", + "description": "Demo automation composition instance 0", + "elements": { + "709c62b3-8918-41b9-a747-d21eb79c6c21": { + "id": "709c62b3-8918-41b9-a747-d21eb79c6c21", + "definition": { + "name": "onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement", + "version": "1.2.3" + }, + "description": "Starter Automation Composition Element for the Demo", + "properties": { + "chart": { + "chartId": { + "name": "ransliceassurance", + "version": "1.0.0" + }, + "namespace": "nonrtric", + "releaseName": "ransliceassurance", + "podName": "ransliceassurance", + "repository": { + "repoName": "local", + "address": "http://10.101.3.22:8879/charts" + } + } + } + } + } +} \ No newline at end of file diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/kserve-instance.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/kserve-instance.json new file mode 100755 index 0000000..aaf63a1 --- /dev/null +++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/kserve-instance.json @@ -0,0 +1,29 @@ +{ + "name": "KserveInstance0", + "version": "1.0.1", + "compositionId": "COMPOSITIONID", + "description": "Demo automation composition instance 0", + "elements": { + "709c62b3-8918-41b9-a747-d21eb79c6c20": { + "id": "709c62b3-8918-41b9-a747-d21eb79c6c20", + "definition": { + "name": "onap.policy.clamp.ac.element.KserveAutomationCompositionElement", + "version": "1.2.3" + }, + "description": "Starter Automation Composition Element for the Demo", + "properties": { + "kserveInferenceEntities": [ + { + "kserveInferenceEntityId": { + "name": "entity1", + "version": "1.0.1" + }, + "name": "sklearn-iris", + "namespace": "kserve-test", + "payload": "{\"apiVersion\": \"serving.kserve.io/v1beta1\",\"kind\": \"InferenceService\",\"metadata\": {\"name\": \"sklearn-iris\"},\"spec\": {\"predictor\": {\"model\":{\"modelFormat\": {\"name\": \"sklearn\"},\"storageUri\": \"gs://kfserving-examples/models/sklearn/1.0/model\"}}}}" + } + ] + } + } + } +} \ No newline at end of file diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instantiation.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instantiation.json deleted file mode 100755 index c17f49b..0000000 --- a/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instantiation.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "name": "RappInstance0", - "version": "1.0.1", - "compositionId": "COMPOSITIONID", - "description": "Demo automation composition instance 0", - "elements": { - "709c62b3-8918-41b9-a747-d21eb79c6c20": { - "id": "709c62b3-8918-41b9-a747-d21eb79c6c20", - "definition": { - "name": "onap.policy.clamp.ac.element.KserveAutomationCompositionElement", - "version": "1.2.3" - }, - "description": "Starter Automation Composition Element for the Demo", - "properties": { - "kserveInferenceEntities": [ - { - "kserveInferenceEntityId": { - "name": "entity1", - "version": "1.0.1" - }, - "name": "sklearn-iris", - "namespace": "rapps", - "payload": "{\"apiVersion\": \"serving.kserve.io/v1beta1\",\"kind\": \"InferenceService\",\"metadata\": {\"name\": \"sklearn-iris\"},\"spec\": {\"predictor\": {\"model\":{\"modelFormat\": {\"name\": \"sklearn\"},\"storageUri\": \"gs://kfserving-examples/models/sklearn/1.0/model\"}}}}" - } - ] - } - }, - "709c62b3-8918-41b9-a747-d21eb79c6c12": { - "id": "709c62b3-8918-41b9-a747-d21eb79c6c12", - "definition": { - "name": "onap.policy.clamp.ac.element.A1PMSAutomationCompositionElement", - "version": "1.2.3" - }, - "description": "Starter Automation Composition Element for the Demo", - "properties": { - "policyServiceEntities": [ - { - "a1PolicyServiceEntityId": { - "name": "entity1", - "version": "1.0.1" - }, - "clientId": "firstService", - "callbackUrl": "http:\\localhost" - } - ] - } - }, - "709c62b3-8918-41b9-a747-d21eb79c6c21": { - "id": "709c62b3-8918-41b9-a747-d21eb79c6c21", - "definition": { - "name": "onap.policy.clamp.ac.element.K8S_StarterAutomationCompositionElement", - "version": "1.2.3" - }, - "description": "Starter Automation Composition Element for the Demo", - "properties": { - "chart": { - "chartId": { - "name": "ransliceassurance", - "version": "1.0.0" - }, - "namespace": "nonrtric", - "releaseName": "ransliceassurance", - "podName": "ransliceassurance", - "repository": { - "repoName": "local", - "address": "http://10.101.2.254:8879/charts" - } - } - } - } - } -} \ No newline at end of file diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/invoker.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/invokers/invoker-app1.json similarity index 65% rename from rapp-manager-application/src/main/resources/resource-csar/Files/Sme/invoker.json rename to rapp-manager-application/src/main/resources/resource-csar/Files/Sme/invokers/invoker-app1.json index 141a860..612af40 100755 --- a/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/invoker.json +++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/invokers/invoker-app1.json @@ -1,10 +1,10 @@ [ { - "apiInvokerInformation": "rApp as invoker 1", + "apiInvokerInformation": "Invoker App 1", "apiList": [ {} ], - "notificationDestination": "http://invoker-app:8086/callback", + "notificationDestination": "http://invoker-app1:8086/callback", "onboardingInformation": { "apiInvokerPublicKey": "{PUBLIC_KEY_INVOKER_1}", "apiInvokerCertificate": "apiInvokerCertificate" diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/invokers/invoker-app2.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/invokers/invoker-app2.json new file mode 100755 index 0000000..27e1063 --- /dev/null +++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/invokers/invoker-app2.json @@ -0,0 +1,14 @@ +[ + { + "apiInvokerInformation": "Invoker App 2", + "apiList": [ + {} + ], + "notificationDestination": "http://invoker-app2:8086/callback", + "onboardingInformation": { + "apiInvokerPublicKey": "{PUBLIC_KEY_INVOKER_1}", + "apiInvokerCertificate": "apiInvokerCertificate" + }, + "requestTestNotification": true + } +] \ No newline at end of file diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/provider-domain.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/providers/aef-provider-function.json similarity index 100% rename from rapp-manager-application/src/main/resources/resource-csar/Files/Sme/provider-domain.json rename to rapp-manager-application/src/main/resources/resource-csar/Files/Sme/providers/aef-provider-function.json diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/providers/amf-provider-function.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/providers/amf-provider-function.json new file mode 100755 index 0000000..7bb2984 --- /dev/null +++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/providers/amf-provider-function.json @@ -0,0 +1,13 @@ +{ + "apiProvDomInfo": "provider domain rApp as AMF", + "apiProvFuncs": [ + { + "apiProvFuncInfo": "rApp as AMF", + "apiProvFuncRole": "AMF", + "regInfo": { + "apiProvPubKey": "AMF-PublicKey" + } + } + ], + "regSec": "PSK" +} \ No newline at end of file diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/providers/apf-provider-function.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/providers/apf-provider-function.json new file mode 100755 index 0000000..8a9383a --- /dev/null +++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/providers/apf-provider-function.json @@ -0,0 +1,13 @@ +{ + "apiProvDomInfo": "provider domain rApp as APF", + "apiProvFuncs": [ + { + "apiProvFuncInfo": "rApp as APF", + "apiProvFuncRole": "APF", + "regInfo": { + "apiProvPubKey": "APF-PublicKey" + } + } + ], + "regSec": "PSK" +} \ No newline at end of file diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/providers/gateway-provider-function.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/providers/gateway-provider-function.json new file mode 100755 index 0000000..fae856a --- /dev/null +++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/providers/gateway-provider-function.json @@ -0,0 +1,13 @@ +{ + "apiProvDomInfo": "provider domain Gateway as entrypoint AEF", + "apiProvFuncs": [ + { + "apiProvFuncInfo": "Gateway as entrypoint AEF", + "apiProvFuncRole": "AEF", + "regInfo": { + "apiProvPubKey": "AEF-Gateway-PublicKey" + } + } + ], + "regSec": "PSK" +} \ No newline at end of file diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/provider-api.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/serviceapis/api-set-1.json similarity index 96% rename from rapp-manager-application/src/main/resources/resource-csar/Files/Sme/provider-api.json rename to rapp-manager-application/src/main/resources/resource-csar/Files/Sme/serviceapis/api-set-1.json index 7c58c9c..21afb1c 100755 --- a/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/provider-api.json +++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/serviceapis/api-set-1.json @@ -1,5 +1,5 @@ { - "apiName": "Rapp API", + "apiName": "Rapp API Set A", "description": "Example A API of rApp", "aefProfiles": [ { diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/serviceapis/api-set-2.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/serviceapis/api-set-2.json new file mode 100755 index 0000000..8b377fe --- /dev/null +++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Sme/serviceapis/api-set-2.json @@ -0,0 +1,45 @@ +{ + "apiName": "Rapp API Set B", + "description": "Example B API of rApp", + "aefProfiles": [ + { + "aefId": "rApp as AEF", + "description": "Example B rApp as AEF", + "versions": [ + { + "apiVersion": "v1", + "resources": [ + { + "resourceName": "exampleA", + "commType": "REQUEST_RESPONSE", + "uri": "/exampleA/subscription/subscription_id_1", + "operations": [ + "GET" + ] + } + ] + } + ], + "protocol": "HTTP_1_1", + "securityMethods": [ + "PSK" + ], + "interfaceDescriptions": [ + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": [ + "PKI" + ] + }, + { + "ipv4Addr": "string", + "port": 65535, + "securityMethods": [ + "PKI" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/OnboardingControllerTest.java b/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/OnboardingControllerTest.java deleted file mode 100755 index c64e999..0000000 --- a/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/OnboardingControllerTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/*- - * ============LICENSE_START====================================================================== - * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.rest; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.oransc.rappmanager.acm.service.AcmDeployer; -import com.oransc.rappmanager.configuration.RappManagerConfiguration; -import com.oransc.rappmanager.models.RappState; -import com.oransc.rappmanager.sme.service.SmeDeployer; -import java.io.File; -import java.io.FileInputStream; -import java.util.UUID; -import org.apache.http.entity.ContentType; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@TestPropertySource(properties = "rappmanager.csarlocation=src/test/resources") -@AutoConfigureMockMvc -public class OnboardingControllerTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - RappManagerConfiguration rappManagerConfiguration; - - @MockBean - AcmDeployer acmDeployer; - - @MockBean - SmeDeployer smeDeployer; - - private final String validRappFile = "valid-rapp-package.csar"; - - private final String invalidRappFile = "invalid-rapp-package.csar"; - - @Test - void testOnboardCsarPackage() throws Exception { - String rappCsarPath = rappManagerConfiguration.getCsarLocation() + File.separator + validRappFile; - MockMultipartFile multipartFile = - new MockMultipartFile("file", validRappFile, ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPath)); - mockMvc.perform( - MockMvcRequestBuilders.multipart("/rapps/{rapp_id}/onboard", UUID.randomUUID()).file(multipartFile)) - .andExpect(status().isAccepted()); - } - - @Test - void testOnboardCsarPackageFailure() throws Exception { - String rappCsarPath = rappManagerConfiguration.getCsarLocation() + File.separator + invalidRappFile; - MockMultipartFile multipartFile = - new MockMultipartFile("file", invalidRappFile, ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPath)); - mockMvc.perform( - MockMvcRequestBuilders.multipart("/rapps/{rapp_id}/onboard", UUID.randomUUID()).file(multipartFile)) - .andExpect(status().isBadRequest()); - } - - @Test - void testGetRapp() throws Exception { - UUID rappId = UUID.randomUUID(); - this.onBoardRappCsar(rappId); - this.mockMvc.perform(MockMvcRequestBuilders.get("/rapps/{rapp_id}", rappId)).andExpect(status().isOk()) - .andExpect(jsonPath("$.name").value(rappId.toString())) - .andExpect(jsonPath("$.state").value(RappState.ONBOARDED.name())); - } - - @Test - void testGetInvalidRapp() throws Exception { - UUID rappId = UUID.randomUUID(); - this.mockMvc.perform(MockMvcRequestBuilders.get("/rapps/{rapp_id}", rappId)).andDo(print()) - .andExpect(status().isBadRequest()); - } - - @Test - void testRappDeploy() throws Exception { - UUID rappId = UUID.randomUUID(); - this.onBoardRappCsar(rappId); - when(acmDeployer.deployRapp(any())).thenReturn(true); - when(smeDeployer.deployRapp(any())).thenReturn(true); - mockMvc.perform(MockMvcRequestBuilders.multipart("/rapps/{rapp_id}/deploy", rappId)) - .andExpect(status().isAccepted()); - } - - @Test - void testInvalidRappDeploy() throws Exception { - UUID rappId = UUID.randomUUID(); - when(acmDeployer.deployRapp(any())).thenReturn(false); - mockMvc.perform(MockMvcRequestBuilders.multipart("/rapps/{rapp_id}/deploy", rappId)) - .andExpect(status().isInternalServerError()); - } - - @Test - void testRappUndeploy() throws Exception { - UUID rappId = UUID.randomUUID(); - this.onBoardRappCsar(rappId); - when(acmDeployer.undeployRapp(any())).thenReturn(true); - when(smeDeployer.undeployRapp(any())).thenReturn(true); - mockMvc.perform(MockMvcRequestBuilders.multipart("/rapps/{rapp_id}/undeploy", rappId)) - .andExpect(status().isAccepted()); - } - - @Test - void testInvalidRappUndeploy() throws Exception { - UUID rappId = UUID.randomUUID(); - when(acmDeployer.undeployRapp(any())).thenReturn(false); - mockMvc.perform(MockMvcRequestBuilders.multipart("/rapps/{rapp_id}/undeploy", rappId)) - .andExpect(status().isInternalServerError()); - } - - void onBoardRappCsar(UUID rappId) throws Exception { - String rappCsarPath = rappManagerConfiguration.getCsarLocation() + File.separator + validRappFile; - MockMultipartFile multipartFile = - new MockMultipartFile("file", validRappFile, ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPath)); - mockMvc.perform(MockMvcRequestBuilders.multipart("/rapps/{rapp_id}/onboard", rappId).file(multipartFile)) - .andExpect(status().isAccepted()); - } - -} diff --git a/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/RappControllerTest.java b/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/RappControllerTest.java new file mode 100755 index 0000000..896eef3 --- /dev/null +++ b/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/RappControllerTest.java @@ -0,0 +1,144 @@ +package com.oransc.rappmanager.rest; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.oransc.rappmanager.acm.service.AcmDeployer; +import com.oransc.rappmanager.models.rapp.PrimeOrder; +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.rapp.RappPrimeOrder; +import com.oransc.rappmanager.models.rapp.RappState; +import com.oransc.rappmanager.models.cache.RappCacheService; +import java.io.File; +import java.io.FileInputStream; +import java.util.UUID; +import org.apache.http.entity.ContentType; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +public class RappControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private RappCacheService rappCacheService; + + @MockBean + AcmDeployer acmDeployer; + + private final String validRappFile = "valid-rapp-package.csar"; + + private final String invalidRappFile = "invalid-rapp-package.csar"; + private final String validCsarFileLocation = "src/test/resources/"; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + void testGetRapps() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/rapps")).andExpect(status().isOk()); + } + + @Test + void testGetRapp() throws Exception { + UUID rappId = UUID.randomUUID(); + Rapp rapp = Rapp.builder().rappId(rappId).name(String.valueOf(rappId)).packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + rappCacheService.putRapp(rapp); + mockMvc.perform(MockMvcRequestBuilders.get("/rapps/{rapp_id}", rappId)).andExpect(status().isOk()) + .andExpect(jsonPath("$.rappId").value(rappId.toString())) + .andExpect(jsonPath("$.state").value(RappState.COMMISSIONED.name())); + } + + @Test + void testGetInvalidRapp() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/rapps/{rapp_id}", UUID.randomUUID())) + .andExpect(status().isBadRequest()); + } + + @Test + void testCreateRapp() throws Exception { + String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; + MockMultipartFile multipartFile = + new MockMultipartFile("file", validRappFile, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + mockMvc.perform(MockMvcRequestBuilders.multipart("/rapps/{rapp_id}", UUID.randomUUID()).file(multipartFile)) + .andExpect(status().isAccepted()); + } + + @Test + void testCreateInvalidRapp() throws Exception { + String rappCsarPath = validCsarFileLocation + File.separator + invalidRappFile; + MockMultipartFile multipartFile = + new MockMultipartFile("file", invalidRappFile, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + mockMvc.perform(MockMvcRequestBuilders.multipart("/rapps/{rapp_id}", UUID.randomUUID()).file(multipartFile)) + .andExpect(status().isBadRequest()); + } + + @Test + void testPrimeRapp() throws Exception { + UUID rappId = UUID.randomUUID(); + Rapp rapp = Rapp.builder().rappId(rappId).name(String.valueOf(rappId)).packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + rappCacheService.putRapp(rapp); + when(acmDeployer.primeRapp(any())).thenReturn(true); + RappPrimeOrder rappPrimeOrder = new RappPrimeOrder(); + rappPrimeOrder.setPrimeOrder(PrimeOrder.PRIME); + mockMvc.perform(MockMvcRequestBuilders.put("/rapps/{rapp_id}", rappId).contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(rappPrimeOrder))).andExpect(status().isOk()); + } + + @ParameterizedTest + @EnumSource(value = PrimeOrder.class, names = {"PRIME", "DEPRIME"}) + void testPrimeRappFailure(PrimeOrder primeOrder) throws Exception { + RappPrimeOrder rappPrimeOrder = new RappPrimeOrder(); + rappPrimeOrder.setPrimeOrder(primeOrder); + mockMvc.perform(MockMvcRequestBuilders.put("/rapps/{rapp_id}", UUID.randomUUID()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(rappPrimeOrder))) + .andExpect(status().isNotFound()); + } + + @Test + void testDeprimeRapp() throws Exception { + UUID rappId = UUID.randomUUID(); + Rapp rapp = Rapp.builder().rappId(rappId).name(String.valueOf(rappId)).packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.PRIMED).build(); + rappCacheService.putRapp(rapp); + when(acmDeployer.deprimeRapp(any())).thenReturn(true); + RappPrimeOrder rappPrimeOrder = new RappPrimeOrder(); + rappPrimeOrder.setPrimeOrder(PrimeOrder.DEPRIME); + mockMvc.perform(MockMvcRequestBuilders.put("/rapps/{rapp_id}", rappId).contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(rappPrimeOrder))).andExpect(status().isOk()); + } + + @Test + void testDeleteRapp() throws Exception { + UUID rappId = UUID.randomUUID(); + Rapp rapp = Rapp.builder().rappId(rappId).name(String.valueOf(rappId)).packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + rappCacheService.putRapp(rapp); + mockMvc.perform(MockMvcRequestBuilders.delete("/rapps/{rapp_id}", rappId)).andExpect(status().isOk()); + } + + @Test + void testDeleteRappFailure() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.delete("/rapps/{rapp_id}", UUID.randomUUID())) + .andExpect(status().isNotFound()); + } +} diff --git a/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/RappInstanceControllerTest.java b/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/RappInstanceControllerTest.java new file mode 100755 index 0000000..3ad2059 --- /dev/null +++ b/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/RappInstanceControllerTest.java @@ -0,0 +1,277 @@ +package com.oransc.rappmanager.rest; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.oransc.rappmanager.acm.service.AcmDeployer; +import com.oransc.rappmanager.models.rappinstance.DeployOrder; +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.rappinstance.RappInstance; +import com.oransc.rappmanager.models.rappinstance.RappInstanceDeployOrder; +import com.oransc.rappmanager.models.rappinstance.RappInstanceState; +import com.oransc.rappmanager.models.rapp.RappState; +import com.oransc.rappmanager.models.cache.RappCacheService; +import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine; +import com.oransc.rappmanager.sme.service.SmeDeployer; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +public class RappInstanceControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private RappCacheService rappCacheService; + + @Autowired + private RappInstanceStateMachine rappInstanceStateMachine; + + @MockBean + AcmDeployer acmDeployer; + + @MockBean + SmeDeployer smeDeployer; + + private final String validRappFile = "valid-rapp-package.csar"; + + private final String invalidRappFile = "invalid-rapp-package.csar"; + private final String validCsarFileLocation = "src/test/resources/"; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + void testGetAllRappInstances() throws Exception { + UUID rappId = UUID.randomUUID(); + UUID rappInstanceId = UUID.randomUUID(); + Rapp rapp = getRapp(rappId, rappInstanceId); + rappCacheService.putRapp(rapp); + mockMvc.perform(MockMvcRequestBuilders.get("/rapps/{rapp_id}/instance", rappId)).andExpect(status().isOk()) + .andExpect( + jsonPath("$." + rappInstanceId.toString() + ".rappInstanceId").value(rappInstanceId.toString())) + .andExpect(jsonPath("$." + rappInstanceId.toString() + ".state").value( + RappInstanceState.UNDEPLOYED.name())); + } + + @Test + void testGetAllRappInstancesFailure() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/rapps/{rapp_id}/instance", UUID.randomUUID())) + .andExpect(status().isNotFound()); + } + + @Test + void testCreateRappInstance() throws Exception { + UUID rappId = UUID.randomUUID(); + UUID rappInstanceId = UUID.randomUUID(); + RappInstance rappInstance = new RappInstance(); + rappInstance.setRappInstanceId(rappInstanceId); + rappInstance.setState(RappInstanceState.UNDEPLOYED); + Rapp rapp = Rapp.builder().rappId(rappId).name(String.valueOf(rappId)).packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.PRIMED).build(); + rappCacheService.putRapp(rapp); + mockMvc.perform( + MockMvcRequestBuilders.post("/rapps/{rapp_id}/instance", rappId).contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(rappInstance))).andExpect(status().isOk()); + Rapp rappResult = rappCacheService.getRapp(String.valueOf(rappId)).get(); + assertNotNull(rappResult.getRappInstances().get(rappInstanceId)); + } + + @Test + void testCreateRappInstanceFailure() throws Exception { + RappInstance rappInstance = new RappInstance(); + rappInstance.setRappInstanceId(UUID.randomUUID()); + rappInstance.setState(RappInstanceState.UNDEPLOYED); + mockMvc.perform(MockMvcRequestBuilders.post("/rapps/{rapp_id}/instance", UUID.randomUUID()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(rappInstance))) + .andExpect(status().isNotFound()); + } + + @Test + void testGetRappInstance() throws Exception { + UUID rappId = UUID.randomUUID(); + UUID rappInstanceId = UUID.randomUUID(); + Rapp rapp = getRapp(rappId, rappInstanceId); + rappCacheService.putRapp(rapp); + rappInstanceStateMachine.onboardRappInstance(rappInstanceId); + mockMvc.perform(MockMvcRequestBuilders.get("/rapps/{rapp_id}/instance/{instance_id}", rappId, rappInstanceId)) + .andExpect(status().isOk()).andExpect(jsonPath("$.rappInstanceId").value(rappInstanceId.toString())) + .andExpect(jsonPath("$.state").value(RappInstanceState.UNDEPLOYED.name())); + } + + @Test + void testGetRappInstanceNoRappFailure() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/rapps/{rapp_id}/instance/{instance_id}", UUID.randomUUID(), + UUID.randomUUID())).andExpect(status().isNotFound()); + } + + @Test + void testGetRappInstanceNoRappInstanceFailure() throws Exception { + UUID rappId = UUID.randomUUID(); + UUID rappInstanceId = UUID.randomUUID(); + Rapp rapp = Rapp.builder().rappId(rappId).name(String.valueOf(rappId)).packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.PRIMED).build(); + rappCacheService.putRapp(rapp); + mockMvc.perform(MockMvcRequestBuilders.get("/rapps/{rapp_id}/instance/{instance_id}", rappId, rappInstanceId)) + .andExpect(status().isNotFound()); + } + + @Test + void testDeployRappInstance() throws Exception { + UUID rappId = UUID.randomUUID(); + UUID rappInstanceId = UUID.randomUUID(); + Rapp rapp = getRapp(rappId, rappInstanceId); + rappCacheService.putRapp(rapp); + rappInstanceStateMachine.onboardRappInstance(rappInstanceId); + RappInstanceDeployOrder rappInstanceDeployOrder = new RappInstanceDeployOrder(); + rappInstanceDeployOrder.setDeployOrder(DeployOrder.DEPLOY); + when(acmDeployer.deployRappInstance(any(), any())).thenReturn(true); + when(smeDeployer.deployRappInstance(any(), any())).thenReturn(true); + mockMvc.perform(MockMvcRequestBuilders.put("/rapps/{rapp_id}/instance/{instance_id}", rappId, rappInstanceId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(rappInstanceDeployOrder))) + .andExpect(status().isAccepted()); + } + + + @Test + void testDeployNoRappInstanceFailure() throws Exception { + UUID rappId = UUID.randomUUID(); + UUID rappInstanceId = UUID.randomUUID(); + Rapp rapp = getRapp(rappId, rappInstanceId); + rapp.setRappInstances(Map.of()); + rappCacheService.putRapp(rapp); + RappInstanceDeployOrder rappInstanceDeployOrder = new RappInstanceDeployOrder(); + rappInstanceDeployOrder.setDeployOrder(DeployOrder.DEPLOY); + when(acmDeployer.deployRappInstance(any(), any())).thenReturn(true); + when(smeDeployer.deployRappInstance(any(), any())).thenReturn(true); + mockMvc.perform(MockMvcRequestBuilders.put("/rapps/{rapp_id}/instance/{instance_id}", rappId, rappInstanceId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(rappInstanceDeployOrder))) + .andExpect(status().isNotFound()); + } + + @Test + void testDeployNoRappFailure() throws Exception { + RappInstanceDeployOrder rappInstanceDeployOrder = new RappInstanceDeployOrder(); + rappInstanceDeployOrder.setDeployOrder(DeployOrder.DEPLOY); + when(acmDeployer.deployRappInstance(any(), any())).thenReturn(true); + when(smeDeployer.deployRappInstance(any(), any())).thenReturn(true); + mockMvc.perform(MockMvcRequestBuilders.put("/rapps/{rapp_id}/instance/{instance_id}", UUID.randomUUID(), + UUID.randomUUID()).contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(rappInstanceDeployOrder))) + .andExpect(status().isNotFound()); + } + + @Test + void testUndeployRappInstance() throws Exception { + UUID rappId = UUID.randomUUID(); + UUID rappInstanceId = UUID.randomUUID(); + Rapp rapp = getRapp(rappId, rappInstanceId); + rapp.getRappInstances().forEach((uuid, rappInstance) -> rappInstance.setState(RappInstanceState.DEPLOYED)); + rappCacheService.putRapp(rapp); + rappInstanceStateMachine.onboardRappInstance(rappInstanceId); + RappInstanceDeployOrder rappInstanceDeployOrder = new RappInstanceDeployOrder(); + rappInstanceDeployOrder.setDeployOrder(DeployOrder.UNDEPLOY); + when(acmDeployer.undeployRappInstance(any(), any())).thenReturn(true); + when(smeDeployer.undeployRappInstance(any(), any())).thenReturn(true); + mockMvc.perform(MockMvcRequestBuilders.put("/rapps/{rapp_id}/instance/{instance_id}", rappId, rappInstanceId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(rappInstanceDeployOrder))) + .andExpect(status().isAccepted()); + } + + @Test + void testUndeployNoRappInstanceFailure() throws Exception { + UUID rappId = UUID.randomUUID(); + UUID rappInstanceId = UUID.randomUUID(); + Rapp rapp = getRapp(rappId, rappInstanceId); + rapp.setRappInstances(Map.of()); + rappCacheService.putRapp(rapp); + rappInstanceStateMachine.onboardRappInstance(rappInstanceId); + RappInstanceDeployOrder rappInstanceDeployOrder = new RappInstanceDeployOrder(); + rappInstanceDeployOrder.setDeployOrder(DeployOrder.UNDEPLOY); + when(acmDeployer.undeployRappInstance(any(), any())).thenReturn(true); + when(smeDeployer.undeployRappInstance(any(), any())).thenReturn(true); + mockMvc.perform(MockMvcRequestBuilders.put("/rapps/{rapp_id}/instance/{instance_id}", rappId, rappInstanceId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(rappInstanceDeployOrder))) + .andExpect(status().isNotFound()); + } + + @Test + void testUndeployNoRappFailure() throws Exception { + UUID rappId = UUID.randomUUID(); + UUID rappInstanceId = UUID.randomUUID(); + RappInstanceDeployOrder rappInstanceDeployOrder = new RappInstanceDeployOrder(); + rappInstanceDeployOrder.setDeployOrder(DeployOrder.UNDEPLOY); + when(acmDeployer.undeployRappInstance(any(), any())).thenReturn(true); + when(smeDeployer.undeployRappInstance(any(), any())).thenReturn(true); + mockMvc.perform(MockMvcRequestBuilders.put("/rapps/{rapp_id}/instance/{instance_id}", rappId, rappInstanceId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(rappInstanceDeployOrder))) + .andExpect(status().isNotFound()); + } + + @Test + void testDeleteRappInstance() throws Exception { + UUID rappId = UUID.randomUUID(); + UUID rappInstanceId = UUID.randomUUID(); + Rapp rapp = getRapp(rappId, rappInstanceId); + rappCacheService.putRapp(rapp); + rappInstanceStateMachine.onboardRappInstance(rappInstanceId); + mockMvc.perform( + MockMvcRequestBuilders.delete("/rapps/{rapp_id}/instance/{instance_id}", rappId, rappInstanceId)) + .andExpect(status().isNoContent()); + } + + @Test + void testDeleteRappNoRappFailure() throws Exception { + UUID rappId = UUID.randomUUID(); + UUID rappInstanceId = UUID.randomUUID(); + mockMvc.perform( + MockMvcRequestBuilders.delete("/rapps/{rapp_id}/instance/{instance_id}", rappId, rappInstanceId)) + .andExpect(status().isNotFound()); + } + + @Test + void testDeleteRappNoInstanceFailure() throws Exception { + UUID rappId = UUID.randomUUID(); + UUID rappInstanceId = UUID.randomUUID(); + Rapp rapp = getRapp(rappId, rappInstanceId); + rapp.setRappInstances(Map.of()); + rappCacheService.putRapp(rapp); + rappInstanceStateMachine.onboardRappInstance(rappInstanceId); + mockMvc.perform( + MockMvcRequestBuilders.delete("/rapps/{rapp_id}/instance/{instance_id}", rappId, rappInstanceId)) + .andExpect(status().isNotFound()); + } + + Rapp getRapp(UUID rappId, UUID rappInstanceId) { + RappInstance rappInstance = new RappInstance(); + rappInstance.setRappInstanceId(rappInstanceId); + rappInstance.setState(RappInstanceState.UNDEPLOYED); + Map instances = new HashMap(); + instances.put(rappInstanceId, rappInstance); + Rapp rapp = Rapp.builder().rappId(rappId).name(String.valueOf(rappId)).packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.PRIMED).rappInstances(instances) + .build(); + return rapp; + } + +} diff --git a/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/AcmDeployerTest.java b/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/AcmDeployerTest.java deleted file mode 100755 index 5682ca0..0000000 --- a/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/AcmDeployerTest.java +++ /dev/null @@ -1,313 +0,0 @@ -/*- - * ============LICENSE_START====================================================================== - * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.service; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.oransc.rappmanager.acm.configuration.ACMConfiguration; -import com.oransc.rappmanager.acm.service.AcmDeployer; -import com.oransc.rappmanager.configuration.RappManagerConfiguration; -import com.oransc.rappmanager.models.Rapp; -import com.oransc.rappmanager.models.RappEvent; -import com.oransc.rappmanager.models.RappState; -import com.oransc.rappmanager.models.cache.RappCacheService; -import com.oransc.rappmanager.models.statemachine.RappStateMachine; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.UUID; -import org.apache.http.entity.ContentType; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; -import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; -import org.onap.policy.clamp.models.acm.concepts.DeployState; -import org.onap.policy.clamp.models.acm.concepts.LockState; -import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse; -import org.onap.policy.clamp.models.acm.messages.rest.commissioning.PrimeOrder; -import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.web.client.ExpectedCount; -import org.springframework.test.web.client.MockRestServiceServer; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import org.springframework.web.client.RestTemplate; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@TestPropertySource(properties = "rappmanager.csarlocation=src/test/resources") -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -@AutoConfigureMockMvc -public class AcmDeployerTest { - - MockRestServiceServer mockServer; - @SpyBean - AcmDeployer acmDeployer; - @Autowired - RestTemplate restTemplate; - @Autowired - ACMConfiguration acmConfiguration; - @Autowired - RappManagerConfiguration rappManagerConfiguration; - @Autowired - private MockMvc mockMvc; - @Autowired - RappCacheService rappCacheService; - @SpyBean - RappStateMachine rappStateMachine; - private final String validRappFile = "valid-rapp-package.csar"; - ObjectMapper objectMapper = new ObjectMapper(); - String URI_ACM_COMPOSITIONS, URI_ACM_COMPOSITION, URI_ACM_INSTANCES, URI_ACM_INSTANCE; - - @BeforeAll - void initACMURI() { - URI_ACM_COMPOSITIONS = acmConfiguration.getBaseUrl() + "compositions"; - URI_ACM_COMPOSITION = acmConfiguration.getBaseUrl() + "compositions/%s"; - URI_ACM_INSTANCES = acmConfiguration.getBaseUrl() + "compositions/%s/instances"; - URI_ACM_INSTANCE = acmConfiguration.getBaseUrl() + "compositions/%s/instances/%s"; - } - - - @BeforeEach - public void init() { - mockServer = MockRestServiceServer.createServer(restTemplate); - } - - @Test - void testCreateComposition() throws IOException { - String compositionPayload = Files.readString(Path.of(acmConfiguration.getCompositionDefinitionLocation())); - CommissioningResponse commissioningResponseExpected = new CommissioningResponse(); - commissioningResponseExpected.setCompositionId(UUID.randomUUID()); - mockServer.expect(ExpectedCount.once(), requestTo(URI_ACM_COMPOSITIONS)).andExpect(method(HttpMethod.POST)) - .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) - .body(objectMapper.writeValueAsString(commissioningResponseExpected))); - CommissioningResponse commissioningResponseActual = acmDeployer.createComposition(compositionPayload); - mockServer.verify(); - assertEquals(commissioningResponseActual.getCompositionId(), commissioningResponseExpected.getCompositionId()); - } - - @Test - void testCreateCompositionFailure() throws IOException { - String compositionPayload = Files.readString(Path.of(acmConfiguration.getCompositionDefinitionLocation())); - mockServer.expect(ExpectedCount.once(), requestTo(URI_ACM_COMPOSITIONS)).andExpect(method(HttpMethod.POST)) - .andRespond(withStatus(HttpStatus.BAD_GATEWAY)); - CommissioningResponse commissioningResponseActual = acmDeployer.createComposition(compositionPayload); - mockServer.verify(); - assertNull(commissioningResponseActual); - } - - @Test - void testCompositionPriming() { - UUID compositionId = UUID.randomUUID(); - mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId))) - .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED)); - - acmDeployer.primeACMComposition(compositionId, PrimeOrder.PRIME); - mockServer.verify(); - } - - @Test - void testDeployRapp() throws Exception { - - UUID compositionId = UUID.randomUUID(); - when(acmDeployer.getCompositionId()).thenReturn(compositionId); - UUID rappId = UUID.randomUUID(); - UUID instanceId = UUID.randomUUID(); - Rapp rapp = Rapp.builder().name(rappId.toString()).packageName(validRappFile).compositionId(compositionId) - .packageLocation(rappManagerConfiguration.getCsarLocation()).state(RappState.ONBOARDED) - .build(); - onBoardRappCsar(rappId); - InstantiationResponse instantiationResponse = new InstantiationResponse(); - instantiationResponse.setInstanceId(instanceId); - mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCES, compositionId))) - .andExpect(method(HttpMethod.POST)).andRespond( - withStatus(HttpStatus.ACCEPTED).contentType(MediaType.APPLICATION_JSON) - .body(objectMapper.writeValueAsString(instantiationResponse))); - - mockServer.expect(ExpectedCount.once(), - requestTo(acmConfiguration.getBaseUrl() + "compositions/" + compositionId + "/instances/" + instanceId)) - .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED)); - - - boolean rappDeployStateActual = acmDeployer.deployRapp(rapp); - assertTrue(rappDeployStateActual); - mockServer.verify(); - } - - @Test - void testDeployRappFailure() throws Exception { - UUID compositionId = UUID.randomUUID(); - when(acmDeployer.getCompositionId()).thenReturn(compositionId); - UUID rappId = UUID.randomUUID(); - UUID instanceId = UUID.randomUUID(); - Rapp rapp = Rapp.builder().name(rappId.toString()).packageName(validRappFile).compositionId(compositionId) - .packageLocation(rappManagerConfiguration.getCsarLocation()).state(RappState.ONBOARDED) - .build(); - onBoardRappCsar(rappId); - InstantiationResponse instantiationResponse = new InstantiationResponse(); - instantiationResponse.setInstanceId(instanceId); - mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCES, compositionId))) - .andExpect(method(HttpMethod.POST)).andRespond(withStatus(HttpStatus.BAD_GATEWAY)); - - boolean rappDeployStateActual = acmDeployer.deployRapp(rapp); - mockServer.verify(); - assertFalse(rappDeployStateActual); - } - - @Test - void testUndeployRapp() throws JsonProcessingException { - UUID compositionId = UUID.randomUUID(); - when(acmDeployer.getCompositionId()).thenReturn(compositionId); - UUID rappId = UUID.randomUUID(); - UUID instanceId = UUID.randomUUID(); - Rapp rapp = Rapp.builder().rappId(rappId).name(rappId.toString()).packageName(validRappFile) - .compositionId(compositionId).compositionInstanceId(instanceId).state(RappState.DEPLOYED) - .build(); - rappCacheService.putRapp(rapp); - rappStateMachine.onboardRapp(rappId); - - expectAcmGetInstanceToReturnDeployedState(compositionId, instanceId, DeployState.DEPLOYED, LockState.LOCKED, - ExpectedCount.once()); - - mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId))) - .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED)); - - expectAcmGetInstanceToReturnDeployedState(compositionId, instanceId, DeployState.UNDEPLOYED, LockState.UNLOCKED, - ExpectedCount.once()); - - mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId))) - .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.NO_CONTENT)); - - - boolean rappUndeployStateActual = acmDeployer.undeployRapp(rapp); - mockServer.verify(); - assertTrue(rappUndeployStateActual); - } - - @Test - void testUndeployRappFailure() throws JsonProcessingException { - UUID compositionId = UUID.randomUUID(); - when(acmDeployer.getCompositionId()).thenReturn(compositionId); - UUID rappId = UUID.randomUUID(); - UUID instanceId = UUID.randomUUID(); - Rapp rapp = Rapp.builder().name(rappId.toString()).packageName(validRappFile).compositionId(compositionId) - .compositionInstanceId(instanceId).state(RappState.DEPLOYED).build(); - rappCacheService.putRapp(rapp); - - expectAcmGetInstanceToReturnDeployedState(compositionId, instanceId, DeployState.DEPLOYED, LockState.LOCKED, - ExpectedCount.once()); - - mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId))) - .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED)); - - expectAcmGetInstanceToReturnDeployedState(compositionId, instanceId, DeployState.UNDEPLOYING, - LockState.UNLOCKING, ExpectedCount.manyTimes()); - - boolean rappUndeployStateActual = acmDeployer.undeployRapp(rapp); - mockServer.verify(); - assertFalse(rappUndeployStateActual); - } - - @Test - void testSyncRappStatus() throws JsonProcessingException { - UUID compositionId = UUID.randomUUID(); - when(acmDeployer.getCompositionId()).thenReturn(compositionId); - UUID rappId = UUID.randomUUID(); - UUID instanceId = UUID.randomUUID(); - Rapp rapp = Rapp.builder().rappId(rappId).name(rappId.toString()).packageName(validRappFile) - .compositionId(compositionId).compositionInstanceId(instanceId).state(RappState.DEPLOYED) - .build(); - rappCacheService.putRapp(rapp); - rappStateMachine.onboardRapp(rappId); - - expectAcmGetInstanceToReturnDeployedState(compositionId, instanceId, DeployState.UNDEPLOYING, - LockState.UNLOCKING, ExpectedCount.once()); - - acmDeployer.syncRappStatus(rapp); - mockServer.verify(); - verify(rappStateMachine, times(1)).sendRappEvent(rapp, RappEvent.UNDEPLOYING); - } - - @Test - void testSyncRappStatusFailure() { - UUID compositionId = UUID.randomUUID(); - when(acmDeployer.getCompositionId()).thenReturn(compositionId); - UUID rappId = UUID.randomUUID(); - UUID instanceId = UUID.randomUUID(); - Rapp rapp = Rapp.builder().name(rappId.toString()).packageName(validRappFile).compositionId(compositionId) - .compositionInstanceId(instanceId).state(RappState.DEPLOYED).build(); - rappCacheService.putRapp(rapp); - - mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId))) - .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.BAD_GATEWAY)); - - acmDeployer.syncRappStatus(rapp); - mockServer.verify(); - verify(rappStateMachine, never()).sendRappEvent(any(), any()); - } - - void expectAcmGetInstanceToReturnDeployedState(UUID compositionId, UUID instanceId, DeployState deployState, - LockState lockState, ExpectedCount expectedCount) throws JsonProcessingException { - AutomationComposition automationCompositionDeployed = new AutomationComposition(); - automationCompositionDeployed.setCompositionId(compositionId); - automationCompositionDeployed.setInstanceId(instanceId); - automationCompositionDeployed.setDeployState(deployState); - automationCompositionDeployed.setLockState(lockState); - - mockServer.expect(expectedCount, requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId))) - .andExpect(method(HttpMethod.GET)).andRespond( - withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) - .body(objectMapper.writeValueAsString(automationCompositionDeployed))); - } - - void onBoardRappCsar(UUID rappId) throws Exception { - String rappCsarPath = rappManagerConfiguration.getCsarLocation() + File.separator + validRappFile; - MockMultipartFile multipartFile = - new MockMultipartFile("file", validRappFile, ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPath)); - mockMvc.perform(MockMvcRequestBuilders.multipart("/rapps/{rapp_id}/onboard", rappId).file(multipartFile)) - .andExpect(status().isAccepted()); - } - - -} diff --git a/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappCsarConfigurationHandlerTest.java b/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappCsarConfigurationHandlerTest.java deleted file mode 100755 index f92becb..0000000 --- a/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappCsarConfigurationHandlerTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/*- - * ============LICENSE_START====================================================================== - * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.service; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.oransc.rappmanager.configuration.RappManagerConfiguration; - -import com.oransc.rappmanager.models.Rapp; -import com.oransc.rappmanager.models.RappCsarConfigurationHandler; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.UUID; -import org.apache.http.entity.ContentType; -import org.junit.jupiter.api.Test; -import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.context.TestPropertySource; -import org.springframework.web.multipart.MultipartFile; - -@SpringBootTest -@TestPropertySource(properties = "rappmanager.csarlocation=src/test/resources") -public class RappCsarConfigurationHandlerTest { - - @Autowired - RappCsarConfigurationHandler rappCsarConfigurationHandler; - - @Autowired - RappManagerConfiguration rappManagerConfiguration; - - ObjectMapper objectMapper = new ObjectMapper(); - - - private final String validRappFile = "valid-rapp-package.csar"; - - private final String invalidRappFile = "invalid-rapp-package.csar"; - - @Test - void testCsarPackageValidationSuccess() throws IOException { - String rappCsarPath = rappManagerConfiguration.getCsarLocation() + File.separator + validRappFile; - MultipartFile multipartFile = - new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPath)); - assertEquals(Boolean.TRUE, rappCsarConfigurationHandler.isValidRappPackage(multipartFile)); - } - - @Test - void testCsarPackageValidationFailure() throws IOException { - String rappCsarPath = rappManagerConfiguration.getCsarLocation() + File.separator + invalidRappFile; - MultipartFile multipartFile = - new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPath)); - assertEquals(Boolean.FALSE, rappCsarConfigurationHandler.isValidRappPackage(multipartFile)); - } - - @Test - void testCsarInstantiationPayload() throws JsonProcessingException { - Rapp rapp = Rapp.builder().name("").packageName(validRappFile) - .packageLocation(rappManagerConfiguration.getCsarLocation()).build(); - UUID compositionId = UUID.randomUUID(); - AutomationComposition automationComposition = - objectMapper.readValue(rappCsarConfigurationHandler.getInstantiationPayload(rapp, compositionId), - AutomationComposition.class); - assertEquals(automationComposition.getCompositionId(), compositionId); - } -} diff --git a/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappServiceTest.java b/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappServiceTest.java new file mode 100755 index 0000000..803504b --- /dev/null +++ b/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappServiceTest.java @@ -0,0 +1,157 @@ +package com.oransc.rappmanager.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import com.oransc.rappmanager.acm.service.AcmDeployer; +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.rappinstance.RappInstance; +import com.oransc.rappmanager.models.rappinstance.RappInstanceState; +import com.oransc.rappmanager.models.rapp.RappState; +import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine; +import com.oransc.rappmanager.sme.service.SmeDeployer; +import java.util.Map; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpStatus; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +public class RappServiceTest { + + @Autowired + RappService rappService; + + @MockBean + AcmDeployer acmDeployer; + + @MockBean + SmeDeployer smeDeployer; + + @Autowired + RappInstanceStateMachine rappInstanceStateMachine; + + String validCsarFileLocation = "src/test/resources/"; + + private final String validRappFile = "valid-rapp-package.csar"; + + private final String invalidRappFile = "invalid-rapp-package.csar"; + + + @Test + void testPrimeRapp() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + when(acmDeployer.primeRapp(any())).thenReturn(true); + assertEquals(HttpStatus.OK, rappService.primeRapp(rapp).getStatusCode()); + } + + @Test + void testPrimeRappInvalidState() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.PRIMING).build(); + assertEquals(HttpStatus.BAD_REQUEST, rappService.primeRapp(rapp).getStatusCode()); + } + + @Test + void testPrimeRappAcmFailure() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + when(acmDeployer.primeRapp(any())).thenReturn(false); + assertEquals(HttpStatus.OK, rappService.primeRapp(rapp).getStatusCode()); + } + + @Test + void testDeprimeRapp() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.PRIMED).build(); + when(acmDeployer.deprimeRapp(any())).thenReturn(true); + assertEquals(HttpStatus.OK, rappService.deprimeRapp(rapp).getStatusCode()); + } + + @Test + void testDeprimeRappFailure() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.PRIMED).build(); + when(acmDeployer.deprimeRapp(any())).thenReturn(false); + assertEquals(HttpStatus.OK, rappService.deprimeRapp(rapp).getStatusCode()); + } + + @Test + void testDeprimeRappInvalidState() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); + assertEquals(HttpStatus.BAD_REQUEST, rappService.deprimeRapp(rapp).getStatusCode()); + } + + @Test + void testDeprimeRappActiveInstances() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED) + .rappInstances(Map.of(UUID.randomUUID(), new RappInstance())).build(); + assertEquals(HttpStatus.BAD_REQUEST, rappService.deprimeRapp(rapp).getStatusCode()); + } + + @Test + void testDeployRappInstance() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.PRIMED).build(); + RappInstance rappInstance = new RappInstance(); + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + when(acmDeployer.deployRappInstance(any(), any())).thenReturn(true); + when(smeDeployer.deployRappInstance(any(), any())).thenReturn(true); + assertEquals(HttpStatus.ACCEPTED, rappService.deployRappInstance(rapp, rappInstance).getStatusCode()); + } + + @Test + void testDeployRappInstanceFailure() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.PRIMED).build(); + RappInstance rappInstance = new RappInstance(); + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + when(acmDeployer.deployRappInstance(any(), any())).thenReturn(true); + when(smeDeployer.deployRappInstance(any(), any())).thenReturn(false); + assertEquals(HttpStatus.BAD_GATEWAY, rappService.deployRappInstance(rapp, rappInstance).getStatusCode()); + } + + @Test + void testUndeployRappInstance() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.PRIMED).build(); + RappInstance rappInstance = new RappInstance(); + rappInstance.setState(RappInstanceState.DEPLOYED); + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + when(acmDeployer.undeployRappInstance(any(), any())).thenReturn(true); + when(smeDeployer.undeployRappInstance(any(), any())).thenReturn(true); + assertEquals(HttpStatus.ACCEPTED, rappService.undeployRappInstance(rapp, rappInstance).getStatusCode()); + } + + @Test + void testUndeployRappInstanceFailure() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.PRIMED).build(); + RappInstance rappInstance = new RappInstance(); + rappInstance.setState(RappInstanceState.DEPLOYED); + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + when(acmDeployer.undeployRappInstance(any(), any())).thenReturn(true); + when(smeDeployer.undeployRappInstance(any(), any())).thenReturn(false); + assertEquals(HttpStatus.BAD_GATEWAY, rappService.undeployRappInstance(rapp, rappInstance).getStatusCode()); + } + + @Test + void testUndeployRappInstanceInvalidStateFailure() { + Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile) + .packageLocation(validCsarFileLocation).state(RappState.PRIMED).build(); + RappInstance rappInstance = new RappInstance(); + rappInstance.setState(RappInstanceState.DEPLOYING); + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + when(acmDeployer.undeployRappInstance(any(), any())).thenReturn(true); + when(smeDeployer.undeployRappInstance(any(), any())).thenReturn(false); + assertEquals(HttpStatus.BAD_REQUEST, rappService.undeployRappInstance(rapp, rappInstance).getStatusCode()); + } +} diff --git a/rapp-manager-application/src/test/java/com/oransc/rappmanager/statemachine/RappStateMachineTest.java b/rapp-manager-application/src/test/java/com/oransc/rappmanager/statemachine/RappStateMachineTest.java deleted file mode 100755 index 6deb839..0000000 --- a/rapp-manager-application/src/test/java/com/oransc/rappmanager/statemachine/RappStateMachineTest.java +++ /dev/null @@ -1,166 +0,0 @@ -/*- - * ============LICENSE_START====================================================================== - * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.statemachine; - -import com.oransc.rappmanager.models.RappEvent; -import com.oransc.rappmanager.models.RappState; -import java.util.UUID; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.statemachine.StateMachine; -import org.springframework.statemachine.config.StateMachineFactory; -import org.springframework.statemachine.test.StateMachineTestPlan; -import org.springframework.statemachine.test.StateMachineTestPlanBuilder; - -@SpringBootTest -public class RappStateMachineTest { - - @Autowired - StateMachineFactory stateMachineFactory; - - StateMachine stateMachine; - - @BeforeEach - void getStateMachine() { - stateMachine = stateMachineFactory.getStateMachine(UUID.randomUUID()); - stateMachine.startReactively().subscribe(); - } - - @AfterEach - void stopStateMachine() { - stateMachine.stopReactively().subscribe(); - } - - @Test - void testOnboardedState() throws Exception { - StateMachineTestPlan plan = - StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() - .expectState(RappState.ONBOARDED).and().build(); - plan.test(); - } - - @Test - void testDeployingState() throws Exception { - StateMachineTestPlan plan = - StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() - .expectState(RappState.ONBOARDED).and().step().sendEvent(RappEvent.DEPLOYING) - .expectState(RappState.DEPLOYING).expectStateChanged(1).and().build(); - plan.test(); - } - - @ParameterizedTest - @EnumSource(value = RappEvent.class, names = {"ACMDEPLOYED", "SMEDEPLOYED"}) - void testIndividualDeployedState(RappEvent rappEvent) throws Exception { - StateMachineTestPlan plan = - StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() - .expectState(RappState.ONBOARDED).and().step().sendEvent(RappEvent.DEPLOYING) - .expectState(RappState.DEPLOYING).expectStateChanged(1).and().step().sendEvent(rappEvent) - .expectState(RappState.DEPLOYING).and().build(); - plan.test(); - } - - @Test - void testDeployedState() throws Exception { - StateMachineTestPlan plan = - StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() - .expectState(RappState.ONBOARDED).and().step().sendEvent(RappEvent.DEPLOYING) - .expectState(RappState.DEPLOYING).expectStateChanged(1).and().step() - .sendEvent(RappEvent.ACMDEPLOYED).expectState(RappState.DEPLOYING).and().step() - .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappState.DEPLOYED).expectStateChanged(1).and() - .build(); - plan.test(); - } - - @Test - void testDeployFailedState() throws Exception { - StateMachineTestPlan plan = - StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() - .expectState(RappState.ONBOARDED).and().step().sendEvent(RappEvent.DEPLOYING) - .expectState(RappState.DEPLOYING).expectStateChanged(1).and().step() - .sendEvent(RappEvent.ACMDEPLOYED).expectState(RappState.DEPLOYING).and().step() - .sendEvent(RappEvent.SMEDEPLOYFAILED).expectState(RappState.FAILED).expectStateChanged(1).and() - .build(); - plan.test(); - } - - @Test - void testUndeployingState() throws Exception { - StateMachineTestPlan plan = - StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() - .expectState(RappState.ONBOARDED).and().step().sendEvent(RappEvent.DEPLOYING) - .expectState(RappState.DEPLOYING).expectStateChanged(1).and().step() - .sendEvent(RappEvent.ACMDEPLOYED).expectState(RappState.DEPLOYING).and().step() - .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappState.DEPLOYED).expectStateChanged(1).and() - .step().sendEvent(RappEvent.UNDEPLOYING).expectState(RappState.UNDEPLOYING) - .expectStateChanged(1).and().build(); - plan.test(); - } - - @ParameterizedTest - @EnumSource(value = RappEvent.class, names = {"ACMUNDEPLOYED", "SMEUNDEPLOYED"}) - void testIndividualUndeployedState(RappEvent rappEvent) throws Exception { - StateMachineTestPlan plan = - StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() - .expectState(RappState.ONBOARDED).and().step().sendEvent(RappEvent.DEPLOYING) - .expectState(RappState.DEPLOYING).expectStateChanged(1).and().step() - .sendEvent(RappEvent.ACMDEPLOYED).expectState(RappState.DEPLOYING).and().step() - .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappState.DEPLOYED).expectStateChanged(1).and() - .step().sendEvent(RappEvent.UNDEPLOYING).expectState(RappState.UNDEPLOYING) - .expectStateChanged(1).and().step().sendEvent(rappEvent).expectState(RappState.UNDEPLOYING) - .and().build(); - plan.test(); - } - - @Test - void testUndeployedState() throws Exception { - StateMachineTestPlan plan = - StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() - .expectState(RappState.ONBOARDED).and().step().sendEvent(RappEvent.DEPLOYING) - .expectState(RappState.DEPLOYING).expectStateChanged(1).and().step() - .sendEvent(RappEvent.ACMDEPLOYED).expectState(RappState.DEPLOYING).and().step() - .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappState.DEPLOYED).expectStateChanged(1).and() - .step().sendEvent(RappEvent.UNDEPLOYING).expectState(RappState.UNDEPLOYING) - .expectStateChanged(1).and().step().sendEvent(RappEvent.ACMUNDEPLOYED) - .expectState(RappState.UNDEPLOYING).and().step().sendEvent(RappEvent.SMEUNDEPLOYED) - .expectState(RappState.UNDEPLOYED).expectStateChanged(1).and().build(); - plan.test(); - } - - @Test - void testUndeployFailedState() throws Exception { - StateMachineTestPlan plan = - StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() - .expectState(RappState.ONBOARDED).and().step().sendEvent(RappEvent.DEPLOYING) - .expectState(RappState.DEPLOYING).expectStateChanged(1).and().step() - .sendEvent(RappEvent.ACMDEPLOYED).expectState(RappState.DEPLOYING).and().step() - .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappState.DEPLOYED).expectStateChanged(1).and() - .step().sendEvent(RappEvent.UNDEPLOYING).expectState(RappState.UNDEPLOYING) - .expectStateChanged(1).and().step().sendEvent(RappEvent.ACMUNDEPLOYED) - .expectState(RappState.UNDEPLOYING).and().step().sendEvent(RappEvent.SMEUNDEPLOYFAILED) - .expectState(RappState.FAILED).expectStateChanged(1).and().build(); - plan.test(); - } - - -} diff --git a/rapp-manager-application/src/test/resources/valid-rapp-package.csar b/rapp-manager-application/src/test/resources/valid-rapp-package.csar index 205094e..b8b36e3 100755 Binary files a/rapp-manager-application/src/test/resources/valid-rapp-package.csar and b/rapp-manager-application/src/test/resources/valid-rapp-package.csar differ diff --git a/rapp-manager-models/pom.xml b/rapp-manager-models/pom.xml index 918d936..4d1414d 100755 --- a/rapp-manager-models/pom.xml +++ b/rapp-manager-models/pom.xml @@ -34,6 +34,12 @@ spring-statemachine-core 3.2.1 + + org.springframework.statemachine + spring-statemachine-test + 3.2.1 + test + org.slf4j slf4j-api @@ -49,6 +55,13 @@ spring-boot-starter-test test + + org.apache.httpcomponents + httpcore + 4.3.2 + test + + \ No newline at end of file diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappCsarConfigurationHandler.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappCsarConfigurationHandler.java deleted file mode 100755 index 5574f38..0000000 --- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappCsarConfigurationHandler.java +++ /dev/null @@ -1,115 +0,0 @@ -/*- - * ============LICENSE_START====================================================================== - * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Path; -import java.util.UUID; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -@Service -public class RappCsarConfigurationHandler { - - Logger logger = LoggerFactory.getLogger(RappCsarConfigurationHandler.class); - private final String acmInstantiationJsonLocation = "Files/Acm/instantiation.json"; - - private final String smeProviderDomainLocation = "Files/Sme/provider-domain.json"; - - private final String smeProviderApiLocation = "Files/Sme/provider-api.json"; - - private final String smeInvokerLocation = "Files/Sme/invoker.json"; - - - public boolean isValidRappPackage(MultipartFile multipartFile) { - return multipartFile.getOriginalFilename() != null && multipartFile.getOriginalFilename().endsWith(".csar") - && isFileExistsInCsar(multipartFile, acmInstantiationJsonLocation); - } - - boolean isFileExistsInCsar(MultipartFile multipartFile, String fileLocation) { - try (ZipInputStream zipInputStream = new ZipInputStream(multipartFile.getInputStream())) { - ZipEntry zipEntry; - while ((zipEntry = zipInputStream.getNextEntry()) != null) { - if (zipEntry.getName().matches(fileLocation)) { - return Boolean.TRUE; - } - } - return Boolean.FALSE; - } catch (IOException e) { - logger.error("Unable to find the CSAR file", e); - return Boolean.FALSE; - } - } - - public Path getRappPackageLocation(String csarLocation, String rappId, String fileName) { - return Path.of(csarLocation, rappId, fileName); - } - - public String getInstantiationPayload(Rapp rapp, UUID compositionId) { - return getPayload(rapp, acmInstantiationJsonLocation).replaceAll("COMPOSITIONID", - String.valueOf(compositionId)); - } - - String getPayload(Rapp rapp, String location) { - File csarFile = new File( - getRappPackageLocation(rapp.getPackageLocation(), rapp.getName(), rapp.getPackageName()).toUri()); - return getFileFromCsar(csarFile, location).toString(); - } - - ByteArrayOutputStream getFileFromCsar(File csarFile, String fileLocation) { - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - try (FileInputStream fileInputStream = new FileInputStream(csarFile); - ZipInputStream zipInputStream = new ZipInputStream(fileInputStream)) { - ZipEntry entry; - while ((entry = zipInputStream.getNextEntry()) != null) { - if (!entry.isDirectory() && entry.getName().equals(fileLocation)) { - byte[] buffer = new byte[1024]; - int bytesRead; - while ((bytesRead = zipInputStream.read(buffer)) != -1) { - byteArrayOutputStream.write(buffer, 0, bytesRead); - } - } - } - } catch (IOException e) { - logger.error("Unable to find the CSAR file", e); - } - return byteArrayOutputStream; - } - - - public String getSmeProviderDomainPayload(Rapp rapp) { - return getPayload(rapp, smeProviderDomainLocation); - } - - public String getSmeProviderApiPayload(Rapp rapp) { - return getPayload(rapp, smeProviderApiLocation); - } - - public String getSmeInvokerPayload(Rapp rapp) { - return getPayload(rapp, smeInvokerLocation); - } - -} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappDeployer.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappDeployer.java index 9c6a410..9aa3fca 100755 --- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappDeployer.java +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappDeployer.java @@ -1,6 +1,33 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models; +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.rappinstance.RappInstance; + public interface RappDeployer { - boolean deployRapp(Rapp rapp); - boolean undeployRapp(Rapp rapp); + + boolean deployRappInstance(Rapp rapp, RappInstance rappInstance); + + boolean undeployRappInstance(Rapp rapp, RappInstance rappInstance); + + boolean primeRapp(Rapp rapp); + + boolean deprimeRapp(Rapp rapp); } diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappEvent.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappEvent.java deleted file mode 100755 index 0f64e55..0000000 --- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappEvent.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.oransc.rappmanager.models; - -public enum RappEvent { - ONBOARDED, DEPLOYING, ACMDEPLOYED, SMEDEPLOYED, ACMDEPLOYFAILED, SMEDEPLOYFAILED, DEPLOYED, UNDEPLOYING, UNDEPLOYED, - ACMUNDEPLOYED, SMEUNDEPLOYED, ACMUNDEPLOYFAILED, SMEUNDEPLOYFAILED -} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/cache/RappCacheService.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/cache/RappCacheService.java index d2b273c..ec7d7b2 100755 --- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/cache/RappCacheService.java +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/cache/RappCacheService.java @@ -18,8 +18,7 @@ package com.oransc.rappmanager.models.cache; -import com.oransc.rappmanager.models.Rapp; -import com.oransc.rappmanager.models.statemachine.RappStateMachine; +import com.oransc.rappmanager.models.rapp.Rapp; import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.cache.Cache; @@ -32,7 +31,6 @@ public class RappCacheService { private final String RAPP_CACHE = "rapp-cache"; private final CacheManager cacheManager; - private final RappStateMachine rappStateMachine; public Cache getAllRapp() { return cacheManager.getCache(RAPP_CACHE); @@ -40,9 +38,7 @@ public class RappCacheService { public Optional getRapp(String rappId) { final Cache cache = cacheManager.getCache(RAPP_CACHE); - Optional rappOptional = Optional.ofNullable(cache.get(rappId, Rapp.class)); - rappOptional.ifPresent(rapp -> rapp.setState(rappStateMachine.getRappState(rapp.getRappId()))); - return rappOptional; + return Optional.ofNullable(cache.get(rappId, Rapp.class)); } public void putRapp(Rapp rapp) { diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandler.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandler.java new file mode 100755 index 0000000..f7cdece --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandler.java @@ -0,0 +1,168 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.csar; + +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.rappinstance.RappACMInstance; +import com.oransc.rappmanager.models.rapp.RappResources; +import com.oransc.rappmanager.models.rappinstance.RappSMEInstance; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; +import java.util.UUID; +import java.util.function.Predicate; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +@Service +public class RappCsarConfigurationHandler { + + Logger logger = LoggerFactory.getLogger(RappCsarConfigurationHandler.class); + private final String acmCompositionJsonLocation = "Files/Acm/definition/compositions.json"; + private final String acmDefinitionLocation = "Files/Acm/definition"; + private final String acmInstancesLocation = "Files/Acm/instances"; + + private final String smeProviderFuncsLocation = "Files/Sme/providers"; + private final String smeServiceApisLocation = "Files/Sme/serviceapis"; + + private final String smeInvokersLocation = "Files/Sme/invokers"; + + + public boolean isValidRappPackage(MultipartFile multipartFile) { + return multipartFile.getOriginalFilename() != null && multipartFile.getOriginalFilename().endsWith(".csar") + && isFileExistsInCsar(multipartFile, acmCompositionJsonLocation); + //TODO Additional file checks needs to be added + } + + boolean isFileExistsInCsar(MultipartFile multipartFile, String fileLocation) { + try (ZipInputStream zipInputStream = new ZipInputStream(multipartFile.getInputStream())) { + ZipEntry zipEntry; + while ((zipEntry = zipInputStream.getNextEntry()) != null) { + if (zipEntry.getName().matches(fileLocation)) { + return Boolean.TRUE; + } + } + return Boolean.FALSE; + } catch (IOException e) { + logger.error("Unable to find the CSAR file", e); + return Boolean.FALSE; + } + } + + public Path getRappPackageLocation(String csarLocation, String rappId, String fileName) { + return Path.of(csarLocation, rappId, fileName); + } + + public String getInstantiationPayload(Rapp rapp, RappACMInstance rappACMInstance, UUID compositionId) { + return getPayload(rapp, getResourceUri(acmInstancesLocation, rappACMInstance.getInstance())).replaceAll( + "COMPOSITIONID", String.valueOf(compositionId)); + } + + String getPayload(Rapp rapp, String location) { + logger.info("Getting payload for {} from {}", rapp.getRappId(), location); + File csarFile = getCsarFile(rapp); + return getFileFromCsar(csarFile, location).toString(); + } + + File getCsarFile(Rapp rapp) { + return new File( + getRappPackageLocation(rapp.getPackageLocation(), rapp.getName(), rapp.getPackageName()).toUri()); + } + + ByteArrayOutputStream getFileFromCsar(File csarFile, String fileLocation) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + try (FileInputStream fileInputStream = new FileInputStream(csarFile); + ZipInputStream zipInputStream = new ZipInputStream(fileInputStream)) { + ZipEntry entry; + while ((entry = zipInputStream.getNextEntry()) != null) { + if (!entry.isDirectory() && entry.getName().equals(fileLocation)) { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = zipInputStream.read(buffer)) != -1) { + byteArrayOutputStream.write(buffer, 0, bytesRead); + } + } + } + } catch (IOException e) { + logger.error("Unable to find the CSAR file", e); + } + return byteArrayOutputStream; + } + + + public String getSmeProviderDomainPayload(Rapp rapp, RappSMEInstance rappSMEInstance) { + return getPayload(rapp, getResourceUri(smeProviderFuncsLocation, rappSMEInstance.getProviderFunction())); + } + + public String getSmeProviderApiPayload(Rapp rapp, RappSMEInstance rappSMEInstance) { + return getPayload(rapp, getResourceUri(smeServiceApisLocation, rappSMEInstance.getServiceApis())); + } + + public String getSmeInvokerPayload(Rapp rapp, RappSMEInstance rappSMEInstance) { + return getPayload(rapp, getResourceUri(smeInvokersLocation, rappSMEInstance.getInvokers())); + } + + public String getAcmCompositionPayload(Rapp rapp) { + return getPayload(rapp, + getResourceUri(acmDefinitionLocation, rapp.getRappResources().getAcm().getCompositionDefinitions())); + } + + String getResourceUri(String resourceLocation, String resource) { + return resourceLocation + "/" + resource + ".json"; + } + + public RappResources getRappResource(Rapp rapp) { + RappResources rappResources = new RappResources(); + try { + File csarFile = getCsarFile(rapp); + if (csarFile.exists()) { + rappResources.setAcm(RappResources.ACMResources.builder().compositionDefinitions( + getFileListFromCsar(csarFile, acmDefinitionLocation).get(0)) + .compositionInstances(getFileListFromCsar(csarFile, acmInstancesLocation)) + .build()); + rappResources.setSme(RappResources.SMEResources.builder() + .providerFunctions(getFileListFromCsar(csarFile, smeProviderFuncsLocation)) + .serviceApis(getFileListFromCsar(csarFile, smeServiceApisLocation)) + .invokers(getFileListFromCsar(csarFile, smeInvokersLocation)).build()); + } + } catch (Exception e) { + logger.warn("Error in getting the rapp resources", e); + } + return rappResources; + } + + List getFileListFromCsar(File csarFile, String dirLocation) { + try (ZipFile zipFile = new ZipFile(csarFile)) { + return zipFile.stream().filter(Predicate.not(ZipEntry::isDirectory)).map(ZipEntry::getName) + .filter(name -> name.startsWith(dirLocation)) + .map(name -> name.substring(name.lastIndexOf("/") + 1, name.lastIndexOf("."))).toList(); + } catch (IOException e) { + logger.warn("Error in listing the files from csar", e); + } + return List.of(); + } +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/PrimeOrder.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/PrimeOrder.java new file mode 100755 index 0000000..9ad0d36 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/PrimeOrder.java @@ -0,0 +1,23 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.rapp; + +public enum PrimeOrder { + PRIME, DEPRIME; +} \ No newline at end of file diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/Rapp.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/Rapp.java similarity index 76% rename from rapp-manager-models/src/main/java/com/oransc/rappmanager/models/Rapp.java rename to rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/Rapp.java index c8b4f6d..0aac806 100755 --- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/Rapp.java +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/Rapp.java @@ -16,17 +16,15 @@ * ============LICENSE_END======================================================================== */ -package com.oransc.rappmanager.models; +package com.oransc.rappmanager.models.rapp; -import java.util.ArrayList; +import com.oransc.rappmanager.models.rappinstance.RappInstance; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.UUID; import lombok.Builder; import lombok.Data; -import lombok.Getter; @Data @Builder(toBuilder = true) @@ -38,14 +36,9 @@ public class Rapp { RappState state; String packageLocation; String packageName; - UUID compositionId; - UUID compositionInstanceId; - String smeApfId; - String smeAefId; - @Builder.Default - Map smeProviderFunctions = new HashMap<>(); - @Builder.Default - List smeServiceApis = new ArrayList<>(); + RappResources rappResources; @Builder.Default - List smeInvokers = new ArrayList<>(); + Map rappInstances = new HashMap<>(); + + UUID compositionId; } diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappEvent.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappEvent.java new file mode 100755 index 0000000..1bdc67d --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappEvent.java @@ -0,0 +1,32 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.rapp; + +public enum RappEvent { + DEPLOYING, + ACMDEPLOYED, + SMEDEPLOYED, + ACMDEPLOYFAILED, + SMEDEPLOYFAILED, + UNDEPLOYING, + ACMUNDEPLOYED, + SMEUNDEPLOYED, + ACMUNDEPLOYFAILED, + SMEUNDEPLOYFAILED +} diff --git a/rapp-manager-application/src/main/java/com/oransc/rappmanager/exception/ACMInvalidStateTransitionException.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappPrimeOrder.java similarity index 75% rename from rapp-manager-application/src/main/java/com/oransc/rappmanager/exception/ACMInvalidStateTransitionException.java rename to rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappPrimeOrder.java index efc7175..759be89 100755 --- a/rapp-manager-application/src/main/java/com/oransc/rappmanager/exception/ACMInvalidStateTransitionException.java +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappPrimeOrder.java @@ -16,14 +16,14 @@ * ============LICENSE_END======================================================================== */ -package com.oransc.rappmanager.exception; +package com.oransc.rappmanager.models.rapp; -public class ACMInvalidStateTransitionException extends RuntimeException { - public ACMInvalidStateTransitionException() { - super(); - } +import com.oransc.rappmanager.models.rapp.PrimeOrder; +import lombok.Data; + +@Data +public class RappPrimeOrder { + + PrimeOrder primeOrder; - public ACMInvalidStateTransitionException(String targetState, String actualState) { - super(); - } } diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappResources.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappResources.java new file mode 100755 index 0000000..4dd5e3a --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappResources.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.rapp; + +import java.util.List; +import lombok.Builder; +import lombok.Data; + +@Data +public class RappResources { + + public ACMResources acm; + public SMEResources sme; + + @Data + @Builder + public static class ACMResources { + + String compositionDefinitions; + List compositionInstances; + } + + @Data + @Builder + public static class SMEResources { + + List providerFunctions; + List serviceApis; + List invokers; + } +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappState.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappState.java similarity index 89% rename from rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappState.java rename to rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappState.java index 6198c47..c7b54a0 100755 --- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/RappState.java +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappState.java @@ -16,8 +16,8 @@ * ============LICENSE_END======================================================================== */ -package com.oransc.rappmanager.models; +package com.oransc.rappmanager.models.rapp; public enum RappState { - ONBOARDED, DEPLOYING, DEPLOYED, UNDEPLOYING, UNDEPLOYED, FAILED + COMMISSIONED, PRIMING, PRIMED, DEPRIMING, } diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/DeployOrder.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/DeployOrder.java new file mode 100755 index 0000000..5e838a1 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/DeployOrder.java @@ -0,0 +1,23 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.rappinstance; + +public enum DeployOrder { + DEPLOY, UNDEPLOY; +} \ No newline at end of file diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappACMInstance.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappACMInstance.java new file mode 100755 index 0000000..e50bb86 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappACMInstance.java @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.rappinstance; + +import java.util.UUID; +import lombok.Data; + +@Data +public class RappACMInstance { + + String instance; + UUID acmInstanceId; + +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstance.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstance.java new file mode 100755 index 0000000..b5e54a7 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstance.java @@ -0,0 +1,31 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.rappinstance; + +import java.util.UUID; +import lombok.Data; + +@Data +public class RappInstance { + + UUID rappInstanceId = UUID.randomUUID(); + RappInstanceState state = RappInstanceState.UNDEPLOYED; + RappACMInstance acm; + RappSMEInstance sme; +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstanceDeployOrder.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstanceDeployOrder.java new file mode 100755 index 0000000..1dc9754 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstanceDeployOrder.java @@ -0,0 +1,27 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.rappinstance; + +import lombok.Data; + +@Data +public class RappInstanceDeployOrder { + + DeployOrder deployOrder; +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstanceState.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstanceState.java new file mode 100755 index 0000000..cb5e6b1 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstanceState.java @@ -0,0 +1,23 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.rappinstance; + +public enum RappInstanceState { + DEPLOYED, DEPLOYING, UNDEPLOYED, UNDEPLOYING; +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappSMEInstance.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappSMEInstance.java new file mode 100755 index 0000000..1ec24b3 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappSMEInstance.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.rappinstance; + +import java.util.List; +import lombok.Data; + +@Data +public class RappSMEInstance { + + String providerFunction; + List providerFunctionIds; + String serviceApis; + List serviceApiIds; + String invokers; + List invokerIds; + + String aefId; + String apfId; + +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachine.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachine.java new file mode 100755 index 0000000..4e10ac0 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachine.java @@ -0,0 +1,63 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.statemachine; + +import com.oransc.rappmanager.models.rapp.RappEvent; +import com.oransc.rappmanager.models.rappinstance.RappInstance; +import com.oransc.rappmanager.models.rappinstance.RappInstanceState; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.statemachine.StateMachine; +import org.springframework.statemachine.config.StateMachineFactory; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class RappInstanceStateMachine { + + Logger logger = LoggerFactory.getLogger(RappInstanceStateMachine.class); + + private final StateMachineFactory stateMachineFactory; + Map> stateMachineMap = new HashMap<>(); + + public void onboardRappInstance(UUID rappInstanceId) { + StateMachine stateMachine = stateMachineFactory.getStateMachine(rappInstanceId); + stateMachineMap.put(rappInstanceId, stateMachine); + stateMachine.start(); + } + + public void sendRappInstanceEvent(RappInstance rappInstance, RappEvent rappEvent) { + logger.info("Sending rapp instance event {} for {}", rappEvent.name(), rappInstance.getRappInstanceId()); + logger.debug("State machine map is {}", stateMachineMap); + stateMachineMap.get(rappInstance.getRappInstanceId()).sendEvent(rappEvent); + } + + public RappInstanceState getRappInstanceState(UUID rappInstanceId) { + return stateMachineMap.get(rappInstanceId).getState().getId(); + } + + public void deleteRappInstance(RappInstance rappInstance) { + stateMachineMap.get(rappInstance.getRappInstanceId()).stop(); + stateMachineMap.remove(rappInstance.getRappInstanceId()); + } +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfig.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfig.java new file mode 100755 index 0000000..e1bc784 --- /dev/null +++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfig.java @@ -0,0 +1,105 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.statemachine; + +import com.oransc.rappmanager.models.rapp.RappEvent; +import com.oransc.rappmanager.models.rappinstance.RappInstanceState; +import java.util.EnumSet; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.config.EnableStateMachineFactory; +import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.guard.Guard; + +@Configuration +@EnableStateMachineFactory +public class RappInstanceStateMachineConfig extends EnumStateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states.withStates().initial(RappInstanceState.UNDEPLOYED).states(EnumSet.allOf(RappInstanceState.class)); + } + + @Override + public void configure(StateMachineConfigurationConfigurer config) throws Exception { + config.withConfiguration(); + } + + // @formatter:off + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions + .withExternal() + .source(RappInstanceState.UNDEPLOYED).target(RappInstanceState.DEPLOYING).event(RappEvent.DEPLOYING) + .and() + .withExternal() + .source(RappInstanceState.DEPLOYING).target(RappInstanceState.UNDEPLOYED).event(RappEvent.ACMDEPLOYFAILED) + .and() + .withExternal() + .source(RappInstanceState.DEPLOYING).target(RappInstanceState.UNDEPLOYED).event(RappEvent.SMEDEPLOYFAILED) + .and() + .withExternal() + .source(RappInstanceState.UNDEPLOYING).target(RappInstanceState.DEPLOYED).event(RappEvent.ACMUNDEPLOYFAILED) + .and() + .withExternal() + .source(RappInstanceState.UNDEPLOYING).target(RappInstanceState.DEPLOYED).event(RappEvent.SMEUNDEPLOYFAILED) + .and() + .withExternal() + .source(RappInstanceState.DEPLOYED).target(RappInstanceState.UNDEPLOYING).event(RappEvent.UNDEPLOYING) + .and() + .withExternal() + .source(RappInstanceState.DEPLOYING).target(RappInstanceState.DEPLOYED).event(RappEvent.ACMDEPLOYED) + .guard(deployedGuard()) + .and() + .withExternal() + .source(RappInstanceState.DEPLOYING).target(RappInstanceState.DEPLOYED).event(RappEvent.SMEDEPLOYED) + .guard(deployedGuard()) + .and() + .withExternal() + .source(RappInstanceState.UNDEPLOYING).target(RappInstanceState.UNDEPLOYED).event(RappEvent.ACMUNDEPLOYED) + .guard(undeployedGuard()) + .and() + .withExternal() + .source(RappInstanceState.UNDEPLOYING).target(RappInstanceState.UNDEPLOYED).event(RappEvent.SMEUNDEPLOYED) + .guard(undeployedGuard()); + + } + // @formatter:on + + @Bean + public Guard deployedGuard() { + return stateContext -> { + stateContext.getExtendedState().getVariables().put(stateContext.getEvent(), true); + return stateContext.getExtendedState().getVariables().get(RappEvent.ACMDEPLOYED) != null + && stateContext.getExtendedState().getVariables().get(RappEvent.SMEDEPLOYED) != null; + }; + } + + @Bean + public Guard undeployedGuard() { + return stateContext -> { + stateContext.getExtendedState().getVariables().put(stateContext.getEvent(), true); + return stateContext.getExtendedState().getVariables().get(RappEvent.ACMUNDEPLOYED) != null + && stateContext.getExtendedState().getVariables().get(RappEvent.SMEUNDEPLOYED) != null; + }; + } +} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappStateMachine.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappStateMachine.java deleted file mode 100755 index fcd6ed3..0000000 --- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappStateMachine.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.oransc.rappmanager.models.statemachine; - -import com.oransc.rappmanager.models.Rapp; -import com.oransc.rappmanager.models.RappEvent; -import com.oransc.rappmanager.models.RappState; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import lombok.RequiredArgsConstructor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.statemachine.StateMachine; -import org.springframework.statemachine.config.StateMachineFactory; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class RappStateMachine { - - Logger logger = LoggerFactory.getLogger(RappStateMachine.class); - - private final StateMachineFactory stateMachineFactory; - private Map> stateMachineMap = new HashMap<>(); - - public void onboardRapp(UUID rappId) { - StateMachine stateMachine = stateMachineFactory.getStateMachine(rappId); - stateMachineMap.put(rappId, stateMachine); - stateMachine.start(); - } - - public void sendRappEvent(Rapp rapp, RappEvent rappEvent) { - logger.info("Sending rapp event {} for {}", rappEvent.name(), rapp.getRappId()); - logger.info("State machine map is {}", stateMachineMap); - stateMachineMap.get(rapp.getRappId()).sendEvent(rappEvent); - } - - public RappState getRappState(UUID rappId) { - return stateMachineMap.get(rappId).getState().getId(); - } - - public void deleteRapp(Rapp rapp) { - stateMachineMap.get(rapp.getRappId()).stop(); - } -} diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappStateMachineConfig.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappStateMachineConfig.java deleted file mode 100755 index 4d7e486..0000000 --- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappStateMachineConfig.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.oransc.rappmanager.models.statemachine; - -import com.oransc.rappmanager.models.RappEvent; -import com.oransc.rappmanager.models.RappState; -import java.util.EnumSet; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.statemachine.config.EnableStateMachineFactory; -import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter; -import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; -import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; -import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; -import org.springframework.statemachine.guard.Guard; - -@Configuration -@EnableStateMachineFactory -public class RappStateMachineConfig extends EnumStateMachineConfigurerAdapter { - - @Override - public void configure(StateMachineStateConfigurer states) throws Exception { - states.withStates().initial(RappState.ONBOARDED).states(EnumSet.allOf(RappState.class)); - } - - @Override - public void configure(StateMachineConfigurationConfigurer config) throws Exception { - config.withConfiguration(); - } - - // @formatter:off - @Override - public void configure(StateMachineTransitionConfigurer transitions) throws Exception { - transitions - .withExternal() - .source(RappState.ONBOARDED).target(RappState.DEPLOYING).event(RappEvent.DEPLOYING) - .and() - .withExternal() - .source(RappState.DEPLOYING).target(RappState.FAILED).event(RappEvent.ACMDEPLOYFAILED) - .and() - .withExternal() - .source(RappState.DEPLOYING).target(RappState.FAILED).event(RappEvent.SMEDEPLOYFAILED) - .and() - .withExternal() - .source(RappState.UNDEPLOYING).target(RappState.FAILED).event(RappEvent.ACMUNDEPLOYFAILED) - .and() - .withExternal() - .source(RappState.UNDEPLOYING).target(RappState.FAILED).event(RappEvent.SMEUNDEPLOYFAILED) - .and() - .withExternal() - .source(RappState.DEPLOYED).target(RappState.UNDEPLOYING).event(RappEvent.UNDEPLOYING) - .and() - .withExternal() - .source(RappState.DEPLOYING).target(RappState.DEPLOYED).event(RappEvent.ACMDEPLOYED) - .guard(deployedGuard()) - .and() - .withExternal() - .source(RappState.DEPLOYING).target(RappState.DEPLOYED).event(RappEvent.SMEDEPLOYED) - .guard(deployedGuard()) - .and() - .withExternal() - .source(RappState.UNDEPLOYING).target(RappState.UNDEPLOYED).event(RappEvent.ACMUNDEPLOYED) - .guard(undeployedGuard()) - .and() - .withExternal() - .source(RappState.UNDEPLOYING).target(RappState.UNDEPLOYED).event(RappEvent.SMEUNDEPLOYED) - .guard(undeployedGuard()); - - } - // @formatter:on - - @Bean - public Guard deployedGuard() { - return stateContext -> { - stateContext.getExtendedState().getVariables().put(stateContext.getEvent(), true); - return stateContext.getExtendedState().getVariables().get(RappEvent.ACMDEPLOYED) != null - && stateContext.getExtendedState().getVariables().get(RappEvent.SMEDEPLOYED) != null; - }; - } - - @Bean - public Guard undeployedGuard() { - return stateContext -> { - stateContext.getExtendedState().getVariables().put(stateContext.getEvent(), true); - return stateContext.getExtendedState().getVariables().get(RappEvent.ACMUNDEPLOYED) != null - && stateContext.getExtendedState().getVariables().get(RappEvent.SMEUNDEPLOYED) != null; - }; - } -} diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java new file mode 100755 index 0000000..10f5d96 --- /dev/null +++ b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java @@ -0,0 +1,191 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.csar; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.rapp.RappResources; +import com.oransc.rappmanager.models.rappinstance.RappACMInstance; +import com.oransc.rappmanager.models.rappinstance.RappSMEInstance; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.List; +import java.util.UUID; +import org.apache.http.entity.ContentType; +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.web.multipart.MultipartFile; + +@SpringBootTest +@ContextConfiguration(classes = RappCsarConfigurationHandler.class) +public class RappCsarConfigurationHandlerTest { + + @Autowired + RappCsarConfigurationHandler rappCsarConfigurationHandler; + + String validCsarFileLocation = "src/test/resources/"; + + + private final String validRappFile = "valid-rapp-package.csar"; + + private final String invalidRappFile = "invalid-rapp-package.csar"; + + @Test + void testCsarPackageValidationSuccess() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + validRappFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + assertEquals(Boolean.TRUE, rappCsarConfigurationHandler.isValidRappPackage(multipartFile)); + } + + @Test + void testCsarPackageValidationFailure() throws IOException { + String rappCsarPath = validCsarFileLocation + File.separator + invalidRappFile; + MultipartFile multipartFile = + new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(), + new FileInputStream(rappCsarPath)); + assertEquals(Boolean.FALSE, rappCsarConfigurationHandler.isValidRappPackage(multipartFile)); + } + + @Test + void testCsarInstantiationPayload() throws JSONException { + Rapp rapp = Rapp.builder().name("").packageName(validRappFile).packageLocation(validCsarFileLocation).build(); + UUID compositionId = UUID.randomUUID(); + RappACMInstance rappACMInstance = new RappACMInstance(); + rappACMInstance.setInstance("kserve-instance"); + JSONObject jsonObject = new JSONObject( + rappCsarConfigurationHandler.getInstantiationPayload(rapp, rappACMInstance, compositionId)); + assertEquals(jsonObject.get("compositionId"), String.valueOf(compositionId)); + } + + @Test + void testFileListing() { + File file = new File(validCsarFileLocation + validRappFile); + List fileListFromCsar = + rappCsarConfigurationHandler.getFileListFromCsar(file, "Files/Sme/serviceapis/"); + assertThat(fileListFromCsar.size()).isEqualTo(2); + } + + @Test + void testInvalidFileListing() { + File file = new File(validCsarFileLocation); + List fileListFromCsar = rappCsarConfigurationHandler.getFileListFromCsar(file, null); + assertThat(fileListFromCsar.size()).isEqualTo(0); + } + + @Test + void testListResources() { + UUID rappId = UUID.randomUUID(); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .build(); + RappResources rappResources = rappCsarConfigurationHandler.getRappResource(rapp); + assertThat(rappResources).isNotNull(); + assertNotNull(rappResources.getAcm().getCompositionDefinitions()); + assertThat(rappResources.getAcm().getCompositionInstances().size()).isEqualTo(3); + assertThat(rappResources.getSme().getProviderFunctions().size()).isEqualTo(4); + assertThat(rappResources.getSme().getServiceApis().size()).isEqualTo(2); + assertThat(rappResources.getSme().getInvokers().size()).isEqualTo(2); + } + + @Test + void testListInvalidResources() { + UUID rappId = UUID.randomUUID(); + Rapp rapp = Rapp.builder().rappId(rappId).name("").build(); + RappResources rappResources = rappCsarConfigurationHandler.getRappResource(rapp); + assertThat(rappResources).isNotNull(); + assertNull(rappResources.getAcm()); + assertNull(rappResources.getSme()); + } + + @Test + void testGetAcmCompositionPayload() { + UUID rappId = UUID.randomUUID(); + RappResources rappResources = new RappResources(); + rappResources.setAcm(RappResources.ACMResources.builder().compositionDefinitions("compositions") + .compositionInstances(List.of()).build()); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .rappResources(rappResources).build(); + String acmCompositionPayload = rappCsarConfigurationHandler.getAcmCompositionPayload(rapp); + assertNotNull(acmCompositionPayload); + } + + @Test + void testGetInvalidAcmCompositionPayload() { + UUID rappId = UUID.randomUUID(); + RappResources rappResources = new RappResources(); + rappResources.setAcm(RappResources.ACMResources.builder().compositionDefinitions("invalidcomposition") + .compositionInstances(List.of()).build()); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .rappResources(rappResources).build(); + String acmCompositionPayload = rappCsarConfigurationHandler.getAcmCompositionPayload(rapp); + assertEquals("", acmCompositionPayload); + } + + @Test + void testGetSmeProviderDomainPayload() { + UUID rappId = UUID.randomUUID(); + RappSMEInstance rappSMEInstance = new RappSMEInstance(); + rappSMEInstance.setProviderFunction("aef-provider-function"); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .build(); + String smeProviderDomainPayload = + rappCsarConfigurationHandler.getSmeProviderDomainPayload(rapp, rappSMEInstance); + assertNotNull(smeProviderDomainPayload); + } + + @Test + void testGetSmeServiceApiPayload() { + UUID rappId = UUID.randomUUID(); + RappSMEInstance rappSMEInstance = new RappSMEInstance(); + rappSMEInstance.setServiceApis("api-set-1"); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .build(); + String smeProviderDomainPayload = rappCsarConfigurationHandler.getSmeProviderApiPayload(rapp, rappSMEInstance); + assertNotNull(smeProviderDomainPayload); + } + + @Test + void testGetSmeInvokerPayload() { + UUID rappId = UUID.randomUUID(); + RappSMEInstance rappSMEInstance = new RappSMEInstance(); + rappSMEInstance.setServiceApis("invoker-app1"); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .build(); + String smeProviderDomainPayload = rappCsarConfigurationHandler.getSmeInvokerPayload(rapp, rappSMEInstance); + assertNotNull(smeProviderDomainPayload); + } + +} diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfigTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfigTest.java new file mode 100755 index 0000000..1ab5481 --- /dev/null +++ b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfigTest.java @@ -0,0 +1,169 @@ +/*- + * ============LICENSE_START====================================================================== + * Copyright (C) 2023 Nordix Foundation. 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 com.oransc.rappmanager.models.statemachine; + +import com.oransc.rappmanager.models.rapp.RappEvent; +import com.oransc.rappmanager.models.rappinstance.RappInstanceState; +import java.util.UUID; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.statemachine.StateMachine; +import org.springframework.statemachine.config.StateMachineFactory; +import org.springframework.statemachine.test.StateMachineTestPlan; +import org.springframework.statemachine.test.StateMachineTestPlanBuilder; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = {RappInstanceStateMachineConfig.class}) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +public class RappInstanceStateMachineConfigTest { + + @Autowired + StateMachineFactory stateMachineFactory; + + StateMachine stateMachine; + + @BeforeEach + void getStateMachine() { + stateMachine = stateMachineFactory.getStateMachine(UUID.randomUUID()); + stateMachine.startReactively().subscribe(); + } + + @AfterEach + void stopStateMachine() { + stateMachine.stopReactively().subscribe(); + } + + @Test + void testOnboardedState() throws Exception { + StateMachineTestPlan plan = + StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() + .expectState(RappInstanceState.UNDEPLOYED).and().build(); + plan.test(); + } + + @Test + void testDeployingState() throws Exception { + StateMachineTestPlan plan = + StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() + .expectState(RappInstanceState.UNDEPLOYED).and().step().sendEvent(RappEvent.DEPLOYING) + .expectState(RappInstanceState.DEPLOYING).expectStateChanged(1).and().build(); + plan.test(); + } + + @ParameterizedTest + @EnumSource(value = RappEvent.class, names = {"ACMDEPLOYED", "SMEDEPLOYED"}) + void testIndividualDeployedState(RappEvent rappEvent) throws Exception { + StateMachineTestPlan plan = + StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() + .expectState(RappInstanceState.UNDEPLOYED).and().step().sendEvent(RappEvent.DEPLOYING) + .expectState(RappInstanceState.DEPLOYING).expectStateChanged(1).and().step() + .sendEvent(rappEvent).expectState(RappInstanceState.DEPLOYING).and().build(); + plan.test(); + } + + @Test + void testDeployedState() throws Exception { + StateMachineTestPlan plan = + StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() + .expectState(RappInstanceState.UNDEPLOYED).and().step().sendEvent(RappEvent.DEPLOYING) + .expectState(RappInstanceState.DEPLOYING).expectStateChanged(1).and().step() + .sendEvent(RappEvent.ACMDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step() + .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappInstanceState.DEPLOYED).expectStateChanged(1) + .and().build(); + plan.test(); + } + + @Test + void testDeployFailedState() throws Exception { + StateMachineTestPlan plan = + StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() + .expectState(RappInstanceState.UNDEPLOYED).and().step().sendEvent(RappEvent.DEPLOYING) + .expectState(RappInstanceState.DEPLOYING).expectStateChanged(1).and().step() + .sendEvent(RappEvent.ACMDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step() + .sendEvent(RappEvent.SMEDEPLOYFAILED).expectState(RappInstanceState.UNDEPLOYED) + .expectStateChanged(1).and().build(); + plan.test(); + } + + @Test + void testUndeployingState() throws Exception { + StateMachineTestPlan plan = + StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() + .expectState(RappInstanceState.UNDEPLOYED).and().step().sendEvent(RappEvent.DEPLOYING) + .expectState(RappInstanceState.DEPLOYING).expectStateChanged(1).and().step() + .sendEvent(RappEvent.ACMDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step() + .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappInstanceState.DEPLOYED).expectStateChanged(1) + .and().step().sendEvent(RappEvent.UNDEPLOYING).expectState(RappInstanceState.UNDEPLOYING) + .expectStateChanged(1).and().build(); + plan.test(); + } + + @ParameterizedTest + @EnumSource(value = RappEvent.class, names = {"ACMUNDEPLOYED", "SMEUNDEPLOYED"}) + void testIndividualUndeployedState(RappEvent rappEvent) throws Exception { + StateMachineTestPlan plan = + StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() + .expectState(RappInstanceState.UNDEPLOYED).and().step().sendEvent(RappEvent.DEPLOYING) + .expectState(RappInstanceState.DEPLOYING).expectStateChanged(1).and().step() + .sendEvent(RappEvent.ACMDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step() + .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappInstanceState.DEPLOYED).expectStateChanged(1) + .and().step().sendEvent(RappEvent.UNDEPLOYING).expectState(RappInstanceState.UNDEPLOYING) + .expectStateChanged(1).and().step().sendEvent(rappEvent) + .expectState(RappInstanceState.UNDEPLOYING).and().build(); + plan.test(); + } + + @Test + void testUndeployedState() throws Exception { + StateMachineTestPlan plan = + StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() + .expectState(RappInstanceState.UNDEPLOYED).and().step().sendEvent(RappEvent.DEPLOYING) + .expectState(RappInstanceState.DEPLOYING).expectStateChanged(1).and().step() + .sendEvent(RappEvent.ACMDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step() + .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappInstanceState.DEPLOYED).expectStateChanged(1) + .and().step().sendEvent(RappEvent.UNDEPLOYING).expectState(RappInstanceState.UNDEPLOYING) + .expectStateChanged(1).and().step().sendEvent(RappEvent.ACMUNDEPLOYED) + .expectState(RappInstanceState.UNDEPLOYING).and().step().sendEvent(RappEvent.SMEUNDEPLOYED) + .expectState(RappInstanceState.UNDEPLOYED).expectStateChanged(1).and().build(); + plan.test(); + } + + @Test + void testUndeployFailedState() throws Exception { + StateMachineTestPlan plan = + StateMachineTestPlanBuilder.builder().stateMachine(stateMachine).step() + .expectState(RappInstanceState.UNDEPLOYED).and().step().sendEvent(RappEvent.DEPLOYING) + .expectState(RappInstanceState.DEPLOYING).expectStateChanged(1).and().step() + .sendEvent(RappEvent.ACMDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step() + .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappInstanceState.DEPLOYED).expectStateChanged(1) + .and().step().sendEvent(RappEvent.UNDEPLOYING).expectState(RappInstanceState.UNDEPLOYING) + .expectStateChanged(1).and().step().sendEvent(RappEvent.ACMUNDEPLOYED) + .expectState(RappInstanceState.UNDEPLOYING).and().step().sendEvent(RappEvent.SMEUNDEPLOYFAILED) + .expectState(RappInstanceState.DEPLOYED).expectStateChanged(1).and().build(); + plan.test(); + } +} diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineTest.java new file mode 100755 index 0000000..db45d14 --- /dev/null +++ b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineTest.java @@ -0,0 +1,61 @@ +package com.oransc.rappmanager.models.statemachine; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import com.oransc.rappmanager.models.rapp.RappEvent; +import com.oransc.rappmanager.models.rappinstance.RappInstance; +import com.oransc.rappmanager.models.rappinstance.RappInstanceState; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = {RappInstanceStateMachine.class, RappInstanceStateMachineConfig.class}) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +public class RappInstanceStateMachineTest { + + @Autowired + RappInstanceStateMachine rappInstanceStateMachine; + + @Test + void testOnboardRappInstance() { + UUID rappInstanceId = UUID.randomUUID(); + rappInstanceStateMachine.onboardRappInstance(rappInstanceId); + assertNotNull(rappInstanceStateMachine.stateMachineMap.get(rappInstanceId)); + } + + @Test + void testSendRappInstanceEvent() { + UUID rappInstanceId = UUID.randomUUID(); + rappInstanceStateMachine.onboardRappInstance(rappInstanceId); + assertEquals(RappInstanceState.UNDEPLOYED, rappInstanceStateMachine.getRappInstanceState(rappInstanceId)); + RappInstance rappInstance = new RappInstance(); + rappInstance.setRappInstanceId(rappInstanceId); + rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DEPLOYING); + assertEquals(RappInstanceState.DEPLOYING, rappInstanceStateMachine.getRappInstanceState(rappInstanceId)); + } + + @Test + void testGetRappInstanceState() { + UUID rappInstanceId = UUID.randomUUID(); + rappInstanceStateMachine.onboardRappInstance(rappInstanceId); + assertEquals(RappInstanceState.UNDEPLOYED, rappInstanceStateMachine.getRappInstanceState(rappInstanceId)); + } + + @Test + void testDeleteRappInstance() { + UUID rappInstanceId = UUID.randomUUID(); + rappInstanceStateMachine.onboardRappInstance(rappInstanceId); + assertNotNull(rappInstanceStateMachine.stateMachineMap.get(rappInstanceId)); + RappInstance rappInstance = new RappInstance(); + rappInstance.setRappInstanceId(rappInstanceId); + rappInstanceStateMachine.deleteRappInstance(rappInstance); + assertNull(rappInstanceStateMachine.stateMachineMap.get(rappInstanceId)); + } +} diff --git a/rapp-manager-models/src/test/resources/invalid-rapp-package.csar b/rapp-manager-models/src/test/resources/invalid-rapp-package.csar new file mode 100755 index 0000000..c9150f0 Binary files /dev/null and b/rapp-manager-models/src/test/resources/invalid-rapp-package.csar differ diff --git a/rapp-manager-models/src/test/resources/valid-rapp-package.csar b/rapp-manager-models/src/test/resources/valid-rapp-package.csar new file mode 100755 index 0000000..b8b36e3 Binary files /dev/null and b/rapp-manager-models/src/test/resources/valid-rapp-package.csar differ diff --git a/rapp-manager-sme/pom.xml b/rapp-manager-sme/pom.xml index cc607b2..ac7c97e 100755 --- a/rapp-manager-sme/pom.xml +++ b/rapp-manager-sme/pom.xml @@ -39,6 +39,17 @@ jackson-databind-nullable 0.2.6 + + org.springframework.boot + spring-boot-starter-test + test + + + org.apache.httpcomponents + httpcore + 4.3.2 + test + diff --git a/rapp-manager-sme/src/main/java/com/oransc/rappmanager/sme/service/SmeDeployer.java b/rapp-manager-sme/src/main/java/com/oransc/rappmanager/sme/service/SmeDeployer.java index 5901417..6a6581a 100755 --- a/rapp-manager-sme/src/main/java/com/oransc/rappmanager/sme/service/SmeDeployer.java +++ b/rapp-manager-sme/src/main/java/com/oransc/rappmanager/sme/service/SmeDeployer.java @@ -21,22 +21,21 @@ package com.oransc.rappmanager.sme.service; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import com.oransc.rappmanager.models.Rapp; -import com.oransc.rappmanager.models.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; import com.oransc.rappmanager.models.RappDeployer; -import com.oransc.rappmanager.models.RappEvent; +import com.oransc.rappmanager.models.rapp.RappEvent; +import com.oransc.rappmanager.models.rappinstance.RappInstance; import com.oransc.rappmanager.models.cache.RappCacheService; -import com.oransc.rappmanager.models.statemachine.RappStateMachine; +import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine; import com.oransc.rappmanager.sme.invoker.data.APIInvokerEnrolmentDetails; import com.oransc.rappmanager.sme.provider.data.APIProviderEnrolmentDetails; import com.oransc.rappmanager.sme.provider.data.APIProviderFunctionDetails; import com.oransc.rappmanager.sme.provider.data.ApiProviderFuncRole; import com.oransc.rappmanager.sme.provider.data.RegistrationInformation; -import com.oransc.rappmanager.sme.publishservice.data.AefProfile; import com.oransc.rappmanager.sme.publishservice.data.ServiceAPIDescription; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,7 +59,7 @@ public class SmeDeployer implements RappDeployer { private final RappCacheService rappCacheService; - private final RappStateMachine rappStateMachine; + private final RappInstanceStateMachine rappInstanceStateMachine; private String amfRegistrationId; @@ -89,16 +88,17 @@ public class SmeDeployer implements RappDeployer { deleteProviderFunc(amfRegistrationId); } - @Override - public boolean deployRapp(Rapp rapp) { - logger.debug("Deploying SME functions for Rapp {}", rapp.getName()); + public boolean deployRappInstance(Rapp rapp, RappInstance rappInstance) { + logger.debug("Deploying SME functions for RappInstance {}", rappInstance.getRappInstanceId()); try { - boolean deployState = createProviderDomain(rapp) && createPublishApi(rapp) && createInvoker(rapp); + boolean deployState = + createProviderDomain(rapp, rappInstance) && createPublishApi(rapp, rappInstance) && createInvoker( + rapp, rappInstance); if (deployState) { - rappStateMachine.sendRappEvent(rapp, RappEvent.SMEDEPLOYED); + rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.SMEDEPLOYED); } else { - rappStateMachine.sendRappEvent(rapp, RappEvent.SMEDEPLOYFAILED); + rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.SMEDEPLOYFAILED); } return deployState; } catch (JsonProcessingException e) { @@ -108,40 +108,60 @@ public class SmeDeployer implements RappDeployer { } @Override - public boolean undeployRapp(Rapp rapp) { + public boolean undeployRappInstance(Rapp rapp, RappInstance rappInstance) { logger.debug("Undeploying SME functions for Rapp {}", rapp.getName()); try { - rapp.getSmeInvokers().forEach(this::deleteInvoker); - rapp.getSmeServiceApis().forEach(s -> deletePublishApi(s, rapp.getSmeApfId())); - rapp.getSmeProviderFunctions().values().forEach(this::deleteProviderFunc); - rappStateMachine.sendRappEvent(rapp, RappEvent.SMEUNDEPLOYED); + rappInstance.getSme().getInvokerIds().forEach(this::deleteInvoker); + rappInstance.getSme().getServiceApiIds() + .forEach(s -> deletePublishApi(s, rappInstance.getSme().getApfId())); + rappInstance.getSme().getProviderFunctionIds().forEach(this::deleteProviderFunc); + rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.SMEUNDEPLOYED); return true; } catch (Exception e) { - logger.warn("Failed to Undeploy SME functions for Rapp {}", rapp.getName()); + logger.warn("Failed to Undeploy SME functions for Rapp {}", rapp.getName(), e); } return false; } - boolean createProviderDomain(Rapp rapp) throws JsonProcessingException { + @Override + public boolean primeRapp(Rapp rapp) { + //If there is any priming operations on SME + return true; + } + + @Override + public boolean deprimeRapp(Rapp rapp) { + //If there is any deprimgng operations + return true; + } + + boolean createProviderDomain(Rapp rapp, RappInstance rappInstance) throws JsonProcessingException { logger.debug("Creating provider domain for Rapp {}", rapp.getName()); try { - String providerDomainPayload = rappCsarConfigurationHandler.getSmeProviderDomainPayload(rapp); + String providerDomainPayload = + rappCsarConfigurationHandler.getSmeProviderDomainPayload(rapp, rappInstance.getSme()); + logger.info("provider domain payload " + providerDomainPayload); if (providerDomainPayload != null) { APIProviderEnrolmentDetails apiProviderEnrolmentDetails = objectMapper.readValue(providerDomainPayload, APIProviderEnrolmentDetails.class); + //TODO Fix this Temporary workaround + apiProviderEnrolmentDetails.setRegSec( + apiProviderEnrolmentDetails.getRegSec() + rappInstance.getRappInstanceId()); APIProviderEnrolmentDetails responseApiEnrollmentDetails = providerDefaultApiClient.postRegistrations(apiProviderEnrolmentDetails); if (responseApiEnrollmentDetails.getApiProvFuncs() != null) { + rappInstance.getSme().setProviderFunctionIds(responseApiEnrollmentDetails.getApiProvFuncs().stream() + .map(APIProviderFunctionDetails::getApiProvFuncId) + .toList()); + getProviderFuncId(responseApiEnrollmentDetails.getApiProvFuncs(), - ApiProviderFuncRole.APF).ifPresent(apiProviderFunctionDetails -> rapp.setSmeApfId( - apiProviderFunctionDetails.getApiProvFuncId())); + ApiProviderFuncRole.APF).ifPresent(apiProviderFunctionDetails -> rappInstance.getSme() + .setApfId( + apiProviderFunctionDetails.getApiProvFuncId())); getProviderFuncId(responseApiEnrollmentDetails.getApiProvFuncs(), - ApiProviderFuncRole.AEF).ifPresent(apiProviderFunctionDetails -> rapp.setSmeAefId( - apiProviderFunctionDetails.getApiProvFuncId())); - rapp.setSmeProviderFunctions(responseApiEnrollmentDetails.getApiProvFuncs().stream().collect( - Collectors.toMap(APIProviderFunctionDetails::getApiProvFuncInfo, - APIProviderFunctionDetails::getApiProvFuncId))); - rappCacheService.putRapp(rapp); + ApiProviderFuncRole.AEF).ifPresent(apiProviderFunctionDetails -> rappInstance.getSme() + .setAefId( + apiProviderFunctionDetails.getApiProvFuncId())); return true; } } @@ -163,24 +183,23 @@ public class SmeDeployer implements RappDeployer { } - boolean createPublishApi(Rapp rapp) throws JsonProcessingException { + boolean createPublishApi(Rapp rapp, RappInstance rappInstance) throws JsonProcessingException { logger.debug("Creating publish api for Rapp {}", rapp.getName()); try { - String providerApiPayload = rappCsarConfigurationHandler.getSmeProviderApiPayload(rapp); + String providerApiPayload = + rappCsarConfigurationHandler.getSmeProviderApiPayload(rapp, rappInstance.getSme()); if (providerApiPayload != null) { ServiceAPIDescription serviceAPIDescription = objectMapper.readValue(providerApiPayload, ServiceAPIDescription.class); serviceAPIDescription.getAefProfiles().forEach(aefProfile -> { - aefProfile.setAefId(rapp.getSmeProviderFunctions().get(aefProfile.getAefId())); + aefProfile.setAefId(rappInstance.getSme().getAefId()); }); ServiceAPIDescription serviceAPIDescriptionResponse = - publishServiceDefaultApiClient.postApfIdServiceApis(rapp.getSmeApfId(), serviceAPIDescription); + publishServiceDefaultApiClient.postApfIdServiceApis(rappInstance.getSme().getApfId(), + serviceAPIDescription); if (serviceAPIDescriptionResponse.getAefProfiles() != null) { - rapp.setSmeServiceApis( - serviceAPIDescriptionResponse.getAefProfiles().stream().map(AefProfile::getAefId) - .collect(Collectors.toList())); - rappCacheService.putRapp(rapp); + rappInstance.getSme().setServiceApiIds(List.of(serviceAPIDescriptionResponse.getApiId())); return true; } } @@ -194,10 +213,10 @@ public class SmeDeployer implements RappDeployer { publishServiceDefaultApiClient.deleteApfIdServiceApisServiceApiId(serviceApiId, apfId); } - boolean createInvoker(Rapp rapp) throws JsonProcessingException { + boolean createInvoker(Rapp rapp, RappInstance rappInstance) throws JsonProcessingException { logger.debug("Creating provider domain for Rapp {}", rapp.getName()); try { - String invokerPayload = rappCsarConfigurationHandler.getSmeInvokerPayload(rapp); + String invokerPayload = rappCsarConfigurationHandler.getSmeInvokerPayload(rapp, rappInstance.getSme()); if (invokerPayload != null) { List apiInvokerEnrolmentDetails = objectMapper.readValue(invokerPayload, new TypeReference<>() { }); @@ -205,10 +224,8 @@ public class SmeDeployer implements RappDeployer { APIInvokerEnrolmentDetails apiInvokerEnrolmentDetailsResponse = invokerDefaultApiClient.postOnboardedInvokers(apiInvokerEnrolmentDetail); if (apiInvokerEnrolmentDetailsResponse.getApiList() != null) { - rapp.getSmeInvokers().addAll(apiInvokerEnrolmentDetailsResponse.getApiList().stream() - .map(com.oransc.rappmanager.sme.invoker.data.ServiceAPIDescription::getApiId) - .toList()); - rappCacheService.putRapp(rapp); + rappInstance.getSme() + .setInvokerIds(List.of(apiInvokerEnrolmentDetailsResponse.getApiInvokerId())); } }); return true; diff --git a/rapp-manager-sme/src/main/java/com/oransc/rappmanager/sme/service/SmeLifecycleManager.java b/rapp-manager-sme/src/main/java/com/oransc/rappmanager/sme/service/SmeLifecycleManager.java index 0c21c1b..cb5b049 100755 --- a/rapp-manager-sme/src/main/java/com/oransc/rappmanager/sme/service/SmeLifecycleManager.java +++ b/rapp-manager-sme/src/main/java/com/oransc/rappmanager/sme/service/SmeLifecycleManager.java @@ -41,7 +41,7 @@ public class SmeLifecycleManager implements SmartLifecycle { APIProviderEnrolmentDetails providerServiceAMF = smeDeployer.createAMF(); logger.info("Rapp Manager AMF Registration Id: " + providerServiceAMF.getApiProvDomId()); running = true; - }catch (Exception e){ + } catch (Exception e) { logger.warn("Error in initializing AMF", e); running = false; } diff --git a/rapp-manager-sme/src/test/java/com/oransc/rappmanager/sme/service/BeanTestConfiguration.java b/rapp-manager-sme/src/test/java/com/oransc/rappmanager/sme/service/BeanTestConfiguration.java new file mode 100755 index 0000000..191ed07 --- /dev/null +++ b/rapp-manager-sme/src/test/java/com/oransc/rappmanager/sme/service/BeanTestConfiguration.java @@ -0,0 +1,79 @@ +package com.oransc.rappmanager.sme.service; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.oransc.rappmanager.sme.configuration.SmeConfiguration; +import com.oransc.rappmanager.sme.provider.rest.DefaultApiClient; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.cache.CacheManager; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; + +@TestConfiguration +@RequiredArgsConstructor +public class BeanTestConfiguration { + + private final SmeConfiguration smeConfiguration; + + @Bean + public ObjectMapper objectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + return objectMapper; + } + + @Bean + public RestTemplateBuilder restTemplateBuilder() { + return new RestTemplateBuilder(); + } + + @Bean + public CacheManager cacheManager() { + return new ConcurrentMapCacheManager(); // or any other CacheManager implementation you want to use in the test + } + + @Bean + public RestTemplate restTemplate(RestTemplateBuilder builder) { + return builder.build(); + } + + @Bean("smeProviderApiClient") + public com.oransc.rappmanager.sme.provider.ApiClient smeProviderApiClient(RestTemplate restTemplate) { + return new com.oransc.rappmanager.sme.provider.ApiClient(restTemplate); + } + + @Bean("smePublishServiceApiClient") + public com.oransc.rappmanager.sme.publishservice.ApiClient smePublishServiceApiClient(RestTemplate restTemplate) { + return new com.oransc.rappmanager.sme.publishservice.ApiClient(restTemplate); + } + + @Bean("smeInvokerApiClient") + public com.oransc.rappmanager.sme.invoker.ApiClient smeInvokerApiClient(RestTemplate restTemplate) { + return new com.oransc.rappmanager.sme.invoker.ApiClient(restTemplate); + } + + @Bean + public DefaultApiClient defaultProviderApiClient( + @Qualifier("smeProviderApiClient") com.oransc.rappmanager.sme.provider.ApiClient apiClient) { + apiClient.setBasePath(smeConfiguration.getBaseUrl() + smeConfiguration.getProviderBasePath()); + return new DefaultApiClient(apiClient); + } + + @Bean + public com.oransc.rappmanager.sme.publishservice.rest.DefaultApiClient defaultPublishServiceApiClient( + @Qualifier("smePublishServiceApiClient") com.oransc.rappmanager.sme.publishservice.ApiClient apiClient) { + apiClient.setBasePath(smeConfiguration.getBaseUrl() + smeConfiguration.getPublishApiBasePath()); + return new com.oransc.rappmanager.sme.publishservice.rest.DefaultApiClient(apiClient); + } + + @Bean + public com.oransc.rappmanager.sme.invoker.rest.DefaultApiClient defaultInvokerApiClient( + @Qualifier("smeInvokerApiClient") com.oransc.rappmanager.sme.invoker.ApiClient apiClient) { + apiClient.setBasePath(smeConfiguration.getBaseUrl() + smeConfiguration.getInvokerBasePath()); + return new com.oransc.rappmanager.sme.invoker.rest.DefaultApiClient(apiClient); + } +} diff --git a/rapp-manager-application/src/test/java/com/oransc/rappmanager/sme/service/SmeDeployerTest.java b/rapp-manager-sme/src/test/java/com/oransc/rappmanager/sme/service/SmeDeployerTest.java similarity index 78% rename from rapp-manager-application/src/test/java/com/oransc/rappmanager/sme/service/SmeDeployerTest.java rename to rapp-manager-sme/src/test/java/com/oransc/rappmanager/sme/service/SmeDeployerTest.java index b45d855..9a8faf6 100755 --- a/rapp-manager-application/src/test/java/com/oransc/rappmanager/sme/service/SmeDeployerTest.java +++ b/rapp-manager-sme/src/test/java/com/oransc/rappmanager/sme/service/SmeDeployerTest.java @@ -25,15 +25,17 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.oransc.rappmanager.configuration.RappManagerConfiguration; -import com.oransc.rappmanager.models.Rapp; -import com.oransc.rappmanager.models.RappState; +import com.oransc.rappmanager.models.rapp.Rapp; +import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler; +import com.oransc.rappmanager.models.rappinstance.RappInstance; +import com.oransc.rappmanager.models.rappinstance.RappSMEInstance; +import com.oransc.rappmanager.models.rapp.RappState; import com.oransc.rappmanager.models.cache.RappCacheService; -import com.oransc.rappmanager.models.statemachine.RappStateMachine; +import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine; +import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachineConfig; import com.oransc.rappmanager.sme.configuration.SmeConfiguration; import com.oransc.rappmanager.sme.invoker.data.APIInvokerEnrolmentDetails; import com.oransc.rappmanager.sme.provider.data.APIProviderEnrolmentDetails; @@ -41,12 +43,9 @@ import com.oransc.rappmanager.sme.provider.data.APIProviderFunctionDetails; import com.oransc.rappmanager.sme.provider.data.ApiProviderFuncRole; import com.oransc.rappmanager.sme.publishservice.data.AefProfile; import com.oransc.rappmanager.sme.publishservice.data.ServiceAPIDescription; -import java.io.File; -import java.io.FileInputStream; import java.util.List; import java.util.Map; import java.util.UUID; -import org.apache.http.entity.ContentType; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -58,37 +57,33 @@ import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.context.TestPropertySource; import org.springframework.test.web.client.ExpectedCount; import org.springframework.test.web.client.MockRestServiceServer; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.web.client.RestTemplate; -@SpringBootTest -@TestPropertySource(properties = "rappmanager.csarlocation=src/test/resources") +@SpringBootTest(classes = {SmeConfiguration.class, SmeDeployer.class, BeanTestConfiguration.class, + RappCsarConfigurationHandler.class, RappCacheService.class, RappInstanceStateMachineConfig.class, + RappInstanceStateMachine.class}) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @AutoConfigureMockMvc public class SmeDeployerTest { MockRestServiceServer mockServer; + @Autowired @SpyBean SmeDeployer smeDeployer; @Autowired RestTemplate restTemplate; @Autowired SmeConfiguration smeConfiguration; + String validCsarFileLocation = "src/test/resources/"; @Autowired - RappManagerConfiguration rappManagerConfiguration; - @Autowired - private MockMvc mockMvc; + RappInstanceStateMachine rappInstanceStateMachine; @Autowired RappCacheService rappCacheService; - @SpyBean - RappStateMachine rappStateMachine; + @Autowired + ObjectMapper objectMapper; private final String validRappFile = "valid-rapp-package.csar"; - ObjectMapper objectMapper = new ObjectMapper(); String URI_PROVIDER_REGISTRATIONS, URI_PROVIDER_REGISTRATION, URI_PUBLISH_APIS, URI_PUBLISH_API, URI_INVOKERS, URI_INVOKER; @@ -150,16 +145,16 @@ public class SmeDeployerTest { @Test void testCreateProviderDomain() throws Exception { UUID rappId = UUID.randomUUID(); - Rapp rapp = Rapp.builder().rappId(rappId).name(rappId.toString()).packageName(validRappFile) - .packageLocation(rappManagerConfiguration.getCsarLocation()).state(RappState.ONBOARDED) - .build(); - onBoardRappCsar(rappId); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .state(RappState.COMMISSIONED).build(); APIProviderEnrolmentDetails apiProviderEnrolmentDetails = getProviderDomainApiEnrollmentDetails(); mockServer.expect(ExpectedCount.once(), requestTo(URI_PROVIDER_REGISTRATIONS)) .andExpect(method(HttpMethod.POST)).andRespond( withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) .body(objectMapper.writeValueAsString(apiProviderEnrolmentDetails))); - boolean createProviderDomain = smeDeployer.createProviderDomain(rapp); + RappInstance rappInstance = getRappInstance(); + boolean createProviderDomain = smeDeployer.createProviderDomain(rapp, rappInstance); mockServer.verify(); assertTrue(createProviderDomain); } @@ -167,13 +162,13 @@ public class SmeDeployerTest { @Test void testCreateProviderDomainFailure() throws Exception { UUID rappId = UUID.randomUUID(); - Rapp rapp = Rapp.builder().rappId(rappId).name(rappId.toString()).packageName(validRappFile) - .packageLocation(rappManagerConfiguration.getCsarLocation()).state(RappState.ONBOARDED) - .build(); - onBoardRappCsar(rappId); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .state(RappState.COMMISSIONED).build(); mockServer.expect(ExpectedCount.once(), requestTo(URI_PROVIDER_REGISTRATIONS)) .andExpect(method(HttpMethod.POST)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR)); - boolean createProviderDomain = smeDeployer.createProviderDomain(rapp); + RappInstance rappInstance = getRappInstance(); + boolean createProviderDomain = smeDeployer.createProviderDomain(rapp, rappInstance); mockServer.verify(); assertFalse(createProviderDomain); } @@ -191,16 +186,17 @@ public class SmeDeployerTest { void testCreatePublishApi() throws Exception { UUID rappId = UUID.randomUUID(); UUID apfId = UUID.randomUUID(); - Rapp rapp = Rapp.builder().rappId(rappId).name(rappId.toString()).packageName(validRappFile) - .packageLocation(rappManagerConfiguration.getCsarLocation()).state(RappState.ONBOARDED) - .smeApfId(String.valueOf(apfId)).build(); - onBoardRappCsar(rappId); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .state(RappState.COMMISSIONED).build(); ServiceAPIDescription serviceAPIDescription = getServiceApiDescription(); mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_PUBLISH_APIS, apfId))) .andExpect(method(HttpMethod.POST)).andRespond( withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) .body(objectMapper.writeValueAsString(serviceAPIDescription))); - boolean publishApi = smeDeployer.createPublishApi(rapp); + RappInstance rappInstance = getRappInstance(); + rappInstance.getSme().setApfId(String.valueOf(apfId)); + boolean publishApi = smeDeployer.createPublishApi(rapp, rappInstance); mockServer.verify(); assertTrue(publishApi); } @@ -210,13 +206,14 @@ public class SmeDeployerTest { void testCreatePublishApiFailure() throws Exception { UUID rappId = UUID.randomUUID(); UUID apfId = UUID.randomUUID(); - Rapp rapp = Rapp.builder().rappId(rappId).name(rappId.toString()).packageName(validRappFile) - .packageLocation(rappManagerConfiguration.getCsarLocation()).state(RappState.ONBOARDED) - .smeApfId(String.valueOf(apfId)).build(); - onBoardRappCsar(rappId); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .state(RappState.COMMISSIONED).build(); mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_PUBLISH_APIS, apfId))) .andExpect(method(HttpMethod.POST)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR)); - boolean publishApi = smeDeployer.createPublishApi(rapp); + RappInstance rappInstance = getRappInstance(); + rappInstance.getSme().setApfId(String.valueOf(apfId)); + boolean publishApi = smeDeployer.createPublishApi(rapp, rappInstance); mockServer.verify(); assertFalse(publishApi); } @@ -234,16 +231,15 @@ public class SmeDeployerTest { @Test void testCreateInvoker() throws Exception { UUID rappId = UUID.randomUUID(); - UUID apfId = UUID.randomUUID(); - Rapp rapp = Rapp.builder().rappId(rappId).name(rappId.toString()).packageName(validRappFile) - .packageLocation(rappManagerConfiguration.getCsarLocation()).state(RappState.ONBOARDED) - .smeApfId(String.valueOf(apfId)).build(); - onBoardRappCsar(rappId); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .state(RappState.COMMISSIONED).build(); APIInvokerEnrolmentDetails apiInvokerEnrolmentDetails = getApiInvokerEnrollmentDetails(); mockServer.expect(ExpectedCount.once(), requestTo(URI_INVOKERS)).andExpect(method(HttpMethod.POST)).andRespond( withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) .body(objectMapper.writeValueAsString(apiInvokerEnrolmentDetails))); - boolean createInvoker = smeDeployer.createInvoker(rapp); + RappInstance rappInstance = getRappInstance(); + boolean createInvoker = smeDeployer.createInvoker(rapp, rappInstance); mockServer.verify(); assertTrue(createInvoker); } @@ -251,14 +247,13 @@ public class SmeDeployerTest { @Test void testCreateInvokerFailure() throws Exception { UUID rappId = UUID.randomUUID(); - UUID apfId = UUID.randomUUID(); - Rapp rapp = Rapp.builder().rappId(rappId).name(rappId.toString()).packageName(validRappFile) - .packageLocation(rappManagerConfiguration.getCsarLocation()).state(RappState.ONBOARDED) - .smeApfId(String.valueOf(apfId)).build(); - onBoardRappCsar(rappId); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .state(RappState.COMMISSIONED).build(); mockServer.expect(ExpectedCount.once(), requestTo(URI_INVOKERS)).andExpect(method(HttpMethod.POST)) .andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR)); - boolean createInvoker = smeDeployer.createInvoker(rapp); + RappInstance rappInstance = getRappInstance(); + boolean createInvoker = smeDeployer.createInvoker(rapp, rappInstance); mockServer.verify(); assertFalse(createInvoker); } @@ -273,15 +268,16 @@ public class SmeDeployerTest { } @Test - void testDeployRapp() throws Exception { + void testDeployRappInstance() throws Exception { UUID rappId = UUID.randomUUID(); APIProviderEnrolmentDetails apiProviderEnrolmentDetails = getProviderDomainApiEnrollmentDetails(); APIProviderFunctionDetails apfProviderFunctionDetails = apiProviderEnrolmentDetails.getApiProvFuncs().stream() .filter(apiProviderFunctionDetails -> apiProviderFunctionDetails.getApiProvFuncRole() .equals(ApiProviderFuncRole.APF)) .findFirst().get(); - onBoardRappCsar(rappId); - Rapp rapp = rappCacheService.getRapp(String.valueOf(rappId)).get(); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .state(RappState.COMMISSIONED).build(); mockServer.expect(ExpectedCount.once(), requestTo(URI_PROVIDER_REGISTRATIONS)) .andExpect(method(HttpMethod.POST)).andRespond( withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) @@ -296,7 +292,9 @@ public class SmeDeployerTest { mockServer.expect(ExpectedCount.once(), requestTo(URI_INVOKERS)).andExpect(method(HttpMethod.POST)).andRespond( withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) .body(objectMapper.writeValueAsString(apiInvokerEnrolmentDetails))); - boolean deployRapp = smeDeployer.deployRapp(rapp); + RappInstance rappInstance = getRappInstance(); + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + boolean deployRapp = smeDeployer.deployRappInstance(rapp, rappInstance); mockServer.verify(); assertTrue(deployRapp); } @@ -309,8 +307,9 @@ public class SmeDeployerTest { .filter(apiProviderFunctionDetails -> apiProviderFunctionDetails.getApiProvFuncRole() .equals(ApiProviderFuncRole.APF)) .findFirst().get(); - onBoardRappCsar(rappId); - Rapp rapp = rappCacheService.getRapp(String.valueOf(rappId)).get(); + Rapp rapp = + Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation) + .state(RappState.COMMISSIONED).build(); mockServer.expect(ExpectedCount.once(), requestTo(URI_PROVIDER_REGISTRATIONS)) .andExpect(method(HttpMethod.POST)).andRespond( withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON) @@ -323,13 +322,15 @@ public class SmeDeployerTest { .body(objectMapper.writeValueAsString(serviceAPIDescription))); mockServer.expect(ExpectedCount.once(), requestTo(URI_INVOKERS)).andExpect(method(HttpMethod.POST)) .andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR)); - boolean deployRapp = smeDeployer.deployRapp(rapp); + RappInstance rappInstance = getRappInstance(); + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + boolean deployRapp = smeDeployer.deployRappInstance(rapp, rappInstance); mockServer.verify(); assertFalse(deployRapp); } @Test - void testUndeployRapp() throws Exception { + void testUndeployRappInstance() { UUID rappId = UUID.randomUUID(); UUID apfId = UUID.randomUUID(); List invokers = List.of(String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID())); @@ -337,11 +338,7 @@ public class SmeDeployerTest { Map providerFuncs = Map.of(String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID())); Rapp rapp = Rapp.builder().rappId(rappId).name(rappId.toString()).packageName(validRappFile) - .packageLocation(rappManagerConfiguration.getCsarLocation()).state(RappState.ONBOARDED) - .smeApfId(String.valueOf(apfId)).smeInvokers(invokers).smeServiceApis(serviceApis) - .smeProviderFunctions(providerFuncs).build(); - onBoardRappCsar(rappId); - rapp.setRappId(rappCacheService.getRapp(String.valueOf(rappId)).get().getRappId()); + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INVOKER, invokers.get(0)))) .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.NO_CONTENT)); mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INVOKER, invokers.get(1)))) @@ -356,14 +353,19 @@ public class SmeDeployerTest { mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_PROVIDER_REGISTRATION, providerFuncs.values().toArray()[1]))) .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.NO_CONTENT)); - - boolean undeployRapp = smeDeployer.undeployRapp(rapp); + RappInstance rappInstance = getRappInstance(); + rappInstance.getSme().setApfId(String.valueOf(apfId)); + rappInstance.getSme().setProviderFunctionIds(providerFuncs.values().stream().toList()); + rappInstance.getSme().setServiceApiIds(serviceApis); + rappInstance.getSme().setInvokerIds(invokers); + rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId()); + boolean undeployRapp = smeDeployer.undeployRappInstance(rapp, rappInstance); mockServer.verify(); assertTrue(undeployRapp); } @Test - void testUndeployRappFailure() throws Exception { + void testUndeployRappInstanceFailure() throws Exception { UUID rappId = UUID.randomUUID(); UUID apfId = UUID.randomUUID(); List invokers = List.of(String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID())); @@ -371,10 +373,7 @@ public class SmeDeployerTest { Map providerFuncs = Map.of(String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID())); Rapp rapp = Rapp.builder().rappId(rappId).name(rappId.toString()).packageName(validRappFile) - .packageLocation(rappManagerConfiguration.getCsarLocation()).state(RappState.ONBOARDED) - .smeApfId(String.valueOf(apfId)).smeInvokers(invokers).smeServiceApis(serviceApis) - .smeProviderFunctions(providerFuncs).build(); - onBoardRappCsar(rappId); + .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build(); mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INVOKER, invokers.get(0)))) .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.NO_CONTENT)); mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INVOKER, invokers.get(1)))) @@ -389,12 +388,28 @@ public class SmeDeployerTest { mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_PROVIDER_REGISTRATION, providerFuncs.values().toArray()[1]))) .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR)); - - boolean undeployRapp = smeDeployer.undeployRapp(rapp); + RappInstance rappInstance = getRappInstance(); + rappInstance.getSme().setApfId(String.valueOf(apfId)); + rappInstance.getSme().setProviderFunctionIds(providerFuncs.values().stream().toList()); + rappInstance.getSme().setServiceApiIds(serviceApis); + rappInstance.getSme().setInvokerIds(invokers); + boolean undeployRapp = smeDeployer.undeployRappInstance(rapp, rappInstance); mockServer.verify(); assertFalse(undeployRapp); } + RappInstance getRappInstance() { + RappSMEInstance rappSMEInstance = new RappSMEInstance(); + rappSMEInstance.setInvokers("invoker-app1"); + rappSMEInstance.setServiceApis("api-set-1"); + rappSMEInstance.setAefId("TEST_AEF_ID"); + rappSMEInstance.setApfId(String.valueOf(UUID.randomUUID())); + rappSMEInstance.setProviderFunction("aef-provider-function"); + RappInstance rappInstance = new RappInstance(); + rappInstance.setSme(rappSMEInstance); + return rappInstance; + } + APIProviderEnrolmentDetails getProviderDomainApiEnrollmentDetails() { APIProviderEnrolmentDetails apiProviderEnrolmentDetails = new APIProviderEnrolmentDetails(UUID.randomUUID().toString()); @@ -414,6 +429,7 @@ public class SmeDeployerTest { ServiceAPIDescription getServiceApiDescription() { ServiceAPIDescription serviceAPIDescription = new ServiceAPIDescription(); + serviceAPIDescription.setApiId(String.valueOf(UUID.randomUUID())); AefProfile aefProfile = new AefProfile(); aefProfile.setAefId(String.valueOf(UUID.randomUUID())); serviceAPIDescription.setAefProfiles(List.of(aefProfile)); @@ -421,20 +437,12 @@ public class SmeDeployerTest { } APIInvokerEnrolmentDetails getApiInvokerEnrollmentDetails() { - APIInvokerEnrolmentDetails apiInvokerEnrolmentDetails = new APIInvokerEnrolmentDetails(); + APIInvokerEnrolmentDetails apiInvokerEnrolmentDetails = + new APIInvokerEnrolmentDetails(String.valueOf(UUID.randomUUID())); com.oransc.rappmanager.sme.invoker.data.ServiceAPIDescription serviceAPIDescription = new com.oransc.rappmanager.sme.invoker.data.ServiceAPIDescription(); serviceAPIDescription.setApiId(String.valueOf(UUID.randomUUID())); apiInvokerEnrolmentDetails.setApiList(List.of(serviceAPIDescription)); return apiInvokerEnrolmentDetails; } - - void onBoardRappCsar(UUID rappId) throws Exception { - String rappCsarPath = rappManagerConfiguration.getCsarLocation() + File.separator + validRappFile; - MockMultipartFile multipartFile = - new MockMultipartFile("file", validRappFile, ContentType.MULTIPART_FORM_DATA.getMimeType(), - new FileInputStream(rappCsarPath)); - mockMvc.perform(MockMvcRequestBuilders.multipart("/rapps/{rapp_id}/onboard", rappId).file(multipartFile)) - .andExpect(status().isAccepted()); - } } diff --git a/rapp-manager-sme/src/test/resources/application.yaml b/rapp-manager-sme/src/test/resources/application.yaml new file mode 100755 index 0000000..c2b8a9d --- /dev/null +++ b/rapp-manager-sme/src/test/resources/application.yaml @@ -0,0 +1,8 @@ +rappmanager: + sme: + baseurl: http://localhost:56379 #http://10.101.3.22:61761 + providerBasePath: /api-provider-management/v1/ + invokerBasePath: /api-invoker-management/v1/ + publishApiBasePath: /published-apis/v1/ + maxRetries: 3 + retryInterval: 2 #seconds \ No newline at end of file diff --git a/rapp-manager-sme/src/test/resources/valid-rapp-package.csar b/rapp-manager-sme/src/test/resources/valid-rapp-package.csar new file mode 100755 index 0000000..b8b36e3 Binary files /dev/null and b/rapp-manager-sme/src/test/resources/valid-rapp-package.csar differ