Improved update of AAI information 09/127709/1
authorLukasz Rajewski <lukasz.rajewski@orange.com>
Fri, 11 Mar 2022 17:24:40 +0000 (18:24 +0100)
committerLukasz Rajewski <lukasz.rajewski@orange.com>
Fri, 11 Mar 2022 17:24:40 +0000 (18:24 +0100)
Split of create, delete and update bulk
operations to deal with AAI problems when
different types of bulk oeprations are mixed.

Issue-ID: SO-3845
Signed-off-by: Lukasz Rajewski <lukasz.rajewski@orange.com>
Change-Id: I547ba8fa4dc26753954f9174a9ce8149e6348731

so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/rest/SubscriptionNotifyController.java
so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/service/aai/AaiService.java
so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/util/AaiRepository.java
so-cnf-adapter-application/src/main/java/org/onap/so/adapters/cnf/util/IAaiRepository.java
so-cnf-adapter-application/src/test/java/org/onap/so/adapters/cnf/service/aai/AaiServiceTest.java

index 88df42b..b1a330f 100644 (file)
@@ -22,6 +22,7 @@ package org.onap.so.adapters.cnf.rest;
 
 
 import com.google.gson.Gson;
+import org.onap.aaiclient.client.graphinventory.exceptions.BulkProcessFailed;
 import org.onap.so.adapters.cnf.model.aai.AaiRequest;
 import org.onap.so.adapters.cnf.model.synchronization.NotificationRequest;
 import org.onap.so.adapters.cnf.service.aai.AaiService;
