Add rapp instances.
Move deployment lifecycle to rapp instance.
Issue-ID: NONRTRIC-897
Signed-off-by: aravind.est <aravindhan.a@est.tech>
Change-Id: I36cb3c204b5a2aa4fdfd2d3361c4abc7cf38f236
String baseUrl;
String username;
String password;
- String compositionDefinitionLocation;
int maxRetries;
int retryInterval;
}
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;
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<ParticipantInformation> 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) {
commissioningResponse =
automationCompositionDefinitionApiClient.createCompositionDefinitions(compositionPayload,
UUID.randomUUID());
- compositionId = commissioningResponse.getCompositionId();
} catch (Exception e) {
logger.warn("Error in creating composition", e);
}
}
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) {
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 {
}
}
} 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) {
}
@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);
}
}
}
+++ /dev/null
-/*-
- * ============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;
- }
-}
--- /dev/null
+/*-
+ * ============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)));
+ }
+}
--- /dev/null
+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);
+ }
+
+
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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
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) {
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;
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;
@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<Cache> getRapps() {
}
@GetMapping("{rapp_id}")
- public ResponseEntity<Rapp> getRapps(@PathVariable("rapp_id") String rappId) {
- Optional<Rapp> rappOptional = rappCacheService.getRapp(rappId);
- if (rappOptional.isPresent()) {
- acmDeployer.syncRappStatus(rappOptional.get());
- return ResponseEntity.ok(rappCacheService.getRapp(rappId).get());
- }
- return ResponseEntity.badRequest().build();
+ public ResponseEntity<Rapp> getRapp(@PathVariable("rapp_id") String rappId) {
+ return rappCacheService.getRapp(rappId).map(ResponseEntity::ok).orElse(ResponseEntity.badRequest().build());
}
- @PostMapping("{rapp_id}/onboard")
- public ResponseEntity<Object> uploadRappCsarFile(@PathVariable("rapp_id") String rappId,
+ @PostMapping("{rapp_id}")
+ public ResponseEntity<Rapp> createRapp(@PathVariable("rapp_id") String rappId,
@RequestPart("file") MultipartFile csarFilePart) throws IOException {
if (rappCsarConfigurationHandler.isValidRappPackage(csarFilePart)) {
File csarFile = new File(
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);
}
}
- @PostMapping("{rapp_id}/deploy")
- public ResponseEntity<?> deployRapp(@PathVariable("rapp_id") String rappId) {
- Optional<Rapp> 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<String> 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<Rapp> 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<Object> getInfo() {
- return ResponseEntity.ok(acmDeployer.getAllParticipants());
+ @DeleteMapping("{rapp_id}")
+ public ResponseEntity<Object> 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
}
-
}
--- /dev/null
+/*-
+ * ============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<Map<UUID, RappInstance>> getAllRappInstances(@PathVariable("rapp_id") String rappId) {
+ return rappCacheService.getRapp(rappId).map(Rapp::getRappInstances).map(ResponseEntity::ok)
+ .orElse(ResponseEntity.notFound().build());
+ }
+
+ @PostMapping
+ public ResponseEntity<RappInstance> 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<RappInstance> 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<String> 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<Object> 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());
+ }
+
+}
--- /dev/null
+/*-
+ * ============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<String> 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<String> 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<String> 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<String> 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);
+ }
+}
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/
endpoints:
web:
exposure:
- include: "*"
\ No newline at end of file
+ include: "*"
--- /dev/null
+{
+ "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
--- /dev/null
+{
+ "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
--- /dev/null
+{
+ "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
+++ /dev/null
-{
- "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
[
{
- "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"
--- /dev/null
+[
+ {
+ "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
--- /dev/null
+{
+ "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
--- /dev/null
+{
+ "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
--- /dev/null
+{
+ "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
{
- "apiName": "Rapp API",
+ "apiName": "Rapp API Set A",
"description": "Example A API of rApp",
"aefProfiles": [
{
--- /dev/null
+{
+ "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
+++ /dev/null
-/*-
- * ============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());
- }
-
-}
--- /dev/null
+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());
+ }
+}
--- /dev/null
+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<UUID, RappInstance> 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;
+ }
+
+}
+++ /dev/null
-/*-
- * ============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());
- }
-
-
-}
+++ /dev/null
-/*-
- * ============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);
- }
-}
--- /dev/null
+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());
+ }
+}
+++ /dev/null
-/*-
- * ============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<RappState, RappEvent> stateMachineFactory;
-
- StateMachine<RappState, RappEvent> 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.<RappState, RappEvent>builder().stateMachine(stateMachine).step()
- .expectState(RappState.ONBOARDED).and().build();
- plan.test();
- }
-
- @Test
- void testDeployingState() throws Exception {
- StateMachineTestPlan plan =
- StateMachineTestPlanBuilder.<RappState, RappEvent>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.<RappState, RappEvent>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.<RappState, RappEvent>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.<RappState, RappEvent>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.<RappState, RappEvent>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.<RappState, RappEvent>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.<RappState, RappEvent>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.<RappState, RappEvent>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();
- }
-
-
-}
<artifactId>spring-statemachine-core</artifactId>
<version>3.2.1</version>
</dependency>
+ <dependency>
+ <groupId>org.springframework.statemachine</groupId>
+ <artifactId>spring-statemachine-test</artifactId>
+ <version>3.2.1</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ <version>4.3.2</version>
+ <scope>test</scope>
+ </dependency>
+
</dependencies>
</project>
\ No newline at end of file
+++ /dev/null
-/*-
- * ============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);
- }
-
-}
+/*-
+ * ============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);
}
+++ /dev/null
-package com.oransc.rappmanager.models;
-
-public enum RappEvent {
- ONBOARDED, DEPLOYING, ACMDEPLOYED, SMEDEPLOYED, ACMDEPLOYFAILED, SMEDEPLOYFAILED, DEPLOYED, UNDEPLOYING, UNDEPLOYED,
- ACMUNDEPLOYED, SMEUNDEPLOYED, ACMUNDEPLOYFAILED, SMEUNDEPLOYFAILED
-}
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;
private final String RAPP_CACHE = "rapp-cache";
private final CacheManager cacheManager;
- private final RappStateMachine rappStateMachine;
public Cache getAllRapp() {
return cacheManager.getCache(RAPP_CACHE);
public Optional<Rapp> getRapp(String rappId) {
final Cache cache = cacheManager.getCache(RAPP_CACHE);
- Optional<Rapp> 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) {
--- /dev/null
+/*-
+ * ============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<String> 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();
+ }
+}
--- /dev/null
+/*-
+ * ============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
* ============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)
RappState state;
String packageLocation;
String packageName;
- UUID compositionId;
- UUID compositionInstanceId;
- String smeApfId;
- String smeAefId;
- @Builder.Default
- Map<String, String> smeProviderFunctions = new HashMap<>();
- @Builder.Default
- List<String> smeServiceApis = new ArrayList<>();
+ RappResources rappResources;
@Builder.Default
- List<String> smeInvokers = new ArrayList<>();
+ Map<UUID, RappInstance> rappInstances = new HashMap<>();
+
+ UUID compositionId;
}
--- /dev/null
+/*-
+ * ============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
+}
* ============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();
- }
}
--- /dev/null
+/*-
+ * ============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<String> compositionInstances;
+ }
+
+ @Data
+ @Builder
+ public static class SMEResources {
+
+ List<String> providerFunctions;
+ List<String> serviceApis;
+ List<String> invokers;
+ }
+}
* ============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,
}
--- /dev/null
+/*-
+ * ============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
--- /dev/null
+/*-
+ * ============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;
+
+}
--- /dev/null
+/*-
+ * ============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;
+}
--- /dev/null
+/*-
+ * ============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;
+}
--- /dev/null
+/*-
+ * ============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;
+}
--- /dev/null
+/*-
+ * ============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<String> providerFunctionIds;
+ String serviceApis;
+ List<String> serviceApiIds;
+ String invokers;
+ List<String> invokerIds;
+
+ String aefId;
+ String apfId;
+
+}
--- /dev/null
+/*-
+ * ============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<RappInstanceState, RappEvent> stateMachineFactory;
+ Map<UUID, StateMachine<RappInstanceState, RappEvent>> stateMachineMap = new HashMap<>();
+
+ public void onboardRappInstance(UUID rappInstanceId) {
+ StateMachine<RappInstanceState, RappEvent> 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());
+ }
+}
--- /dev/null
+/*-
+ * ============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<RappInstanceState, RappEvent> {
+
+ @Override
+ public void configure(StateMachineStateConfigurer<RappInstanceState, RappEvent> states) throws Exception {
+ states.withStates().initial(RappInstanceState.UNDEPLOYED).states(EnumSet.allOf(RappInstanceState.class));
+ }
+
+ @Override
+ public void configure(StateMachineConfigurationConfigurer<RappInstanceState, RappEvent> config) throws Exception {
+ config.withConfiguration();
+ }
+
+ // @formatter:off
+ @Override
+ public void configure(StateMachineTransitionConfigurer<RappInstanceState, RappEvent> 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<RappInstanceState, RappEvent> 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<RappInstanceState, RappEvent> 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;
+ };
+ }
+}
+++ /dev/null
-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<RappState, RappEvent> stateMachineFactory;
- private Map<UUID, StateMachine<RappState, RappEvent>> stateMachineMap = new HashMap<>();
-
- public void onboardRapp(UUID rappId) {
- StateMachine<RappState, RappEvent> 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();
- }
-}
+++ /dev/null
-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<RappState, RappEvent> {
-
- @Override
- public void configure(StateMachineStateConfigurer<RappState, RappEvent> states) throws Exception {
- states.withStates().initial(RappState.ONBOARDED).states(EnumSet.allOf(RappState.class));
- }
-
- @Override
- public void configure(StateMachineConfigurationConfigurer<RappState, RappEvent> config) throws Exception {
- config.withConfiguration();
- }
-
- // @formatter:off
- @Override
- public void configure(StateMachineTransitionConfigurer<RappState, RappEvent> 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<RappState, RappEvent> 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<RappState, RappEvent> 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;
- };
- }
-}
--- /dev/null
+/*-
+ * ============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<String> fileListFromCsar =
+ rappCsarConfigurationHandler.getFileListFromCsar(file, "Files/Sme/serviceapis/");
+ assertThat(fileListFromCsar.size()).isEqualTo(2);
+ }
+
+ @Test
+ void testInvalidFileListing() {
+ File file = new File(validCsarFileLocation);
+ List<String> 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);
+ }
+
+}
--- /dev/null
+/*-
+ * ============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<RappInstanceState, RappEvent> stateMachineFactory;
+
+ StateMachine<RappInstanceState, RappEvent> 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.<RappInstanceState, RappEvent>builder().stateMachine(stateMachine).step()
+ .expectState(RappInstanceState.UNDEPLOYED).and().build();
+ plan.test();
+ }
+
+ @Test
+ void testDeployingState() throws Exception {
+ StateMachineTestPlan plan =
+ StateMachineTestPlanBuilder.<RappInstanceState, RappEvent>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.<RappInstanceState, RappEvent>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.<RappInstanceState, RappEvent>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.<RappInstanceState, RappEvent>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.<RappInstanceState, RappEvent>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.<RappInstanceState, RappEvent>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.<RappInstanceState, RappEvent>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.<RappInstanceState, RappEvent>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();
+ }
+}
--- /dev/null
+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));
+ }
+}
<artifactId>jackson-databind-nullable</artifactId>
<version>0.2.6</version>
</dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ <version>4.3.2</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
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;
private final RappCacheService rappCacheService;
- private final RappStateMachine rappStateMachine;
+ private final RappInstanceStateMachine rappInstanceStateMachine;
private String amfRegistrationId;
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) {
}
@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;
}
}
}
- 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;
}
}
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> apiInvokerEnrolmentDetails =
objectMapper.readValue(invokerPayload, new TypeReference<>() { });
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;
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;
}
--- /dev/null
+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);
+ }
+}
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;
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;
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;
@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);
}
@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);
}
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);
}
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);
}
@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);
}
@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);
}
}
@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)
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);
}
.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)
.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<String> invokers = List.of(String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID()));
Map<String, String> 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))))
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<String> invokers = List.of(String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID()));
Map<String, String> 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))))
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());
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));
}
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());
- }
}
--- /dev/null
+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