A1-PMS, make service id optional in PUT Policy 82/132482/2
authorPatrikBuhr <patrik.buhr@est.tech>
Mon, 28 Nov 2022 08:40:36 +0000 (09:40 +0100)
committerPatrik Buhr <patrik.buhr@est.tech>
Tue, 6 Dec 2022 14:44:33 +0000 (14:44 +0000)
Improved API documentation.

Fixed a bug that lead to that a policy could be connected to several services if the service_id was changed.

Change-Id: I211f5db32747fc912b7ba85bfbc15ce50ee725dd
Issue-ID: CCSDK-3819
Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
a1-policy-management/api/pms-api.json
a1-policy-management/api/pms-api.yaml
a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/SwaggerConfig.java
a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyInfo.java
a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceController.java
a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ServiceRegistrationInfo.java
a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/repository/Policies.java
a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java
docs/offeredapis/swagger/pms-api.json
docs/offeredapis/swagger/pms-api.yaml

index a81070f..ce2d9aa 100644 (file)
                 "policy_data",
                 "policy_id",
                 "policytype_id",
-                "ric_id",
-                "service_id"
+                "ric_id"
             ],
             "properties": {
                 "ric_id": {
                     "example": null
                 },
                 "transient": {
+                    "default": false,
                     "description": "if true, the policy is deleted at RIC restart. If false, its value is maintained by this service until explicitly deleted. Default false.",
                     "type": "boolean",
-                    "example": null
+                    "example": false
                 },
                 "service_id": {
-                    "description": "the identity of the service owning the policy",
+                    "description": "the identity of the service owning the policy. This can be used to group the policies (it is possible to get all policies associated to a service). Note that the service does not need to be registerred.",
                     "type": "string",
                     "example": null
                 },
                     }},
                     "required": true
                 },
-                "description": "Registering a service is needed to:<ul><li>Get callbacks.<\/li><li>Activate supervision of the service. If a service is inactive, its policies will be deleted.<\/li><\/ul>",
+                "description": "Registering a service is needed to:<ul><li>Get callbacks about available NearRT RICs.<\/li><li>Activate supervision of the service. If a service is inactive, its policies will automatically be deleted.<\/li><\/ul>Policies can be created even if the service is not registerred. This is a feature which it is optional to use.",
                 "operationId": "putService",
                 "responses": {
                     "200": {
             "name": "Copyright (C) 2020-2022 Nordix Foundation. Licensed under the Apache License.",
             "url": "http://www.apache.org/licenses/LICENSE-2.0"
         },
-        "description": "<h2>General<\/h2><p>The O-RAN Non-RT RIC Policy Management Service provides a REST API for management of A1 policies. <br/>The main tasks of the service are:<\/p><ul><li>A1 Policy creation, modification and deletion.<\/li><li>Monitoring and maintaining consistency of the SMO view of A1 policies and the Near-RT RICs<\/li><li>Maintaining a view of supported Near-RT RIC policy types<\/li><li>Supervision of using services (R-APPs). When a service is unavailable, its policies are removed.<\/li><\/ul><h2>APIs provided by the service<\/h2><h3>A1 Policy Management<\/h3><p>This is an API for management of A1 Policies.<\/p><ul><li>A1 Policy retrieval, creation, modification and deletion.<\/li><li>Retrieval of supported A1 Policy types for a Near-RT RIC<\/li><li>Retrieval of status for existing A1 policies<\/li><\/ul><h3>Management of configuration<\/h3><p>API for updating and retrieval of the component configuration. Note that there other ways to maintain the configuration.<\/p><h3>Callbacks<\/h3><p>These are endpoints that are invoked by this service. The callbacks are registered in this service at service registration.<\/p><h3>NearRT-RIC Repository<\/h3><p>This is an API that provides support for looking up a NearRT-RIC. Each A1 policy is targeted for one Near-RT RIC.<\/p><h3>Health Check<\/h3><p>API used for supervision of the PMS component.<\/p><h3>Service Registry and Supervision<\/h3><p>API used for registering services that uses PMS. Each A1 policy is owned by a service. PMS can supervise each registered service and will automatically remove policies for unavailable services.<\/p>",
+        "description": "<h2>General<\/h2><p>The O-RAN Non-RT RIC Policy Management Service provides a REST API for management of A1 policies. <br/>The main tasks of the service are:<\/p><ul><li>A1 Policy creation, modification and deletion.<\/li><li>Monitoring and maintaining consistency of the SMO view of A1 policies and the Near-RT RICs<\/li><li>Maintaining a view of supported Near-RT RIC policy types<\/li><li>Supervision of using services (R-APPs). When a service is unavailable, its policies are removed.<\/li><\/ul><h2>APIs provided by the service<\/h2><h3>A1 Policy Management<\/h3><p>This is an API for management of A1 Policies.<\/p><ul><li>A1 Policy retrieval, creation, modification and deletion.<\/li><li>Retrieval of supported A1 Policy types for a Near-RT RIC<\/li><li>Retrieval of status for existing A1 policies<\/li><\/ul><h3>Management of configuration<\/h3><p>API for updating and retrieval of the component configuration. Note that there other ways to maintain the configuration.<\/p><h3>Callbacks<\/h3><p>These are endpoints that are invoked by this service. The callbacks are registered in this service at service registration.<\/p><h3>NearRT-RIC Repository<\/h3><p>This is an API that provides support for looking up a NearRT-RIC. Each A1 policy is targeted for one Near-RT RIC.<\/p><h3>Health Check<\/h3><p>API used for supervision of the PMS component.<\/p><h3>Service Registry and Supervision<\/h3><p>API used for registering services that uses PMS. Each A1 policy is optionally owned by a service. PMS can supervise each registered service by a heart-beat supervision and will automatically remove policies for unavailable services. Note that a service does not need to be registered in order to create A1 Policies. This is a feature that is optional to use.<\/p>",
         "title": "A1 Policy Management Service",
         "version": "1.1.0"
     },
