Integrated DME to create info type, producer and consumer as per the configuration from rApp package.
Issue-ID: NONRTRIC-913
Signed-off-by: aravind.est <aravindhan.a@est.tech>
Change-Id: Ib7a41f8a4200503f3a0b0ffee8e80a0cda3c0871
<module>rapp-manager-models</module>
<module>rapp-manager-acm</module>
<module>rapp-manager-sme</module>
+ <module>rapp-manager-dme</module>
<module>rapp-manager-application</module>
</modules>
<repositories>
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;
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");
primeACMComposition(rapp.getCompositionId(), PrimeOrder.DEPRIME);
CommissioningResponse commissioningResponse = deleteComposition(rapp.getCompositionId());
if (commissioningResponse != null) {
- rapp.setState(RappState.COMMISSIONED);
return true;
}
} catch (Exception e) {
boolean primeRapp = acmDeployer.primeRapp(rapp);
mockServer.verify();
assertTrue(primeRapp);
- assertEquals(RappState.PRIMED, rapp.getState());
-
}
@Test
<artifactId>rapp-manager-sme</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.o-ran-sc.nonrtric.plt.rappmanager</groupId>
+ <artifactId>rapp-manager-dme</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.onap.policy.clamp</groupId>
<artifactId>policy-clamp-models</artifactId>
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.dme.configuration.DmeConfiguration;
+import com.oransc.rappmanager.dme.rest.DataConsumerApiClient;
+import com.oransc.rappmanager.dme.rest.DataProducerRegistrationApiClient;
import com.oransc.rappmanager.sme.configuration.SmeConfiguration;
import com.oransc.rappmanager.sme.provider.rest.DefaultApiClient;
import lombok.RequiredArgsConstructor;
private final ACMConfiguration acmConfiguration;
private final SmeConfiguration smeConfiguration;
+ private final DmeConfiguration dmeConfiguration;
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return new com.oransc.rappmanager.sme.invoker.rest.DefaultApiClient(apiClient);
}
+ @Bean
+ public com.oransc.rappmanager.dme.ApiClient dmeApiClient(RestTemplate restTemplate) {
+ com.oransc.rappmanager.dme.ApiClient apiClient = new com.oransc.rappmanager.dme.ApiClient(restTemplate);
+ return apiClient.setBasePath(dmeConfiguration.getBaseUrl());
+ }
+
+ @Bean
+ public DataProducerRegistrationApiClient dataProducerRegistrationApiClient(
+ com.oransc.rappmanager.dme.ApiClient apiClient) {
+ return new DataProducerRegistrationApiClient(apiClient);
+ }
+
+ @Bean
+ public DataConsumerApiClient dataConsumerApiClient(com.oransc.rappmanager.dme.ApiClient apiClient) {
+ return new DataConsumerApiClient(apiClient);
+ }
+
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager();
package com.oransc.rappmanager.service;
import com.oransc.rappmanager.acm.service.AcmDeployer;
+import com.oransc.rappmanager.dme.service.DmeDeployer;
import com.oransc.rappmanager.models.rapp.Rapp;
import com.oransc.rappmanager.models.rapp.RappEvent;
import com.oransc.rappmanager.models.rapp.RappState;
private final AcmDeployer acmDeployer;
private final SmeDeployer smeDeployer;
+ private final DmeDeployer dmeDeployer;
private final RappInstanceStateMachine rappInstanceStateMachine;
private static final String STATE_TRANSITION_NOT_PERMITTED = "State transition from %s to %s is not permitted.";
public ResponseEntity<String> primeRapp(Rapp rapp) {
if (rapp.getState().equals(RappState.COMMISSIONED)) {
rapp.setState(RappState.PRIMING);
- if (!acmDeployer.primeRapp(rapp)) {
+ if (acmDeployer.primeRapp(rapp) && dmeDeployer.primeRapp(rapp)) {
+ rapp.setState(RappState.PRIMED);
+ } else {
rapp.setState(RappState.COMMISSIONED);
}
return ResponseEntity.ok().build();
public ResponseEntity<String> deprimeRapp(Rapp rapp) {
if (rapp.getState().equals(RappState.PRIMED) && rapp.getRappInstances().isEmpty()) {
rapp.setState(RappState.DEPRIMING);
- if (!acmDeployer.deprimeRapp(rapp)) {
+ if (acmDeployer.deprimeRapp(rapp) && dmeDeployer.deprimeRapp(rapp)) {
+ rapp.setState(RappState.COMMISSIONED);
+ } else {
rapp.setState(RappState.PRIMED);
}
return ResponseEntity.ok().build();
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)) {
+ if (acmDeployer.deployRappInstance(rapp, rappInstance) && smeDeployer.deployRappInstance(rapp, rappInstance)
+ && dmeDeployer.deployRappInstance(rapp, rappInstance)) {
return ResponseEntity.accepted().build();
}
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).build();
if (rappInstance.getState().equals(RappInstanceState.DEPLOYED)) {
rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.UNDEPLOYING);
if (acmDeployer.undeployRappInstance(rapp, rappInstance) && smeDeployer.undeployRappInstance(rapp,
- rappInstance)) {
+ rappInstance) && dmeDeployer.undeployRappInstance(rapp, rappInstance)) {
return ResponseEntity.accepted().build();
}
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).build();
rappmanager:
csarlocation: src/test/resources/csar
acm:
- baseurl: http://10.101.3.22:30442/onap/policy/clamp/acm/v2/
+ baseurl: http://10.101.2.41:30442/onap/policy/clamp/acm/v2/
username: runtimeUser
password: zb!XztG34
- maxRetries: 3
+ maxRetries: 10
retryInterval: 2 #seconds
sme:
- baseurl: http://localhost:60821 #http://10.101.3.22:61761
+ baseurl: http://localhost:56571 #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
+ dme:
+ baseurl: http://localhost:63475 #http://10.101.3.22:61761
logging:
level:
root: INFO
- com.oransc.rapps: DEBUG
+ com.oransc: DEBUG
org.apache.http: DEBUG
httpclient.wire: DEBUG
org.springframework.web.client.RestTemplate: TRACE
"name": "org.onap.policy.clamp.acm.KserveParticipant",
"version": "2.3.4"
},
- "uninitializedToPassiveTimeout": 60,
+ "uninitializedToPassiveTimeout": 300,
"statusCheckInterval": 30
}
},
"podName": "ransliceassurance",
"repository": {
"repoName": "local",
- "address": "http://10.101.3.22:8879/charts"
+ "address": "http://10.101.2.41:8879/charts"
}
}
}
--- /dev/null
+{
+ "info_type_id": "json-file-data-from-filestore",
+ "job_owner": "console",
+ "status_notification_uri": "http://callback.nonrtric:80/post",
+ "job_definition": {
+ "db-url": "http://influxdb2.nonrtric:8086",
+ "db-org": "est",
+ "db-bucket": "pm-bucket",
+ "db-token": "token",
+ "filterType": "pmdata",
+ "filter": {}
+ }
+}
\ No newline at end of file
--- /dev/null
+{
+ "info_type_id": "xml-file-data-from-filestore",
+ "job_owner": "console",
+ "status_notification_uri": "http://callback.nonrtric:80/post",
+ "job_definition": {
+ "db-url": "http://influxdb2.nonrtric:8086",
+ "db-org": "est",
+ "db-bucket": "pm-bucket",
+ "db-token": "token",
+ "filterType": "pmdata",
+ "filter": {}
+ }
+}
\ No newline at end of file
--- /dev/null
+{
+ "info_job_callback_url": "http://localhost/jsonproducerjobcallback",
+ "info_producer_supervision_callback_url": "http://localhost/jsonproducersupervisioncallback",
+ "supported_info_types": [
+ "json-file-data-from-filestore"
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "info_job_callback_url": "http://localhost/xmlproducerjobcallback",
+ "info_producer_supervision_callback_url": "http://localhost/xmlproducersupervisioncallback",
+ "supported_info_types": [
+ "xml-file-data-from-filestore"
+ ]
+}
\ No newline at end of file
--- /dev/null
+{
+ "info_job_data_schema": {
+ "schema": "http://json-schema.org/draft-07/schema#",
+ "title": "json-file-data-from-filestore",
+ "description": "json-file-data-from-filestore",
+ "type": "object"
+ }
+}
\ No newline at end of file
--- /dev/null
+{
+ "info_job_data_schema": {
+ "schema": "http://json-schema.org/draft-07/schema#",
+ "title": "xml-file-data-to-filestore",
+ "description": "xml-file-data-to-filestore",
+ "type": "object"
+ }
+}
\ No newline at end of file
Source: Artifacts/Deployment/HELM/free5gc-1.1.3.tgz\r
Source: Artifacts/Deployment/HELM/ueransim-2.0.14.tgz\r
Source: Files/rapp1/rapp.zip\r
-Source: Files/Acm/instantiation.yaml\r
+Source: Files/Acm/definition/compositions.json\r
+Source: Files/Acm/instances/a1pms-instance.json\r
+Source: Files/Acm/instances/k8s-instance.json\r
+Source: Files/Acm/instances/kserve-instance.json\r
+Source: Files/Dme/infoconsumers/json-file-consumer.json\r
+Source: Files/Dme/infoconsumers/xml-file-consumer.json\r
+Source: Files/Dme/infoproducers/json-file-data-producer.json\r
+Source: Files/Dme/infoproducers/xml-file-data-producer.json\r
+Source: Files/Dme/infotypes/json-file-data-from-filestore.json\r
+Source: Files/Dme/infotypes/xml-file-data-from-filestore.json\r
+Source: Files/Sme/invokers/invoker-app1.json\r
+Source: Files/Sme/invokers/invoker-app2.json\r
+Source: Files/Sme/provider/aef-provider-function.json\r
+Source: Files/Sme/provider/amf-provider-function.json\r
+Source: Files/Sme/provider/apf-provider-function.json\r
+Source: Files/Sme/provider/gateway-provider-function.json\r
+Source: Files/Sme/serviceapis/api-set-1.json\r
+Source: Files/Sme/serviceapis/api-set-2.json\r
\r
non_mano_artifact_sets:\r
onap_ves_events:\r
import com.fasterxml.jackson.databind.ObjectMapper;
import com.oransc.rappmanager.acm.service.AcmDeployer;
+import com.oransc.rappmanager.dme.service.DmeDeployer;
import com.oransc.rappmanager.models.rappinstance.DeployOrder;
import com.oransc.rappmanager.models.rapp.Rapp;
import com.oransc.rappmanager.models.rappinstance.RappInstance;
@MockBean
SmeDeployer smeDeployer;
+ @MockBean
+ DmeDeployer dmeDeployer;
+
@MockBean
SmeLifecycleManager smeLifecycleManager;
rappInstanceDeployOrder.setDeployOrder(DeployOrder.DEPLOY);
when(acmDeployer.deployRappInstance(any(), any())).thenReturn(true);
when(smeDeployer.deployRappInstance(any(), any())).thenReturn(true);
+ when(dmeDeployer.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)))
rappInstanceDeployOrder.setDeployOrder(DeployOrder.DEPLOY);
when(acmDeployer.deployRappInstance(any(), any())).thenReturn(true);
when(smeDeployer.deployRappInstance(any(), any())).thenReturn(true);
+ when(dmeDeployer.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)))
rappInstanceDeployOrder.setDeployOrder(DeployOrder.DEPLOY);
when(acmDeployer.deployRappInstance(any(), any())).thenReturn(true);
when(smeDeployer.deployRappInstance(any(), any())).thenReturn(true);
+ when(dmeDeployer.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)))
rappInstanceDeployOrder.setDeployOrder(DeployOrder.UNDEPLOY);
when(acmDeployer.undeployRappInstance(any(), any())).thenReturn(true);
when(smeDeployer.undeployRappInstance(any(), any())).thenReturn(true);
+ when(dmeDeployer.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)))
rappInstanceDeployOrder.setDeployOrder(DeployOrder.UNDEPLOY);
when(acmDeployer.undeployRappInstance(any(), any())).thenReturn(true);
when(smeDeployer.undeployRappInstance(any(), any())).thenReturn(true);
+ when(dmeDeployer.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)))
rappInstanceDeployOrder.setDeployOrder(DeployOrder.UNDEPLOY);
when(acmDeployer.undeployRappInstance(any(), any())).thenReturn(true);
when(smeDeployer.undeployRappInstance(any(), any())).thenReturn(true);
+ when(dmeDeployer.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)))
import static org.mockito.Mockito.when;
import com.oransc.rappmanager.acm.service.AcmDeployer;
+import com.oransc.rappmanager.dme.service.DmeDeployer;
import com.oransc.rappmanager.models.rapp.Rapp;
import com.oransc.rappmanager.models.rapp.RappState;
import com.oransc.rappmanager.models.rappinstance.RappInstance;
@MockBean
SmeDeployer smeDeployer;
+ @MockBean
+ DmeDeployer dmeDeployer;
+
@MockBean
SmeLifecycleManager smeLifecycleManager;
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);
+ when(dmeDeployer.primeRapp(any())).thenReturn(true);
assertEquals(HttpStatus.OK, rappService.primeRapp(rapp).getStatusCode());
+ assertEquals(RappState.PRIMED, rapp.getState());
}
@Test
Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
.packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build();
when(acmDeployer.primeRapp(any())).thenReturn(false);
+ when(dmeDeployer.primeRapp(any())).thenReturn(true);
+ assertEquals(HttpStatus.OK, rappService.primeRapp(rapp).getStatusCode());
+ assertEquals(RappState.COMMISSIONED, rapp.getState());
+ }
+ @Test
+ void testPrimeRappDmeFailure() {
+ Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
+ .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build();
+ when(acmDeployer.primeRapp(any())).thenReturn(true);
+ when(dmeDeployer.primeRapp(any())).thenReturn(false);
assertEquals(HttpStatus.OK, rappService.primeRapp(rapp).getStatusCode());
+ assertEquals(RappState.COMMISSIONED, rapp.getState());
}
+
@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);
+ when(dmeDeployer.deprimeRapp(any())).thenReturn(true);
assertEquals(HttpStatus.OK, rappService.deprimeRapp(rapp).getStatusCode());
+ assertEquals(RappState.COMMISSIONED, rapp.getState());
}
@Test
- void testDeprimeRappFailure() {
+ void testDeprimeRappAcmFailure() {
Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
.packageLocation(validCsarFileLocation).state(RappState.PRIMED).build();
when(acmDeployer.deprimeRapp(any())).thenReturn(false);
+ when(dmeDeployer.deprimeRapp(any())).thenReturn(true);
assertEquals(HttpStatus.OK, rappService.deprimeRapp(rapp).getStatusCode());
+ assertEquals(RappState.PRIMED, rapp.getState());
+ }
+
+ @Test
+ void testDeprimeRappDmeFailure() {
+ Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
+ .packageLocation(validCsarFileLocation).state(RappState.PRIMED).build();
+ when(acmDeployer.deprimeRapp(any())).thenReturn(true);
+ when(dmeDeployer.deprimeRapp(any())).thenReturn(false);
+ assertEquals(HttpStatus.OK, rappService.deprimeRapp(rapp).getStatusCode());
+ assertEquals(RappState.PRIMED, rapp.getState());
}
@Test
Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
.packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build();
assertEquals(HttpStatus.BAD_REQUEST, rappService.deprimeRapp(rapp).getStatusCode());
+ assertEquals(RappState.COMMISSIONED, rapp.getState());
}
@Test
void testDeprimeRappActiveInstances() {
Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
- .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED)
+ .packageLocation(validCsarFileLocation).state(RappState.PRIMED)
.rappInstances(Map.of(UUID.randomUUID(), new RappInstance())).build();
assertEquals(HttpStatus.BAD_REQUEST, rappService.deprimeRapp(rapp).getStatusCode());
+ assertEquals(RappState.PRIMED, rapp.getState());
}
@Test
rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
when(acmDeployer.deployRappInstance(any(), any())).thenReturn(true);
when(smeDeployer.deployRappInstance(any(), any())).thenReturn(true);
+ when(dmeDeployer.deployRappInstance(any(), any())).thenReturn(true);
assertEquals(HttpStatus.ACCEPTED, rappService.deployRappInstance(rapp, rappInstance).getStatusCode());
}
rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
when(acmDeployer.deployRappInstance(any(), any())).thenReturn(true);
when(smeDeployer.deployRappInstance(any(), any())).thenReturn(false);
+ when(dmeDeployer.deployRappInstance(any(), any())).thenReturn(true);
+ assertEquals(HttpStatus.BAD_GATEWAY, rappService.deployRappInstance(rapp, rappInstance).getStatusCode());
+ }
+
+ @Test
+ void testDeployRappInstanceDmeFailure() {
+ 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);
+ when(dmeDeployer.deployRappInstance(any(), any())).thenReturn(false);
assertEquals(HttpStatus.BAD_GATEWAY, rappService.deployRappInstance(rapp, rappInstance).getStatusCode());
}
rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
when(acmDeployer.undeployRappInstance(any(), any())).thenReturn(true);
when(smeDeployer.undeployRappInstance(any(), any())).thenReturn(true);
+ when(dmeDeployer.undeployRappInstance(any(), any())).thenReturn(true);
assertEquals(HttpStatus.ACCEPTED, rappService.undeployRappInstance(rapp, rappInstance).getStatusCode());
}
rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
when(acmDeployer.undeployRappInstance(any(), any())).thenReturn(true);
when(smeDeployer.undeployRappInstance(any(), any())).thenReturn(false);
+ when(dmeDeployer.undeployRappInstance(any(), any())).thenReturn(true);
+ assertEquals(HttpStatus.BAD_GATEWAY, rappService.undeployRappInstance(rapp, rappInstance).getStatusCode());
+ }
+
+ @Test
+ void testUndeployRappInstanceDmeFailure() {
+ 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);
+ when(dmeDeployer.undeployRappInstance(any(), any())).thenReturn(false);
assertEquals(HttpStatus.BAD_GATEWAY, rappService.undeployRappInstance(rapp, rappInstance).getStatusCode());
}
rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
when(acmDeployer.undeployRappInstance(any(), any())).thenReturn(true);
when(smeDeployer.undeployRappInstance(any(), any())).thenReturn(false);
+ when(dmeDeployer.undeployRappInstance(any(), any())).thenReturn(true);
assertEquals(HttpStatus.BAD_REQUEST, rappService.undeployRappInstance(rapp, rappInstance).getStatusCode());
}
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+* ========================LICENSE_START=================================
+* O-RAN-SC
+* %%
+* Copyright (C) 2023 Nordix Foundation
+* %%
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* ========================LICENSE_END===================================
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.o-ran-sc.nonrtric.plt</groupId>
+ <artifactId>rappmanager</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.o-ran-sc.nonrtric.plt.rappmanager</groupId>
+ <artifactId>rapp-manager-dme</artifactId>
+
+ <properties>
+ <maven.compiler.source>17</maven.compiler.source>
+ <maven.compiler.target>17</maven.compiler.target>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.o-ran-sc.nonrtric.plt.rappmanager</groupId>
+ <artifactId>rapp-manager-models</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.openapitools</groupId>
+ <artifactId>jackson-databind-nullable</artifactId>
+ <version>${openapi.jackson.databind.nullable.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.openapitools</groupId>
+ <artifactId>openapi-generator-maven-plugin</artifactId>
+ <version>${openapi.maven.version}</version>
+ <executions>
+ <execution>
+ <id>dme-spec-generator</id>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ <configuration>
+ <inputSpec>${project.basedir}/src/main/resources/openapi/ics-api.yaml</inputSpec>
+ <generatorName>java</generatorName>
+ <library>resttemplate</library>
+ <generateApiTests>false</generateApiTests>
+ <generateModelTests>false</generateModelTests>
+ <generateApiDocumentation>false</generateApiDocumentation>
+ <generateModelDocumentation>false</generateModelDocumentation>
+ <generateModels>true</generateModels>
+ <additionalProperties>
+ <additionalProperty>apiNameSuffix=ApiClient</additionalProperty>
+ </additionalProperties>
+ <configOptions>
+ <sourceFolder>src/main/java</sourceFolder>
+ <useJakartaEe>true</useJakartaEe>
+ <invokerPackage>com.oransc.rappmanager.dme</invokerPackage>
+ <apiPackage>com.oransc.rappmanager.dme.rest</apiPackage>
+ <modelPackage>com.oransc.rappmanager.dme.data</modelPackage>
+ <generateClientAsBean>false</generateClientAsBean>
+ </configOptions>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</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.dme.configuration;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConfigurationProperties(prefix = "rappmanager.dme")
+@Data
+public class DmeConfiguration {
+ String baseUrl;
+}
--- /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.dme.service;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.oransc.rappmanager.dme.data.ConsumerJob;
+import com.oransc.rappmanager.dme.data.ProducerInfoTypeInfo;
+import com.oransc.rappmanager.dme.data.ProducerRegistrationInfo;
+import com.oransc.rappmanager.dme.rest.DataConsumerApiClient;
+import com.oransc.rappmanager.dme.rest.DataProducerRegistrationApiClient;
+import com.oransc.rappmanager.models.RappDeployer;
+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.rappinstance.RappInstance;
+import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import lombok.RequiredArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+public class DmeDeployer implements RappDeployer {
+
+ Logger logger = LoggerFactory.getLogger(DmeDeployer.class);
+
+ private final DataProducerRegistrationApiClient dataProducerRegistrationApiClient;
+
+ private final DataConsumerApiClient dataConsumerApiClient;
+
+ private final RappCsarConfigurationHandler rappCsarConfigurationHandler;
+
+ private final ObjectMapper objectMapper;
+
+ private final RappInstanceStateMachine rappInstanceStateMachine;
+
+ @Override
+ public boolean deployRappInstance(Rapp rapp, RappInstance rappInstance) {
+ logger.debug("Deploying DME functions for RappInstance {}", rappInstance.getRappInstanceId());
+ boolean deployState = true;
+ if (rappInstance.getDme().getInfoTypesProducer() != null
+ || rappInstance.getDme().getInfoTypeConsumer() != null) {
+ Set<String> infoTypes = new HashSet<>();
+ if (rappInstance.getDme().getInfoTypesProducer() != null) {
+ infoTypes.addAll(rappInstance.getDme().getInfoTypesProducer());
+ }
+ if (rappInstance.getDme().getInfoTypeConsumer() != null) {
+ infoTypes.add(rappInstance.getDme().getInfoTypeConsumer());
+ }
+ deployState = createInfoTypes(rapp, infoTypes);
+ }
+ if (rappInstance.getDme().getInfoProducer() != null) {
+ deployState = deployState && createInfoProducer(rapp, rappInstance.getDme().getInfoProducer());
+ }
+ if (rappInstance.getDme().getInfoConsumer() != null) {
+ deployState = deployState && createInfoConsumer(rapp, rappInstance.getDme().getInfoConsumer());
+ }
+ if (deployState) {
+ rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEDEPLOYED);
+ } else {
+ rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEDEPLOYFAILED);
+ }
+ return deployState;
+ }
+
+ @Override
+ public boolean undeployRappInstance(Rapp rapp, RappInstance rappInstance) {
+ logger.debug("Undeploying DME functions for RappInstance {}", rappInstance.getRappInstanceId());
+ boolean undeployState = true;
+ if (rappInstance.getDme().getInfoConsumer() != null) {
+ undeployState = deleteInfoConsumer(rapp, rappInstance.getDme().getInfoConsumer());
+ }
+ if (rappInstance.getDme().getInfoProducer() != null) {
+ undeployState = undeployState && deleteInfoProducer(rapp, rappInstance.getDme().getInfoProducer());
+ }
+ if (undeployState) {
+ rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEUNDEPLOYED);
+ } else {
+ rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEUNDEPLOYFAILED);
+ }
+ return undeployState;
+ }
+
+ @Override
+ public boolean primeRapp(Rapp rapp) {
+ logger.debug("Priming DME functions for rApp {}", rapp.getRappId());
+ try {
+ Set<String> requiredInfoTypes = new HashSet<>();
+ for (String producerResourceName : rapp.getRappResources().getDme().getInfoProducers()) {
+ String producerPayload =
+ rappCsarConfigurationHandler.getDmeInfoProducerPayload(rapp, producerResourceName);
+ ProducerRegistrationInfo producerRegistrationInfo =
+ objectMapper.readValue(producerPayload, ProducerRegistrationInfo.class);
+ requiredInfoTypes.addAll(producerRegistrationInfo.getSupportedInfoTypes());
+ }
+ for (String consumerResourceName : rapp.getRappResources().getDme().getInfoConsumers()) {
+ String consumerPayload =
+ rappCsarConfigurationHandler.getDmeInfoConsumerPayload(rapp, consumerResourceName);
+ ConsumerJob consumerJob = objectMapper.readValue(consumerPayload, ConsumerJob.class);
+ requiredInfoTypes.add(consumerJob.getInfoTypeId());
+ }
+ Set<String> allInfoTypes = new HashSet<>(rapp.getRappResources().getDme().getInfoTypes());
+ requiredInfoTypes.removeAll(allInfoTypes);
+ if (!requiredInfoTypes.isEmpty()) {
+ allInfoTypes.addAll(dataProducerRegistrationApiClient.getInfoTypdentifiers());
+ requiredInfoTypes.removeAll(allInfoTypes);
+ if (!requiredInfoTypes.isEmpty()) {
+ logger.info("Invalid rapp package as the following info types cannot be found {}",
+ requiredInfoTypes);
+ rapp.setIsDmeValid(false);
+ } else {
+ rapp.setIsDmeValid(true);
+ }
+ } else {
+ rapp.setIsDmeValid(true);
+ }
+ return true;
+ } catch (Exception e) {
+ logger.warn("Failed to prime DME", e);
+ rapp.setIsDmeValid(false);
+ return false;
+ }
+ }
+
+ @Override
+ public boolean deprimeRapp(Rapp rapp) {
+ logger.debug("Depriming DME functions for rApp {}", rapp.getRappId());
+ rapp.setIsDmeValid(null);
+ return true;
+ }
+
+ boolean createInfoTypes(Rapp rApp, Set<String> infoTypes) {
+ logger.debug("Creating DME info types {} for rApp {}", infoTypes, rApp.getRappId());
+ try {
+ Map<String, ProducerInfoTypeInfo> producerInfoTypeInfoMap = new HashMap<>();
+ for (String infoType : infoTypes) {
+ String infoTypePayload = rappCsarConfigurationHandler.getDmeInfoTypePayload(rApp, infoType);
+ if (infoTypePayload != null && !infoTypePayload.isEmpty()) {
+ producerInfoTypeInfoMap.put(infoType,
+ objectMapper.readValue(infoTypePayload, ProducerInfoTypeInfo.class));
+ }
+ }
+ return producerInfoTypeInfoMap.entrySet().stream().map(stringProducerInfoTypeInfoEntry -> {
+ ResponseEntity<Object> objectResponseEntity = dataProducerRegistrationApiClient.putInfoTypeWithHttpInfo(
+ stringProducerInfoTypeInfoEntry.getKey(), stringProducerInfoTypeInfoEntry.getValue());
+ return objectResponseEntity.getStatusCode().is2xxSuccessful();
+ }).reduce(true, (a, b) -> a && b);
+ } catch (Exception e) {
+ logger.warn("Error in creating info types {} for rApp {}", infoTypes, rApp.getRappId(), e);
+ return false;
+ }
+ }
+
+ boolean createInfoProducer(Rapp rApp, String producerResource) {
+ logger.debug("Creating DME info producer {} for rApp {}", producerResource, rApp.getRappId());
+ try {
+ String infoProducerPayload = rappCsarConfigurationHandler.getDmeInfoProducerPayload(rApp, producerResource);
+ ProducerRegistrationInfo producerRegistrationInfo =
+ objectMapper.readValue(infoProducerPayload, ProducerRegistrationInfo.class);
+
+ ResponseEntity<Object> objectResponseEntity =
+ dataProducerRegistrationApiClient.putInfoProducerWithHttpInfo(producerResource,
+ producerRegistrationInfo);
+ return objectResponseEntity.getStatusCode().is2xxSuccessful();
+ } catch (Exception e) {
+ logger.warn("Error in creating info producer {} for rApp {}", producerResource, rApp.getRappId(), e);
+ return false;
+ }
+ }
+
+ boolean createInfoConsumer(Rapp rApp, String consumerResource) {
+ logger.debug("Creating DME info consumer {} for rApp {}", consumerResource, rApp.getRappId());
+ try {
+ String infoJobPayload = rappCsarConfigurationHandler.getDmeInfoConsumerPayload(rApp, consumerResource);
+ ConsumerJob consumerJob = objectMapper.readValue(infoJobPayload, ConsumerJob.class);
+ ResponseEntity<Object> objectResponseEntity =
+ dataConsumerApiClient.putIndividualInfoJobWithHttpInfo(consumerResource, consumerJob);
+ return objectResponseEntity.getStatusCode().is2xxSuccessful();
+ } catch (Exception e) {
+ logger.warn("Error in creating info consumer {} for rApp {}", consumerResource, rApp.getRappId(), e);
+ return false;
+ }
+ }
+
+ boolean deleteInfoProducer(Rapp rApp, String producerResource) {
+ logger.debug("Deleting DME info producer {} for rApp {}", producerResource, rApp.getRappId());
+ try {
+ ResponseEntity<Object> objectResponseEntity =
+ dataProducerRegistrationApiClient.deleteInfoProducerWithHttpInfo(producerResource);
+ return objectResponseEntity.getStatusCode().is2xxSuccessful();
+ } catch (Exception e) {
+ logger.warn("Error in deleting info producer {} for rApp {}", producerResource, rApp.getRappId(), e);
+ return false;
+ }
+ }
+
+ boolean deleteInfoConsumer(Rapp rApp, String consumerResource) {
+ logger.debug("Deleting DME info consumer {} for rApp {}", consumerResource, rApp.getRappId());
+ try {
+ ResponseEntity<Object> objectResponseEntity =
+ dataConsumerApiClient.deleteIndividualInfoJobWithHttpInfo(consumerResource);
+ return objectResponseEntity.getStatusCode().is2xxSuccessful();
+ } catch (Exception e) {
+ logger.warn("Error in deleting info consumer {} for rApp {}", consumerResource, rApp.getRappId(), e);
+ return false;
+ }
+ }
+}
--- /dev/null
+openapi: 3.0.1
+info:
+ title: Data management and exposure
+ description: <h1>API documentation</h1><h2>General</h2><p> The service is mainly
+ a broker between data producers and data consumers. A data producer has the ability
+ to produce one or several types of data (Information Type). One type of data can
+ be produced by zero to many producers. <br /><br />A data consumer can have several
+ active data subscriptions (Information Job). One Information Job consists of the
+ type of data to produce and additional parameters for filtering of the data. These
+ parameters are different for different data types.</p><h2>APIs provided by the
+ service</h2><h4>A1-EI</h4><p> This API is between Near-RT RIC and the Non-RT
+ RIC. The Near-RT RIC is a data consumer, which creates Information Jobs to subscribe
+ for data. In this context, the information is referred to as 'Enrichment Information',
+ EI.</p><h4>Data producer API</h4><p> This API is provided by the Non-RT RIC platform
+ and is intended to be part of the O-RAN R1 interface. The API is for use by different
+ kinds of data producers and provides support for:<ul><li>Registry of supported
+ information types and which parameters needed to setup a subscription.</li><li>Registry
+ of existing data producers.</li><li>Callback API provided by producers to setup
+ subscriptions.</li></ul></p><h4>Data consumer API</h4><p> This API is provided
+ by the Non-RT RIC platform and is intended to be part of the O-RAN R1 interface. The
+ API is for use by different kinds of data consumers and provides support for:<ul><li>Querying
+ of available types of data to consume.</li><li>Management of data subscription
+ jobs</li><li>Optional callback API provided by consumers to get notification on
+ added and removed information types.</li></ul></p><h4>Service status</h4><p> This
+ API provides a means to monitor the health of this service.</p>
+ license:
+ name: Copyright (C) 2020-2023 Nordix Foundation. Licensed under the Apache License.
+ url: http://www.apache.org/licenses/LICENSE-2.0
+ version: "1.0"
+servers:
+- url: /
+tags:
+- name: A1-EI (registration)
+ description: Data consumer EI job registration
+- name: A1-EI (callbacks)
+ description: Data consumer EI job status callbacks
+- name: Data consumer (callbacks)
+ description: API for data consumers
+- name: Data producer (registration)
+ description: API for data producers
+- name: Data producer (callbacks)
+ description: API implemented by data producers
+- name: Data consumer
+ description: API for data consumers
+- name: Service status
+ description: API for monitoring of the service
+- name: Actuator
+ description: Monitor and interact
+ externalDocs:
+ description: Spring Boot Actuator Web API Documentation
+ url: https://docs.spring.io/spring-boot/docs/current/actuator-api/html/
+- name: Authorization API
+ description: API used for authorization of information job access (this is provided
+ by an authorization producer such as OPA)
+paths:
+ /example-authz-check:
+ post:
+ tags:
+ - Authorization API
+ summary: Request for access authorization.
+ description: The authorization function decides if access is granted.
+ operationId: subscriptionAuth
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/subscription_authorization'
+ required: true
+ responses:
+ 200:
+ description: OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/authorization_result'
+ /data-producer/v1/info-types:
+ get:
+ tags:
+ - Data producer (registration)
+ summary: Info Type identifiers
+ operationId: getInfoTypdentifiers
+ responses:
+ 200:
+ description: Info Type identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ /actuator/threaddump:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'threaddump'
+ operationId: threaddump
+ responses:
+ 200:
+ description: OK
+ content:
+ text/plain;charset=UTF-8:
+ schema:
+ type: object
+ application/vnd.spring-boot.actuator.v3+json:
+ schema:
+ type: object
+ application/json:
+ schema:
+ type: object
+ application/vnd.spring-boot.actuator.v2+json:
+ schema:
+ type: object
+ /A1-EI/v1/eitypes/{eiTypeId}:
+ get:
+ tags:
+ - A1-EI (registration)
+ summary: Individual EI type
+ operationId: getEiType
+ parameters:
+ - name: eiTypeId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: EI type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EiTypeObject'
+ 404:
+ description: Enrichment Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /data-producer/v1/info-types/{infoTypeId}:
+ get:
+ tags:
+ - Data producer (registration)
+ summary: Individual Information Type
+ operationId: getInfoType
+ parameters:
+ - name: infoTypeId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Info Type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/producer_info_type_info'
+ 404:
+ description: Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ put:
+ tags:
+ - Data producer (registration)
+ summary: Individual Information Type
+ operationId: putInfoType
+ parameters:
+ - name: infoTypeId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/producer_info_type_info'
+ required: true
+ responses:
+ 200:
+ description: Type updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 201:
+ description: Type created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 400:
+ description: Input validation failed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ delete:
+ tags:
+ - Data producer (registration)
+ summary: Individual Information Type
+ description: Existing jobs of the type will be automatically deleted.
+ operationId: deleteInfoType
+ parameters:
+ - name: infoTypeId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Not used
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 204:
+ description: Producer deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 404:
+ description: Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ 409:
+ description: The Information type has one or several active producers
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /data-consumer/v1/info-type-subscription/{subscriptionId}:
+ get:
+ tags:
+ - Data consumer
+ summary: Individual subscription for information types (registration/deregistration)
+ operationId: getIndividualTypeSubscription
+ parameters:
+ - name: subscriptionId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Type subscription
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_type_subscription_info'
+ 404:
+ description: Subscription is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ put:
+ tags:
+ - Data consumer
+ summary: Individual subscription for information types (registration/deregistration)
+ description: This service operation is used to subscribe to notifications for
+ changes in the availability of data types.
+ operationId: putIndividualTypeSubscription
+ parameters:
+ - name: subscriptionId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_type_subscription_info'
+ required: true
+ responses:
+ 200:
+ description: Subscription updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 201:
+ description: Subscription created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ delete:
+ tags:
+ - Data consumer
+ summary: Individual subscription for information types (registration/deregistration)
+ operationId: deleteIndividualTypeSubscription
+ parameters:
+ - name: subscriptionId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Not used
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 204:
+ description: Subscription deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 404:
+ description: Subscription is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /example-dataproducer/health-check:
+ get:
+ tags:
+ - Data producer (callbacks)
+ summary: Producer supervision
+ description: The endpoint is provided by the Information Producer and is used
+ for supervision of the producer.
+ operationId: producerSupervision
+ responses:
+ 200:
+ description: The producer is OK
+ content:
+ application/json:
+ schema:
+ type: string
+ /actuator/loggers:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'loggers'
+ operationId: loggers
+ responses:
+ 200:
+ description: OK
+ content:
+ application/vnd.spring-boot.actuator.v3+json:
+ schema:
+ type: object
+ application/json:
+ schema:
+ type: object
+ application/vnd.spring-boot.actuator.v2+json:
+ schema:
+ type: object
+ /actuator/health/**:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'health-path'
+ operationId: health-path
+ responses:
+ 200:
+ description: OK
+ content:
+ application/vnd.spring-boot.actuator.v3+json:
+ schema:
+ type: object
+ application/json:
+ schema:
+ type: object
+ application/vnd.spring-boot.actuator.v2+json:
+ schema:
+ type: object
+ /data-consumer/v1/info-types:
+ get:
+ tags:
+ - Data consumer
+ summary: Information type identifiers
+ operationId: getinfoTypeIdentifiers
+ responses:
+ 200:
+ description: Information type identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ /example-dataconsumer/info-type-status:
+ post:
+ tags:
+ - Data consumer (callbacks)
+ summary: Callback for changed Information type registration status
+ description: The primitive is implemented by the data consumer and is invoked
+ when a Information type status has been changed. <br/>Subscription are managed
+ by primitives in 'Data consumer'
+ operationId: typeStatusCallback
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_type_registration_info'
+ required: true
+ responses:
+ 200:
+ description: OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ /actuator/shutdown:
+ post:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'shutdown'
+ operationId: shutdown
+ responses:
+ 200:
+ description: OK
+ content:
+ application/vnd.spring-boot.actuator.v3+json:
+ schema:
+ type: object
+ application/json:
+ schema:
+ type: object
+ application/vnd.spring-boot.actuator.v2+json:
+ schema:
+ type: object
+ /actuator/metrics/{requiredMetricName}:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'metrics-requiredMetricName'
+ operationId: metrics-requiredMetricName
+ parameters:
+ - name: requiredMetricName
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: OK
+ content:
+ application/vnd.spring-boot.actuator.v3+json:
+ schema:
+ type: object
+ application/json:
+ schema:
+ type: object
+ application/vnd.spring-boot.actuator.v2+json:
+ schema:
+ type: object
+ /actuator:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator root web endpoint
+ operationId: links
+ responses:
+ 200:
+ description: OK
+ content:
+ application/vnd.spring-boot.actuator.v3+json:
+ schema:
+ type: object
+ additionalProperties:
+ type: object
+ additionalProperties:
+ $ref: '#/components/schemas/Link'
+ application/json:
+ schema:
+ type: object
+ additionalProperties:
+ type: object
+ additionalProperties:
+ $ref: '#/components/schemas/Link'
+ application/vnd.spring-boot.actuator.v2+json:
+ schema:
+ type: object
+ additionalProperties:
+ type: object
+ additionalProperties:
+ $ref: '#/components/schemas/Link'
+ /data-consumer/v1/info-jobs:
+ get:
+ tags:
+ - Data consumer
+ summary: Information Job identifiers
+ description: query for information job identifiers
+ operationId: getJobIds
+ parameters:
+ - name: infoTypeId
+ in: query
+ description: selects subscription jobs of matching information type
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: string
+ - name: owner
+ in: query
+ description: selects result for one owner
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information information job identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ 404:
+ description: Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ delete:
+ tags:
+ - Data consumer
+ summary: Information Jobs
+ description: delete all jobs for one owner
+ operationId: deleteJobsForOwner
+ parameters:
+ - name: owner
+ in: query
+ description: selects result for one owner
+ required: true
+ style: form
+ explode: true
+ schema:
+ type: string
+ responses:
+ 204:
+ description: No Content
+ content:
+ application/json:
+ schema:
+ type: object
+ /actuator/loggers/{name}:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'loggers-name'
+ operationId: loggers-name
+ parameters:
+ - name: name
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: OK
+ content:
+ application/vnd.spring-boot.actuator.v3+json:
+ schema:
+ type: object
+ application/json:
+ schema:
+ type: object
+ application/vnd.spring-boot.actuator.v2+json:
+ schema:
+ type: object
+ post:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'loggers-name'
+ operationId: loggers-name_2
+ parameters:
+ - name: name
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: string
+ enum:
+ - TRACE
+ - DEBUG
+ - INFO
+ - WARN
+ - ERROR
+ - FATAL
+ - OFF
+ responses:
+ 200:
+ description: OK
+ content:
+ '*/*':
+ schema:
+ type: object
+ /example-dataproducer/info-job:
+ post:
+ tags:
+ - Data producer (callbacks)
+ summary: Callback for Information Job creation/modification
+ description: The call is invoked to activate or to modify a data subscription.
+ The endpoint is provided by the Information Producer.
+ operationId: jobCreatedCallback
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/producer_info_job_request'
+ required: true
+ responses:
+ 200:
+ description: OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ /example-dataproducer/info-job/{infoJobId}:
+ delete:
+ tags:
+ - Data producer (callbacks)
+ summary: Callback for Information Job deletion
+ description: The call is invoked to terminate a data subscription. The endpoint
+ is provided by the Information Producer.
+ operationId: jobDeletedCallback
+ parameters:
+ - name: infoJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ /A1-EI/v1/eijobs/{eiJobId}/status:
+ get:
+ tags:
+ - A1-EI (registration)
+ summary: EI job status
+ operationId: getEiJobStatus
+ parameters:
+ - name: eiJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: EI job status
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EiJobStatusObject'
+ 404:
+ description: Enrichment Information job is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /data-producer/v1/info-producers/{infoProducerId}/status:
+ get:
+ tags:
+ - Data producer (registration)
+ summary: Information producer status
+ operationId: getInfoProducerStatus
+ parameters:
+ - name: infoProducerId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information producer status
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/producer_status'
+ 404:
+ description: Information producer is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /data-consumer/v1/info-jobs/{infoJobId}/status:
+ get:
+ tags:
+ - Data consumer
+ summary: Job status
+ operationId: getInfoJobStatus
+ parameters:
+ - name: infoJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information subscription job status
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_job_status'
+ 404:
+ description: Information subscription job is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /actuator/metrics:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'metrics'
+ operationId: metrics
+ responses:
+ 200:
+ description: OK
+ content:
+ application/vnd.spring-boot.actuator.v3+json:
+ schema:
+ type: object
+ application/json:
+ schema:
+ type: object
+ application/vnd.spring-boot.actuator.v2+json:
+ schema:
+ type: object
+ /example-dataconsumer/info-jobs/{infoJobId}/status:
+ post:
+ tags:
+ - A1-EI (callbacks)
+ summary: Callback for changed Information Job status
+ description: The primitive is implemented by the data consumer and is invoked
+ when a Information Job status has been changed.
+ operationId: jobStatusCallback
+ parameters:
+ - name: infoJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EiJobStatusObject'
+ required: true
+ responses:
+ 200:
+ description: OK
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ /actuator/info:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'info'
+ operationId: info
+ responses:
+ 200:
+ description: OK
+ content:
+ application/vnd.spring-boot.actuator.v3+json:
+ schema:
+ type: object
+ application/json:
+ schema:
+ type: object
+ application/vnd.spring-boot.actuator.v2+json:
+ schema:
+ type: object
+ /A1-EI/v1/eitypes:
+ get:
+ tags:
+ - A1-EI (registration)
+ summary: EI type identifiers
+ operationId: getEiTypeIdentifiers
+ responses:
+ 200:
+ description: EI type identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ /data-producer/v1/info-producers/{infoProducerId}:
+ get:
+ tags:
+ - Data producer (registration)
+ summary: Individual Information Producer
+ operationId: getInfoProducer
+ parameters:
+ - name: infoProducerId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information producer
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/producer_registration_info'
+ 404:
+ description: Information producer is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ put:
+ tags:
+ - Data producer (registration)
+ summary: Individual Information Producer
+ operationId: putInfoProducer
+ parameters:
+ - name: infoProducerId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/producer_registration_info'
+ required: true
+ responses:
+ 200:
+ description: Producer updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 201:
+ description: Producer created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 400:
+ description: Input validation failed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ 404:
+ description: Producer type not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ delete:
+ tags:
+ - Data producer (registration)
+ summary: Individual Information Producer
+ operationId: deleteInfoProducer
+ parameters:
+ - name: infoProducerId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Not used
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 204:
+ description: Producer deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 404:
+ description: Producer is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /status:
+ get:
+ tags:
+ - Service status
+ summary: Returns status and statistics of this service
+ operationId: getStatus
+ responses:
+ 200:
+ description: Service is living
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/service_status_info'
+ /data-consumer/v1/info-type-subscription:
+ get:
+ tags:
+ - Data consumer
+ summary: Information type subscription identifiers
+ description: query for information type subscription identifiers
+ operationId: getInfoTypeSubscriptions
+ parameters:
+ - name: owner
+ in: query
+ description: selects result for one owner
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information type subscription identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ /A1-EI/v1/eijobs/{eiJobId}:
+ get:
+ tags:
+ - A1-EI (registration)
+ summary: Individual EI job
+ operationId: getIndividualEiJob
+ parameters:
+ - name: eiJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: EI job
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EiJobObject'
+ 404:
+ description: Enrichment Information job is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ put:
+ tags:
+ - A1-EI (registration)
+ summary: Individual EI job
+ description: If the requested info_type_id is not found, an attempt to find
+ a compatible version is made. As an example, 'type_1.9.0' is backwards compatible
+ with 'type_1.0.0'
+ operationId: putIndividualEiJob
+ parameters:
+ - name: eiJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/EiJobObject'
+ required: true
+ responses:
+ 200:
+ description: Job updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 201:
+ description: Job created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 400:
+ description: Input validation failed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ 404:
+ description: Enrichment Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ 409:
+ description: Cannot modify job type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ delete:
+ tags:
+ - A1-EI (registration)
+ summary: Individual EI job
+ operationId: deleteIndividualEiJob
+ parameters:
+ - name: eiJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Not used
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 204:
+ description: Job deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 404:
+ description: Enrichment Information job is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /actuator/logfile:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'logfile'
+ operationId: logfile
+ responses:
+ 200:
+ description: OK
+ content:
+ text/plain;charset=UTF-8:
+ schema:
+ type: object
+ /data-consumer/v1/info-jobs/{infoJobId}:
+ get:
+ tags:
+ - Data consumer
+ summary: Individual data subscription job
+ operationId: getIndividualInfoJob
+ parameters:
+ - name: infoJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information subscription job
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_job'
+ 404:
+ description: Information subscription job is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ put:
+ tags:
+ - Data consumer
+ summary: Individual data subscription job
+ description: The job will be enabled when a producer is available. If the requested
+ info_type_id is not found, an attempt to find a compatible version is made.
+ As an example, 'type_1.9.0' is backwards compatible with 'type_1.0.0'
+ operationId: putIndividualInfoJob
+ parameters:
+ - name: infoJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_job'
+ required: true
+ responses:
+ 200:
+ description: Job updated
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 201:
+ description: Job created
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 400:
+ description: Input validation failed
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ 404:
+ description: Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ 409:
+ description: Cannot modify job type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ delete:
+ tags:
+ - Data consumer
+ summary: Individual data subscription job
+ operationId: deleteIndividualInfoJob
+ parameters:
+ - name: infoJobId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Not used
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 204:
+ description: Job deleted
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Void'
+ 404:
+ description: Information subscription job is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /data-producer/v1/info-producers:
+ get:
+ tags:
+ - Data producer (registration)
+ summary: Information producer identifiers
+ operationId: getInfoProducerIdentifiers
+ parameters:
+ - name: infoTypeId
+ in: query
+ description: If given, only the producers for the Info Type is returned.
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information producer identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ /data-consumer/v1/info-types/{infoTypeId}:
+ get:
+ tags:
+ - Data consumer
+ summary: Individual information type
+ operationId: getInfoType_1
+ parameters:
+ - name: infoTypeId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information type
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/consumer_information_type'
+ 404:
+ description: Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /actuator/health:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'health'
+ operationId: health
+ responses:
+ 200:
+ description: OK
+ content:
+ application/vnd.spring-boot.actuator.v3+json:
+ schema:
+ type: object
+ application/json:
+ schema:
+ type: object
+ application/vnd.spring-boot.actuator.v2+json:
+ schema:
+ type: object
+ /A1-EI/v1/eijobs:
+ get:
+ tags:
+ - A1-EI (registration)
+ summary: EI job identifiers
+ description: query for EI job identifiers
+ operationId: getEiJobIds
+ parameters:
+ - name: eiTypeId
+ in: query
+ description: selects EI jobs of matching EI type
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: string
+ - name: owner
+ in: query
+ description: selects EI jobs for one EI job owner
+ required: false
+ style: form
+ explode: true
+ schema:
+ type: string
+ responses:
+ 200:
+ description: EI job identifiers
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ type: string
+ 404:
+ description: Enrichment Information type is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /data-producer/v1/info-producers/{infoProducerId}/info-jobs:
+ get:
+ tags:
+ - Data producer (registration)
+ summary: Information Job definitions
+ description: Information Job definitions for one Information Producer
+ operationId: getInfoProducerJobs
+ parameters:
+ - name: infoProducerId
+ in: path
+ required: true
+ style: simple
+ explode: false
+ schema:
+ type: string
+ responses:
+ 200:
+ description: Information producer
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/producer_info_job_request'
+ 404:
+ description: Information producer is not found
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProblemDetails'
+ /actuator/heapdump:
+ get:
+ tags:
+ - Actuator
+ summary: Actuator web endpoint 'heapdump'
+ operationId: heapdump
+ responses:
+ 200:
+ description: OK
+ content:
+ application/octet-stream:
+ schema:
+ type: object
+components:
+ schemas:
+ consumer_information_type:
+ required:
+ - job_data_schema
+ - no_of_producers
+ - type_status
+ type: object
+ properties:
+ no_of_producers:
+ type: integer
+ description: The number of registered producers for the type
+ format: int32
+ type_status:
+ type: string
+ description: 'Allowed values: <br/>ENABLED: one or several producers for
+ the information type are available <br/>DISABLED: no producers for the
+ information type are available'
+ enum:
+ - ENABLED
+ - DISABLED
+ job_data_schema:
+ type: object
+ description: Json schema for the job data
+ description: Information for an Information type
+ EiTypeObject:
+ type: object
+ description: Information for an EI type
+ authorization_result:
+ required:
+ - result
+ type: object
+ properties:
+ result:
+ type: boolean
+ description: If true, the access is granted
+ description: Result of authorization
+ service_status_info:
+ required:
+ - no_of_jobs
+ - no_of_producers
+ - no_of_types
+ - status
+ type: object
+ properties:
+ no_of_producers:
+ type: integer
+ description: Number of Information Producers
+ format: int32
+ no_of_types:
+ type: integer
+ description: Number of Information Types
+ format: int32
+ no_of_jobs:
+ type: integer
+ description: Number of Information Jobs
+ format: int32
+ status:
+ type: string
+ description: status text
+ producer_registration_info:
+ required:
+ - info_job_callback_url
+ - info_producer_supervision_callback_url
+ - supported_info_types
+ type: object
+ properties:
+ info_producer_supervision_callback_url:
+ type: string
+ description: callback for producer supervision
+ supported_info_types:
+ type: array
+ description: Supported Information Type IDs
+ items:
+ type: string
+ description: Supported Information Type IDs
+ info_job_callback_url:
+ type: string
+ description: callback for Information Job
+ description: Information for an Information Producer
+ consumer_type_registration_info:
+ required:
+ - info_type_id
+ - job_data_schema
+ - status
+ type: object
+ properties:
+ info_type_id:
+ type: string
+ description: Information type identifier
+ job_data_schema:
+ type: object
+ description: Json schema for the job data
+ status:
+ type: string
+ description: 'Allowed values: <br/>REGISTERED: the information type has
+ been registered <br/>DEREGISTERED: the information type has been removed'
+ enum:
+ - REGISTERED
+ - DEREGISTERED
+ description: Information for an Information type
+ ProblemDetails:
+ type: object
+ properties:
+ detail:
+ type: string
+ description: A human-readable explanation specific to this occurrence of
+ the problem.
+ example: Information Job type not found
+ status:
+ type: integer
+ description: The HTTP status code generated by the origin server for this
+ occurrence of the problem.
+ format: int32
+ example: 404
+ description: A problem detail to carry details in a HTTP response according
+ to RFC 7807
+ EiJobStatusObject:
+ required:
+ - eiJobStatus
+ type: object
+ properties:
+ eiJobStatus:
+ type: string
+ description: 'Allowed values for EI job status: <br/>ENABLED: the A1-EI
+ producer is able to deliver EI result for the EI job <br/>DISABLED: the
+ A1-EI producer is unable to deliver EI result for the EI job'
+ enum:
+ - ENABLED
+ - DISABLED
+ description: Status for an EI job
+ consumer_job_status:
+ required:
+ - info_job_status
+ - producers
+ type: object
+ properties:
+ info_job_status:
+ type: string
+ description: 'Allowed values: <br/>ENABLED: the A1-Information producer
+ is able to deliver result for the Information Job <br/>DISABLED: the A1-Information
+ producer is unable to deliver result for the Information Job'
+ enum:
+ - ENABLED
+ - DISABLED
+ producers:
+ type: array
+ description: An array of all registered Information Producer Identifiers.
+ items:
+ type: string
+ description: An array of all registered Information Producer Identifiers.
+ description: Status for an Information Job
+ EiJobObject:
+ required:
+ - eiTypeId
+ - jobDefinition
+ - jobOwner
+ - jobResultUri
+ type: object
+ properties:
+ eiTypeId:
+ type: string
+ description: EI type Idenitifier of the EI job
+ jobResultUri:
+ type: string
+ description: The target URI of the EI data
+ jobOwner:
+ type: string
+ description: Identity of the owner of the job
+ statusNotificationUri:
+ type: string
+ description: The target of EI job status notifications
+ jobDefinition:
+ type: object
+ description: EI type specific job data
+ description: Information for an Enrichment Information Job
+ subscription_authorization:
+ required:
+ - input
+ type: object
+ properties:
+ input:
+ $ref: '#/components/schemas/input'
+ description: Authorization request for subscription requests
+ producer_info_type_info:
+ required:
+ - info_job_data_schema
+ type: object
+ properties:
+ info_type_information:
+ type: object
+ description: Type specific information for the information type
+ info_job_data_schema:
+ type: object
+ description: Json schema for the job data
+ description: Information for an Information Type
+ producer_info_job_request:
+ required:
+ - info_job_identity
+ type: object
+ properties:
+ owner:
+ type: string
+ description: The owner of the job. This is a string that indentifies the
+ job owner, which could be an application, a POD or something else.
+ last_updated:
+ type: string
+ description: The time when the job was last updated or created (ISO-8601)
+ info_job_identity:
+ type: string
+ description: Identity of the Information Job
+ target_uri:
+ type: string
+ description: URI for the target of the produced Information. Note, this
+ is deprecated and will be removed. The information on how the data is
+ delivered is type specific and should be defined in the type specific
+ info_job_data.
+ info_job_data:
+ type: object
+ description: Json for the job data
+ info_type_identity:
+ type: string
+ description: Type identity for the job
+ description: The body of the Information Producer callbacks for Information
+ Job creation and deletion
+ input:
+ required:
+ - access_type
+ - auth_token
+ - info_type_id
+ - job_definition
+ type: object
+ properties:
+ access_type:
+ type: string
+ description: Access type
+ enum:
+ - READ
+ - WRITE
+ info_type_id:
+ type: string
+ description: Information type identifier
+ job_definition:
+ type: object
+ description: Information type specific job data
+ auth_token:
+ type: string
+ description: Authorization token
+ description: input
+ consumer_job:
+ required:
+ - info_type_id
+ - job_definition
+ - job_owner
+ - job_result_uri
+ type: object
+ properties:
+ info_type_id:
+ type: string
+ description: Information type Idenitifier of the subscription job
+ job_result_uri:
+ type: string
+ description: The target URI of the subscribed information
+ job_owner:
+ type: string
+ description: Identity of the owner of the job
+ job_definition:
+ type: object
+ description: Information type specific job data
+ status_notification_uri:
+ type: string
+ description: The target of Information subscription job status notifications
+ description: Information for an Information Job
+ producer_status:
+ required:
+ - operational_state
+ type: object
+ properties:
+ operational_state:
+ type: string
+ description: Represents the operational states
+ enum:
+ - ENABLED
+ - DISABLED
+ description: Status for an Info Producer
+ Void:
+ type: object
+ description: 'Void/empty '
+ Link:
+ type: object
+ properties:
+ templated:
+ type: boolean
+ href:
+ type: string
+ consumer_type_subscription_info:
+ required:
+ - owner
+ - status_result_uri
+ type: object
+ properties:
+ owner:
+ type: string
+ description: Identity of the owner of the subscription
+ status_result_uri:
+ type: string
+ description: The target URI of the subscribed information
+ description: Information for an information type subscription
--- /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.dme.service;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.oransc.rappmanager.dme.configuration.DmeConfiguration;
+import com.oransc.rappmanager.dme.rest.DataConsumerApiClient;
+import com.oransc.rappmanager.dme.rest.DataProducerRegistrationApiClient;
+import lombok.RequiredArgsConstructor;
+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 DmeConfiguration dmeConfiguration;
+
+ @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
+ public com.oransc.rappmanager.dme.ApiClient dmeApiClient(RestTemplate restTemplate) {
+ com.oransc.rappmanager.dme.ApiClient apiClient = new com.oransc.rappmanager.dme.ApiClient(restTemplate);
+ return apiClient.setBasePath(dmeConfiguration.getBaseUrl());
+ }
+
+ @Bean
+ public DataProducerRegistrationApiClient dataProducerRegistrationApiClient(
+ com.oransc.rappmanager.dme.ApiClient apiClient) {
+ return new DataProducerRegistrationApiClient(apiClient);
+ }
+
+ @Bean
+ public DataConsumerApiClient dataConsumerApiClient(com.oransc.rappmanager.dme.ApiClient apiClient) {
+ return new DataConsumerApiClient(apiClient);
+ }
+}
--- /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.dme.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.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.dme.configuration.DmeConfiguration;
+import com.oransc.rappmanager.models.cache.RappCacheService;
+import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler;
+import com.oransc.rappmanager.models.rapp.Rapp;
+import com.oransc.rappmanager.models.rapp.RappDmeResourceBuilder;
+import com.oransc.rappmanager.models.rapp.RappResources;
+import com.oransc.rappmanager.models.rapp.RappState;
+import com.oransc.rappmanager.models.rappinstance.RappInstance;
+import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine;
+import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachineConfig;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Stream;
+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.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+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 = {DmeConfiguration.class, DmeDeployer.class, BeanTestConfiguration.class,
+ RappCsarConfigurationHandler.class, RappCacheService.class, RappInstanceStateMachineConfig.class,
+ RappInstanceStateMachine.class})
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+@AutoConfigureMockMvc
+class DmeDeployerTest {
+
+ MockRestServiceServer mockServer;
+ @SpyBean
+ DmeDeployer dmeDeployer;
+ @Autowired
+ RestTemplate restTemplate;
+ @Autowired
+ DmeConfiguration dmeConfiguration;
+ @SpyBean
+ RappInstanceStateMachine rappInstanceStateMachine;
+
+ RappDmeResourceBuilder rappDmeResourceBuilder = new RappDmeResourceBuilder();
+
+ private static final String validRappFile = "valid-rapp-package.csar";
+ private static final String validRappFileNewInfoType = "valid-rapp-package-new-info-type.csar";
+ String validCsarFileLocation = "src/test/resources/";
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ String URI_INFO_TYPES, URI_INFO_TYPE, URI_INFO_PRODUCER, URI_INFO_CONSUMER;
+
+ @BeforeAll
+ void initACMURI() {
+ URI_INFO_TYPES = dmeConfiguration.getBaseUrl() + "/data-producer/v1/info-types";
+ URI_INFO_TYPE = dmeConfiguration.getBaseUrl() + "/data-producer/v1/info-types/%s";
+ URI_INFO_PRODUCER = dmeConfiguration.getBaseUrl() + "/data-producer/v1/info-producers/%s";
+ URI_INFO_CONSUMER = dmeConfiguration.getBaseUrl() + "/data-consumer/v1/info-jobs/%s";
+ }
+
+ @BeforeEach
+ public void init() {
+ mockServer = MockRestServiceServer.createServer(restTemplate);
+ }
+
+ @ParameterizedTest
+ @MethodSource("getSuccessParamsWithUnavailableInfoTypes")
+ void testPrimeRappSuccessWithUnavailableInfoType(String rappFile, boolean result) throws JsonProcessingException {
+ RappResources rappResources = rappDmeResourceBuilder.getResources();
+ Rapp rapp = getRapp(Optional.empty());
+ rapp.setPackageName(rappFile);
+ rapp.setRappResources(rappResources);
+ List<String> infoTypes = List.of();
+ mockServer.expect(ExpectedCount.once(), requestTo(URI_INFO_TYPES)).andExpect(method(HttpMethod.GET)).andRespond(
+ withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON)
+ .body(objectMapper.writeValueAsString(infoTypes)));
+ assertTrue(dmeDeployer.primeRapp(rapp));
+ if (rappFile.equals(validRappFileNewInfoType)) {
+ mockServer.verify();
+ }
+ assertEquals(rapp.getIsDmeValid(), result);
+ }
+
+ private static Stream<Arguments> getSuccessParamsWithUnavailableInfoTypes() {
+ return Stream.of(Arguments.of(validRappFile, true), Arguments.of(validRappFileNewInfoType, false));
+ }
+
+ @ParameterizedTest
+ @MethodSource("getSuccessParamsWithAvailableInfoTypes")
+ void testPrimeRappSuccessWithValidInfoType(String rappFile, boolean result) throws JsonProcessingException {
+ RappResources rappResources = rappDmeResourceBuilder.getResources();
+ Rapp rapp = getRapp(Optional.empty());
+ rapp.setPackageName(rappFile);
+ rapp.setRappResources(rappResources);
+ List<String> infoTypes = List.of("new-info-type-not-available");
+ mockServer.expect(ExpectedCount.once(), requestTo(URI_INFO_TYPES)).andExpect(method(HttpMethod.GET)).andRespond(
+ withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON)
+ .body(objectMapper.writeValueAsString(infoTypes)));
+ assertTrue(dmeDeployer.primeRapp(rapp));
+ if (rappFile.equals(validRappFileNewInfoType)) {
+ mockServer.verify();
+ }
+ assertEquals(rapp.getIsDmeValid(), result);
+ }
+
+ private static Stream<Arguments> getSuccessParamsWithAvailableInfoTypes() {
+ return Stream.of(Arguments.of(validRappFile, true), Arguments.of(validRappFileNewInfoType, true));
+ }
+
+ @Test
+ void testPrimeRappFailure() {
+ RappResources rappResources = rappDmeResourceBuilder.getResources();
+ RappResources.DMEResources dme = rappResources.getDme();
+ Set<String> infoProducers = new HashSet<>(rappResources.getDme().getInfoProducers());
+ infoProducers.add("invalid-producer-not-available-in-rapp");
+ dme.setInfoProducers(infoProducers);
+ rappResources.setDme(dme);
+ Rapp rapp = getRapp(Optional.empty());
+ rapp.setRappResources(rappResources);
+ assertFalse(dmeDeployer.primeRapp(rapp));
+ assertFalse(rapp.getIsDmeValid());
+ }
+
+ @Test
+ void testDeprimeRapp() {
+ Rapp rapp = getRapp(Optional.empty());
+ rapp.setIsDmeValid(true);
+ assertTrue(dmeDeployer.deprimeRapp(rapp));
+ assertNull(rapp.getIsDmeValid());
+ }
+
+ @Test
+ void testDeployrAppInstanceSuccess() {
+ Rapp rapp = getRapp(Optional.empty());
+ RappInstance rappInstance = rappDmeResourceBuilder.getRappInstance();
+ getMockServerClientCreateInfoType(rappInstance.getDme().getInfoTypesProducer().toArray()[0].toString(), true);
+ getMockServerClientCreateInfoProducer(rappInstance.getDme().getInfoProducer(), true);
+ getMockServerClientCreateInfoConsumer(rappInstance.getDme().getInfoConsumer(), true);
+ rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
+ assertTrue(dmeDeployer.deployRappInstance(rapp, rappInstance));
+ mockServer.verify();
+ }
+
+ @Test
+ void testDeployrAppInstanceSuccessWithoutConsumer() {
+ Rapp rapp = getRapp(Optional.empty());
+ RappInstance rappInstance = rappDmeResourceBuilder.getRappInstance();
+ rappInstance.getDme().setInfoTypeConsumer(null);
+ rappInstance.getDme().setInfoConsumer(null);
+ getMockServerClientCreateInfoType(rappInstance.getDme().getInfoTypesProducer().toArray()[0].toString(), true);
+ getMockServerClientCreateInfoProducer(rappInstance.getDme().getInfoProducer(), true);
+ rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
+ assertTrue(dmeDeployer.deployRappInstance(rapp, rappInstance));
+ mockServer.verify();
+ }
+
+ @Test
+ void testDeployrAppInstanceWithoutProducer() {
+ Rapp rapp = getRapp(Optional.empty());
+ RappInstance rappInstance = rappDmeResourceBuilder.getRappInstance();
+ rappInstance.getDme().setInfoTypesProducer(null);
+ rappInstance.getDme().setInfoProducer(null);
+ getMockServerClientCreateInfoType(rappInstance.getDme().getInfoTypeConsumer(), true);
+ getMockServerClientCreateInfoConsumer(rappInstance.getDme().getInfoConsumer(), true);
+ rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
+ assertTrue(dmeDeployer.deployRappInstance(rapp, rappInstance));
+ mockServer.verify();
+ }
+
+ @Test
+ void testDeployrAppInstanceFailureWithInfoType() {
+ Rapp rapp = getRapp(Optional.empty());
+ RappInstance rappInstance = rappDmeResourceBuilder.getRappInstance();
+ getMockServerClientCreateInfoType(rappInstance.getDme().getInfoTypesProducer().toArray()[0].toString(), false);
+ rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
+ assertFalse(dmeDeployer.deployRappInstance(rapp, rappInstance));
+ mockServer.verify();
+ }
+
+ @Test
+ void testDeployrAppInstanceFailureWithInfoProducer() {
+ Rapp rapp = getRapp(Optional.empty());
+ RappInstance rappInstance = rappDmeResourceBuilder.getRappInstance();
+ getMockServerClientCreateInfoType(rappInstance.getDme().getInfoTypesProducer().toArray()[0].toString(), true);
+ getMockServerClientCreateInfoProducer(rappInstance.getDme().getInfoProducer(), false);
+ rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
+ assertFalse(dmeDeployer.deployRappInstance(rapp, rappInstance));
+ mockServer.verify();
+ }
+
+ @Test
+ void testDeployrAppInstanceFailureWithInfoConsumer() {
+ Rapp rapp = getRapp(Optional.empty());
+ RappInstance rappInstance = rappDmeResourceBuilder.getRappInstance();
+ getMockServerClientCreateInfoType(rappInstance.getDme().getInfoTypesProducer().toArray()[0].toString(), true);
+ getMockServerClientCreateInfoProducer(rappInstance.getDme().getInfoProducer(), true);
+ getMockServerClientCreateInfoConsumer(rappInstance.getDme().getInfoConsumer(), false);
+ rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
+ assertFalse(dmeDeployer.deployRappInstance(rapp, rappInstance));
+ mockServer.verify();
+ }
+
+ @Test
+ void testUndeployrAppInstanceSuccess() {
+ Rapp rapp = getRapp(Optional.empty());
+ rapp.setState(RappState.PRIMED);
+ RappInstance rappInstance = rappDmeResourceBuilder.getRappInstance();
+ getMockServerClientDeleteInfoConsumer(rappInstance.getDme().getInfoConsumer(), true);
+ getMockServerClientDeleteInfoProducer(rappInstance.getDme().getInfoProducer(), true);
+ rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
+ assertTrue(dmeDeployer.undeployRappInstance(rapp, rappInstance));
+ mockServer.verify();
+ }
+
+
+ @Test
+ void testUndeployrAppInstanceFailureWithInfoProducer() {
+ Rapp rapp = getRapp(Optional.empty());
+ rapp.setState(RappState.PRIMED);
+ RappInstance rappInstance = rappDmeResourceBuilder.getRappInstance();
+ getMockServerClientDeleteInfoConsumer(rappInstance.getDme().getInfoConsumer(), true);
+ getMockServerClientDeleteInfoProducer(rappInstance.getDme().getInfoProducer(), false);
+ rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
+ assertFalse(dmeDeployer.undeployRappInstance(rapp, rappInstance));
+ mockServer.verify();
+ }
+
+ @Test
+ void testUndeployrAppInstanceFailureWithInfoConsumer() {
+ Rapp rapp = getRapp(Optional.empty());
+ rapp.setState(RappState.PRIMED);
+ RappInstance rappInstance = rappDmeResourceBuilder.getRappInstance();
+ getMockServerClientDeleteInfoConsumer(rappInstance.getDme().getInfoConsumer(), false);
+ rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
+ assertFalse(dmeDeployer.undeployRappInstance(rapp, rappInstance));
+ mockServer.verify();
+ }
+
+ @Test
+ void testCreateInfoTypeFailureInvalidInfoType() {
+ Rapp rapp = getRapp(Optional.empty());
+ assertFalse(dmeDeployer.createInfoTypes(rapp, null));
+ }
+
+ @Test
+ void testCreateInfoTypeFailureInvalidInfoProducer() {
+ Rapp rapp = getRapp(Optional.empty());
+ assertFalse(dmeDeployer.createInfoProducer(rapp, ""));
+ }
+
+ @Test
+ void testCreateInfoTypeFailureInvalidInfoConsumer() {
+ Rapp rapp = getRapp(Optional.empty());
+ assertFalse(dmeDeployer.createInfoConsumer(rapp, ""));
+ }
+
+ Rapp getRapp(Optional<UUID> rappOptional) {
+ return Rapp.builder().rappId(rappOptional.orElse(UUID.randomUUID())).name("").packageName(validRappFile)
+ .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build();
+ }
+
+ void getMockServerClientCreateInfoType(String infoType, boolean isSuccess) {
+ if (isSuccess) {
+ mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INFO_TYPE, infoType)))
+ .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.CREATED));
+ } else {
+ mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INFO_TYPE, infoType)))
+ .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.BAD_GATEWAY));
+ }
+ }
+
+ void getMockServerClientCreateInfoProducer(String infoProducer, boolean isSuccess) {
+ if (isSuccess) {
+ mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INFO_PRODUCER, infoProducer)))
+ .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.CREATED));
+ } else {
+ mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INFO_PRODUCER, infoProducer)))
+ .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.BAD_GATEWAY));
+ }
+ }
+
+ void getMockServerClientCreateInfoConsumer(String infoConsumer, boolean isSuccess) {
+ if (isSuccess) {
+ mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INFO_CONSUMER, infoConsumer)))
+ .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.CREATED));
+ } else {
+ mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INFO_CONSUMER, infoConsumer)))
+ .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.BAD_GATEWAY));
+ }
+ }
+
+ void getMockServerClientDeleteInfoProducer(String infoProducer, boolean isSuccess) {
+ if (isSuccess) {
+ mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INFO_PRODUCER, infoProducer)))
+ .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.NO_CONTENT));
+ } else {
+ mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INFO_PRODUCER, infoProducer)))
+ .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.BAD_GATEWAY));
+ }
+ }
+
+ void getMockServerClientDeleteInfoConsumer(String infoConsumer, boolean isSuccess) {
+ if (isSuccess) {
+ mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INFO_CONSUMER, infoConsumer)))
+ .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.NO_CONTENT));
+ } else {
+ mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_INFO_CONSUMER, infoConsumer)))
+ .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.BAD_GATEWAY));
+ }
+ }
+
+}
--- /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 com.oransc.rappmanager.models.rappinstance.RappDMEInstance;
+import com.oransc.rappmanager.models.rappinstance.RappInstance;
+import java.util.Set;
+
+public class RappDmeResourceBuilder {
+
+ public RappResources getResources() {
+ RappResources rappResources = new RappResources();
+ RappResources.DMEResources dmeResources =
+ new RappResources.DMEResources(Set.of("json-file-data-from-filestore", "xml-file-data-from-filestore"),
+ Set.of("json-file-data-producer", "xml-file-data-producer"),
+ Set.of("json-file-consumer", "xml-file-consumer"));
+ rappResources.setDme(dmeResources);
+ return rappResources;
+ }
+
+ public RappInstance getRappInstance() {
+ RappInstance rappInstance = new RappInstance();
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoTypesProducer(Set.of("json-file-data-from-filestore"));
+ rappDMEInstance.setInfoProducer("json-file-data-producer");
+ rappDMEInstance.setInfoTypeConsumer("json-file-data-from-filestore");
+ rappDMEInstance.setInfoConsumer("json-file-consumer");
+ rappInstance.setDme(rappDMEInstance);
+ return rappInstance;
+ }
+}
--- /dev/null
+rappmanager:
+ dme:
+ baseurl: http://localhost:39390
private static final String ACM_COMPOSITION_JSON_LOCATION = "Files/Acm/definition/compositions.json";
private static final String ACM_DEFINITION_LOCATION = "Files/Acm/definition";
private static final String ACM_INSTANCES_LOCATION = "Files/Acm/instances";
-
private static final String SME_PROVIDER_FUNCS_LOCATION = "Files/Sme/providers";
private static final String SME_SERVICE_APIS_LOCATION = "Files/Sme/serviceapis";
-
private static final String SME_INVOKERS_LOCATION = "Files/Sme/invokers";
+ private static final String DME_INFO_TYPES_LOCATION = "Files/Dme/infotypes";
+ private static final String DME_INFO_PRODUCERS_LOCATION = "Files/Dme/infoproducers";
+ private static final String DME_INFO_CONSUMERS_LOCATION = "Files/Dme/infoconsumers";
public boolean isValidRappPackage(MultipartFile multipartFile) {
}
String getPayload(Rapp rapp, String location) {
- logger.info("Getting payload for {} from {}", rapp.getRappId(), location);
+ logger.debug("Getting payload for {} from {}", rapp.getRappId(), location);
File csarFile = getCsarFile(rapp);
return getFileFromCsar(csarFile, location).toString();
}
getResourceUri(ACM_DEFINITION_LOCATION, rapp.getRappResources().getAcm().getCompositionDefinitions()));
}
+ public String getDmeInfoProducerPayload(Rapp rapp, String producerIdentifier) {
+ return getPayload(rapp, getResourceUri(DME_INFO_PRODUCERS_LOCATION, producerIdentifier));
+ }
+
+ public String getDmeInfoTypePayload(Rapp rapp, String infoTypeIdentifier) {
+ return getPayload(rapp, getResourceUri(DME_INFO_TYPES_LOCATION, infoTypeIdentifier));
+ }
+
+ public String getDmeInfoConsumerPayload(Rapp rapp, String infoConsumerIdentifier) {
+ return getPayload(rapp, getResourceUri(DME_INFO_CONSUMERS_LOCATION, infoConsumerIdentifier));
+ }
+
String getResourceUri(String resourceLocation, String resource) {
return resourceLocation + "/" + resource + ".json";
}
getFileListFromCsar(csarFile, SME_PROVIDER_FUNCS_LOCATION))
.serviceApis(getFileListFromCsar(csarFile, SME_SERVICE_APIS_LOCATION))
.invokers(getFileListFromCsar(csarFile, SME_INVOKERS_LOCATION)).build());
+ rappResources.setDme(RappResources.DMEResources.builder()
+ .infoTypes(getFileListFromCsar(csarFile, DME_INFO_TYPES_LOCATION))
+ .infoProducers(getFileListFromCsar(csarFile, DME_INFO_PRODUCERS_LOCATION))
+ .infoConsumers(getFileListFromCsar(csarFile, DME_INFO_CONSUMERS_LOCATION)).build());
}
} catch (Exception e) {
logger.warn("Error in getting the rapp resources", e);
Map<UUID, RappInstance> rappInstances = new HashMap<>();
UUID compositionId;
+ Boolean isDmeValid;
}
ACMUNDEPLOYED,
SMEUNDEPLOYED,
ACMUNDEPLOYFAILED,
- SMEUNDEPLOYFAILED
+ SMEUNDEPLOYFAILED,
+ DMEDEPLOYED,
+ DMEDEPLOYFAILED,
+ DMEUNDEPLOYED,
+ DMEUNDEPLOYFAILED
}
ACMResources acm;
SMEResources sme;
+ DMEResources dme;
@Data
@Builder
Set<String> serviceApis;
Set<String> invokers;
}
+
+ @Data
+ @Builder
+ public static class DMEResources {
+
+ Set<String> infoTypes;
+ Set<String> infoProducers;
+ Set<String> infoConsumers;
+ }
}
--- /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.Set;
+import lombok.Data;
+
+@Data
+public class RappDMEInstance {
+
+ Set<String> infoTypesProducer;
+ String infoProducer;
+ String infoTypeConsumer;
+ String infoConsumer;
+}
RappInstanceState state = RappInstanceState.UNDEPLOYED;
RappACMInstance acm;
RappSMEInstance sme;
+ RappDMEInstance dme;
}
.withExternal()
.source(RappInstanceState.DEPLOYING).target(RappInstanceState.UNDEPLOYED).event(RappEvent.SMEDEPLOYFAILED)
.and()
+ .withExternal()
+ .source(RappInstanceState.DEPLOYING).target(RappInstanceState.UNDEPLOYED).event(RappEvent.DMEDEPLOYFAILED)
+ .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.UNDEPLOYING).target(RappInstanceState.DEPLOYED).event(RappEvent.DMEUNDEPLOYFAILED)
+ .and()
.withExternal()
.source(RappInstanceState.DEPLOYED).target(RappInstanceState.UNDEPLOYING).event(RappEvent.UNDEPLOYING)
.and()
.source(RappInstanceState.DEPLOYING).target(RappInstanceState.DEPLOYED).event(RappEvent.SMEDEPLOYED)
.guard(deployedGuard())
.and()
+ .withExternal()
+ .source(RappInstanceState.DEPLOYING).target(RappInstanceState.DEPLOYED).event(RappEvent.DMEDEPLOYED)
+ .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())
+ .and()
+ .withExternal()
+ .source(RappInstanceState.UNDEPLOYING).target(RappInstanceState.UNDEPLOYED).event(RappEvent.DMEUNDEPLOYED)
.guard(undeployedGuard());
}
return stateContext -> {
stateContext.getExtendedState().getVariables().put(stateContext.getEvent(), true);
return stateContext.getExtendedState().getVariables().get(RappEvent.ACMDEPLOYED) != null
- && stateContext.getExtendedState().getVariables().get(RappEvent.SMEDEPLOYED) != null;
+ && stateContext.getExtendedState().getVariables().get(RappEvent.SMEDEPLOYED) != null
+ && stateContext.getExtendedState().getVariables().get(RappEvent.DMEDEPLOYED) != null;
};
}
return stateContext -> {
stateContext.getExtendedState().getVariables().put(stateContext.getEvent(), true);
return stateContext.getExtendedState().getVariables().get(RappEvent.ACMUNDEPLOYED) != null
- && stateContext.getExtendedState().getVariables().get(RappEvent.SMEUNDEPLOYED) != null;
+ && stateContext.getExtendedState().getVariables().get(RappEvent.SMEUNDEPLOYED) != null
+ && stateContext.getExtendedState().getVariables().get(RappEvent.DMEUNDEPLOYED) != null;
};
}
}
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 static org.mockito.Mockito.mock;
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.RappDMEInstance;
import com.oransc.rappmanager.models.rappinstance.RappSMEInstance;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
assertEquals(Boolean.FALSE, rappCsarConfigurationHandler.isValidRappPackage(multipartFile));
}
+ @Test
+ void testCsarPackageValidationFailureWithoutOrginalName() throws IOException {
+ MultipartFile multipartFile = mock(MultipartFile.class);
+ assertEquals(Boolean.FALSE, rappCsarConfigurationHandler.isValidRappPackage(multipartFile));
+ }
+
+ @Test
+ void testInvalidCsarFileExist() {
+ MultipartFile multipartFile = mock(MultipartFile.class);
+ assertEquals(Boolean.FALSE, rappCsarConfigurationHandler.isFileExistsInCsar(multipartFile, "INVALID_LOCATION"));
+ }
+
@Test
void testCsarInstantiationPayload() throws JSONException {
Rapp rapp = Rapp.builder().name("").packageName(validRappFile).packageLocation(validCsarFileLocation).build();
assertThat(fileListFromCsar).isEmpty();
}
+ @Test
+ void testInvalidFileListingFromCsar() {
+ File file = new File("InvalidFile");
+ ByteArrayOutputStream fileByteArray = rappCsarConfigurationHandler.getFileFromCsar(file, null);
+ assertThat(fileByteArray.size()).isZero();
+ }
+
@Test
void testListResources() {
UUID rappId = UUID.randomUUID();
RappResources rappResources = rappCsarConfigurationHandler.getRappResource(rapp);
assertThat(rappResources).isNotNull();
assertNotNull(rappResources.getAcm().getCompositionDefinitions());
- assertThat(rappResources.getAcm().getCompositionInstances()).hasSize(3);
+ assertThat(rappResources.getAcm().getCompositionInstances()).hasSize(4);
assertThat(rappResources.getSme().getProviderFunctions()).hasSize(4);
assertThat(rappResources.getSme().getServiceApis()).hasSize(2);
assertThat(rappResources.getSme().getInvokers()).hasSize(2);
+ assertThat(rappResources.getDme().getInfoTypes()).hasSize(2);
+ assertThat(rappResources.getDme().getInfoProducers()).hasSize(2);
+ assertThat(rappResources.getDme().getInfoConsumers()).hasSize(2);
}
@Test
assertThat(rappResources).isNotNull();
assertNull(rappResources.getAcm());
assertNull(rappResources.getSme());
+ assertNull(rappResources.getDme());
}
@Test
assertNotNull(smeProviderDomainPayload);
}
+ @Test
+ void testGetDmeInfoTypePayload() {
+ UUID rappId = UUID.randomUUID();
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoTypesProducer(Set.of("json-file-data-from-filestore"));
+ Rapp rapp =
+ Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation)
+ .build();
+ String dmeInfoTypePayload = rappCsarConfigurationHandler.getDmeInfoTypePayload(rapp,
+ rappDMEInstance.getInfoTypesProducer().iterator().next());
+ assertNotNull(dmeInfoTypePayload);
+ }
+
+ @Test
+ void testGetDmeInfoProducerPayload() {
+ UUID rappId = UUID.randomUUID();
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoProducer("json-file-data-producer");
+ Rapp rapp =
+ Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation)
+ .build();
+ String dmeInfoProducerPayload =
+ rappCsarConfigurationHandler.getDmeInfoProducerPayload(rapp, rappDMEInstance.getInfoProducer());
+ assertNotNull(dmeInfoProducerPayload);
+ }
+
+ @Test
+ void testGetDmeInfoConsumerPayload() {
+ UUID rappId = UUID.randomUUID();
+ RappDMEInstance rappDMEInstance = new RappDMEInstance();
+ rappDMEInstance.setInfoConsumer("json-file-consumer");
+ Rapp rapp =
+ Rapp.builder().rappId(rappId).name("").packageName(validRappFile).packageLocation(validCsarFileLocation)
+ .build();
+ String dmeInfoConsumerPayload =
+ rappCsarConfigurationHandler.getDmeInfoConsumerPayload(rapp, rappDMEInstance.getInfoConsumer());
+ assertNotNull(dmeInfoConsumerPayload);
+ }
+
}
}
@ParameterizedTest
- @EnumSource(value = RappEvent.class, names = {"ACMDEPLOYED", "SMEDEPLOYED"})
+ @EnumSource(value = RappEvent.class, names = {"ACMDEPLOYED", "SMEDEPLOYED", "DMEDEPLOYED" })
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.ACMDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step()
- .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappInstanceState.DEPLOYED).expectStateChanged(1)
+ .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step()
+ .sendEvent(RappEvent.DMEDEPLOYED).expectState(RappInstanceState.DEPLOYED).expectStateChanged(1)
.and().build();
plan.test();
}
@Test
- void testDeployFailedState() throws Exception {
+ void testAcmDeployFailedState() 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.SMEDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step()
+ .sendEvent(RappEvent.DMEDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step()
+ .sendEvent(RappEvent.ACMDEPLOYFAILED).expectState(RappInstanceState.UNDEPLOYED)
+ .expectStateChanged(1).and().build();
+ plan.test();
+ }
+
+ @Test
+ void testSmeDeployFailedState() 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.DMEDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step()
.sendEvent(RappEvent.SMEDEPLOYFAILED).expectState(RappInstanceState.UNDEPLOYED)
.expectStateChanged(1).and().build();
plan.test();
}
+ @Test
+ void testDmeDeployFailedState() 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.DEPLOYING).and().step()
+ .sendEvent(RappEvent.DMEDEPLOYFAILED).expectState(RappInstanceState.UNDEPLOYED)
+ .expectStateChanged(1).and().build();
+ plan.test();
+ }
+
@Test
void testUndeployingState() throws Exception {
StateMachineTestPlan plan =
.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)
+ .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step()
+ .sendEvent(RappEvent.DMEDEPLOYED).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"})
+ @EnumSource(value = RappEvent.class, names = {"ACMUNDEPLOYED", "SMEUNDEPLOYED", "DMEUNDEPLOYED" })
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)
+ .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step()
+ .sendEvent(RappEvent.DMEDEPLOYED).expectState(RappInstanceState.DEPLOYED).expectStateChanged(1)
.and().step().sendEvent(RappEvent.UNDEPLOYING).expectState(RappInstanceState.UNDEPLOYING)
.expectStateChanged(1).and().step().sendEvent(rappEvent)
.expectState(RappInstanceState.UNDEPLOYING).and().build();
.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)
+ .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step()
+ .sendEvent(RappEvent.DMEDEPLOYED).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();
+ .expectState(RappInstanceState.UNDEPLOYING).and().step().sendEvent(RappEvent.DMEUNDEPLOYED)
+ .expectStateChanged(1).and().build();
+ plan.test();
+ }
+
+ @Test
+ void testUndeployAcmFailedState() 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.DEPLOYING).and().step()
+ .sendEvent(RappEvent.DMEDEPLOYED).expectState(RappInstanceState.DEPLOYED).expectStateChanged(1)
+ .and().step().sendEvent(RappEvent.UNDEPLOYING).expectState(RappInstanceState.UNDEPLOYING)
+ .expectStateChanged(1).and().step().sendEvent(RappEvent.SMEUNDEPLOYED)
+ .expectState(RappInstanceState.UNDEPLOYING).and().step().sendEvent(RappEvent.DMEUNDEPLOYED)
+ .expectState(RappInstanceState.UNDEPLOYING).and().step().sendEvent(RappEvent.ACMUNDEPLOYFAILED)
+ .expectState(RappInstanceState.DEPLOYED).expectStateChanged(1).and().build();
plan.test();
}
@Test
- void testUndeployFailedState() throws Exception {
+ void testUndeploySmeFailedState() 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)
+ .sendEvent(RappEvent.SMEDEPLOYED).expectState(RappInstanceState.DEPLOYING).and().step()
+ .sendEvent(RappEvent.DMEDEPLOYED).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.DMEUNDEPLOYED)
.expectState(RappInstanceState.UNDEPLOYING).and().step().sendEvent(RappEvent.SMEUNDEPLOYFAILED)
.expectState(RappInstanceState.DEPLOYED).expectStateChanged(1).and().build();
plan.test();
}
+
+ @Test
+ void testUndeployDmeFailedState() 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.DEPLOYING).and().step()
+ .sendEvent(RappEvent.DMEDEPLOYED).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.UNDEPLOYING).and().step().sendEvent(RappEvent.DMEUNDEPLOYFAILED)
+ .expectState(RappInstanceState.DEPLOYED).expectStateChanged(1).and().build();
+ plan.test();
+ }
}
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.Rapp;
-import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler;
import com.oransc.rappmanager.models.RappDeployer;
+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.rappinstance.RappInstance;
-import com.oransc.rappmanager.models.cache.RappCacheService;
import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine;
import com.oransc.rappmanager.sme.invoker.data.APIInvokerEnrolmentDetails;
import com.oransc.rappmanager.sme.provider.data.APIProviderEnrolmentDetails;
private final com.oransc.rappmanager.sme.provider.rest.DefaultApiClient providerDefaultApiClient;
+
private final com.oransc.rappmanager.sme.publishservice.rest.DefaultApiClient publishServiceDefaultApiClient;
private final com.oransc.rappmanager.sme.invoker.rest.DefaultApiClient invokerDefaultApiClient;
private final ObjectMapper objectMapper;
- private final RappCacheService rappCacheService;
-
private final RappInstanceStateMachine rappInstanceStateMachine;
private String amfRegistrationId;
@Override
public boolean deprimeRapp(Rapp rapp) {
- //If there is any deprimgng operations
+ //If there is any depriming operations
return true;
}
if (providerApiPayload != null) {
ServiceAPIDescription serviceAPIDescription =
objectMapper.readValue(providerApiPayload, ServiceAPIDescription.class);
- serviceAPIDescription.getAefProfiles().forEach(aefProfile -> aefProfile.setAefId(rappInstance.getSme().getAefId()));
+ serviceAPIDescription.getAefProfiles()
+ .forEach(aefProfile -> aefProfile.setAefId(rappInstance.getSme().getAefId()));
ServiceAPIDescription serviceAPIDescriptionResponse =
publishServiceDefaultApiClient.postApfIdServiceApis(rappInstance.getSme().getApfId(),
serviceAPIDescription);