Add a new filter to /instances endpoint 64/141664/2 master
authoradheli.tavares <adheli.tavares@est.tech>
Fri, 8 Aug 2025 15:29:10 +0000 (16:29 +0100)
committeradheli.tavares <adheli.tavares@est.tech>
Fri, 8 Aug 2025 15:44:15 +0000 (16:44 +0100)
Issue-ID: POLICY-5425
Change-Id: Ia8ff03956b1b1ddd2bbbd71e134821c30f2d1af4
Signed-off-by: adheli.tavares <adheli.tavares@est.tech>
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProvider.java
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/AutomationCompositionRepository.java
models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/AutomationCompositionProviderTest.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/instantiation/AutomationCompositionInstantiationProvider.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/InstantiationController.java
runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/stub/InstantiationControllerStub.java
runtime-acm/src/main/resources/openapi/openapi.yaml
runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/instantiation/rest/InstantiationControllerTest.java

index c8a862c..eb0d9b4 100644 (file)
@@ -335,17 +335,22 @@ public class AutomationCompositionProvider {
      * Retrieves a list of AutomationComposition instances filtered by the specified state change results
      * and deployment states. The result can be paginated and sorted based on the provided parameters.
      *
+     * @param compositionIds a list of composition UUIDs to filter the AutomationComposition instances
      * @param stateChangeResults a list of StateChangeResult values to filter the AutomationComposition instances
      * @param deployStates a list of DeployState values to filter the AutomationComposition instances
      * @param pageable the pagination information including page size and page number
      * @return a list of AutomationComposition instances that match the specified filters
      */
-    public List<AutomationComposition> getAcInstancesByStateResultDeployState(
+    public List<AutomationComposition> getAcInstancesByFilter(
+            @NonNull final List<String> compositionIds,
             @NonNull final List<StateChangeResult> stateChangeResults,
             @NonNull final List<DeployState> deployStates,
             @NonNull final Pageable pageable) {
         Page<JpaAutomationComposition> page;
-        if (stateChangeResults.isEmpty() && deployStates.isEmpty()) {
+
+        if (!compositionIds.isEmpty()) {
+            page = filterWithCompositionIds(compositionIds, stateChangeResults, deployStates, pageable);
+        } else if (stateChangeResults.isEmpty() && deployStates.isEmpty()) {
             page = automationCompositionRepository.findAll(pageable);
         } else if (!stateChangeResults.isEmpty() && deployStates.isEmpty()) {
             page = automationCompositionRepository.findByStateChangeResultIn(stateChangeResults, pageable);
@@ -358,4 +363,22 @@ public class AutomationCompositionProvider {
 
         return ProviderUtils.asEntityList(page.toList());
     }
+
+    private Page<JpaAutomationComposition> filterWithCompositionIds(final List<String> compositionIds,
+                                                                    final List<StateChangeResult> stages,
+                                                                    final List<DeployState> deployStates,
+                                                                    final Pageable pageable) {
+        if (stages.isEmpty() && deployStates.isEmpty()) {
+            return automationCompositionRepository.findByCompositionIdIn(compositionIds, pageable);
+        } else if (!stages.isEmpty() && deployStates.isEmpty()) {
+            return automationCompositionRepository.findByCompositionIdInAndStateChangeResultIn(
+                compositionIds, stages, pageable);
+        } else if (stages.isEmpty()) {
+            return automationCompositionRepository.findByCompositionIdInAndDeployStateIn(
+                compositionIds, deployStates, pageable);
+        } else {
+            return automationCompositionRepository.findByCompositionIdInAndStateChangeResultInAndDeployStateIn(
+                compositionIds, stages, deployStates, pageable);
+        }
+    }
 }
index 10fe0b1..7fa1647 100644 (file)
@@ -52,4 +52,16 @@ public interface AutomationCompositionRepository extends JpaRepository<JpaAutoma
 
     Page<JpaAutomationComposition> findByStateChangeResultIn(Collection<StateChangeResult> stateChangeResults,
                                                              Pageable pageable);
+
+    Page<JpaAutomationComposition> findByCompositionIdIn(Collection<String> compositionIds, Pageable pageable);
+
+    Page<JpaAutomationComposition> findByCompositionIdInAndStateChangeResultIn(
+        Collection<String> compositionIds, Collection<StateChangeResult> stateChangeResults, Pageable pageable);
+
+    Page<JpaAutomationComposition> findByCompositionIdInAndDeployStateIn(
+        Collection<String> compositionIds, Collection<DeployState> deployStates, Pageable pageable);
+
+    Page<JpaAutomationComposition> findByCompositionIdInAndStateChangeResultInAndDeployStateIn(
+        Collection<String> compositionIds, Collection<StateChangeResult> stateChangeResults,
+        Collection<DeployState> deployStates, Pageable pageable);
 }
index c9df95d..0e51a24 100644 (file)
@@ -26,6 +26,7 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyCollection;
 import static org.mockito.ArgumentMatchers.anyIterable;
@@ -188,6 +189,7 @@ class AutomationCompositionProviderTest {
         when(automationCompositionRepository.findById(automationComposition.getInstanceId().toString()))
                 .thenReturn(Optional.of(inputAutomationCompositionsJpa.get(0)));
         acOpt = automationCompositionProvider.findAutomationComposition(automationComposition.getInstanceId());
+        assertTrue(acOpt.isPresent());
         assertEquals(automationComposition, acOpt.get());
     }
 
@@ -417,7 +419,7 @@ class AutomationCompositionProviderTest {
     }
 
     @Test
-    void testGetAcInstancesByFilter() {
+    void testGetAcInstancesByFilter_WithoutCompositionIds() {
         Page<JpaAutomationComposition> mockPage = new PageImpl<>(inputAutomationCompositionsJpa);
         var acRepository = mock(AutomationCompositionRepository.class);
         when(acRepository.findByStateChangeResultIn(anyCollection(), any(Pageable.class)))
@@ -425,6 +427,7 @@ class AutomationCompositionProviderTest {
         when(acRepository.findByDeployStateIn(anyCollection(), any(Pageable.class)))
             .thenReturn(mockPage);
 
+        var acIds = new ArrayList<String>();
         var stateChangeResults = new ArrayList<StateChangeResult>();
         var deployStates = new ArrayList<DeployState>();
         var pageable = Pageable.unpaged();
@@ -434,20 +437,59 @@ class AutomationCompositionProviderTest {
         var acProvider = new AutomationCompositionProvider(acRepository,
             mock(AutomationCompositionElementRepository.class), mock(AutomationCompositionRollbackRepository.class));
 
-        var acInstances = acProvider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
+        var acInstances = acProvider.getAcInstancesByFilter(acIds, stateChangeResults, deployStates, pageable);
         assertNotNull(acInstances);
         assertEquals(2, acInstances.size());
 
         stateChangeResults.add(StateChangeResult.NO_ERROR);
-        acInstances = acProvider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
+        acInstances = acProvider.getAcInstancesByFilter(acIds, stateChangeResults, deployStates, pageable);
         assertNotNull(acInstances);
 
         deployStates.add(DeployState.DEPLOYED);
-        acInstances = acProvider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
+        acInstances = acProvider.getAcInstancesByFilter(acIds, stateChangeResults, deployStates, pageable);
         assertNotNull(acInstances);
 
         stateChangeResults.clear();
-        acInstances = acProvider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
+        acInstances = acProvider.getAcInstancesByFilter(acIds, stateChangeResults, deployStates, pageable);
+        assertNotNull(acInstances);
+    }
+
+    @Test
+    void testGetAcInstancesByFilter_WithCompositionIds() {
+        Page<JpaAutomationComposition> mockPage = new PageImpl<>(inputAutomationCompositionsJpa);
+        var acRepository = mock(AutomationCompositionRepository.class);
+
+        var acIds = new ArrayList<String>();
+        var stateChangeResults = new ArrayList<StateChangeResult>();
+        var deployStates = new ArrayList<DeployState>();
+        var pageable = Pageable.unpaged();
+
+        when(acRepository.findByCompositionIdInAndStateChangeResultInAndDeployStateIn(
+            acIds, stateChangeResults, deployStates, pageable)).thenReturn(mockPage);
+        when(acRepository.findByCompositionIdInAndStateChangeResultIn(acIds, stateChangeResults, pageable))
+            .thenReturn(mockPage);
+        when(acRepository.findByCompositionIdInAndDeployStateIn(acIds, deployStates, pageable)).thenReturn(mockPage);
+        when(acRepository.findByCompositionIdIn(acIds, pageable)).thenReturn(mockPage);
+
+        var acProvider = new AutomationCompositionProvider(acRepository,
+            mock(AutomationCompositionElementRepository.class), mock(AutomationCompositionRollbackRepository.class));
+
+        acIds.add(inputAutomationCompositions.getAutomationCompositionList().get(0).getCompositionId().toString());
+
+        var acInstances = acProvider.getAcInstancesByFilter(acIds, stateChangeResults, deployStates, pageable);
+        assertNotNull(acInstances);
+        assertEquals(2, acInstances.size());
+
+        stateChangeResults.add(StateChangeResult.NO_ERROR);
+        acInstances = acProvider.getAcInstancesByFilter(acIds, stateChangeResults, deployStates, pageable);
+        assertNotNull(acInstances);
+
+        deployStates.add(DeployState.DEPLOYED);
+        acInstances = acProvider.getAcInstancesByFilter(acIds, stateChangeResults, deployStates, pageable);
+        assertNotNull(acInstances);
+
+        stateChangeResults.clear();
+        acInstances = acProvider.getAcInstancesByFilter(acIds, stateChangeResults, deployStates, pageable);
         assertNotNull(acInstances);
     }
 
@@ -455,14 +497,17 @@ class AutomationCompositionProviderTest {
     void testGetAcInstancesByFilterWithNull() {
         var provider = new AutomationCompositionProvider(mock(AutomationCompositionRepository.class),
             mock(AutomationCompositionElementRepository.class), mock(AutomationCompositionRollbackRepository.class));
+        var acIds = new ArrayList<String>();
         var stateChangeResults = new ArrayList<StateChangeResult>();
         var deployStates = new ArrayList<DeployState>();
         var pageable = Pageable.unpaged();
         assertThrows(NullPointerException.class, () ->
-            provider.getAcInstancesByStateResultDeployState(null, deployStates, pageable));
+            provider.getAcInstancesByFilter(null, stateChangeResults, deployStates, pageable));
+        assertThrows(NullPointerException.class, () ->
+            provider.getAcInstancesByFilter(acIds, null, deployStates, pageable));
         assertThrows(NullPointerException.class, () ->
-            provider.getAcInstancesByStateResultDeployState(stateChangeResults, null, pageable));
+            provider.getAcInstancesByFilter(acIds, stateChangeResults, null, pageable));
         assertThrows(NullPointerException.class, () ->
-            provider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, null));
+            provider.getAcInstancesByFilter(acIds, stateChangeResults, deployStates, null));
     }
 }
index c619015..670f30b 100644 (file)
@@ -487,7 +487,7 @@ public class AutomationCompositionInstantiationProvider {
                 dbAcElement.setDefinition(element.getValue().getDefinition());
             }
         }
-        // Remove element which is not present in the new Ac instance
+        // Remove elements which are not present in the new Ac instance
         var elementsRemoved = getElementRemoved(acToBeUpdated, automationComposition);
         elementsRemoved.forEach(element -> acToBeUpdated.getElements().remove(element.getId()));
 
@@ -511,15 +511,21 @@ public class AutomationCompositionInstantiationProvider {
      * Retrieves a list of AutomationComposition instances filtered by the specified state change results
      * and deployment states. The result can be paginated and sorted based on the provided parameters.
      *
+     * @param compositionIds a list of composition UUIDs to filter the AutomationComposition instances
      * @param stateChangeResults a list of StateChangeResult values to filter the AutomationComposition instances
      * @param deployStates a list of DeployState values to filter the AutomationComposition instances
      * @param pageable the pagination information including page size and page number
      * @return a list of AutomationComposition instances that match the specified filters
      */
-    public AutomationCompositions getAcInstancesByStateResultDeployState(
-        final String stateChangeResults, final String deployStates,
+    public AutomationCompositions getAcInstancesByFilter(
+        final String compositionIds, final String stateChangeResults, final String deployStates,
         final Pageable pageable) {
 
+        List<String> acIds = new ArrayList<>();
+        if (compositionIds != null) {
+            Arrays.stream(compositionIds.split(",")).forEach(acId -> acIds.add(acId.trim()));
+        }
+
         List<StateChangeResult> stateChangeResultList = new ArrayList<>();
         if (stateChangeResults != null) {
             Arrays.stream(stateChangeResults.split(","))
@@ -532,7 +538,7 @@ public class AutomationCompositionInstantiationProvider {
                 .forEach(deployState -> deployStateList.add(DeployState.valueOf(deployState)));
         }
 
-        var instances = automationCompositionProvider.getAcInstancesByStateResultDeployState(stateChangeResultList,
+        var instances = automationCompositionProvider.getAcInstancesByFilter(acIds, stateChangeResultList,
             deployStateList, pageable);
         return new AutomationCompositions(instances);
     }
index 5fc5f2c..0e4efdd 100644 (file)
@@ -111,10 +111,11 @@ public class InstantiationController extends AbstractRestController implements A
      * @return a {@link ResponseEntity} containing an {@link AutomationCompositions} object
      */
     @Override
-    public ResponseEntity<AutomationCompositions> queryCompositionInstancesByStateChangeDeployState(String deployStates,
-         String stateChangeResults, Integer page, Integer size, String sort, String sortOrder, UUID requestId) {
+    public ResponseEntity<AutomationCompositions> queryCompositionInstancesByFilter(
+        String compositionIds, String deployStates, String stateChangeResults,
+        Integer page, Integer size, String sort, String sortOrder, UUID requestId) {
         var pageable = getPageableWithSorting(page, size, sort, sortOrder);
-        var instances = provider.getAcInstancesByStateResultDeployState(stateChangeResults, deployStates, pageable);
+        var instances = provider.getAcInstancesByFilter(compositionIds, stateChangeResults, deployStates, pageable);
         return ResponseEntity.ok().body(instances);
     }
 
index 269c86c..fc16be8 100644 (file)
@@ -97,8 +97,9 @@ public class InstantiationControllerStub extends AbstractRestController implemen
     }
 
     @Override
-    public ResponseEntity<AutomationCompositions> queryCompositionInstancesByStateChangeDeployState(String deployState,
-            String stateChangeResult, Integer page, Integer size, String sort, String sortOrder, UUID onapRequestId) {
+    public ResponseEntity<AutomationCompositions> queryCompositionInstancesByFilter(
+        String compositionIds, String deployState, String stateChangeResult,
+        Integer page, Integer size, String sort, String sortOrder, UUID onapRequestId) {
         return stubUtils.getResponse(pathToAllInstances, AutomationCompositions.class);
     }
 }
index d070178..0953e76 100644 (file)
@@ -1923,8 +1923,14 @@ paths:
         - Automation Composition Instance
       summary: Query a list of automation composition instances
       description: Query a list of automation composition instances based on the query filter
-      operationId: queryCompositionInstancesByStateChangeDeployState
+      operationId: queryCompositionInstancesByFilter
       parameters:
+        - name: compositionIds
+          in: query
+          required: false
+          schema:
+            type: string
+          description: Filter to get instances by compositionId (two or more to be comma-separated)
         - name: deployState
           in: query
           required: false
index 33703ee..2ce195c 100644 (file)
@@ -454,7 +454,7 @@ class InstantiationControllerTest extends CommonRestController {
     }
 
     @Test
-    void test_QueryCompositionInstancesByStateChangeDeployState() {
+    void test_queryCompositionInstancesByFilter_WithoutCompositionIds() {
         // test setup
         var compositionId = createAcDefinitionInDB("Query");
         var automationComposition =
@@ -475,6 +475,27 @@ class InstantiationControllerTest extends CommonRestController {
         validateQueryPageable("instances?sort=name&sortOrder=DESC", 10);
     }
 
+    @Test
+    void test_queryCompositionInstancesByFilter_WithCompositionIds() {
+        // test setup
+        var compositionId = createAcDefinitionInDB("Query");
+        var automationComposition =
+            InstantiationUtils.getAutomationCompositionFromResource(AC_INSTANTIATION_CREATE_JSON, "Query");
+        assertNotNull(automationComposition);
+        automationComposition.setCompositionId(compositionId);
+        for (var i = 0; i < NUMBER_INSTANCES; i++) {
+            automationComposition.setName("acmr_" + i);
+            instantiationProvider.createAutomationComposition(compositionId, automationComposition);
+        }
+
+        validateQueryPageable("instances?compositionIds=" + compositionId, 10);
+        validateQueryPageable("instances?page=1&size=4&compositionIds=" + compositionId, 4);
+        validateQueryPageable("instances?size=4&compositionIds=" + compositionId, 10);
+        validateQueryPageable("instances?stateChangeResult=FAILED,TIMEOUT&compositionIds=" + compositionId, 0);
+        validateQueryPageable("instances?deployState=UNDEPLOYED&compositionIds=" + compositionId, 10);
+        validateQueryPageable("instances?sort=name&sortOrder=DESC&compositionIds=" + compositionId, 10);
+    }
+
     private UUID createAcDefinitionInDB(String name) {
         var serviceTemplateCreate = new ToscaServiceTemplate(serviceTemplate);
         serviceTemplateCreate.setName(name);