index 1f84399..6d620c2 100644 (file)
@@ -18,8 +18,10 @@ info:
     provides support for looking up a NearRT-RIC. Each A1 policy is targeted for one
     Near-RT RIC.</p><h3>Health Check</h3><p>API used for supervision of the PMS component.</p><h3>Service
     Registry and Supervision</h3><p>API used for registering services that uses PMS.
-    Each A1 policy is owned by a service. PMS can supervise each registered service
-    and will automatically remove policies for unavailable services.</p>
+    Each A1 policy is optionally owned by a service. PMS can supervise each registered
+    service by a heart-beat supervision and will automatically remove policies for
+    unavailable services. Note that a service does not need to be registered in order
+    to create A1 Policies. This is a feature that is optional to use.</p>
   license:
     name: Copyright (C) 2020-2022 Nordix Foundation. Licensed under the Apache License.
     url: http://www.apache.org/licenses/LICENSE-2.0
@@ -539,9 +541,11 @@ paths:
       tags:
       - Service Registry and Supervision
       summary: Register a service
-      description: Registering a service is needed to:<ul><li>Get callbacks.</li><li>Activate
-        supervision of the service. If a service is inactive, its policies will be
-        deleted.</li></ul>
+      description: Registering a service is needed to:<ul><li>Get callbacks about
+        available NearRT RICs.</li><li>Activate supervision of the service. If a service
+        is inactive, its policies will automatically be deleted.</li></ul>Policies
+        can be created even if the service is not registerred. This is a feature which
+        it is optional to use.
       operationId: putService
       requestBody:
         content:
@@ -977,7 +981,6 @@ components:
       - policy_id
       - policytype_id
       - ric_id
-      - service_id
       type: object
       properties:
         ric_id:
@@ -991,9 +994,13 @@ components:
           description: if true, the policy is deleted at RIC restart. If false, its
             value is maintained by this service until explicitly deleted. Default
             false.
+          example: false
+          default: false
         service_id:
           type: string
-          description: the identity of the service owning the policy
+          description: the identity of the service owning the policy. This can be
+            used to group the policies (it is possible to get all policies associated
+            to a service). Note that the service does not need to be registerred.
         policy_data:
           type: object
           description: the configuration of the policy
