From: aravind.est
Date: Wed, 20 Sep 2023 11:22:18 +0000 (+0100)
Subject: Add DME integration
X-Git-Tag: 0.0.1~39
X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F03%2F11803%2F1;p=nonrtric%2Fplt%2Frappmanager.git
Add DME integration
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
Change-Id: Ib7a41f8a4200503f3a0b0ffee8e80a0cda3c0871
---
diff --git a/pom.xml b/pom.xml
index a0f222a..9491a02 100755
--- a/pom.xml
+++ b/pom.xml
@@ -36,6 +36,7 @@
rapp-manager-modelsrapp-manager-acmrapp-manager-sme
+ rapp-manager-dmerapp-manager-application
diff --git a/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/service/AcmDeployer.java b/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/service/AcmDeployer.java
index 41f4bae..eb93ed3 100755
--- a/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/service/AcmDeployer.java
+++ b/rapp-manager-acm/src/main/java/com/oransc/rappmanager/acm/service/AcmDeployer.java
@@ -25,7 +25,6 @@ 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.rapp.RappState;
import com.oransc.rappmanager.models.rappinstance.RappACMInstance;
import com.oransc.rappmanager.models.rappinstance.RappInstance;
import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine;
@@ -172,7 +171,6 @@ public class AcmDeployer implements RappDeployer {
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");
@@ -189,7 +187,6 @@ public class AcmDeployer implements RappDeployer {
primeACMComposition(rapp.getCompositionId(), PrimeOrder.DEPRIME);
CommissioningResponse commissioningResponse = deleteComposition(rapp.getCompositionId());
if (commissioningResponse != null) {
- rapp.setState(RappState.COMMISSIONED);
return true;
}
} catch (Exception e) {
diff --git a/rapp-manager-acm/src/test/java/com/oransc/rappmanager/acm/service/AcmDeployerTest.java b/rapp-manager-acm/src/test/java/com/oransc/rappmanager/acm/service/AcmDeployerTest.java
index 59e69a6..f3016b0 100755
--- a/rapp-manager-acm/src/test/java/com/oransc/rappmanager/acm/service/AcmDeployerTest.java
+++ b/rapp-manager-acm/src/test/java/com/oransc/rappmanager/acm/service/AcmDeployerTest.java
@@ -287,8 +287,6 @@ class AcmDeployerTest {
boolean primeRapp = acmDeployer.primeRapp(rapp);
mockServer.verify();
assertTrue(primeRapp);
- assertEquals(RappState.PRIMED, rapp.getState());
-
}
@Test
diff --git a/rapp-manager-acm/src/test/resources/valid-rapp-package.csar b/rapp-manager-acm/src/test/resources/valid-rapp-package.csar
index b8b36e3..398a516 100755
Binary files a/rapp-manager-acm/src/test/resources/valid-rapp-package.csar and b/rapp-manager-acm/src/test/resources/valid-rapp-package.csar differ
diff --git a/rapp-manager-application/pom.xml b/rapp-manager-application/pom.xml
index ee830cf..5bd7dd1 100755
--- a/rapp-manager-application/pom.xml
+++ b/rapp-manager-application/pom.xml
@@ -53,6 +53,11 @@
rapp-manager-sme${project.version}
+
+ org.o-ran-sc.nonrtric.plt.rappmanager
+ rapp-manager-dme
+ ${project.version}
+ org.onap.policy.clamppolicy-clamp-models
diff --git a/rapp-manager-application/src/main/java/com/oransc/rappmanager/BeanConfiguration.java b/rapp-manager-application/src/main/java/com/oransc/rappmanager/BeanConfiguration.java
index 0d3bd3d..4e7f7fd 100755
--- a/rapp-manager-application/src/main/java/com/oransc/rappmanager/BeanConfiguration.java
+++ b/rapp-manager-application/src/main/java/com/oransc/rappmanager/BeanConfiguration.java
@@ -23,6 +23,9 @@ import com.oransc.rappmanager.acm.configuration.ACMConfiguration;
import com.oransc.rappmanager.acm.rest.AutomationCompositionDefinitionApiClient;
import com.oransc.rappmanager.acm.rest.AutomationCompositionInstanceApiClient;
import com.oransc.rappmanager.acm.rest.ParticipantMonitoringApiClient;
+import com.oransc.rappmanager.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;
@@ -40,6 +43,7 @@ public class BeanConfiguration {
private final ACMConfiguration acmConfiguration;
private final SmeConfiguration smeConfiguration;
+ private final DmeConfiguration dmeConfiguration;
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
@@ -108,6 +112,23 @@ public class BeanConfiguration {
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();
diff --git a/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/RappService.java b/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/RappService.java
index 6411b2b..1b9fb68 100755
--- a/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/RappService.java
+++ b/rapp-manager-application/src/main/java/com/oransc/rappmanager/service/RappService.java
@@ -19,6 +19,7 @@
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;
@@ -37,13 +38,16 @@ public class RappService {
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 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();
@@ -57,7 +61,9 @@ public class RappService {
public ResponseEntity 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();
@@ -75,8 +81,8 @@ public class RappService {
public ResponseEntity deployRappInstance(Rapp rapp, RappInstance rappInstance) {
if (rappInstance.getState().equals(RappInstanceState.UNDEPLOYED)) {
rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DEPLOYING);
- if (acmDeployer.deployRappInstance(rapp, rappInstance) && smeDeployer.deployRappInstance(rapp,
- rappInstance)) {
+ if (acmDeployer.deployRappInstance(rapp, rappInstance) && smeDeployer.deployRappInstance(rapp, rappInstance)
+ && dmeDeployer.deployRappInstance(rapp, rappInstance)) {
return ResponseEntity.accepted().build();
}
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).build();
@@ -91,7 +97,7 @@ public class RappService {
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();
diff --git a/rapp-manager-application/src/main/resources/application.yaml b/rapp-manager-application/src/main/resources/application.yaml
index 0672fd2..8a30abb 100755
--- a/rapp-manager-application/src/main/resources/application.yaml
+++ b/rapp-manager-application/src/main/resources/application.yaml
@@ -1,23 +1,25 @@
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
diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/definition/compositions.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/definition/compositions.json
index bc568ad..e64d882 100755
--- a/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/definition/compositions.json
+++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/definition/compositions.json
@@ -263,7 +263,7 @@
"name": "org.onap.policy.clamp.acm.KserveParticipant",
"version": "2.3.4"
},
- "uninitializedToPassiveTimeout": 60,
+ "uninitializedToPassiveTimeout": 300,
"statusCheckInterval": 30
}
},
diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/k8s-instance.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/k8s-instance.json
index 286a943..562b5a2 100755
--- a/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/k8s-instance.json
+++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Acm/instances/k8s-instance.json
@@ -22,7 +22,7 @@
"podName": "ransliceassurance",
"repository": {
"repoName": "local",
- "address": "http://10.101.3.22:8879/charts"
+ "address": "http://10.101.2.41:8879/charts"
}
}
}
diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infoconsumers/json-file-consumer.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infoconsumers/json-file-consumer.json
new file mode 100755
index 0000000..b18a643
--- /dev/null
+++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infoconsumers/json-file-consumer.json
@@ -0,0 +1,13 @@
+{
+ "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
diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infoconsumers/xml-file-consumer.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infoconsumers/xml-file-consumer.json
new file mode 100755
index 0000000..b33482a
--- /dev/null
+++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infoconsumers/xml-file-consumer.json
@@ -0,0 +1,13 @@
+{
+ "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
diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infoproducers/json-file-data-producer.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infoproducers/json-file-data-producer.json
new file mode 100755
index 0000000..ed74384
--- /dev/null
+++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infoproducers/json-file-data-producer.json
@@ -0,0 +1,7 @@
+{
+ "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
diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infoproducers/xml-file-data-producer.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infoproducers/xml-file-data-producer.json
new file mode 100755
index 0000000..33075de
--- /dev/null
+++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infoproducers/xml-file-data-producer.json
@@ -0,0 +1,7 @@
+{
+ "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
diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infotypes/json-file-data-from-filestore.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infotypes/json-file-data-from-filestore.json
new file mode 100755
index 0000000..a5f9d02
--- /dev/null
+++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infotypes/json-file-data-from-filestore.json
@@ -0,0 +1,8 @@
+{
+ "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
diff --git a/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infotypes/xml-file-data-from-filestore.json b/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infotypes/xml-file-data-from-filestore.json
new file mode 100755
index 0000000..3585603
--- /dev/null
+++ b/rapp-manager-application/src/main/resources/resource-csar/Files/Dme/infotypes/xml-file-data-from-filestore.json
@@ -0,0 +1,8 @@
+{
+ "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
diff --git a/rapp-manager-application/src/main/resources/resource-csar/asd.mf b/rapp-manager-application/src/main/resources/resource-csar/asd.mf
index 39218a5..09818fc 100755
--- a/rapp-manager-application/src/main/resources/resource-csar/asd.mf
+++ b/rapp-manager-application/src/main/resources/resource-csar/asd.mf
@@ -17,7 +17,24 @@ Source: TOSCA-Metadata/TOSCA.meta
Source: Artifacts/Deployment/HELM/free5gc-1.1.3.tgz
Source: Artifacts/Deployment/HELM/ueransim-2.0.14.tgz
Source: Files/rapp1/rapp.zip
-Source: Files/Acm/instantiation.yaml
+Source: Files/Acm/definition/compositions.json
+Source: Files/Acm/instances/a1pms-instance.json
+Source: Files/Acm/instances/k8s-instance.json
+Source: Files/Acm/instances/kserve-instance.json
+Source: Files/Dme/infoconsumers/json-file-consumer.json
+Source: Files/Dme/infoconsumers/xml-file-consumer.json
+Source: Files/Dme/infoproducers/json-file-data-producer.json
+Source: Files/Dme/infoproducers/xml-file-data-producer.json
+Source: Files/Dme/infotypes/json-file-data-from-filestore.json
+Source: Files/Dme/infotypes/xml-file-data-from-filestore.json
+Source: Files/Sme/invokers/invoker-app1.json
+Source: Files/Sme/invokers/invoker-app2.json
+Source: Files/Sme/provider/aef-provider-function.json
+Source: Files/Sme/provider/amf-provider-function.json
+Source: Files/Sme/provider/apf-provider-function.json
+Source: Files/Sme/provider/gateway-provider-function.json
+Source: Files/Sme/serviceapis/api-set-1.json
+Source: Files/Sme/serviceapis/api-set-2.json
non_mano_artifact_sets:
onap_ves_events:
diff --git a/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/RappInstanceControllerTest.java b/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/RappInstanceControllerTest.java
index d6ba4ce..9eb959a 100755
--- a/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/RappInstanceControllerTest.java
+++ b/rapp-manager-application/src/test/java/com/oransc/rappmanager/rest/RappInstanceControllerTest.java
@@ -8,6 +8,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
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;
@@ -49,6 +50,9 @@ class RappInstanceControllerTest {
@MockBean
SmeDeployer smeDeployer;
+ @MockBean
+ DmeDeployer dmeDeployer;
+
@MockBean
SmeLifecycleManager smeLifecycleManager;
@@ -146,6 +150,7 @@ class RappInstanceControllerTest {
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)))
@@ -164,6 +169,7 @@ class RappInstanceControllerTest {
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)))
@@ -176,6 +182,7 @@ class RappInstanceControllerTest {
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)))
@@ -194,6 +201,7 @@ class RappInstanceControllerTest {
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)))
@@ -212,6 +220,7 @@ class RappInstanceControllerTest {
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)))
@@ -226,6 +235,7 @@ class RappInstanceControllerTest {
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)))
diff --git a/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappServiceTest.java b/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappServiceTest.java
index dbb3da7..c50f0b4 100755
--- a/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappServiceTest.java
+++ b/rapp-manager-application/src/test/java/com/oransc/rappmanager/service/RappServiceTest.java
@@ -5,6 +5,7 @@ import static org.mockito.ArgumentMatchers.any;
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;
@@ -34,6 +35,9 @@ class RappServiceTest {
@MockBean
SmeDeployer smeDeployer;
+ @MockBean
+ DmeDeployer dmeDeployer;
+
@MockBean
SmeLifecycleManager smeLifecycleManager;
@@ -44,15 +48,15 @@ class RappServiceTest {
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
@@ -67,23 +71,49 @@ class RappServiceTest {
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
@@ -91,14 +121,16 @@ class RappServiceTest {
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
@@ -109,6 +141,7 @@ class RappServiceTest {
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());
}
@@ -120,6 +153,19 @@ class RappServiceTest {
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());
}
@@ -132,6 +178,7 @@ class RappServiceTest {
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());
}
@@ -144,6 +191,20 @@ class RappServiceTest {
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());
}
@@ -156,6 +217,7 @@ class RappServiceTest {
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());
}
}
diff --git a/rapp-manager-dme/pom.xml b/rapp-manager-dme/pom.xml
new file mode 100755
index 0000000..6b8e83f
--- /dev/null
+++ b/rapp-manager-dme/pom.xml
@@ -0,0 +1,106 @@
+
+
+
+ 4.0.0
+
+ org.o-ran-sc.nonrtric.plt
+ rappmanager
+ 0.0.1-SNAPSHOT
+
+
+ org.o-ran-sc.nonrtric.plt.rappmanager
+ rapp-manager-dme
+
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ org.o-ran-sc.nonrtric.plt.rappmanager
+ rapp-manager-models
+ ${project.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.openapitools
+ jackson-databind-nullable
+ ${openapi.jackson.databind.nullable.version}
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.openapitools
+ openapi-generator-maven-plugin
+ ${openapi.maven.version}
+
+
+ dme-spec-generator
+
+ generate
+
+
+ ${project.basedir}/src/main/resources/openapi/ics-api.yaml
+ java
+ resttemplate
+ false
+ false
+ false
+ false
+ true
+
+ apiNameSuffix=ApiClient
+
+
+ src/main/java
+ true
+ com.oransc.rappmanager.dme
+ com.oransc.rappmanager.dme.rest
+ com.oransc.rappmanager.dme.data
+ false
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rapp-manager-dme/src/main/java/com/oransc/rappmanager/dme/configuration/DmeConfiguration.java b/rapp-manager-dme/src/main/java/com/oransc/rappmanager/dme/configuration/DmeConfiguration.java
new file mode 100755
index 0000000..e7cc151
--- /dev/null
+++ b/rapp-manager-dme/src/main/java/com/oransc/rappmanager/dme/configuration/DmeConfiguration.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2023 Nordix Foundation. All rights reserved.
+ * ===============================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END========================================================================
+ */
+
+package com.oransc.rappmanager.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;
+}
diff --git a/rapp-manager-dme/src/main/java/com/oransc/rappmanager/dme/service/DmeDeployer.java b/rapp-manager-dme/src/main/java/com/oransc/rappmanager/dme/service/DmeDeployer.java
new file mode 100755
index 0000000..388a565
--- /dev/null
+++ b/rapp-manager-dme/src/main/java/com/oransc/rappmanager/dme/service/DmeDeployer.java
@@ -0,0 +1,230 @@
+/*-
+ * ============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 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 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 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 infoTypes) {
+ logger.debug("Creating DME info types {} for rApp {}", infoTypes, rApp.getRappId());
+ try {
+ Map 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
Data consumer API
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:
Querying
+ of available types of data to consume.
Management of data subscription
+ jobs
Optional callback API provided by consumers to get notification on
+ added and removed information types.
Service status
This
+ API provides a means to monitor the health of this service.
+ 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. 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: ENABLED: one or several producers for
+ the information type are available 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: REGISTERED: the information type has
+ been registered 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: ENABLED: the A1-EI
+ producer is able to deliver EI result for the EI job 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: ENABLED: the A1-Information producer
+ is able to deliver result for the Information Job 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
diff --git a/rapp-manager-dme/src/test/java/com/oransc/rappmanager/dme/service/BeanTestConfiguration.java b/rapp-manager-dme/src/test/java/com/oransc/rappmanager/dme/service/BeanTestConfiguration.java
new file mode 100755
index 0000000..d22e939
--- /dev/null
+++ b/rapp-manager-dme/src/test/java/com/oransc/rappmanager/dme/service/BeanTestConfiguration.java
@@ -0,0 +1,78 @@
+/*-
+ * ============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);
+ }
+}
diff --git a/rapp-manager-dme/src/test/java/com/oransc/rappmanager/dme/service/DmeDeployerTest.java b/rapp-manager-dme/src/test/java/com/oransc/rappmanager/dme/service/DmeDeployerTest.java
new file mode 100755
index 0000000..5b97b2d
--- /dev/null
+++ b/rapp-manager-dme/src/test/java/com/oransc/rappmanager/dme/service/DmeDeployerTest.java
@@ -0,0 +1,350 @@
+/*-
+ * ============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 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 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 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 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 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 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));
+ }
+ }
+
+}
diff --git a/rapp-manager-dme/src/test/java/com/oransc/rappmanager/models/rapp/RappDmeResourceBuilder.java b/rapp-manager-dme/src/test/java/com/oransc/rappmanager/models/rapp/RappDmeResourceBuilder.java
new file mode 100755
index 0000000..c12d981
--- /dev/null
+++ b/rapp-manager-dme/src/test/java/com/oransc/rappmanager/models/rapp/RappDmeResourceBuilder.java
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2023 Nordix Foundation. All rights reserved.
+ * ===============================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END========================================================================
+ */
+
+package com.oransc.rappmanager.models.rapp;
+
+import 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;
+ }
+}
diff --git a/rapp-manager-dme/src/test/resources/application.yaml b/rapp-manager-dme/src/test/resources/application.yaml
new file mode 100755
index 0000000..3c53841
--- /dev/null
+++ b/rapp-manager-dme/src/test/resources/application.yaml
@@ -0,0 +1,3 @@
+rappmanager:
+ dme:
+ baseurl: http://localhost:39390
diff --git a/rapp-manager-dme/src/test/resources/valid-rapp-package-new-info-type.csar b/rapp-manager-dme/src/test/resources/valid-rapp-package-new-info-type.csar
new file mode 100755
index 0000000..67ae27c
Binary files /dev/null and b/rapp-manager-dme/src/test/resources/valid-rapp-package-new-info-type.csar differ
diff --git a/rapp-manager-dme/src/test/resources/valid-rapp-package.csar b/rapp-manager-dme/src/test/resources/valid-rapp-package.csar
new file mode 100755
index 0000000..b3d75b2
Binary files /dev/null and b/rapp-manager-dme/src/test/resources/valid-rapp-package.csar differ
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandler.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandler.java
index 73c644e..05bf056 100755
--- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandler.java
+++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandler.java
@@ -47,11 +47,12 @@ public class RappCsarConfigurationHandler {
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) {
@@ -88,7 +89,7 @@ public class RappCsarConfigurationHandler {
}
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();
}
@@ -136,6 +137,18 @@ public class RappCsarConfigurationHandler {
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";
}
@@ -152,6 +165,10 @@ public class RappCsarConfigurationHandler {
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);
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/Rapp.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/Rapp.java
index 0aac806..a845fac 100755
--- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/Rapp.java
+++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/Rapp.java
@@ -41,4 +41,5 @@ public class Rapp {
Map rappInstances = new HashMap<>();
UUID compositionId;
+ Boolean isDmeValid;
}
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappEvent.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappEvent.java
index 1bdc67d..7cb00be 100755
--- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappEvent.java
+++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappEvent.java
@@ -28,5 +28,9 @@ public enum RappEvent {
ACMUNDEPLOYED,
SMEUNDEPLOYED,
ACMUNDEPLOYFAILED,
- SMEUNDEPLOYFAILED
+ SMEUNDEPLOYFAILED,
+ DMEDEPLOYED,
+ DMEDEPLOYFAILED,
+ DMEUNDEPLOYED,
+ DMEUNDEPLOYFAILED
}
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappResources.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappResources.java
index a3033e2..d9344e4 100755
--- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappResources.java
+++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rapp/RappResources.java
@@ -27,6 +27,7 @@ public class RappResources {
ACMResources acm;
SMEResources sme;
+ DMEResources dme;
@Data
@Builder
@@ -44,4 +45,13 @@ public class RappResources {
Set serviceApis;
Set invokers;
}
+
+ @Data
+ @Builder
+ public static class DMEResources {
+
+ Set infoTypes;
+ Set infoProducers;
+ Set infoConsumers;
+ }
}
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappDMEInstance.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappDMEInstance.java
new file mode 100755
index 0000000..bd1d19d
--- /dev/null
+++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappDMEInstance.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2023 Nordix Foundation. All rights reserved.
+ * ===============================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END========================================================================
+ */
+
+package com.oransc.rappmanager.models.rappinstance;
+
+import java.util.Set;
+import lombok.Data;
+
+@Data
+public class RappDMEInstance {
+
+ Set infoTypesProducer;
+ String infoProducer;
+ String infoTypeConsumer;
+ String infoConsumer;
+}
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstance.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstance.java
index b5e54a7..39d2709 100755
--- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstance.java
+++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/rappinstance/RappInstance.java
@@ -28,4 +28,5 @@ public class RappInstance {
RappInstanceState state = RappInstanceState.UNDEPLOYED;
RappACMInstance acm;
RappSMEInstance sme;
+ RappDMEInstance dme;
}
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfig.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfig.java
index e1bc784..34c9a92 100755
--- a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfig.java
+++ b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfig.java
@@ -57,12 +57,18 @@ public class RappInstanceStateMachineConfig extends EnumStateMachineConfigurerAd
.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()
@@ -74,12 +80,20 @@ public class RappInstanceStateMachineConfig extends EnumStateMachineConfigurerAd
.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());
}
@@ -90,7 +104,8 @@ public class RappInstanceStateMachineConfig extends EnumStateMachineConfigurerAd
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;
};
}
@@ -99,7 +114,8 @@ public class RappInstanceStateMachineConfig extends EnumStateMachineConfigurerAd
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;
};
}
}
diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java
index 0a18ec4..d5e8d42 100755
--- a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java
+++ b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java
@@ -22,11 +22,14 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
+import 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;
@@ -74,6 +77,18 @@ class RappCsarConfigurationHandlerTest {
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();
@@ -99,6 +114,13 @@ class RappCsarConfigurationHandlerTest {
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();
@@ -108,10 +130,13 @@ class RappCsarConfigurationHandlerTest {
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
@@ -122,6 +147,7 @@ class RappCsarConfigurationHandlerTest {
assertThat(rappResources).isNotNull();
assertNull(rappResources.getAcm());
assertNull(rappResources.getSme());
+ assertNull(rappResources.getDme());
}
@Test
@@ -187,4 +213,43 @@ class RappCsarConfigurationHandlerTest {
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);
+ }
+
}
diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfigTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfigTest.java
index 59d5c94..4657c76 100755
--- a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfigTest.java
+++ b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/statemachine/RappInstanceStateMachineConfigTest.java
@@ -75,7 +75,7 @@ class RappInstanceStateMachineConfigTest {
}
@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.builder().stateMachine(stateMachine).step()
@@ -92,23 +92,51 @@ class RappInstanceStateMachineConfigTest {
.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.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.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.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 =
@@ -116,21 +144,23 @@ class RappInstanceStateMachineConfigTest {
.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.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();
@@ -144,26 +174,64 @@ class RappInstanceStateMachineConfigTest {
.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.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.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.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();
+ }
}
diff --git a/rapp-manager-models/src/test/resources/valid-rapp-package.csar b/rapp-manager-models/src/test/resources/valid-rapp-package.csar
index b8b36e3..b3d75b2 100755
Binary files a/rapp-manager-models/src/test/resources/valid-rapp-package.csar and b/rapp-manager-models/src/test/resources/valid-rapp-package.csar differ
diff --git a/rapp-manager-sme/src/main/java/com/oransc/rappmanager/sme/service/SmeDeployer.java b/rapp-manager-sme/src/main/java/com/oransc/rappmanager/sme/service/SmeDeployer.java
index 1760e9c..fc42f4d 100755
--- a/rapp-manager-sme/src/main/java/com/oransc/rappmanager/sme/service/SmeDeployer.java
+++ b/rapp-manager-sme/src/main/java/com/oransc/rappmanager/sme/service/SmeDeployer.java
@@ -21,12 +21,11 @@ package com.oransc.rappmanager.sme.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.oransc.rappmanager.models.rapp.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;
@@ -49,6 +48,7 @@ public class SmeDeployer implements RappDeployer {
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;
@@ -57,8 +57,6 @@ public class SmeDeployer implements RappDeployer {
private final ObjectMapper objectMapper;
- private final RappCacheService rappCacheService;
-
private final RappInstanceStateMachine rappInstanceStateMachine;
private String amfRegistrationId;
@@ -131,7 +129,7 @@ public class SmeDeployer implements RappDeployer {
@Override
public boolean deprimeRapp(Rapp rapp) {
- //If there is any deprimgng operations
+ //If there is any depriming operations
return true;
}
@@ -190,7 +188,8 @@ public class SmeDeployer implements RappDeployer {
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);