@@ -53,7 +54,7 @@ public class SubscriptionNotifyController {
 
     @PostMapping(value = "/api/cnf-adapter/v1/instance/{instanceId}/status/notify")
     public ResponseEntity subscriptionNotifyEndpoint(@PathVariable String instanceId,
-                                                     @RequestBody NotificationRequest body) throws BadResponseException {
+                                                     @RequestBody NotificationRequest body) throws BadResponseException, BulkProcessFailed {
         String subscriptionName = synchronizationService.getSubscriptionName(instanceId);
         boolean isSubscriptionActive = synchronizationService.isSubscriptionActive(subscriptionName);
         if (isSubscriptionActive) {
index ff454b8..2fd1502 100644 (file)
@@ -21,6 +21,7 @@
 
 package org.onap.so.adapters.cnf.service.aai;
 
+import org.onap.aaiclient.client.graphinventory.exceptions.BulkProcessFailed;
 import org.onap.so.adapters.cnf.AaiConfiguration;
 import org.onap.so.adapters.cnf.client.MulticloudClient;
 import org.onap.so.adapters.cnf.model.aai.AaiRequest;
@@ -50,7 +51,7 @@ public class AaiService {
         this.configuration = configuration;
     }
 
-    public void aaiUpdate(AaiRequest aaiRequest) throws BadResponseException {
+    public void aaiUpdate(AaiRequest aaiRequest) throws BadResponseException, BulkProcessFailed {
         List<KubernetesResource> k8sResList = parseStatus(aaiRequest);
         IAaiRepository aaiRepository = IAaiRepository.instance(configuration.isEnabled());
         k8sResList.forEach(status -> aaiRepository.update(status, aaiRequest));
@@ -58,7 +59,7 @@ public class AaiService {
         aaiRepository.commit(false);
     }
 
-    public void aaiDelete(AaiRequest aaiRequest) throws BadResponseException {
+    public void aaiDelete(AaiRequest aaiRequest) throws BulkProcessFailed {
         String instanceID = aaiRequest.getInstanceId();
         boolean enabled = configuration.isEnabled();
         if (instanceID == null || instanceID.isEmpty() || instanceID.equals("null")) {
index 3f89c53..05fc3a9 100644 (file)
@@ -32,8 +32,10 @@ import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder;
 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder.Types;
 import org.onap.aaiclient.client.generated.fluentbuilders.K8sResource;
 import org.onap.aaiclient.client.graphinventory.exceptions.BulkProcessFailed;
+import org.onap.so.adapters.cnf.exceptions.ApplicationException;
 import org.onap.so.adapters.cnf.model.aai.AaiRequest;
 import org.onap.so.adapters.cnf.service.aai.KubernetesResource;
+import org.onap.so.client.exception.BadResponseException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -45,17 +47,15 @@ import java.util.stream.Collectors;
 public class AaiRepository implements IAaiRepository {
     private final static Logger logger = LoggerFactory.getLogger(IAaiRepository.class);
 
-    private final AAIResourcesClient aaiClient;
-    private final ObjectMapper objectMapper;
     private final AAITransactionHelper aaiTransactionHelper;
+    private final ObjectMapper objectMapper;
 
     public static IAaiRepository instance() {
         return new AaiRepository();
     }
 
     private AaiRepository() {
-        aaiClient = new AAIResourcesClient(AAIVersion.LATEST);
-        aaiTransactionHelper = new AAITransactionHelper(aaiClient);
+        aaiTransactionHelper = new AAITransactionHelper();
         this.objectMapper = new ObjectMapper();
     }
 
@@ -64,7 +64,7 @@ public class AaiRepository implements IAaiRepository {
     }
 
     @Override
-    public void commit(boolean dryrun) {
+    public void commit(boolean dryrun) throws BulkProcessFailed {
         aaiTransactionHelper.execute(dryrun);
     }
 
@@ -80,6 +80,7 @@ public class AaiRepository implements IAaiRepository {
         AAIResourceUri k8sResourceUri =
                 AAIUriFactory.createResourceUri(k8sResource.build(), aaiRequest.getCloudOwner(), aaiRequest.getCloudRegion(), aaiRequest.getTenantId(), resource.getId());
 
+        AAIResourcesClient aaiClient = aaiTransactionHelper.getAaiClient();
         var k8sResourceInstance = aaiClient.get(k8sResourceUri);
         boolean updateK8sResource = true;
         if (!k8sResourceInstance.isEmpty()) {
@@ -100,7 +101,10 @@ public class AaiRepository implements IAaiRepository {
                 throw new RuntimeException(e);
             }
             logger.debug("K8s resource URI: " + k8sResourceUri + " with payload [" + payload + "]");
-            getTransaction().create(k8sResourceUri, payload);
+            if (resource.getResourceVersion() != null)
+                getTransaction().update(k8sResourceUri, payload);
+            else
+                getTransaction().create(k8sResourceUri, payload);
         }
 
         final String genericVnfId = aaiRequest.getGenericVnfId();
@@ -147,6 +151,8 @@ public class AaiRepository implements IAaiRepository {
 
         var vfModuleUri = AAIUriFactory.createResourceUri(
                 AAIFluentTypeBuilder.network().genericVnf(genericVnfId).vfModule(vfModuleId));
+
+        AAIResourcesClient aaiClient = aaiTransactionHelper.getAaiClient();
         var instance = aaiClient.get(vfModuleUri);
 
         if (instance.hasRelationshipsTo(Types.K8S_RESOURCE) && instance.getRelationships().isPresent()) {
@@ -174,13 +180,54 @@ public class AaiRepository implements IAaiRepository {
     }
 
     static class AAITransactionHelper {
-        private List<AAITransactionalClient> transactions;
         private final AAIResourcesClient aaiClient;
-        private int transactionCount;
+        private final AAITransactionStore createStore;
+        private final AAITransactionStore updateStore;
+        private final AAITransactionStore deleteStore;
+
+        AAITransactionHelper() {
+            this.aaiClient = new AAIResourcesClient(AAIVersion.LATEST);
+            this.createStore = new AAITransactionStore(this.aaiClient, "Create");
+            this.updateStore = new AAITransactionStore(this.aaiClient, "Update");
+            this.deleteStore = new AAITransactionStore(this.aaiClient, "Delete");
+        }
+
+        AAIResourcesClient getAaiClient() {
+            return this.aaiClient;
+        }
+
+        void execute(boolean dryRun) throws BulkProcessFailed {
+            this.createStore.execute(dryRun);
+            this.updateStore.execute(dryRun);
+            this.deleteStore.execute(dryRun);
+        }
+
+        void create(AAIResourceUri uri, String payload) {
+            createStore.create(uri, payload);
+        }
+
+        void update(AAIResourceUri uri, String payload) {
+            updateStore.create(uri, payload);
+        }
 
+        void connect(AAIResourceUri uriA, AAIResourceUri uriB) {
+            createStore.connect(uriA, uriB);
+        }
+
+        void delete(AAIResourceUri uri) {
+            deleteStore.delete(uri);
+        }
+    }
+
+    static class AAITransactionStore {
+        private AAIResourcesClient aaiClient;
+        private List<AAITransactionalClient> transactions;
+        private int transactionCount;
         private static final int TRANSACTION_LIMIT = 30;
+        private final String label;
 
-        AAITransactionHelper(AAIResourcesClient aaiClient) {
+        public AAITransactionStore(AAIResourcesClient aaiClient, String label) {
+            this.label = label;
             this.aaiClient = aaiClient;
             transactions = new ArrayList<>();
             transactionCount = TRANSACTION_LIMIT;
@@ -194,18 +241,14 @@ public class AaiRepository implements IAaiRepository {
             return transactions.get(transactions.size() - 1);
         }
 
-        void execute(boolean dryRun) {
+        void execute(boolean dryRun) throws BulkProcessFailed {
             if (transactions.size() > 0) {
-                transactions.forEach(transaction -> {
-                    try {
-                        transaction.execute(dryRun);
-                    } catch (BulkProcessFailed e) {
-                        throw new RuntimeException("Failed to execute transaction", e);
-                    }
-                });
+                for (AAITransactionalClient transaction : transactions) {
+                    transaction.execute(dryRun);
+                }
                 transactions.clear();
             } else
-                logger.info("Nothing to commit in AAI");
+                logger.info("Nothing to commit in AAI for " + label + " transactions");
         }
 
         void create(AAIResourceUri uri, String payload) {
index 8a865d7..7908b3d 100644 (file)
@@ -21,6 +21,7 @@
 
 package org.onap.so.adapters.cnf.util;
 
+import org.onap.aaiclient.client.graphinventory.exceptions.BulkProcessFailed;
 import org.onap.so.adapters.cnf.model.aai.AaiRequest;
 import org.onap.so.adapters.cnf.service.aai.KubernetesResource;
 import org.slf4j.Logger;
@@ -42,7 +43,7 @@ public interface IAaiRepository {
 
     void delete(AaiRequest request, List<KubernetesResource> excludedList);
 
-    void commit(boolean dryRun) throws RuntimeException;
+    void commit(boolean dryRun) throws RuntimeException, BulkProcessFailed;
 
     static class AaiRepositoryDummy implements IAaiRepository {
         private static final Logger logger = LoggerFactory.getLogger(IAaiRepository.class);
index 651b433..3411ae1 100644 (file)
@@ -4,6 +4,7 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.onap.aaiclient.client.graphinventory.exceptions.BulkProcessFailed;
 import org.onap.so.adapters.cnf.AaiConfiguration;
 import org.onap.so.adapters.cnf.client.MulticloudClient;
 import org.onap.so.adapters.cnf.model.aai.AaiRequest;
@@ -36,7 +37,7 @@ public class AaiServiceTest {
     private AaiConfiguration aaiConfiguration;
 
     @Test
-    public void shouldTestAaiUpdate() throws BadResponseException {
+    public void shouldTestAaiUpdate() throws BadResponseException, BulkProcessFailed {
         // given
         String instanceId = "instanceId";
         AaiRequest aaiRequest = mock(AaiRequest.class);
@@ -62,7 +63,7 @@ public class AaiServiceTest {
 
 
     @Test
-    public void shouldTestAaiDelete() throws BadResponseException {
+    public void shouldTestAaiDelete() throws BadResponseException, BulkProcessFailed {
         // given
         String instanceId = "instanceId";
         AaiRequest aaiRequest = mock(AaiRequest.class);