index 4e4ec2d..4c3a0c7 100644 (file)
@@ -83,7 +83,10 @@ public class SwaggerConfig {
             + H3 + StatusController.API_NAME + H3_END + //
             "<p>API used for supervision of the PMS component.</p>" + //
             H3 + ServiceController.API_NAME + H3_END + //
-            "<p>API used for registering services that uses PMS. Each A1 policy is owned by a service. PMS can supervise each registered service and will automatically remove policies for unavailable services.</p>";
+            "<p>" + "API used for registering services that uses PMS."
+            + " Each A1 policy is optionally owned by a service. PMS can supervise each registered service by a heart-beat supervision and will automatically remove policies for unavailable services."
+            + " Note that a service does not need to be registered in order to create A1 Policies. This is a feature that is optional to use."
+            + "</p>";
 
     public static final String VERSION = "1.1.0";
 }
index 55a9343..a3870b2 100644 (file)
@@ -48,19 +48,24 @@ public class PolicyInfo {
     @SerializedName("policy_data")
     public Object policyData;
 
-    @Schema(name = "service_id", description = "the identity of the service owning the policy", required = true)
-    @JsonProperty(value = "service_id", required = true)
+    private static final String SERVICE_ID_DESCRIPTION = "the identity of the service owning the policy."
+            + " This can be used to group the policies (it is possible to get all policies associated to a service)."
+            + " Note that the service does not need to be registerred.";
+
+    @Schema(name = "service_id", description = SERVICE_ID_DESCRIPTION, required = false, defaultValue = "")
+    @JsonProperty(value = "service_id", required = false)
     @SerializedName("service_id")
-    public String serviceId;
+    public String serviceId = "";
 
     @Schema(name = "transient",
             description = "if true, the policy is deleted at RIC restart. If false, its value is maintained by this service until explicitly deleted. Default false.",
-            required = false)
+            required = false, defaultValue = "false", example = "false")
     @JsonProperty(value = "transient", required = false, defaultValue = "false")
     @SerializedName("transient")
     public boolean isTransient = false;
 
-    @Schema(name = "status_notification_uri", description = "Callback URI for policy status updates", required = false)
+    @Schema(name = "status_notification_uri", description = "Callback URI for policy status updates", required = false,
+            defaultValue = "")
     @JsonProperty(value = "status_notification_uri", required = false)
     @SerializedName("status_notification_uri")
     public String statusNotificationUri = "";
index faa152c..c3f4176 100644 (file)
@@ -128,10 +128,10 @@ public class ServiceController {
 
     private static final String REGISTER_SERVICE_DETAILS = "Registering a service is needed to:" //
             + "<ul>" //
-            + "<li>Get callbacks.</li>" //
-            + "<li>Activate supervision of the service. If a service is inactive, its policies will be deleted.</li>"//
+            + "<li>Get callbacks about available NearRT RICs.</li>" //
+            + "<li>Activate supervision of the service. If a service is inactive, its policies will automatically be deleted.</li>"//
             + "</ul>" //
-    ;
+            + "Policies can be created even if the service is not registerred. This is a feature which it is optional to use.";
 
     @PutMapping(Consts.V2_API_ROOT + "/services")
     @Operation(summary = "Register a service", description = REGISTER_SERVICE_DETAILS)
index 0f975c2..c016b6f 100644 (file)
@@ -42,7 +42,7 @@ public class ServiceRegistrationInfo {
     @JsonProperty("keep_alive_interval_seconds")
     public long keepAliveIntervalSeconds = 0;
 
-    @Schema(description = "callback for notifying of Near-RT RIC state changes", required = false)
+    @Schema(description = "callback for notifying of Near-RT RIC state changes", required = false, defaultValue = "")
     @SerializedName("callback_url")
     @JsonProperty("callback_url")
     public String callbackUrl = "";
index 09f59ca..6161fbd 100644 (file)
@@ -97,6 +97,11 @@ public class Policies {
     }
 
     public synchronized void put(Policy policy) {
+        Policy previousDef = this.get(policy.getId());
+        if (previousDef != null) {
+            removeFromMaps(previousDef);
+        }
+
         policiesId.put(policy.getId(), policy);
         policiesRic.put(policy.getRic().id(), policy.getId(), policy);
         policiesService.put(policy.getOwnerServiceId(), policy.getId(), policy);
@@ -150,10 +155,7 @@ public class Policies {
         if (!policy.isTransient()) {
             dataStore.deleteObject(getPath(policy)).subscribe();
         }
-        policiesId.remove(policy.getId());
-        policiesRic.remove(policy.getRic().id(), policy.getId());
-        policiesService.remove(policy.getOwnerServiceId(), policy.getId());
-        policiesType.remove(policy.getType().getId(), policy.getId());
+        removeFromMaps(policy);
     }
 
     public synchronized void removePoliciesForRic(String ricId) {
@@ -189,7 +191,7 @@ public class Policies {
         dataStore.deleteAllObjects().onErrorResume(t -> Mono.empty()).subscribe();
     }
 
-    public void store(Policy policy) {
+    private void store(Policy policy) {
 
         byte[] bytes = gson.toJson(toStorageObject(policy)).getBytes();
         this.dataStore.writeObject(this.getPath(policy), bytes) //
@@ -197,6 +199,13 @@ public class Policies {
                 .subscribe();
     }
 
+    private void removeFromMaps(Policy policy) {
+        policiesId.remove(policy.getId());
+        policiesRic.remove(policy.getRic().id(), policy.getId());
+        policiesService.remove(policy.getOwnerServiceId(), policy.getId());
+        policiesType.remove(policy.getType().getId(), policy.getId());
+    }
+
     private boolean isMatch(String filterValue, String actualValue) {
         return filterValue == null || actualValue.equals(filterValue);
     }
index 76838bb..bec5573 100644 (file)
@@ -434,7 +434,7 @@ class ApplicationTest {
     }
 
     private String putPolicyBody(String serviceName, String ricId, String policyTypeName, String policyInstanceId,
-            boolean isTransient) {
+            boolean isTransient, String statusNotificationUri) {
         PolicyInfo info = new PolicyInfo();
         info.policyId = policyInstanceId;
         info.policyTypeId = policyTypeName;
@@ -445,12 +445,12 @@ class ApplicationTest {
         if (isTransient) {
             info.isTransient = isTransient;
         }
-        info.statusNotificationUri = "statusNotificationUri";
+        info.statusNotificationUri = statusNotificationUri;
         return gson.toJson(info);
     }
 
     private String putPolicyBody(String serviceName, String ricId, String policyTypeName, String policyInstanceId) {
-        return putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId, false);
+        return putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId, false, "statusUri");
     }
 
     @Test
@@ -465,7 +465,7 @@ class ApplicationTest {
 
         // PUT a transient policy
         String url = "/policies";
-        String policyBody = putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId, true);
+        String policyBody = putPolicyBody(serviceName, ricId, policyTypeName, policyInstanceId, true, "statusNotif");
         this.rics.getRic(ricId).setState(Ric.RicState.AVAILABLE);
 
         restClient().put(url, policyBody).block();
@@ -506,6 +506,27 @@ class ApplicationTest {
         this.rics.getRic(ricId).setState(Ric.RicState.AVAILABLE);
     }
 
+    @Test
+    void testPutPolicy_NoServiceNoStatusUri() throws Exception {
+        String ricId = "ric.1";
+        String policyTypeName = "type1_1.2.3";
+        String policyInstanceId = "instance_1.2.3";
+
+        addPolicyType(policyTypeName, ricId);
+
+        // PUT a transient policy
+        String url = "/policies";
+        String policyBody = putPolicyBody(null, ricId, policyTypeName, policyInstanceId, true, null);
+        this.rics.getRic(ricId).setState(Ric.RicState.AVAILABLE);
+
+        restClient().put(url, policyBody).block();
+
+        Policy policy = policies.getPolicy(policyInstanceId);
+        assertThat(policy).isNotNull();
+        assertThat(policy.getOwnerServiceId()).isBlank();
+        assertThat(policy.getStatusNotificationUri()).isBlank();
+    }
+
     @Test
     /**
      * Test that HttpStatus and body from failing REST call to A1 is passed on to
@@ -553,6 +574,25 @@ class ApplicationTest {
         assertThat(policyInfo.policyTypeId).isEmpty();
     }
 
+    @Test
+    void testUpdateService() throws Exception {
+        this.addRic("ric1");
+        this.addPolicy("p", "type1", "", "ric1");
+
+        String url = "/policies?service_id=";
+        String resp = restClient().get(url).block();
+        assertThat(resp).contains("[\"p\"]");
+
+        this.addPolicy("p", "type1", "service", "ric1");
+        url = "/policies?service_id=";
+        resp = restClient().get(url).block();
+        assertThat(resp).contains("[]");
+
+        url = "/policies?service_id=service";
+        resp = restClient().get(url).block();
+        assertThat(resp).contains("[\"p\"]");
+    }
+
     @Test
     void testRefuseToUpdatePolicy() throws Exception {
         // Test that only the json can be changed for a already created policy
index a81070f..ce2d9aa 100644 (file)
                 "policy_data",
                 "policy_id",
                 "policytype_id",
-                "ric_id",
-                "service_id"
+                "ric_id"
             ],
             "properties": {
                 "ric_id": {
                     "example": null
                 },
                 "transient": {
+                    "default": false,
                     "description": "if true, the policy is deleted at RIC restart. If false, its value is maintained by this service until explicitly deleted. Default false.",
                     "type": "boolean",
-                    "example": null
+                    "example": false
                 },
                 "service_id": {
-                    "description": "the identity of the service owning the policy",
+                    "description": "the identity of the service owning the policy. This can be used to group the policies (it is possible to get all policies associated to a service). Note that the service does not need to be registerred.",
                     "type": "string",
                     "example": null
                 },
                     }},
                     "required": true
                 },
-                "description": "Registering a service is needed to:<ul><li>Get callbacks.<\/li><li>Activate supervision of the service. If a service is inactive, its policies will be deleted.<\/li><\/ul>",
+                "description": "Registering a service is needed to:<ul><li>Get callbacks about available NearRT RICs.<\/li><li>Activate supervision of the service. If a service is inactive, its policies will automatically be deleted.<\/li><\/ul>Policies can be created even if the service is not registerred. This is a feature which it is optional to use.",
                 "operationId": "putService",
                 "responses": {
                     "200": {
             "name": "Copyright (C) 2020-2022 Nordix Foundation. Licensed under the Apache License.",
             "url": "http://www.apache.org/licenses/LICENSE-2.0"
         },
-        "description": "<h2>General<\/h2><p>The O-RAN Non-RT RIC Policy Management Service provides a REST API for management of A1 policies. <br/>The main tasks of the service are:<\/p><ul><li>A1 Policy creation, modification and deletion.<\/li><li>Monitoring and maintaining consistency of the SMO view of A1 policies and the Near-RT RICs<\/li><li>Maintaining a view of supported Near-RT RIC policy types<\/li><li>Supervision of using services (R-APPs). When a service is unavailable, its policies are removed.<\/li><\/ul><h2>APIs provided by the service<\/h2><h3>A1 Policy Management<\/h3><p>This is an API for management of A1 Policies.<\/p><ul><li>A1 Policy retrieval, creation, modification and deletion.<\/li><li>Retrieval of supported A1 Policy types for a Near-RT RIC<\/li><li>Retrieval of status for existing A1 policies<\/li><\/ul><h3>Management of configuration<\/h3><p>API for updating and retrieval of the component configuration. Note that there other ways to maintain the configuration.<\/p><h3>Callbacks<\/h3><p>These are endpoints that are invoked by this service. The callbacks are registered in this service at service registration.<\/p><h3>NearRT-RIC Repository<\/h3><p>This is an API that provides support for looking up a NearRT-RIC. Each A1 policy is targeted for one Near-RT RIC.<\/p><h3>Health Check<\/h3><p>API used for supervision of the PMS component.<\/p><h3>Service Registry and Supervision<\/h3><p>API used for registering services that uses PMS. Each A1 policy is owned by a service. PMS can supervise each registered service and will automatically remove policies for unavailable services.<\/p>",
+        "description": "<h2>General<\/h2><p>The O-RAN Non-RT RIC Policy Management Service provides a REST API for management of A1 policies. <br/>The main tasks of the service are:<\/p><ul><li>A1 Policy creation, modification and deletion.<\/li><li>Monitoring and maintaining consistency of the SMO view of A1 policies and the Near-RT RICs<\/li><li>Maintaining a view of supported Near-RT RIC policy types<\/li><li>Supervision of using services (R-APPs). When a service is unavailable, its policies are removed.<\/li><\/ul><h2>APIs provided by the service<\/h2><h3>A1 Policy Management<\/h3><p>This is an API for management of A1 Policies.<\/p><ul><li>A1 Policy retrieval, creation, modification and deletion.<\/li><li>Retrieval of supported A1 Policy types for a Near-RT RIC<\/li><li>Retrieval of status for existing A1 policies<\/li><\/ul><h3>Management of configuration<\/h3><p>API for updating and retrieval of the component configuration. Note that there other ways to maintain the configuration.<\/p><h3>Callbacks<\/h3><p>These are endpoints that are invoked by this service. The callbacks are registered in this service at service registration.<\/p><h3>NearRT-RIC Repository<\/h3><p>This is an API that provides support for looking up a NearRT-RIC. Each A1 policy is targeted for one Near-RT RIC.<\/p><h3>Health Check<\/h3><p>API used for supervision of the PMS component.<\/p><h3>Service Registry and Supervision<\/h3><p>API used for registering services that uses PMS. Each A1 policy is optionally owned by a service. PMS can supervise each registered service by a heart-beat supervision and will automatically remove policies for unavailable services. Note that a service does not need to be registered in order to create A1 Policies. This is a feature that is optional to use.<\/p>",
         "title": "A1 Policy Management Service",
         "version": "1.1.0"
     },
index 1f84399..6d620c2 100644 (file)
@@ -18,8 +18,10 @@ info:
     provides support for looking up a NearRT-RIC. Each A1 policy is targeted for one
     Near-RT RIC.</p><h3>Health Check</h3><p>API used for supervision of the PMS component.</p><h3>Service
     Registry and Supervision</h3><p>API used for registering services that uses PMS.
-    Each A1 policy is owned by a service. PMS can supervise each registered service
-    and will automatically remove policies for unavailable services.</p>
+    Each A1 policy is optionally owned by a service. PMS can supervise each registered
+    service by a heart-beat supervision and will automatically remove policies for
+    unavailable services. Note that a service does not need to be registered in order
+    to create A1 Policies. This is a feature that is optional to use.</p>
   license:
     name: Copyright (C) 2020-2022 Nordix Foundation. Licensed under the Apache License.
     url: http://www.apache.org/licenses/LICENSE-2.0
@@ -539,9 +541,11 @@ paths:
       tags:
       - Service Registry and Supervision
       summary: Register a service
-      description: Registering a service is needed to:<ul><li>Get callbacks.</li><li>Activate
-        supervision of the service. If a service is inactive, its policies will be
-        deleted.</li></ul>
+      description: Registering a service is needed to:<ul><li>Get callbacks about
+        available NearRT RICs.</li><li>Activate supervision of the service. If a service
+        is inactive, its policies will automatically be deleted.</li></ul>Policies
+        can be created even if the service is not registerred. This is a feature which
+        it is optional to use.
       operationId: putService
       requestBody:
         content:
@@ -977,7 +981,6 @@ components:
       - policy_id
       - policytype_id
       - ric_id
-      - service_id
       type: object
       properties:
         ric_id:
@@ -991,9 +994,13 @@ components:
           description: if true, the policy is deleted at RIC restart. If false, its
             value is maintained by this service until explicitly deleted. Default
             false.
+          example: false
+          default: false
         service_id:
           type: string
-          description: the identity of the service owning the policy
+          description: the identity of the service owning the policy. This can be
+            used to group the policies (it is possible to get all policies associated
+            to a service). Note that the service does not need to be registerred.
         policy_data:
           type: object
           description: the configuration of the policy